{"model_name":"gpt-5.5-medium","codes":{"1":{"ahc001":"#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 now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\nmt19937 rng(1234567);\nTimer timer_;\n\nlong long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\ndouble score_area(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    double mn = (double)min(s, r);\n    double mx = (double)max(s, r);\n    double q = mn / mx;\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble evaluate(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; i++) {\n        const auto& e = rects[i];\n        bool ok = (e.a <= xs[i] && xs[i] + 1 <= e.c && e.b <= ys[i] && ys[i] + 1 <= e.d);\n        if (!ok) continue;\n        sum += score_area(area(e), rs[i]);\n    }\n    return sum;\n}\n\nbool overlap1d(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\n/* ---------- recursive slicing construction ---------- */\n\nstruct SplitCand {\n    int axis; // 0:x, 1:y\n    int k;\n    int cut;\n    double cost;\n};\n\nlong long sum_r(const vector<int>& ids) {\n    long long s = 0;\n    for (int id : ids) s += rs[id];\n    return s;\n}\n\nvoid build_rec(\n    const vector<int>& ids,\n    int L, int B, int R, int T,\n    vector<Rect>& out,\n    int topK\n) {\n    int m = (int)ids.size();\n    if (m == 1) {\n        out[ids[0]] = {L, B, R, T};\n        return;\n    }\n\n    long long totalTarget = 0;\n    for (int id : ids) totalTarget += rs[id];\n\n    long long regionArea = 1LL * (R - L) * (T - B);\n    vector<SplitCand> cands;\n\n    for (int axis = 0; axis < 2; axis++) {\n        vector<int> v = ids;\n        if (axis == 0) {\n            sort(v.begin(), v.end(), [&](int p, int q) {\n                if (xs[p] != xs[q]) return xs[p] < xs[q];\n                return ys[p] < ys[q];\n            });\n        } else {\n            sort(v.begin(), v.end(), [&](int p, int q) {\n                if (ys[p] != ys[q]) return ys[p] < ys[q];\n                return xs[p] < xs[q];\n            });\n        }\n\n        vector<long long> pref(m + 1, 0);\n        for (int i = 0; i < m; i++) pref[i + 1] = pref[i] + rs[v[i]];\n\n        for (int k = 1; k < m; k++) {\n            int coordL = (axis == 0 ? xs[v[k - 1]] : ys[v[k - 1]]);\n            int coordR = (axis == 0 ? xs[v[k]] : ys[v[k]]);\n            if (coordL >= coordR) continue;\n\n            int start = (axis == 0 ? L : B);\n            int end = (axis == 0 ? R : T);\n            int otherLen = (axis == 0 ? T - B : R - L);\n            int len = end - start;\n\n            int lo = coordL + 1;\n            int hi = coordR;\n            lo = max(lo, start + 1);\n            hi = min(hi, end - 1);\n            if (lo > hi) continue;\n\n            long double ratio = (long double)pref[k] / (long double)totalTarget;\n            int desired = (int)llround((long double)start + ratio * len);\n            int cut = min(max(desired, lo), hi);\n\n            long long leftArea = 1LL * (cut - start) * otherLen;\n            long long rightArea = regionArea - leftArea;\n            long long leftTarget = pref[k];\n            long long rightTarget = totalTarget - leftTarget;\n\n            double scale = (double)regionArea / (double)totalTarget;\n            double er1 = fabs((double)leftArea / (double)leftTarget - scale);\n            double er2 = fabs((double)rightArea / (double)rightTarget - scale);\n            double cost = er1 * ((double)leftTarget / totalTarget)\n                        + er2 * ((double)rightTarget / totalTarget);\n\n            // If a child is already a leaf, slightly prefer good actual leaf area.\n            if (k == 1) {\n                int id = v[0];\n                cost += 0.08 * (1.0 - score_area(leftArea, rs[id]));\n            }\n            if (m - k == 1) {\n                int id = v[m - 1];\n                cost += 0.08 * (1.0 - score_area(rightArea, rs[id]));\n            }\n\n            cands.push_back({axis, k, cut, cost});\n        }\n    }\n\n    if (cands.empty()) {\n        // This should practically never happen for distinct points.\n        // Fallback: split by index with a legal-looking middle cut.\n        vector<int> v = ids;\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (xs[p] != xs[q]) return xs[p] < xs[q];\n            return ys[p] < ys[q];\n        });\n        int k = m / 2;\n        int cut = (L + R) / 2;\n        if (cut <= L) cut = L + 1;\n        if (cut >= R) cut = R - 1;\n        vector<int> A(v.begin(), v.begin() + k), C(v.begin() + k, v.end());\n        build_rec(A, L, B, cut, T, out, topK);\n        build_rec(C, cut, B, R, T, out, topK);\n        return;\n    }\n\n    sort(cands.begin(), cands.end(), [](const SplitCand& x, const SplitCand& y) {\n        return x.cost < y.cost;\n    });\n\n    int pick = 0;\n    if (topK > 1) {\n        int lim = min<int>(topK, cands.size());\n        double u = uniform_real_distribution<double>(0.0, 1.0)(rng);\n        // biased toward better candidates\n        pick = min(lim - 1, (int)(u * u * lim));\n    }\n\n    SplitCand ch = cands[pick];\n\n    vector<int> v = ids;\n    if (ch.axis == 0) {\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (xs[p] != xs[q]) return xs[p] < xs[q];\n            return ys[p] < ys[q];\n        });\n    } else {\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (ys[p] != ys[q]) return ys[p] < ys[q];\n            return xs[p] < xs[q];\n        });\n    }\n\n    vector<int> left(v.begin(), v.begin() + ch.k);\n    vector<int> right(v.begin() + ch.k, v.end());\n\n    if (ch.axis == 0) {\n        build_rec(left, L, B, ch.cut, T, out, topK);\n        build_rec(right, ch.cut, B, R, T, out, topK);\n    } else {\n        build_rec(left, L, B, R, ch.cut, out, topK);\n        build_rec(right, L, ch.cut, R, T, out, topK);\n    }\n}\n\nvector<Rect> build_slicing(int topK) {\n    vector<Rect> res(n);\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    build_rec(ids, 0, 0, 10000, 10000, res, topK);\n    return res;\n}\n\n/* ---------- local improvement: shrink oversized rectangles, expand undersized ones ---------- */\n\nbool shrink_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect cur = rects[id];\n        long long A = area(cur);\n        double curScore = score_area(A, rs[id]);\n\n        Rect best = cur;\n        double bestGain = 1e-15;\n\n        auto try_delta = [&](int dir, int maxd) {\n            if (maxd <= 0) return;\n            int len = (dir < 2 ? cur.d - cur.b : cur.c - cur.a);\n            if (len <= 0) return;\n\n            vector<int> ds;\n            long long excess = A - rs[id];\n            if (excess > 0) {\n                long long q = excess / len;\n                for (long long z : {q - 1, q, q + 1, q + 2}) {\n                    if (1 <= z && z <= maxd) ds.push_back((int)z);\n                }\n            }\n            ds.push_back(maxd);\n            ds.push_back(1);\n            sort(ds.begin(), ds.end());\n            ds.erase(unique(ds.begin(), ds.end()), ds.end());\n\n            for (int dlt : ds) {\n                Rect nr = cur;\n                if (dir == 0) nr.a += dlt;      // shrink left\n                if (dir == 1) nr.c -= dlt;      // shrink right\n                if (dir == 2) nr.b += dlt;      // shrink bottom\n                if (dir == 3) nr.d -= dlt;      // shrink top\n                if (!(nr.a < nr.c && nr.b < nr.d)) continue;\n                if (!(nr.a <= xs[id] && xs[id] + 1 <= nr.c && nr.b <= ys[id] && ys[id] + 1 <= nr.d)) continue;\n\n                double ns = score_area(area(nr), rs[id]);\n                double gain = ns - curScore;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = nr;\n                }\n            }\n        };\n\n        try_delta(0, xs[id] - cur.a);\n        try_delta(1, cur.c - (xs[id] + 1));\n        try_delta(2, ys[id] - cur.b);\n        try_delta(3, cur.d - (ys[id] + 1));\n\n        if (bestGain > 1e-14) {\n            rects[id] = best;\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nint max_expand_delta(const vector<Rect>& rects, int id, int dir) {\n    const Rect& r = rects[id];\n    int lim = 0;\n\n    if (dir == 0) { // left\n        lim = r.a;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.b, r.d, o.b, o.d) && o.c <= r.a) {\n                lim = min(lim, r.a - o.c);\n            }\n        }\n    } else if (dir == 1) { // right\n        lim = 10000 - r.c;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.b, r.d, o.b, o.d) && o.a >= r.c) {\n                lim = min(lim, o.a - r.c);\n            }\n        }\n    } else if (dir == 2) { // down\n        lim = r.b;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.a, r.c, o.a, o.c) && o.d <= r.b) {\n                lim = min(lim, r.b - o.d);\n            }\n        }\n    } else { // up\n        lim = 10000 - r.d;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.a, r.c, o.a, o.c) && o.b >= r.d) {\n                lim = min(lim, o.b - r.d);\n            }\n        }\n    }\n\n    return lim;\n}\n\nbool expand_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect cur = rects[id];\n        long long A = area(cur);\n        double curScore = score_area(A, rs[id]);\n\n        Rect best = cur;\n        double bestGain = 1e-15;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int maxd = max_expand_delta(rects, id, dir);\n            if (maxd <= 0) continue;\n\n            int len = (dir < 2 ? cur.d - cur.b : cur.c - cur.a);\n            if (len <= 0) continue;\n\n            vector<int> ds;\n            long long need = rs[id] - A;\n            if (need > 0) {\n                long long q = need / len;\n                for (long long z : {q - 1, q, q + 1, q + 2}) {\n                    if (1 <= z && z <= maxd) ds.push_back((int)z);\n                }\n            }\n            ds.push_back(maxd);\n            ds.push_back(1);\n            sort(ds.begin(), ds.end());\n            ds.erase(unique(ds.begin(), ds.end()), ds.end());\n\n            for (int dlt : ds) {\n                Rect nr = cur;\n                if (dir == 0) nr.a -= dlt;\n                if (dir == 1) nr.c += dlt;\n                if (dir == 2) nr.b -= dlt;\n                if (dir == 3) nr.d += dlt;\n\n                double ns = score_area(area(nr), rs[id]);\n                double gain = ns - curScore;\n\n                // tiny random tie breaker\n                gain += uniform_real_distribution<double>(0.0, 1e-16)(rng);\n\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = nr;\n                }\n            }\n        }\n\n        if (bestGain > 1e-14) {\n            rects[id] = best;\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nvoid shrink_only(vector<Rect>& rects, double deadline) {\n    for (int it = 0; it < 20 && timer_.elapsed() < deadline; it++) {\n        bool mv = shrink_pass(rects, false, deadline);\n        if (!mv) break;\n    }\n}\n\nvoid improve_solution(vector<Rect>& rects, double deadline) {\n    for (int it = 0; timer_.elapsed() < deadline; it++) {\n        bool moved = false;\n        moved |= shrink_pass(rects, true, deadline);\n        moved |= expand_pass(rects, true, deadline);\n        if (!moved) break;\n    }\n}\n\n/* ---------- main ---------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n    for (int i = 0; i < n; i++) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    vector<Rect> best(n);\n    for (int i = 0; i < n; i++) {\n        best[i] = {xs[i], ys[i], xs[i] + 1, ys[i] + 1};\n    }\n    double bestScore = evaluate(best);\n\n    auto consider_best = [&](const vector<Rect>& sol) {\n        double sc = evaluate(sol);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = sol;\n        }\n    };\n\n    vector<pair<double, vector<Rect>>> tops;\n\n    auto insert_top = [&](vector<Rect> sol) {\n        double sc = evaluate(sol);\n        tops.push_back({sc, sol});\n        sort(tops.begin(), tops.end(), [](auto& p, auto& q) {\n            return p.first > q.first;\n        });\n        if ((int)tops.size() > 8) tops.pop_back();\n        consider_best(sol);\n    };\n\n    // Generate many slicing partitions.\n    int cnt = 0;\n    while (timer_.elapsed() < 3.20) {\n        int topK;\n        if (cnt == 0) topK = 1;\n        else if (cnt % 4 == 0) topK = 3;\n        else if (cnt % 4 == 1) topK = 5;\n        else topK = 10;\n\n        vector<Rect> sol = build_slicing(topK);\n        shrink_only(sol, 3.20);\n        insert_top(sol);\n        cnt++;\n    }\n\n    sort(tops.begin(), tops.end(), [](auto& p, auto& q) {\n        return p.first > q.first;\n    });\n\n    // Improve best slicing candidates.\n    int m = (int)tops.size();\n    for (int i = 0; i < m && timer_.elapsed() < 4.72; i++) {\n        vector<Rect> sol = tops[i].second;\n        double remain = 4.72 - timer_.elapsed();\n        double deadline = timer_.elapsed() + remain / max(1, m - i);\n        improve_solution(sol, deadline);\n        consider_best(sol);\n    }\n\n    // One extra expansion-only solution from unit rectangles, useful for some cases.\n    if (timer_.elapsed() < 4.90) {\n        vector<Rect> sol(n);\n        for (int i = 0; i < n; i++) {\n            sol[i] = {xs[i], ys[i], xs[i] + 1, ys[i] + 1};\n        }\n        improve_solution(sol, 4.90);\n        consider_best(sol);\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' ' << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nconstexpr int N = 50;\nconstexpr int V = N * N;\n\nint si, sj;\nint tile_id[V];\nint point_val[V];\n\nint nb[V][4];\nchar nb_dir[V][4];\n\nstruct Path {\n    int score = 0;\n    vector<int> cells;\n    string moves;\n};\n\nstruct Params {\n    double wp;\n    double wd;\n    double w1;\n    double w2;\n    double noise;\n    double randomMoveProb;\n};\n\nParams make_params(XorShift &rng) {\n    int mode = rng.nextInt(8);\n    Params p;\n\n    if (mode == 0) {\n        // score-heavy\n        p = {1.8, 4.0, 0.20, 0.08, 30.0, 0.02};\n    } else if (mode == 1) {\n        // Warnsdorff-like: prefer low onward degree\n        p = {1.0, -22.0, 0.10, 0.05, 45.0, 0.03};\n    } else if (mode == 2) {\n        // balanced\n        p = {1.2, 8.0, 0.35, 0.10, 55.0, 0.04};\n    } else if (mode == 3) {\n        // strongly randomized\n        p = {1.0, 0.0, 0.15, 0.05, 120.0, 0.12};\n    } else if (mode == 4) {\n        // low-degree explorer\n        p = {0.8, -35.0, 0.05, 0.03, 60.0, 0.04};\n    } else if (mode == 5) {\n        // future-option preserving\n        p = {1.0, 18.0, 0.45, 0.15, 45.0, 0.02};\n    } else if (mode == 6) {\n        // high score but avoid immediate dead ends\n        p = {2.4, -8.0, 0.25, 0.08, 40.0, 0.02};\n    } else {\n        // almost random greedy\n        p = {0.9, 2.0, 0.10, 0.04, 160.0, 0.15};\n    }\n\n    double a = 0.75 + rng.nextDouble() * 0.7;\n    p.wp *= a;\n    p.wd *= 0.75 + rng.nextDouble() * 0.7;\n    p.w1 *= 0.7 + rng.nextDouble() * 0.8;\n    p.w2 *= 0.7 + rng.nextDouble() * 0.8;\n    p.noise *= 0.7 + rng.nextDouble() * 0.8;\n\n    return p;\n}\n\nint choose_next(\n    int pos,\n    const vector<int> &seen,\n    int mark,\n    const Params &par,\n    XorShift &rng,\n    char &out_dir\n) {\n    int cand[4];\n    char cdir[4];\n    int cnt = 0;\n\n    for (int k = 0; k < 4; k++) {\n        int to = nb[pos][k];\n        if (to < 0) continue;\n        int tid = tile_id[to];\n        if (seen[tid] == mark) continue;\n        cand[cnt] = to;\n        cdir[cnt] = nb_dir[pos][k];\n        cnt++;\n    }\n\n    if (cnt == 0) return -1;\n    if (cnt == 1) {\n        out_dir = cdir[0];\n        return cand[0];\n    }\n\n    if (rng.nextDouble() < par.randomMoveProb) {\n        int id = rng.nextInt(cnt);\n        out_dir = cdir[id];\n        return cand[id];\n    }\n\n    double best_score = -1e100;\n    int best_id = 0;\n\n    for (int idx = 0; idx < cnt; idx++) {\n        int to = cand[idx];\n        int tid_to = tile_id[to];\n\n        int degree1 = 0;\n        int best_next_point = 0;\n        double best_look2 = 0.0;\n\n        for (int k = 0; k < 4; k++) {\n            int v1 = nb[to][k];\n            if (v1 < 0) continue;\n            int tid1 = tile_id[v1];\n            if (tid1 == tid_to) continue;\n            if (seen[tid1] == mark) continue;\n\n            degree1++;\n            best_next_point = max(best_next_point, point_val[v1]);\n\n            int degree2 = 0;\n            int best_p2 = 0;\n            for (int l = 0; l < 4; l++) {\n                int v2 = nb[v1][l];\n                if (v2 < 0) continue;\n                int tid2 = tile_id[v2];\n                if (tid2 == tid_to || tid2 == tid1) continue;\n                if (seen[tid2] == mark) continue;\n                degree2++;\n                best_p2 = max(best_p2, point_val[v2]);\n            }\n\n            double look2 = point_val[v1] + 8.0 * degree2 + 0.25 * best_p2;\n            best_look2 = max(best_look2, look2);\n        }\n\n        double eval = 0.0;\n        eval += par.wp * point_val[to];\n        eval += par.wd * degree1;\n        eval += par.w1 * best_next_point;\n        eval += par.w2 * best_look2;\n        eval += par.noise * (rng.nextDouble() - 0.5);\n\n        if (eval > best_score) {\n            best_score = eval;\n            best_id = idx;\n        }\n    }\n\n    out_dir = cdir[best_id];\n    return cand[best_id];\n}\n\nPath build_path_from_prefix(\n    const Path *base,\n    int prefix_len,\n    vector<int> &seen,\n    int mark,\n    XorShift &rng\n) {\n    Path cur;\n    cur.cells.reserve(V);\n    cur.moves.reserve(V);\n\n    if (base == nullptr) {\n        int start = si * N + sj;\n        cur.cells.push_back(start);\n        cur.score = point_val[start];\n        seen[tile_id[start]] = mark;\n    } else {\n        prefix_len = max(prefix_len, 1);\n        prefix_len = min(prefix_len, (int)base->cells.size());\n\n        cur.cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n        cur.moves.assign(base->moves.begin(), base->moves.begin() + max(0, prefix_len - 1));\n\n        cur.score = 0;\n        for (int c : cur.cells) {\n            cur.score += point_val[c];\n            seen[tile_id[c]] = mark;\n        }\n    }\n\n    Params par = make_params(rng);\n\n    while (true) {\n        int pos = cur.cells.back();\n        char d = '?';\n        int nxt = choose_next(pos, seen, mark, par, rng, d);\n        if (nxt < 0) break;\n\n        seen[tile_id[nxt]] = mark;\n        cur.cells.push_back(nxt);\n        cur.moves.push_back(d);\n        cur.score += point_val[nxt];\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tid = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            int id = i * N + j;\n            tile_id[id] = x;\n            max_tid = max(max_tid, x);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> point_val[i * N + j];\n        }\n    }\n\n    for (int i = 0; i < V; i++) {\n        for (int k = 0; k < 4; k++) {\n            nb[i][k] = -1;\n            nb_dir[i][k] = '?';\n        }\n    }\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            for (int k = 0; k < 4; k++) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    nb[id][k] = ni * N + nj;\n                    nb_dir[id][k] = dc[k];\n                }\n            }\n        }\n    }\n\n    uint64_t seed = 123456789;\n    seed ^= (uint64_t)(si * 51 + sj + 1) * 1000003ULL;\n    for (int i = 0; i < V; i++) {\n        seed ^= (uint64_t)(tile_id[i] + 1) * 11995408973635179863ULL;\n        seed ^= (uint64_t)(point_val[i] + 7) * 10150724397891781847ULL;\n        seed = seed * 6364136223846793005ULL + 1442695040888963407ULL;\n    }\n\n    XorShift rng(seed);\n\n    vector<int> seen(max_tid + 1, 0);\n    int mark = 1;\n\n    Path best;\n    vector<Path> pool;\n    const int POOL_SIZE = 18;\n\n    auto consider = [&](const Path &p) {\n        if (p.score > best.score) {\n            best = p;\n        }\n\n        if ((int)pool.size() < POOL_SIZE) {\n            pool.push_back(p);\n        } else {\n            int worst = 0;\n            for (int i = 1; i < (int)pool.size(); i++) {\n                if (pool[i].score < pool[worst].score) worst = i;\n            }\n            if (p.score > pool[worst].score) {\n                pool[worst] = p;\n            }\n        }\n    };\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.90;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        Path cur;\n\n        bool fresh = pool.empty() || rng.nextInt(100) < 25;\n\n        if (fresh) {\n            cur = build_path_from_prefix(nullptr, 0, seen, mark, rng);\n        } else {\n            const Path *base;\n            if (rng.nextInt(100) < 65) {\n                base = &best;\n            } else {\n                base = &pool[rng.nextInt((int)pool.size())];\n            }\n\n            int L = (int)base->cells.size();\n            int prefix_len = 1;\n\n            if (L <= 1) {\n                prefix_len = 1;\n            } else {\n                double u = rng.nextDouble();\n                double x;\n                int typ = rng.nextInt(100);\n\n                if (typ < 50) {\n                    // keep a long prefix, rebuild only the tail\n                    x = sqrt(u);\n                } else if (typ < 82) {\n                    // uniform cut\n                    x = u;\n                } else {\n                    // sometimes change early decisions\n                    x = u * u;\n                }\n\n                prefix_len = 1 + (int)(x * (L - 1));\n                prefix_len = min(prefix_len, L - 1);\n                prefix_len = max(prefix_len, 1);\n            }\n\n            cur = build_path_from_prefix(base, prefix_len, seen, mark, rng);\n        }\n\n        consider(cur);\n    }\n\n    cout << best.moves << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HEDGE = 30 * 29;\nstatic constexpr int VEDGE = 29 * 30;\nstatic constexpr int E = HEDGE + VEDGE;\nstatic constexpr int VAR = 60;\n\nstruct Obs {\n    array<int, VAR> x;\n    long long y;\n};\n\nvector<Obs> observations;\n\ndouble hcost[N], vcost[N];\ndouble offset_edge[E];\nint edge_count[E];\n\nuint64_t rng_state = 88172645463325252ull;\n\nuint64_t xorshift() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\ndouble clamp_double(double x, double lo, double hi) {\n    return max(lo, min(hi, x));\n}\n\nint hid(int i, int j) {\n    return i * 29 + j;\n}\n\nint vid(int i, int j) {\n    return HEDGE + i * 30 + j;\n}\n\ndouble smooth_offset_h(int i, int j) {\n    double num = 0.0;\n    double den = 5.0;\n\n    for (int dj = -2; dj <= 2; dj++) {\n        int nj = j + dj;\n        if (nj < 0 || nj >= 29) continue;\n\n        int id = hid(i, nj);\n        double w = (3 - abs(dj)) * edge_count[id];\n        num += offset_edge[id] * w;\n        den += w;\n    }\n\n    return num / den;\n}\n\ndouble smooth_offset_v(int i, int j) {\n    double num = 0.0;\n    double den = 5.0;\n\n    for (int di = -2; di <= 2; di++) {\n        int ni = i + di;\n        if (ni < 0 || ni >= 29) continue;\n\n        int id = vid(ni, j);\n        double w = (3 - abs(di)) * edge_count[id];\n        num += offset_edge[id] * w;\n        den += w;\n    }\n\n    return num / den;\n}\n\ndouble model_weight_raw(int id) {\n    double w;\n\n    if (id < HEDGE) {\n        int i = id / 29;\n        int j = id % 29;\n        w = hcost[i] + smooth_offset_h(i, j);\n    } else {\n        int x = id - HEDGE;\n        int i = x / 30;\n        int j = x % 30;\n        w = vcost[j] + smooth_offset_v(i, j);\n    }\n\n    return clamp_double(w, 800.0, 9500.0);\n}\n\ndouble model_weight_for_search(int id, int turn) {\n    double learned = model_weight_raw(id);\n\n    double rel = ((double)turn - 50.0) / 500.0;\n    rel = clamp_double(rel, 0.0, 1.0);\n\n    double w = 5000.0 * (1.0 - rel) + learned * rel;\n    return clamp_double(w, 800.0, 9500.0);\n}\n\nvoid solve_row_col_model() {\n    static double a[VAR][VAR + 1];\n\n    for (int i = 0; i < VAR; i++) {\n        for (int j = 0; j <= VAR; j++) {\n            a[i][j] = 0.0;\n        }\n    }\n\n    const double lambda = 200.0;\n\n    for (int i = 0; i < VAR; i++) {\n        a[i][i] += lambda;\n    }\n\n    for (const auto& ob : observations) {\n        vector<pair<int, int>> nz;\n        int len = 0;\n\n        for (int i = 0; i < VAR; i++) {\n            if (ob.x[i]) {\n                nz.push_back({i, ob.x[i]});\n                len += ob.x[i];\n            }\n        }\n\n        double r = (double)ob.y - 5000.0 * len;\n\n        for (auto [i, xi] : nz) {\n            a[i][VAR] += xi * r;\n            for (auto [j, xj] : nz) {\n                a[i][j] += (double)xi * xj;\n            }\n        }\n    }\n\n    for (int col = 0; col < VAR; col++) {\n        int piv = col;\n        for (int row = col + 1; row < VAR; row++) {\n            if (fabs(a[row][col]) > fabs(a[piv][col])) {\n                piv = row;\n            }\n        }\n\n        if (piv != col) {\n            for (int j = col; j <= VAR; j++) {\n                swap(a[piv][j], a[col][j]);\n            }\n        }\n\n        double div = a[col][col];\n        if (fabs(div) < 1e-9) continue;\n\n        for (int j = col; j <= VAR; j++) {\n            a[col][j] /= div;\n        }\n\n        for (int row = 0; row < VAR; row++) {\n            if (row == col) continue;\n\n            double factor = a[row][col];\n            if (fabs(factor) < 1e-12) continue;\n\n            for (int j = col; j <= VAR; j++) {\n                a[row][j] -= factor * a[col][j];\n            }\n        }\n    }\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = clamp_double(5000.0 + a[i][VAR], 1000.0, 9000.0);\n    }\n\n    for (int j = 0; j < 30; j++) {\n        vcost[j] = clamp_double(5000.0 + a[30 + j][VAR], 1000.0, 9000.0);\n    }\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool horizontal_first) {\n    string res;\n\n    auto add_vertical = [&]() {\n        if (si < ti) {\n            while (si < ti) {\n                res.push_back('D');\n                si++;\n            }\n        } else {\n            while (si > ti) {\n                res.push_back('U');\n                si--;\n            }\n        }\n    };\n\n    auto add_horizontal = [&]() {\n        if (sj < tj) {\n            while (sj < tj) {\n                res.push_back('R');\n                sj++;\n            }\n        } else {\n            while (sj > tj) {\n                res.push_back('L');\n                sj--;\n            }\n        }\n    };\n\n    if (horizontal_first) {\n        add_horizontal();\n        add_vertical();\n    } else {\n        add_vertical();\n        add_horizontal();\n    }\n\n    return res;\n}\n\nvoid extract_features(\n    int si,\n    int sj,\n    const string& path,\n    array<int, VAR>& feat,\n    vector<int>& edges\n) {\n    feat.fill(0);\n    edges.clear();\n\n    int i = si;\n    int j = sj;\n\n    for (char c : path) {\n        if (c == 'R') {\n            int id = hid(i, j);\n            edges.push_back(id);\n            feat[i]++;\n            j++;\n        } else if (c == 'L') {\n            int id = hid(i, j - 1);\n            edges.push_back(id);\n            feat[i]++;\n            j--;\n        } else if (c == 'D') {\n            int id = vid(i, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i++;\n        } else if (c == 'U') {\n            int id = vid(i - 1, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i--;\n        }\n    }\n}\n\ndouble estimated_path_cost(int si, int sj, const string& path, int turn) {\n    int i = si;\n    int j = sj;\n    double cost = 0.0;\n\n    for (char c : path) {\n        if (c == 'R') {\n            cost += model_weight_for_search(hid(i, j), turn);\n            j++;\n        } else if (c == 'L') {\n            cost += model_weight_for_search(hid(i, j - 1), turn);\n            j--;\n        } else if (c == 'D') {\n            cost += model_weight_for_search(vid(i, j), turn);\n            i++;\n        } else {\n            cost += model_weight_for_search(vid(i - 1, j), turn);\n            i--;\n        }\n    }\n\n    return cost;\n}\n\nstring choose_early_path(int si, int sj, int ti, int tj, int turn) {\n    string p1 = manhattan_path(si, sj, ti, tj, true);\n    string p2 = manhattan_path(si, sj, ti, tj, false);\n\n    if (p1 == p2) return p1;\n\n    if (turn < 60) {\n        return (xorshift() & 1) ? p1 : p2;\n    }\n\n    double c1 = estimated_path_cost(si, sj, p1, turn);\n    double c2 = estimated_path_cost(si, sj, p2, turn);\n\n    int eps = (turn < 150 ? 20 : 8);\n    if ((int)(xorshift() % 100) < eps) {\n        return (c1 < c2) ? p2 : p1;\n    }\n\n    return (c1 < c2) ? p1 : p2;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    const double INF = 1e100;\n\n    vector<double> dist(900, INF);\n    vector<int> parent(900, -1);\n    vector<char> pchar(900, '?');\n\n    auto node = [](int i, int j) {\n        return i * 30 + j;\n    };\n\n    priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n\n    int s = node(si, sj);\n    int t = node(ti, tj);\n\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\n        if (d != dist[u]) continue;\n        if (u == t) break;\n\n        int i = u / 30;\n        int j = u % 30;\n\n        auto relax = [&](int ni, int nj, char c, int eid) {\n            int v = node(ni, nj);\n            double nd = d + model_weight_for_search(eid, turn);\n\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                pchar[v] = c;\n                pq.push({nd, v});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, 'U', vid(i - 1, j));\n        if (i + 1 < 30) relax(i + 1, j, 'D', vid(i, j));\n        if (j > 0) relax(i, j - 1, 'L', hid(i, j - 1));\n        if (j + 1 < 30) relax(i, j + 1, 'R', hid(i, j));\n    }\n\n    string res;\n    int cur = t;\n\n    while (cur != s) {\n        res.push_back(pchar[cur]);\n        cur = parent[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nvoid update_edge_offsets(long long y, const vector<int>& edges, int turn) {\n    if (edges.empty()) return;\n\n    double pred = 0.0;\n    for (int id : edges) {\n        pred += model_weight_raw(id);\n    }\n\n    double err = (double)y - pred;\n    double alpha = 0.18 / (1.0 + turn / 1200.0);\n    double add = alpha * err / (double)edges.size();\n\n    for (int id : edges) {\n        offset_edge[id] += add;\n        offset_edge[id] = clamp_double(offset_edge[id], -4000.0, 4000.0);\n        edge_count[id]++;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = 5000.0;\n        vcost[i] = 5000.0;\n    }\n\n    for (int i = 0; i < E; i++) {\n        offset_edge[i] = 0.0;\n        edge_count[i] = 0;\n    }\n\n    for (int turn = 0; turn < 1000; turn++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0;\n        }\n\n        string path;\n\n        if (turn < 180) {\n            path = choose_early_path(si, sj, ti, tj, turn);\n        } else {\n            path = dijkstra_path(si, sj, ti, tj, turn);\n        }\n\n        array<int, VAR> feat;\n        vector<int> edges;\n        extract_features(si, sj, path, feat, edges);\n\n        cout << path << endl;\n        cout.flush();\n\n        long long result;\n        if (!(cin >> result)) {\n            return 0;\n        }\n\n        Obs ob;\n        ob.x = feat;\n        ob.y = result;\n        observations.push_back(ob);\n\n        if (turn < 300 || turn % 5 == 4 || turn >= 900) {\n            solve_row_col_model();\n        }\n\n        update_edge_offsets(result, edges, turn);\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int C = 400;\nstatic constexpr int ALPHA = 8;\nstatic constexpr long long BIG = 2000000000LL;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    XorShift() {}\n    XorShift(uint64_t seed) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstruct Evaluator {\n    int M;\n    vector<string> s;\n    vector<unsigned char> board;\n\n    // placement id = sid * 800 + idx\n    // idx: dir * 400 + start_cell\n    vector<unsigned char> mis;\n    vector<array<unsigned short, 13>> hist;\n    vector<long long> val;\n    vector<vector<int>> inc; // code = pid * 8 + required_char\n\n    long long obj = 0;\n    int covered = 0;\n\n    long long nearTable[13] = {\n        0,\n        1000000,\n        300000,\n        100000,\n        30000,\n        10000,\n        3000,\n        1000,\n        300,\n        100,\n        30,\n        10,\n        0\n    };\n\n    Evaluator() {}\n\n    Evaluator(const vector<string>& _s, const vector<unsigned char>& _board) {\n        s = _s;\n        M = (int)s.size();\n        board = _board;\n        build();\n    }\n\n    inline int cellH(int i, int j, int p) const {\n        return i * N + ((j + p) % N);\n    }\n\n    inline int cellV(int i, int j, int p) const {\n        return ((i + p) % N) * N + j;\n    }\n\n    inline long long calcVal(int sid) const {\n        if (hist[sid][0] > 0) {\n            return BIG + min<int>(hist[sid][0], 1000);\n        }\n        for (int d = 1; d <= 12; d++) {\n            if (hist[sid][d] > 0) {\n                return nearTable[d] + min<int>(hist[sid][d], 1000);\n            }\n        }\n        return 0;\n    }\n\n    inline int placementCell(int sid, int idx, int p) const {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n        if (dir == 0) return cellH(i, j, p);\n        else return cellV(i, j, p);\n    }\n\n    void build() {\n        int P = M * 800;\n        mis.assign(P, 0);\n        hist.assign(M, {});\n        val.assign(M, 0);\n        inc.assign(C, {});\n\n        int totalLen = 0;\n        for (auto& t : s) totalLen += (int)t.size();\n        int reservePerCell = max(1, M * 2 * 12);\n        for (int c = 0; c < C; c++) inc[c].reserve(reservePerCell);\n\n        for (int sid = 0; sid < M; sid++) {\n            int len = (int)s[sid].size();\n\n            for (int idx = 0; idx < 800; idx++) {\n                int pid = sid * 800 + idx;\n                int mm = 0;\n\n                for (int p = 0; p < len; p++) {\n                    int cell = placementCell(sid, idx, p);\n                    int req = s[sid][p] - 'A';\n                    if (board[cell] != req) mm++;\n                    inc[cell].push_back(pid * 8 + req);\n                }\n\n                mis[pid] = (unsigned char)mm;\n                hist[sid][mm]++;\n            }\n        }\n\n        obj = 0;\n        covered = 0;\n        for (int sid = 0; sid < M; sid++) {\n            val[sid] = calcVal(sid);\n            obj += val[sid];\n            if (hist[sid][0] > 0) covered++;\n        }\n    }\n\n    long long applyChange(int cell, int nc) {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        long long deltaObj = 0;\n\n        for (int code : inc[cell]) {\n            int req = code & 7;\n            if (req != oc && req != nc) continue;\n\n            int pid = code >> 3;\n            int sid = pid / 800;\n\n            long long oldVal = val[sid];\n            bool oldCov = hist[sid][0] > 0;\n\n            int oldMis = mis[pid];\n            hist[sid][oldMis]--;\n\n            int nm = oldMis;\n            if (req == oc) nm++;\n            if (req == nc) nm--;\n\n            mis[pid] = (unsigned char)nm;\n            hist[sid][nm]++;\n\n            bool newCov = hist[sid][0] > 0;\n            if (oldCov && !newCov) covered--;\n            if (!oldCov && newCov) covered++;\n\n            long long newVal = calcVal(sid);\n            val[sid] = newVal;\n            deltaObj += newVal - oldVal;\n        }\n\n        board[cell] = (unsigned char)nc;\n        obj += deltaObj;\n        return deltaObj;\n    }\n\n    int minMismatchOfString(int sid) const {\n        for (int d = 0; d <= 12; d++) {\n            if (hist[sid][d] > 0) return d;\n        }\n        return 13;\n    }\n\n    int bestPlacementIndex(int sid, XorShift& rng) const {\n        int best = 100;\n        int cnt = 0;\n        int bestIdx = 0;\n\n        int base = sid * 800;\n        for (int idx = 0; idx < 800; idx++) {\n            int mm = mis[base + idx];\n            if (mm < best) {\n                best = mm;\n                cnt = 1;\n                bestIdx = idx;\n            } else if (mm == best) {\n                cnt++;\n                if (rng.nextInt(cnt) == 0) bestIdx = idx;\n            }\n        }\n        return bestIdx;\n    }\n\n    long long stampPlacement(int sid, int idx, vector<pair<int,int>>& changed) {\n        changed.clear();\n        long long delta = 0;\n        int len = (int)s[sid].size();\n\n        for (int p = 0; p < len; p++) {\n            int cell = placementCell(sid, idx, p);\n            int req = s[sid][p] - 'A';\n            if (board[cell] != req) {\n                int old = board[cell];\n                changed.push_back({cell, old});\n                delta += applyChange(cell, req);\n            }\n        }\n        return delta;\n    }\n\n    void revertChanges(vector<pair<int,int>>& changed) {\n        for (int i = (int)changed.size() - 1; i >= 0; i--) {\n            applyChange(changed[i].first, changed[i].second);\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    int inputN, M;\n    cin >> inputN >> M;\n\n    vector<string> s(M);\n    for (int i = 0; i < M; i++) cin >> s[i];\n\n    XorShift rng(123456789);\n\n    vector<int> freq(ALPHA, 1);\n    for (auto& t : s) {\n        for (char ch : t) freq[ch - 'A']++;\n    }\n    vector<int> pref(ALPHA);\n    pref[0] = freq[0];\n    for (int i = 1; i < ALPHA; i++) pref[i] = pref[i - 1] + freq[i];\n    int fsum = pref.back();\n\n    auto randomChar = [&]() {\n        int r = rng.nextInt(fsum);\n        return (unsigned char)(lower_bound(pref.begin(), pref.end(), r + 1) - pref.begin());\n    };\n\n    vector<unsigned char> board(C);\n    for (int i = 0; i < C; i++) board[i] = randomChar();\n\n    auto placementCellRaw = [&](int idx, int p) {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    };\n\n    auto conflictOfPlacement = [&](const string& t, int idx) {\n        int conf = 0;\n        int len = (int)t.size();\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            int req = t[p] - 'A';\n            if (board[cell] != req) conf++;\n        }\n        return conf;\n    };\n\n    auto stampRaw = [&](const string& t, int idx) {\n        int len = (int)t.size();\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            board[cell] = (unsigned char)(t[p] - 'A');\n        }\n    };\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n\n    // Initial construction by repeated stamping.\n    int initPasses = 6;\n    for (int pass = 0; pass < initPasses; pass++) {\n        if (pass == initPasses - 1) {\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return s[a].size() < s[b].size(); // long strings later\n            });\n        } else {\n            shuffle(order.begin(), order.end(), std::mt19937((unsigned)rng.next()));\n        }\n\n        for (int sid : order) {\n            int bestConf = 100;\n            int bestIdx = 0;\n            int cnt = 0;\n\n            for (int idx = 0; idx < 800; idx++) {\n                int conf = conflictOfPlacement(s[sid], idx);\n                if (conf < bestConf) {\n                    bestConf = conf;\n                    bestIdx = idx;\n                    cnt = 1;\n                } else if (conf == bestConf) {\n                    cnt++;\n                    if (rng.nextInt(cnt) == 0) bestIdx = idx;\n                }\n            }\n            stampRaw(s[sid], bestIdx);\n        }\n    }\n\n    Evaluator ev(s, board);\n\n    auto elapsedSec = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    const double searchLimit = 2.65;\n    int iter = 0;\n    double elapsed = 0.0;\n\n    vector<pair<int,int>> changed;\n\n    while (true) {\n        if ((iter & 15) == 0) {\n            elapsed = elapsedSec();\n            if (elapsed > searchLimit) break;\n        }\n\n        double progress = min(1.0, elapsed / searchLimit);\n        double temp = 200000.0 * (1.0 - progress) + 2000.0 * progress;\n\n        if (ev.covered < M && iter % 5 == 0) {\n            // Macro repair: force an uncovered string to match at its closest placement.\n            int bestSid = -1;\n            int bestMM = 100;\n            int cnt = 0;\n\n            for (int sid = 0; sid < M; sid++) {\n                if (ev.hist[sid][0] == 0) {\n                    int mm = ev.minMismatchOfString(sid);\n                    if (mm < bestMM) {\n                        bestMM = mm;\n                        bestSid = sid;\n                        cnt = 1;\n                    } else if (mm == bestMM) {\n                        cnt++;\n                        if (rng.nextInt(cnt) == 0) bestSid = sid;\n                    }\n                }\n            }\n\n            if (bestSid != -1) {\n                int idx = ev.bestPlacementIndex(bestSid, rng);\n                long long delta = ev.stampPlacement(bestSid, idx, changed);\n\n                bool accept = false;\n                if (delta >= 0) accept = true;\n                else if (delta > -BIG / 2) {\n                    double prob = exp((double)delta / temp);\n                    if (rng.nextDouble() < prob) accept = true;\n                }\n\n                if (!accept) ev.revertChanges(changed);\n            }\n        } else {\n            // Single-cell local search.\n            int cell = rng.nextInt(C);\n            int old = ev.board[cell];\n\n            long long bestDelta = 0;\n            int bestChar = old;\n\n            for (int nc = 0; nc < ALPHA; nc++) {\n                if (nc == old) continue;\n                long long d = ev.applyChange(cell, nc);\n                ev.applyChange(cell, old);\n\n                if (d > bestDelta) {\n                    bestDelta = d;\n                    bestChar = nc;\n                }\n            }\n\n            if (bestChar != old) {\n                ev.applyChange(cell, bestChar);\n            } else {\n                int nc = rng.nextInt(ALPHA);\n                if (nc == old) nc = (nc + 1) % ALPHA;\n\n                long long d = ev.applyChange(cell, nc);\n                bool accept = false;\n                if (d >= 0) accept = true;\n                else if (d > -BIG / 2) {\n                    double prob = exp((double)d / temp);\n                    if (rng.nextDouble() < prob) accept = true;\n                }\n\n                if (!accept) ev.applyChange(cell, old);\n            }\n        }\n\n        iter++;\n    }\n\n    // If all strings are covered, greedily replace unnecessary cells by dots.\n    if (ev.covered == M) {\n        vector<int> cells(C);\n        iota(cells.begin(), cells.end(), 0);\n        shuffle(cells.begin(), cells.end(), std::mt19937((unsigned)rng.next()));\n\n        for (int cell : cells) {\n            int old = ev.board[cell];\n            if (old == 8) continue;\n\n            ev.applyChange(cell, 8);\n            if (ev.covered < M) {\n                ev.applyChange(cell, old);\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        string out;\n        for (int j = 0; j < N; j++) {\n            int v = ev.board[i * N + j];\n            if (v == 8) out.push_back('.');\n            else out.push_back(char('A' + v));\n        }\n        cout << out << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<int> ri, rj, cost;\n    int R = 0;\n    int startRid = -1;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R++;\n                ri.push_back(i);\n                rj.push_back(j);\n                cost.push_back(grid[i][j] - '0');\n                if (i == si && j == sj) startRid = id[i][j];\n            }\n        }\n    }\n\n    int W = (R + 63) >> 6;\n\n    auto setbit = [&](vector<uint64_t>& bs, int x) {\n        bs[x >> 6] |= 1ULL << (x & 63);\n    };\n    auto getbit_flat = [&](const vector<uint64_t>& flat, int idx, int x) -> bool {\n        return (flat[(ll)idx * W + (x >> 6)] >> (x & 63)) & 1ULL;\n    };\n\n    vector<int> hid(R), vid(R);\n    vector<vector<int>> hCells, vCells;\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            vector<int> cells;\n            while (j < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                j++;\n            }\n            int h = (int)hCells.size();\n            for (int x : cells) hid[x] = h;\n            hCells.push_back(cells);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            vector<int> cells;\n            while (i < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                i++;\n            }\n            int v = (int)vCells.size();\n            for (int x : cells) vid[x] = v;\n            vCells.push_back(cells);\n        }\n    }\n\n    // coverBits[x] := road cells visible from road cell x\n    vector<uint64_t> coverBits((ll)R * W, 0);\n\n    for (int x = 0; x < R; x++) {\n        uint64_t* bs = &coverBits[(ll)x * W];\n        for (int y : hCells[hid[x]]) bs[y >> 6] |= 1ULL << (y & 63);\n        for (int y : vCells[vid[x]]) bs[y >> 6] |= 1ULL << (y & 63);\n    }\n\n    vector<uint64_t> fullMask(W, 0);\n    for (int x = 0; x < R; x++) fullMask[x >> 6] |= 1ULL << (x & 63);\n\n    auto coversAll = [&](const vector<uint64_t>& bs) -> bool {\n        for (int w = 0; w < W; w++) {\n            if ((bs[w] & fullMask[w]) != fullMask[w]) return false;\n        }\n        return true;\n    };\n\n    auto pop_and = [&](const uint64_t* a, const vector<uint64_t>& b) -> int {\n        int res = 0;\n        for (int w = 0; w < W; w++) res += __builtin_popcountll(a[w] & b[w]);\n        return res;\n    };\n\n    auto erase_cover_from_uncovered = [&](vector<uint64_t>& uncovered, int x) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W; w++) uncovered[w] &= ~bs[w];\n    };\n\n    // Greedy set cover. Start square is observed for free.\n    vector<uint64_t> uncovered = fullMask;\n    erase_cover_from_uncovered(uncovered, startRid);\n\n    vector<char> selectedFlag(R, 0);\n    vector<int> selected;\n\n    auto anyUncovered = [&]() -> bool {\n        for (uint64_t x : uncovered) if (x) return true;\n        return false;\n    };\n\n    while (anyUncovered()) {\n        int best = -1;\n        int bestGain = -1;\n        int bestTie = -1;\n\n        for (int x = 0; x < R; x++) {\n            if (selectedFlag[x]) continue;\n            const uint64_t* bs = &coverBits[(ll)x * W];\n            int gain = pop_and(bs, uncovered);\n            if (gain <= 0) continue;\n\n            int tie = -abs(ri[x] - si) - abs(rj[x] - sj);\n            if (gain > bestGain || (gain == bestGain && tie > bestTie)) {\n                bestGain = gain;\n                bestTie = tie;\n                best = x;\n            }\n        }\n\n        if (best == -1) break;\n        selectedFlag[best] = 1;\n        selected.push_back(best);\n        erase_cover_from_uncovered(uncovered, best);\n    }\n\n    // Remove redundant selected cells using coverage counts.\n    vector<int> cnt(R, 0);\n\n    auto addCoverCount = [&](int x, int delta) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W; w++) {\n            uint64_t v = bs[w];\n            while (v) {\n                int b = __builtin_ctzll(v);\n                int y = (w << 6) + b;\n                if (y < R) cnt[y] += delta;\n                v &= v - 1;\n            }\n        }\n    };\n\n    addCoverCount(startRid, 1);\n    for (int x : selected) addCoverCount(x, 1);\n\n    vector<int> selected2;\n    for (int idx = (int)selected.size() - 1; idx >= 0; idx--) {\n        int x = selected[idx];\n        bool removable = true;\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W && removable; w++) {\n            uint64_t v = bs[w];\n            while (v) {\n                int b = __builtin_ctzll(v);\n                int y = (w << 6) + b;\n                if (y < R && cnt[y] <= 1) {\n                    removable = false;\n                    break;\n                }\n                v &= v - 1;\n            }\n        }\n        if (removable) {\n            addCoverCount(x, -1);\n        } else {\n            selected2.push_back(x);\n        }\n    }\n    reverse(selected2.begin(), selected2.end());\n    selected.swap(selected2);\n\n    // Nodes for TSP: node 0 is start.\n    vector<int> nodeRid;\n    nodeRid.push_back(startRid);\n    for (int x : selected) {\n        if (x != startRid) nodeRid.push_back(x);\n    }\n\n    int M = (int)nodeRid.size();\n\n    // Road graph.\n    vector<vector<pair<int,int>>> adj(R);\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n\n    for (int x = 0; x < R; x++) {\n        int i = ri[x], j = rj[x];\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && id[ni][nj] != -1) {\n                int y = id[ni][nj];\n                adj[x].push_back({y, cost[y]});\n            }\n        }\n    }\n\n    const int INF = 1e9;\n    vector<vector<int>> distMat(M, vector<int>(M, INF));\n    vector<vector<short>> prevNode(M, vector<short>(R, -1));\n\n    for (int s = 0; s < M; s++) {\n        int src = nodeRid[s];\n        vector<int> dist(R, INF);\n        vector<short> pre(R, -1);\n\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top();\n            pq.pop();\n            if (cd != dist[v]) continue;\n\n            for (auto [to, w] : adj[v]) {\n                int nd = cd + w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pre[to] = (short)v;\n                    pq.push({nd, to});\n                }\n            }\n        }\n\n        prevNode[s].swap(pre);\n        for (int t = 0; t < M; t++) {\n            distMat[s][t] = dist[nodeRid[t]];\n        }\n    }\n\n    auto cycleCost = [&](const vector<int>& cyc) -> ll {\n        ll res = 0;\n        int m = (int)cyc.size();\n        for (int i = 0; i < m; i++) {\n            res += distMat[cyc[i]][cyc[(i + 1) % m]];\n        }\n        return res;\n    };\n\n    vector<int> cycle;\n\n    if (M == 1) {\n        cycle = {0};\n    } else if (M <= 380) {\n        // Cheapest insertion.\n        cycle = {0};\n        vector<int> unused;\n        for (int i = 1; i < M; i++) unused.push_back(i);\n\n        while (!unused.empty()) {\n            int bestUIdx = -1;\n            int bestPos = -1;\n            int bestDelta = INF;\n\n            for (int ui = 0; ui < (int)unused.size(); ui++) {\n                int x = unused[ui];\n                int m = (int)cycle.size();\n\n                for (int p = 0; p < m; p++) {\n                    int a = cycle[p];\n                    int b = cycle[(p + 1) % m];\n                    int delta = distMat[a][x] + distMat[x][b] - distMat[a][b];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestUIdx = ui;\n                        bestPos = p;\n                    }\n                }\n            }\n\n            int x = unused[bestUIdx];\n            cycle.insert(cycle.begin() + bestPos + 1, x);\n            unused.erase(unused.begin() + bestUIdx);\n        }\n    } else {\n        // Fallback nearest neighbor for very large selected sets.\n        vector<char> used(M, 0);\n        cycle = {0};\n        used[0] = 1;\n        int cur = 0;\n\n        for (int step = 1; step < M; step++) {\n            int best = -1;\n            int bd = INF;\n            for (int x = 1; x < M; x++) {\n                if (!used[x] && distMat[cur][x] < bd) {\n                    bd = distMat[cur][x];\n                    best = x;\n                }\n            }\n            used[best] = 1;\n            cycle.push_back(best);\n            cur = best;\n        }\n    }\n\n    ll curCost = cycleCost(cycle);\n\n    // Relocation local search.\n    if ((int)cycle.size() <= 700) {\n        bool improved = true;\n        while (improved && timer.elapsed() < 2.05) {\n            improved = false;\n            int m = (int)cycle.size();\n            ll bestDelta = 0;\n            int bestI = -1, bestPos = -1;\n\n            for (int i = 1; i < m; i++) {\n                int x = cycle[i];\n                int a = cycle[i - 1];\n                int b = cycle[(i + 1) % m];\n\n                ll removeDelta = (ll)distMat[a][b] - distMat[a][x] - distMat[x][b];\n\n                for (int pos = 0; pos < m; pos++) {\n                    if (pos == i || pos == i - 1) continue;\n\n                    int c = cycle[pos];\n                    int d = cycle[(pos + 1) % m];\n\n                    ll delta = removeDelta + (ll)distMat[c][x] + distMat[x][d] - distMat[c][d];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestI = i;\n                        bestPos = pos;\n                    }\n                }\n            }\n\n            if (bestI != -1) {\n                int x = cycle[bestI];\n                cycle.erase(cycle.begin() + bestI);\n\n                int insertIdx;\n                if (bestPos < bestI) insertIdx = bestPos + 1;\n                else insertIdx = bestPos;\n\n                cycle.insert(cycle.begin() + insertIdx, x);\n                curCost += bestDelta;\n                improved = true;\n            }\n        }\n    }\n\n    auto reconstructPath = [&](int srcNode, int dstNode) {\n        vector<int> path;\n        int src = nodeRid[srcNode];\n        int dst = nodeRid[dstNode];\n\n        int cur = dst;\n        while (cur != src) {\n            path.push_back(cur);\n            cur = prevNode[srcNode][cur];\n            if (cur < 0) break;\n        }\n        path.push_back(src);\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    struct EdgeCache {\n        int M, W, R;\n        const vector<int>& nodeRid;\n        const vector<vector<short>>& prevNode;\n        const vector<uint64_t>& coverBits;\n        vector<uint64_t> data;\n        vector<unsigned char> done;\n\n        EdgeCache(\n            int M_,\n            int W_,\n            int R_,\n            const vector<int>& nodeRid_,\n            const vector<vector<short>>& prevNode_,\n            const vector<uint64_t>& coverBits_\n        )\n            : M(M_), W(W_), R(R_), nodeRid(nodeRid_),\n              prevNode(prevNode_), coverBits(coverBits_) {\n            data.assign((ll)M * M * W, 0);\n            done.assign((ll)M * M, 0);\n        }\n\n        uint64_t* get(int a, int b) {\n            ll idx = (ll)a * M + b;\n            uint64_t* ret = &data[idx * W];\n            if (done[idx]) return ret;\n            done[idx] = 1;\n\n            int src = nodeRid[a];\n            int dst = nodeRid[b];\n\n            vector<int> path;\n            int cur = dst;\n            while (cur != src) {\n                path.push_back(cur);\n                cur = prevNode[a][cur];\n                if (cur < 0) break;\n            }\n            path.push_back(src);\n\n            for (int x : path) {\n                const uint64_t* bs = &coverBits[(ll)x * W];\n                for (int w = 0; w < W; w++) ret[w] |= bs[w];\n            }\n            return ret;\n        }\n    };\n\n    // Remove redundant waypoints if visibility remains complete.\n    if (M <= 520 && timer.elapsed() < 2.25) {\n        EdgeCache cache(M, W, R, nodeRid, prevNode, coverBits);\n\n        while ((int)cycle.size() > 1 && timer.elapsed() < 2.72) {\n            int m = (int)cycle.size();\n\n            vector<uint64_t> pref((ll)(m + 1) * W, 0);\n            vector<uint64_t> suff((ll)(m + 1) * W, 0);\n\n            for (int e = 0; e < m; e++) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n                for (int w = 0; w < W; w++) {\n                    pref[(ll)(e + 1) * W + w] = pref[(ll)e * W + w] | ec[w];\n                }\n            }\n\n            for (int e = m - 1; e >= 0; e--) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n                for (int w = 0; w < W; w++) {\n                    suff[(ll)e * W + w] = suff[(ll)(e + 1) * W + w] | ec[w];\n                }\n            }\n\n            int bestP = -1;\n            ll bestSave = 0;\n            vector<uint64_t> tmp(W);\n\n            for (int p = 1; p < m; p++) {\n                int prv = cycle[p - 1];\n                int x = cycle[p];\n                int nxt = cycle[(p + 1) % m];\n\n                ll save = (ll)distMat[prv][x] + distMat[x][nxt] - distMat[prv][nxt];\n                if (save <= bestSave) continue;\n\n                uint64_t* ec = cache.get(prv, nxt);\n\n                for (int w = 0; w < W; w++) {\n                    tmp[w] =\n                        pref[(ll)(p - 1) * W + w] |\n                        suff[(ll)(p + 1) * W + w] |\n                        ec[w];\n                }\n\n                bool ok = true;\n                for (int w = 0; w < W; w++) {\n                    if ((tmp[w] & fullMask[w]) != fullMask[w]) {\n                        ok = false;\n                        break;\n                    }\n                }\n\n                if (ok) {\n                    bestSave = save;\n                    bestP = p;\n                }\n            }\n\n            if (bestP == -1) break;\n            cycle.erase(cycle.begin() + bestP);\n            curCost -= bestSave;\n        }\n    }\n\n    // Output actual move sequence.\n    string ans;\n\n    auto moveChar = [&](int a, int b) -> char {\n        int da = ri[b] - ri[a];\n        int db = rj[b] - rj[a];\n        if (da == -1) return 'U';\n        if (da == 1) return 'D';\n        if (db == -1) return 'L';\n        return 'R';\n    };\n\n    int m = (int)cycle.size();\n    for (int e = 0; e < m; e++) {\n        int a = cycle[e];\n        int b = cycle[(e + 1) % m];\n        vector<int> path = reconstructPath(a, b);\n\n        for (int k = 1; k < (int)path.size(); k++) {\n            ans.push_back(moveChar(path[k - 1], path[k]));\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Record {\n    int task;\n    int dur;\n};\n\nint N, M, K, R;\nvector<vector<int>> D;\nvector<vector<int>> children_;\nvector<int> remdep;\nvector<int> status_; // -1:not started, 0:running, 1:done\n\nvector<vector<int>> skill_est;\nvector<vector<Record>> records_;\nvector<int> member_task;\nvector<int> member_start;\n\nvector<double> bottom_priority;\nvector<double> min_cost, avg_cost;\nvector<double> reach_score;\n\nconst int MAX_SKILL = 70;\n\ndouble base_skill;\nconst double PRIOR_COMP = 0.008;\nconst double PRIOR_NORM = 0.003;\nconst double NORM_TARGET = 40.0;\n\ninline double obsPenalty(int w, int t) {\n    static const double p1[5] = {\n        0.0,\n        -log(4.0 / 7.0),\n        -log(3.0 / 7.0),\n        -log(2.0 / 7.0),\n        -log(1.0 / 7.0)\n    };\n\n    if (t == 1) {\n        if (w <= 4) return p1[w];\n        double x = w - 4;\n        return 3.0 + 2.0 * x * x;\n    } else {\n        if (w == 0) {\n            return 5.0 + 1.0 * t * t;\n        }\n        int lo = max(1, t - 3);\n        int hi = t + 3;\n        if (w < lo) {\n            double x = lo - w;\n            return 2.0 * x * x;\n        }\n        if (w > hi) {\n            double x = w - hi;\n            return 2.0 * x * x;\n        }\n        return 1.0 + 0.05 * abs(w - t);\n    }\n}\n\ninline int calcWTaskSkill(int task, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; k++) {\n        if (D[task][k] > s[k]) w += D[task][k] - s[k];\n    }\n    return w;\n}\n\ninline double expectedDurationFromW(int w) {\n    if (w == 0) return 1.0;\n    if (w == 1) return 13.0 / 7.0;\n    if (w == 2) return 17.0 / 7.0;\n    if (w == 3) return 22.0 / 7.0;\n    return (double)w;\n}\n\ninline double expectedDuration(int task, int mem) {\n    int w = 0;\n    const auto& s = skill_est[mem];\n    for (int k = 0; k < K; k++) {\n        if (D[task][k] > s[k]) w += D[task][k] - s[k];\n    }\n    return expectedDurationFromW(w);\n}\n\nvoid optimizeMember(int mem) {\n    auto& recs = records_[mem];\n    if (recs.empty()) return;\n\n    vector<int>& s = skill_est[mem];\n    int Rm = (int)recs.size();\n\n    vector<int> curW(Rm, 0);\n    for (int r = 0; r < Rm; r++) {\n        curW[r] = calcWTaskSkill(recs[r].task, s);\n    }\n\n    double sumsq = 0.0;\n    for (int k = 0; k < K; k++) sumsq += 1.0 * s[k] * s[k];\n\n    int passes = 3;\n    for (int pass = 0; pass < passes; pass++) {\n        bool changed_any = false;\n\n        for (int k = 0; k < K; k++) {\n            int old = s[k];\n\n            double bestObj = 1e100;\n            int bestVal = old;\n\n            double oldCompPrior = PRIOR_COMP * (old - base_skill) * (old - base_skill);\n\n            for (int val = 0; val <= MAX_SKILL; val++) {\n                double obj = 0.0;\n\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    int oldContrib = max(0, D[task][k] - old);\n                    int newContrib = max(0, D[task][k] - val);\n                    int nw = curW[r] - oldContrib + newContrib;\n                    obj += obsPenalty(nw, recs[r].dur);\n                }\n\n                double compPrior = PRIOR_COMP * (val - base_skill) * (val - base_skill);\n\n                double nsumsq = sumsq - 1.0 * old * old + 1.0 * val * val;\n                double norm = sqrt(nsumsq);\n                double normPrior = PRIOR_NORM * (norm - NORM_TARGET) * (norm - NORM_TARGET);\n\n                obj += compPrior + normPrior;\n\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestVal = val;\n                }\n            }\n\n            if (bestVal != old) {\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    curW[r] -= max(0, D[task][k] - old);\n                    curW[r] += max(0, D[task][k] - bestVal);\n                }\n                sumsq = sumsq - 1.0 * old * old + 1.0 * bestVal * bestVal;\n                s[k] = bestVal;\n                changed_any = true;\n            }\n        }\n\n        if (!changed_any) break;\n    }\n}\n\nvoid precomputeReachScore() {\n    vector<double> dp(N, 0.0);\n    for (int i = N - 1; i >= 0; i--) {\n        double v = 0.0;\n        for (int c : children_[i]) {\n            v += 1.0 + dp[c];\n            if (v > 1e6) {\n                v = 1e6;\n                break;\n            }\n        }\n        dp[i] = v;\n    }\n\n    reach_score.assign(N, 0.0);\n    for (int i = 0; i < N; i++) {\n        reach_score[i] = log1p(dp[i]);\n    }\n}\n\nvoid recomputePriorities() {\n    min_cost.assign(N, 0.0);\n    avg_cost.assign(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        if (status_[i] == 1) {\n            min_cost[i] = avg_cost[i] = 0.0;\n            continue;\n        }\n\n        double mn = 1e100;\n        double sum = 0.0;\n        for (int j = 0; j < M; j++) {\n            double e = expectedDuration(i, j);\n            mn = min(mn, e);\n            sum += e;\n        }\n        min_cost[i] = mn;\n        avg_cost[i] = sum / M;\n    }\n\n    bottom_priority.assign(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        if (status_[i] == 1) {\n            bottom_priority[i] = 0.0;\n            continue;\n        }\n\n        double nodeCost = 0.7 * min_cost[i] + 0.3 * avg_cost[i];\n        double mx = 0.0;\n        for (int c : children_[i]) {\n            mx = max(mx, bottom_priority[c]);\n        }\n        bottom_priority[i] = nodeCost + mx;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K >> R;\n\n    D.assign(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) cin >> D[i][k];\n    }\n\n    children_.assign(N, {});\n    remdep.assign(N, 0);\n\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        children_[u].push_back(v);\n        remdep[v]++;\n    }\n\n    base_skill = 35.0 / sqrt((double)K);\n    int init_skill = max(0, (int)round(base_skill));\n\n    skill_est.assign(M, vector<int>(K, init_skill));\n    records_.assign(M, {});\n\n    status_.assign(N, -1);\n    member_task.assign(M, -1);\n    member_start.assign(M, -1);\n\n    precomputeReachScore();\n\n    for (int day = 1; day <= 2000; day++) {\n        recomputePriorities();\n\n        vector<int> free_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready;\n        for (int i = 0; i < N; i++) {\n            if (status_[i] == -1 && remdep[i] == 0) ready.push_back(i);\n        }\n\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (bottom_priority[a] != bottom_priority[b]) {\n                return bottom_priority[a] > bottom_priority[b];\n            }\n            if (reach_score[a] != reach_score[b]) {\n                return reach_score[a] > reach_score[b];\n            }\n            return a < b;\n        });\n\n        vector<pair<int, int>> assignments;\n\n        while (!free_members.empty()) {\n            int bestFi = -1;\n            int bestTask = -1;\n            double bestScore = -1e100;\n\n            int limit = min((int)ready.size(), 300);\n\n            for (int fi = 0; fi < (int)free_members.size(); fi++) {\n                int mem = free_members[fi];\n\n                for (int idx = 0; idx < limit; idx++) {\n                    int task = ready[idx];\n                    if (status_[task] != -1) continue;\n\n                    double pred = expectedDuration(task, mem);\n\n                    double score =\n                        bottom_priority[task]\n                        + 0.15 * reach_score[task]\n                        - 0.70 * pred\n                        + 0.20 * (avg_cost[task] - pred);\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestFi = fi;\n                        bestTask = task;\n                    }\n                }\n            }\n\n            if (bestFi == -1) break;\n\n            int mem = free_members[bestFi];\n\n            status_[bestTask] = 0;\n            member_task[mem] = bestTask;\n            member_start[mem] = day;\n\n            assignments.push_back({mem, bestTask});\n\n            free_members.erase(free_members.begin() + bestFi);\n        }\n\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << mem + 1 << ' ' << task + 1;\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        for (int i = 0; i < cnt; i++) {\n            int f;\n            cin >> f;\n            --f;\n\n            int task = member_task[f];\n            if (task < 0) continue;\n\n            int dur = day - member_start[f] + 1;\n\n            status_[task] = 1;\n            member_task[f] = -1;\n            member_start[f] = -1;\n\n            records_[f].push_back({task, dur});\n            optimizeMember(f);\n\n            for (int c : children_[task]) {\n                remdep[c]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int ax, ay, cx, cy;\n    int score;\n};\n\nstruct Node {\n    int x, y;\n    int id;   // -1 for depot\n    int type; // 0 pickup, 1 delivery\n};\n\nstruct InsertInfo {\n    int cost;\n    int pgap;\n    int dgap;\n};\n\nstruct State {\n    vector<Node> route;\n    vector<int> selected;\n    vector<char> used;\n    int cost;\n};\n\nstatic const int N = 1000;\nstatic const int K = 50;\nstatic const int DEP = 400;\nstatic const int INF = 1e9;\n\nvector<Order> ords;\nchrono::steady_clock::time_point start_time;\n\ninline double elapsed() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\ninline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline int ndist(const Node& a, const Node& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\ninline Node pickupNode(int id) {\n    return Node{ords[id].ax, ords[id].ay, id, 0};\n}\n\ninline Node deliveryNode(int id) {\n    return Node{ords[id].cx, ords[id].cy, id, 1};\n}\n\nint routeCost(const vector<Node>& route) {\n    int res = 0;\n    for (int i = 0; i + 1 < (int)route.size(); i++) {\n        res += ndist(route[i], route[i + 1]);\n    }\n    return res;\n}\n\nInsertInfo bestInsert(const vector<Node>& route, int oid) {\n    const int L = (int)route.size();\n    const int px = ords[oid].ax;\n    const int py = ords[oid].ay;\n    const int dx = ords[oid].cx;\n    const int dy = ords[oid].cy;\n\n    int best = INF;\n    int bestP = -1;\n    int bestD = -1;\n\n    for (int i = 0; i <= L - 2; i++) {\n        const Node& A = route[i];\n        const Node& B = route[i + 1];\n\n        int directAB = ndist(A, B);\n\n        // delivery immediately after pickup\n        int val = mdist(A.x, A.y, px, py)\n                + mdist(px, py, dx, dy)\n                + mdist(dx, dy, B.x, B.y)\n                - directAB;\n\n        if (val < best) {\n            best = val;\n            bestP = i;\n            bestD = i;\n        }\n\n        int addPickup = mdist(A.x, A.y, px, py)\n                      + mdist(px, py, B.x, B.y)\n                      - directAB;\n\n        for (int j = i + 1; j <= L - 2; j++) {\n            const Node& C = route[j];\n            const Node& D = route[j + 1];\n\n            int addDelivery = mdist(C.x, C.y, dx, dy)\n                            + mdist(dx, dy, D.x, D.y)\n                            - ndist(C, D);\n\n            val = addPickup + addDelivery;\n\n            if (val < best) {\n                best = val;\n                bestP = i;\n                bestD = j;\n            }\n        }\n    }\n\n    return InsertInfo{best, bestP, bestD};\n}\n\nvoid applyInsert(vector<Node>& route, int oid, const InsertInfo& ins) {\n    vector<Node> nr;\n    nr.reserve(route.size() + 2);\n\n    Node P = pickupNode(oid);\n    Node D = deliveryNode(oid);\n\n    for (int i = 0; i < (int)route.size(); i++) {\n        nr.push_back(route[i]);\n\n        if (i == ins.pgap) {\n            nr.push_back(P);\n            if (ins.dgap == ins.pgap) {\n                nr.push_back(D);\n            }\n        }\n\n        if (ins.dgap > ins.pgap && i == ins.dgap) {\n            nr.push_back(D);\n        }\n    }\n\n    route.swap(nr);\n}\n\nvector<Node> removeOrder(const vector<Node>& route, int oid) {\n    vector<Node> nr;\n    nr.reserve(route.size() - 2);\n    for (const auto& v : route) {\n        if (v.id != oid) nr.push_back(v);\n    }\n    return nr;\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    double nextDouble() {\n        return (next() + 0.5) / 4294967296.0;\n    }\n};\n\nXorShift rng;\n\nState constructGreedy(const vector<int>& pool, int randomTop) {\n    Node depot{DEP, DEP, -1, -1};\n\n    State st;\n    st.route = {depot, depot};\n    st.used.assign(N, 0);\n    st.selected.clear();\n    st.cost = 0;\n\n    struct Choice {\n        int cost;\n        int oid;\n        InsertInfo ins;\n    };\n\n    for (int step = 0; step < K; step++) {\n        vector<Choice> top;\n\n        for (int oid : pool) {\n            if (st.used[oid]) continue;\n\n            InsertInfo ins = bestInsert(st.route, oid);\n            Choice ch{ins.cost, oid, ins};\n\n            if ((int)top.size() < randomTop) {\n                top.push_back(ch);\n            } else {\n                int worst = 0;\n                for (int i = 1; i < (int)top.size(); i++) {\n                    if (top[i].cost > top[worst].cost) worst = i;\n                }\n                if (ch.cost < top[worst].cost) top[worst] = ch;\n            }\n        }\n\n        sort(top.begin(), top.end(), [](const Choice& a, const Choice& b) {\n            return a.cost < b.cost;\n        });\n\n        int idx = 0;\n        if (randomTop > 1 && top.size() > 1) {\n            int lim = (int)top.size();\n            double u = rng.nextDouble();\n            idx = min(lim - 1, (int)(u * u * lim)); // biased toward better choices\n        }\n\n        Choice ch = top[idx];\n        applyInsert(st.route, ch.oid, ch.ins);\n        st.used[ch.oid] = 1;\n        st.selected.push_back(ch.oid);\n        st.cost += ch.ins.cost;\n    }\n\n    st.cost = routeCost(st.route);\n    return st;\n}\n\nvoid pairReinsertOptimize(State& st) {\n    bool improved = true;\n    int pass = 0;\n\n    while (improved && pass < 5) {\n        improved = false;\n        pass++;\n\n        for (int oid : st.selected) {\n            vector<Node> rem = removeOrder(st.route, oid);\n            int remCost = routeCost(rem);\n\n            InsertInfo ins = bestInsert(rem, oid);\n            int newCost = remCost + ins.cost;\n\n            if (newCost < st.cost) {\n                st.route.swap(rem);\n                applyInsert(st.route, oid, ins);\n                st.cost = newCost;\n                improved = true;\n            }\n        }\n    }\n}\n\nvoid replaceOptimize(State& st, const vector<int>& candList, double limitTime) {\n    while (elapsed() < limitTime) {\n        int bestNewCost = st.cost;\n        int bestRemove = -1;\n        int bestAdd = -1;\n\n        int checks = 0;\n        bool timeout = false;\n\n        for (int remOid : st.selected) {\n            vector<Node> remRoute = removeOrder(st.route, remOid);\n            int remCost = routeCost(remRoute);\n\n            for (int addOid : candList) {\n                if (st.used[addOid]) continue;\n\n                InsertInfo ins = bestInsert(remRoute, addOid);\n                int newCost = remCost + ins.cost;\n\n                if (newCost < bestNewCost) {\n                    bestNewCost = newCost;\n                    bestRemove = remOid;\n                    bestAdd = addOid;\n                }\n\n                if ((++checks & 255) == 0 && elapsed() > limitTime) {\n                    timeout = true;\n                    break;\n                }\n            }\n\n            if (timeout) break;\n        }\n\n        if (bestRemove == -1) break;\n\n        vector<Node> remRoute = removeOrder(st.route, bestRemove);\n        InsertInfo ins = bestInsert(remRoute, bestAdd);\n        st.route.swap(remRoute);\n        applyInsert(st.route, bestAdd, ins);\n\n        st.used[bestRemove] = 0;\n        st.used[bestAdd] = 1;\n\n        for (int& x : st.selected) {\n            if (x == bestRemove) {\n                x = bestAdd;\n                break;\n            }\n        }\n\n        st.cost = routeCost(st.route);\n        pairReinsertOptimize(st);\n\n        if (timeout) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    ords.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> ords[i].ax >> ords[i].ay >> ords[i].cx >> ords[i].cy;\n\n        int centerSum = mdist(DEP, DEP, ords[i].ax, ords[i].ay)\n                      + mdist(DEP, DEP, ords[i].cx, ords[i].cy);\n        int pairDist = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        ords[i].score = centerSum + pairDist / 2;\n    }\n\n    vector<int> allIds(N);\n    iota(allIds.begin(), allIds.end(), 0);\n\n    vector<int> sortedIds = allIds;\n    sort(sortedIds.begin(), sortedIds.end(), [](int a, int b) {\n        return ords[a].score < ords[b].score;\n    });\n\n    // Deterministic greedy using all orders.\n    State best = constructGreedy(allIds, 1);\n    pairReinsertOptimize(best);\n\n    // Randomized constructions using promising orders.\n    vector<int> pool;\n    int poolSize = min(N, 700);\n    for (int i = 0; i < poolSize; i++) pool.push_back(sortedIds[i]);\n\n    while (elapsed() < 1.05) {\n        State cur = constructGreedy(pool, 6);\n        pairReinsertOptimize(cur);\n\n        if (cur.cost < best.cost) {\n            best = cur;\n        }\n    }\n\n    // Try replacing selected orders.\n    replaceOptimize(best, sortedIds, 1.85);\n\n    pairReinsertOptimize(best);\n\n    cout << K;\n    for (int oid : best.selected) {\n        cout << ' ' << oid + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (const Node& v : best.route) {\n        cout << ' ' << v.x << ' ' << v.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 400;\nstatic constexpr int M = 1995;\nstatic constexpr int SAMPLES = 24;\nstatic constexpr long long INF = (1LL << 60);\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n};\n\nstruct DSU {\n    int p[N];\n    int sz[N];\n\n    void init() {\n        for (int i = 0; i < N; i++) {\n            p[i] = i;\n            sz[i] = 1;\n        }\n    }\n\n    int find(int x) const {\n        while (p[x] != x) x = p[x];\n        return x;\n    }\n\n    bool same(int a, int b) const {\n        return find(a) == find(b);\n    }\n\n    bool unite(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n        if (ra == rb) return false;\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<int> u(M), v(M), d(M);\n    for (int i = 0; i < M; i++) {\n        cin >> u[i] >> v[i];\n\n        long long dx = x[u[i]] - x[v[i]];\n        long long dy = y[u[i]] - y[v[i]];\n        d[i] = int(floor(sqrt(double(dx * dx + dy * dy)) + 0.5));\n    }\n\n    XorShift rng;\n\n    vector<vector<int>> sampled_w(SAMPLES, vector<int>(M));\n    vector<vector<int>> order(SAMPLES, vector<int>(M));\n\n    for (int s = 0; s < SAMPLES; s++) {\n        for (int i = 0; i < M; i++) {\n            sampled_w[s][i] = rng.randint(d[i], 3 * d[i]);\n            order[s][i] = i;\n        }\n\n        sort(order[s].begin(), order[s].end(), [&](int a, int b) {\n            if (sampled_w[s][a] != sampled_w[s][b]) {\n                return sampled_w[s][a] < sampled_w[s][b];\n            }\n            return a < b;\n        });\n    }\n\n    DSU accepted;\n    accepted.init();\n\n    int accepted_edges = 0;\n\n    for (int cur = 0; cur < M; cur++) {\n        int len;\n        cin >> len;\n\n        int answer = 0;\n\n        if (!accepted.same(u[cur], v[cur])) {\n            int base_components = N - accepted_edges;\n\n            long long sum_delta = 0;\n            bool reject_impossible = false;\n\n            for (int s = 0; s < SAMPLES; s++) {\n                DSU dsu_reject = accepted;\n                DSU dsu_accept = accepted;\n\n                int comp_reject = base_components;\n                int comp_accept = base_components;\n\n                long long cost_reject = 0;\n                long long cost_accept = len;\n\n                if (dsu_accept.unite(u[cur], v[cur])) {\n                    comp_accept--;\n                }\n\n                for (int pos = 0; pos < M; pos++) {\n                    if (comp_reject == 1 && comp_accept == 1) break;\n\n                    int e = order[s][pos];\n                    if (e <= cur) continue;\n\n                    int a = u[e];\n                    int b = v[e];\n                    int w = sampled_w[s][e];\n\n                    if (comp_reject > 1 && dsu_reject.unite(a, b)) {\n                        cost_reject += w;\n                        comp_reject--;\n                    }\n\n                    if (comp_accept > 1 && dsu_accept.unite(a, b)) {\n                        cost_accept += w;\n                        comp_accept--;\n                    }\n                }\n\n                if (comp_reject > 1) {\n                    reject_impossible = true;\n                    break;\n                }\n\n                if (comp_accept > 1) {\n                    cost_accept = INF;\n                }\n\n                sum_delta += cost_accept - cost_reject;\n            }\n\n            if (reject_impossible || sum_delta < 0) {\n                answer = 1;\n                accepted.unite(u[cur], v[cur]);\n                accepted_edges++;\n            }\n        }\n\n        cout << answer << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct Task {\n    int sx, sy; // standing cell\n    int wx, wy; // wall cell\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\n\nbool wall_[31][31];\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char mvChar[4] = {'U', 'D', 'L', 'R'};\nconst char buildChar[4] = {'u', 'd', 'l', 'r'};\n\nint ori_, S_;\nint x1_, x2_, y1_, y2_;\nvector<Task> tasks;\n\nbool inBoard(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nbool insideRegion(int x, int y) {\n    return x1_ <= x && x <= x2_ && y1_ <= y && y <= y2_;\n}\n\nbool passable(int x, int y) {\n    return inBoard(x, y) && !wall_[x][y];\n}\n\npair<int,int> regionRangeX(int ori, int S) {\n    if (ori == 0 || ori == 1) return {1, S};\n    return {31 - S, 30};\n}\n\npair<int,int> regionRangeY(int ori, int S) {\n    if (ori == 0 || ori == 2) return {1, S};\n    return {31 - S, 30};\n}\n\nbool insideRegionParam(int x, int y, int ori, int S) {\n    auto rx = regionRangeX(ori, S);\n    auto ry = regionRangeY(ori, S);\n    return rx.first <= x && x <= rx.second && ry.first <= y && y <= ry.second;\n}\n\nint distToRegion(int x, int y, int ori, int S) {\n    auto rx = regionRangeX(ori, S);\n    auto ry = regionRangeY(ori, S);\n    int dx = 0, dy = 0;\n    if (x < rx.first) dx = rx.first - x;\n    if (x > rx.second) dx = x - rx.second;\n    if (y < ry.first) dy = ry.first - y;\n    if (y > ry.second) dy = y - ry.second;\n    return dx + dy;\n}\n\nvoid selectRegion() {\n    double bestVal = -1e100;\n    int bestOri = 0, bestS = 10;\n\n    for (int ori = 0; ori < 4; ori++) {\n        for (int S = 8; S <= 18; S++) {\n            int pcnt = 0;\n            for (auto &p : pets) {\n                if (insideRegionParam(p.x, p.y, ori, S)) pcnt++;\n            }\n\n            double avgDist = 0;\n            for (auto &h : humans) {\n                avgDist += distToRegion(h.x, h.y, ori, S);\n            }\n            avgDist /= M;\n\n            double expected = (double)(S * S) / 900.0 * pow(0.5, pcnt);\n            double val = expected - 0.002 * avgDist - 0.0005 * S;\n\n            if (val > bestVal) {\n                bestVal = val;\n                bestOri = ori;\n                bestS = S;\n            }\n        }\n    }\n\n    ori_ = bestOri;\n    S_ = bestS;\n\n    auto rx = regionRangeX(ori_, S_);\n    auto ry = regionRangeY(ori_, S_);\n    x1_ = rx.first;\n    x2_ = rx.second;\n    y1_ = ry.first;\n    y2_ = ry.second;\n}\n\nvoid makeTasks() {\n    tasks.clear();\n\n    int S = S_;\n\n    if (ori_ == 0) {\n        // top-left\n        for (int c = 1; c <= S; c++) {\n            tasks.push_back({S, c, S + 1, c});\n        }\n        for (int r = 1; r <= S; r++) {\n            tasks.push_back({r, S, r, S + 1});\n        }\n    } else if (ori_ == 1) {\n        // top-right\n        int L = 31 - S;\n        for (int c = L; c <= 30; c++) {\n            tasks.push_back({S, c, S + 1, c});\n        }\n        for (int r = 1; r <= S; r++) {\n            tasks.push_back({r, L, r, L - 1});\n        }\n    } else if (ori_ == 2) {\n        // bottom-left\n        int U = 31 - S;\n        for (int c = 1; c <= S; c++) {\n            tasks.push_back({U, c, U - 1, c});\n        }\n        for (int r = U; r <= 30; r++) {\n            tasks.push_back({r, S, r, S + 1});\n        }\n    } else {\n        // bottom-right\n        int U = 31 - S;\n        int L = 31 - S;\n        for (int c = L; c <= 30; c++) {\n            tasks.push_back({U, c, U - 1, c});\n        }\n        for (int r = U; r <= 30; r++) {\n            tasks.push_back({r, L, r, L - 1});\n        }\n    }\n}\n\nbool allHumansInside() {\n    for (auto &h : humans) {\n        if (!insideRegion(h.x, h.y)) return false;\n    }\n    return true;\n}\n\nint petsInside() {\n    int cnt = 0;\n    for (auto &p : pets) {\n        if (insideRegion(p.x, p.y)) cnt++;\n    }\n    return cnt;\n}\n\nbool allTasksDone() {\n    for (auto &t : tasks) {\n        if (!wall_[t.wx][t.wy]) return false;\n    }\n    return true;\n}\n\nchar dirFromTo(int x1, int y1, int x2, int y2, bool build) {\n    for (int d = 0; d < 4; d++) {\n        if (x1 + dx[d] == x2 && y1 + dy[d] == y2) {\n            return build ? buildChar[d] : mvChar[d];\n        }\n    }\n    return '.';\n}\n\nbool validBuildTarget(\n    int x,\n    int y,\n    const bool occH[31][31],\n    const bool occP[31][31]\n) {\n    if (!inBoard(x, y)) return false;\n    if (occH[x][y]) return false;\n    if (occP[x][y]) return false;\n\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (inBoard(nx, ny) && occP[nx][ny]) return false;\n    }\n\n    return true;\n}\n\nchar bfsMove(\n    int sx,\n    int sy,\n    const vector<pair<int,int>> &targets,\n    const bool avoid[31][31],\n    bool restrictInside\n) {\n    if (targets.empty()) return '.';\n\n    bool isTarget[31][31] = {};\n    for (auto [x, y] : targets) {\n        if (inBoard(x, y)) isTarget[x][y] = true;\n    }\n\n    if (isTarget[sx][sy]) return '.';\n\n    int dist[31][31];\n    char first[31][31];\n\n    for (int i = 1; i <= 30; i++) {\n        for (int j = 1; j <= 30; j++) {\n            dist[i][j] = -1;\n            first[i][j] = '.';\n        }\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();\n        q.pop();\n\n        if (isTarget[x][y]) {\n            return first[x][y];\n        }\n\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n\n            if (!inBoard(nx, ny)) continue;\n            if (!passable(nx, ny)) continue;\n            if (avoid[nx][ny]) continue;\n            if (restrictInside && !insideRegion(nx, ny)) continue;\n            if (dist[nx][ny] != -1) continue;\n\n            dist[nx][ny] = dist[x][y] + 1;\n            first[nx][ny] = (x == sx && y == sy) ? mvChar[d] : first[x][y];\n            q.push({nx, ny});\n        }\n    }\n\n    return '.';\n}\n\nvector<pair<int,int>> allInsideCells() {\n    vector<pair<int,int>> res;\n    for (int x = x1_; x <= x2_; x++) {\n        for (int y = y1_; y <= y2_; y++) {\n            if (passable(x, y)) res.push_back({x, y});\n        }\n    }\n    return res;\n}\n\npair<int,int> centerCell() {\n    return {(x1_ + x2_) / 2, (y1_ + y2_) / 2};\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++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    memset(wall_, false, sizeof(wall_));\n\n    selectRegion();\n    makeTasks();\n\n    bool startedBuild = false;\n\n    for (int turn = 0; turn < 300; turn++) {\n        bool occH[31][31] = {};\n        bool occP[31][31] = {};\n\n        for (auto &h : humans) occH[h.x][h.y] = true;\n        for (auto &p : pets) occP[p.x][p.y] = true;\n\n        string ans(M, '.');\n        bool avoid[31][31] = {};\n\n        bool humansIn = allHumansInside();\n\n        if (!humansIn) {\n            vector<pair<int,int>> targets = allInsideCells();\n            for (int i = 0; i < M; i++) {\n                ans[i] = bfsMove(humans[i].x, humans[i].y, targets, avoid, false);\n            }\n        } else {\n            if (!startedBuild) {\n                if (petsInside() == 0 || turn >= 100) {\n                    startedBuild = true;\n                }\n            }\n\n            if (!startedBuild) {\n                auto c = centerCell();\n                vector<pair<int,int>> targets = {c};\n                for (int i = 0; i < M; i++) {\n                    ans[i] = bfsMove(humans[i].x, humans[i].y, targets, avoid, true);\n                }\n            } else if (!allTasksDone()) {\n                bool scheduledWall[31][31] = {};\n\n                // First, humans already standing at task positions try to build.\n                for (int i = 0; i < M; i++) {\n                    int hx = humans[i].x;\n                    int hy = humans[i].y;\n\n                    for (auto &t : tasks) {\n                        if (wall_[t.wx][t.wy]) continue;\n                        if (t.sx != hx || t.sy != hy) continue;\n                        if (scheduledWall[t.wx][t.wy]) continue;\n                        if (!validBuildTarget(t.wx, t.wy, occH, occP)) continue;\n\n                        ans[i] = dirFromTo(hx, hy, t.wx, t.wy, true);\n                        scheduledWall[t.wx][t.wy] = true;\n                        avoid[t.wx][t.wy] = true;\n                        break;\n                    }\n                }\n\n                // Then move idle humans to useful task positions.\n                vector<pair<int,int>> goodTargets;\n                vector<pair<int,int>> fallbackTargets;\n\n                for (auto &t : tasks) {\n                    if (wall_[t.wx][t.wy]) continue;\n                    if (scheduledWall[t.wx][t.wy]) continue;\n\n                    fallbackTargets.push_back({t.sx, t.sy});\n\n                    if (validBuildTarget(t.wx, t.wy, occH, occP)) {\n                        goodTargets.push_back({t.sx, t.sy});\n                    }\n                }\n\n                if (goodTargets.empty()) goodTargets = fallbackTargets;\n\n                for (int i = 0; i < M; i++) {\n                    if (ans[i] != '.') continue;\n\n                    bool restrict = insideRegion(humans[i].x, humans[i].y);\n                    ans[i] = bfsMove(\n                        humans[i].x,\n                        humans[i].y,\n                        goodTargets,\n                        avoid,\n                        restrict\n                    );\n                }\n            } else {\n                auto c = centerCell();\n                vector<pair<int,int>> targets = {c};\n                for (int i = 0; i < M; i++) {\n                    ans[i] = bfsMove(humans[i].x, humans[i].y, targets, avoid, true);\n                }\n            }\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        // Apply human actions and created walls.\n        for (int i = 0; i < M; i++) {\n            char a = ans[i];\n\n            if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                for (int d = 0; d < 4; d++) {\n                    if (a == mvChar[d]) {\n                        humans[i].x += dx[d];\n                        humans[i].y += dy[d];\n                    }\n                }\n            } else if (a == 'u' || a == 'd' || a == 'l' || a == 'r') {\n                for (int d = 0; d < 4; d++) {\n                    if (a == buildChar[d]) {\n                        int wx = humans[i].x + dx[d];\n                        int wy = humans[i].y + dy[d];\n                        if (inBoard(wx, wy)) wall_[wx][wy] = true;\n                    }\n                }\n            }\n        }\n\n        // Read and apply pet movements.\n        for (int i = 0; i < N; i++) {\n            string s;\n            if (!(cin >> s)) return 0;\n\n            if (s == \".\") continue;\n\n            for (char c : s) {\n                if (c == 'U') pets[i].x--;\n                else if (c == 'D') pets[i].x++;\n                else if (c == 'L') pets[i].y--;\n                else if (c == 'R') pets[i].y++;\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int V = 400;\nstatic const int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble p_fail, p_succ;\nstring hwall[20], vwall[19];\n\nint start_id, target_id;\nint nxt_cell[4][V];\nint dist_to_t[V];\nfloat potential_value[MAXL + 1][V];\n\nconst string DIRS = \"UDLR\";\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos(int x) {\n    return {x / N, x % N};\n}\n\nstruct Node {\n    array<float, V> prob;\n    double score;\n    double eval;\n    string path;\n};\n\ndouble evaluate_string(const string& s) {\n    static double cur[V], nxt[V];\n\n    for (int i = 0; i < V; i++) cur[i] = 0.0;\n    cur[start_id] = 1.0;\n\n    double score = 0.0;\n\n    for (int t = 0; t < (int)s.size(); t++) {\n        int dir;\n        if (s[t] == 'U') dir = 0;\n        else if (s[t] == 'D') dir = 1;\n        else if (s[t] == 'L') dir = 2;\n        else dir = 3;\n\n        for (int i = 0; i < V; i++) nxt[i] = 0.0;\n\n        double arrive = 0.0;\n        double remain_mass = 0.0;\n\n        for (int c = 0; c < V; c++) {\n            double pr = cur[c];\n            if (pr < 1e-18) continue;\n\n            int to = nxt_cell[dir][c];\n\n            if (to == target_id) {\n                arrive += pr * p_succ;\n                nxt[c] += pr * p_fail;\n            } else if (to == c) {\n                nxt[c] += pr;\n            } else {\n                nxt[c] += pr * p_fail;\n                nxt[to] += pr * p_succ;\n            }\n        }\n\n        score += arrive * (400 - t);\n\n        for (int i = 0; i < V; i++) {\n            cur[i] = nxt[i];\n            remain_mass += cur[i];\n        }\n\n        if (remain_mass < 1e-18) break;\n    }\n\n    return score;\n}\n\nvoid build_graph() {\n    for (int x = 0; x < V; x++) {\n        auto [i, j] = pos(x);\n\n        // U\n        if (i == 0 || vwall[i - 1][j] == '1') nxt_cell[0][x] = x;\n        else nxt_cell[0][x] = id(i - 1, j);\n\n        // D\n        if (i == N - 1 || vwall[i][j] == '1') nxt_cell[1][x] = x;\n        else nxt_cell[1][x] = id(i + 1, j);\n\n        // L\n        if (j == 0 || hwall[i][j - 1] == '1') nxt_cell[2][x] = x;\n        else nxt_cell[2][x] = id(i, j - 1);\n\n        // R\n        if (j == N - 1 || hwall[i][j] == '1') nxt_cell[3][x] = x;\n        else nxt_cell[3][x] = id(i, j + 1);\n    }\n}\n\nvoid bfs_distance() {\n    const int INF = 1e9;\n    fill(dist_to_t, dist_to_t + V, INF);\n\n    queue<int> q;\n    dist_to_t[target_id] = 0;\n    q.push(target_id);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int to = nxt_cell[d][v];\n            if (to == v) continue;\n            if (dist_to_t[to] > dist_to_t[v] + 1) {\n                dist_to_t[to] = dist_to_t[v] + 1;\n                q.push(to);\n            }\n        }\n    }\n}\n\nvoid build_potential() {\n    for (int t = 0; t <= MAXL; t++) {\n        for (int c = 0; c < V; c++) {\n            int d = dist_to_t[c];\n\n            if (d > MAXL - t) {\n                potential_value[t][c] = 0.0f;\n                continue;\n            }\n\n            double estimated_turn = t + d / p_succ;\n            double val = 401.0 - estimated_turn;\n            if (val < 0.0) val = 0.0;\n\n            potential_value[t][c] = (float)val;\n        }\n    }\n}\n\nstring beam_search() {\n    const int BEAM_WIDTH = 250;\n\n    vector<Node> beam;\n    beam.reserve(BEAM_WIDTH);\n\n    Node init;\n    init.prob.fill(0.0f);\n    init.prob[start_id] = 1.0f;\n    init.score = 0.0;\n    init.eval = potential_value[0][start_id];\n    init.path = \"\";\n    beam.push_back(init);\n\n    for (int depth = 0; depth < MAXL; depth++) {\n        vector<Node> cand;\n        cand.reserve(beam.size() * 4);\n\n        for (const Node& par : beam) {\n            for (int dir = 0; dir < 4; dir++) {\n                Node ch;\n                ch.prob.fill(0.0f);\n\n                float arrive = 0.0f;\n\n                for (int c = 0; c < V; c++) {\n                    float pr = par.prob[c];\n                    if (pr < 1e-12f) continue;\n\n                    int to = nxt_cell[dir][c];\n\n                    if (to == target_id) {\n                        arrive += pr * (float)p_succ;\n                        ch.prob[c] += pr * (float)p_fail;\n                    } else if (to == c) {\n                        ch.prob[c] += pr;\n                    } else {\n                        ch.prob[c] += pr * (float)p_fail;\n                        ch.prob[to] += pr * (float)p_succ;\n                    }\n                }\n\n                int nt = depth + 1;\n                ch.score = par.score + arrive * (400 - depth);\n\n                double pot = 0.0;\n                for (int c = 0; c < V; c++) {\n                    float pr = ch.prob[c];\n                    if (pr < 1e-12f) continue;\n                    pot += pr * potential_value[nt][c];\n                }\n\n                ch.eval = ch.score + pot;\n                ch.path = par.path;\n                ch.path.push_back(DIRS[dir]);\n\n                cand.push_back(std::move(ch));\n            }\n        }\n\n        if ((int)cand.size() > BEAM_WIDTH) {\n            nth_element(\n                cand.begin(),\n                cand.begin() + BEAM_WIDTH,\n                cand.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            );\n            cand.resize(BEAM_WIDTH);\n        }\n\n        beam.swap(cand);\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)beam.size(); i++) {\n        if (beam[i].score > beam[best].score) best = i;\n    }\n\n    return beam[best].path;\n}\n\nvoid local_improve(string& ans, chrono::steady_clock::time_point start_time) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    double best_score = evaluate_string(ans);\n\n    bool improved = true;\n\n    while (improved && elapsed() < 1.85) {\n        improved = false;\n\n        for (int pos = 0; pos < (int)ans.size(); pos++) {\n            if (elapsed() > 1.88) break;\n\n            char original = ans[pos];\n            char best_char = original;\n            double local_best = best_score;\n\n            for (char c : DIRS) {\n                if (c == original) continue;\n\n                ans[pos] = c;\n                double sc = evaluate_string(ans);\n\n                if (sc > local_best + 1e-10) {\n                    local_best = sc;\n                    best_char = c;\n                }\n\n                if (elapsed() > 1.88) break;\n            }\n\n            ans[pos] = best_char;\n\n            if (best_char != original) {\n                best_score = local_best;\n                improved = true;\n            }\n        }\n    }\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    cin >> si_ >> sj_ >> ti_ >> tj_ >> p_fail;\n    p_succ = 1.0 - p_fail;\n\n    for (int i = 0; i < 20; i++) cin >> hwall[i];\n    for (int i = 0; i < 19; i++) cin >> vwall[i];\n\n    start_id = id(si_, sj_);\n    target_id = id(ti_, tj_);\n\n    build_graph();\n    bfs_distance();\n    build_potential();\n\n    string ans = beam_search();\n\n    local_improve(ans, start_time);\n\n    if ((int)ans.size() > MAXL) ans.resize(MAXL);\n\n    cout << ans << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int MAXP = 2000;\n\nstruct XorShift {\n    uint64_t x = chrono::steady_clock::now().time_since_epoch().count();\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n} rng;\n\nint parent_[MAXP], sz_[MAXP], open_[MAXP];\nint sidePid[V][4];\n\nint findp(int x) {\n    while (parent_[x] != x) {\n        parent_[x] = parent_[parent_[x]];\n        x = parent_[x];\n    }\n    return x;\n}\n\nvoid unite(int a, int b) {\n    int ra = findp(a), rb = findp(b);\n    if (ra == rb) return;\n    if (sz_[ra] < sz_[rb]) swap(ra, rb);\n    parent_[rb] = ra;\n    sz_[ra] += sz_[rb];\n}\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nconst int pieceCntOf[8] = {1,1,1,1,2,2,1,1};\nconst int A[8][2] = {\n    {0, -1},\n    {0, -1},\n    {2, -1},\n    {1, -1},\n    {0, 2},\n    {0, 1},\n    {0, -1},\n    {1, -1},\n};\nconst int B[8][2] = {\n    {1, -1},\n    {3, -1},\n    {3, -1},\n    {2, -1},\n    {1, 3},\n    {3, 2},\n    {2, -1},\n    {3, -1},\n};\n\nstruct Eval {\n    long long actual = 0;\n    int l1 = 0;\n    int l2 = 0;\n    double energy = 0;\n};\n\nEval evaluate(const uint8_t state[V]) {\n    memset(sidePid, -1, sizeof(sidePid));\n\n    int pc = 0;\n\n    for (int k = 0; k < V; k++) {\n        int t = state[k];\n        int c = pieceCntOf[t];\n\n        for (int p = 0; p < c; p++) {\n            int id = pc++;\n            parent_[id] = id;\n            sz_[id] = 1;\n            open_[id] = 0;\n\n            int a = A[t][p];\n            int b = B[t][p];\n            sidePid[k][a] = id;\n            sidePid[k][b] = id;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            if (j + 1 < N) {\n                int a = sidePid[k][2];\n                int b = sidePid[k + 1][0];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n\n            if (i + 1 < N) {\n                int a = sidePid[k][3];\n                int b = sidePid[k + N][1];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            for (int d = 0; d < 4; d++) {\n                int id = sidePid[k][d];\n                if (id == -1) continue;\n\n                int ni = i + di[d];\n                int nj = j + dj[d];\n\n                bool bad = false;\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    bad = true;\n                } else {\n                    int nk = ni * N + nj;\n                    int od = (d + 2) & 3;\n                    if (sidePid[nk][od] == -1) bad = true;\n                }\n\n                if (bad) {\n                    open_[findp(id)]++;\n                }\n            }\n        }\n    }\n\n    Eval res;\n    double compBonus = 0.0;\n\n    for (int id = 0; id < pc; id++) {\n        int r = findp(id);\n        if (r != id) continue;\n\n        int s = sz_[r];\n        int op = open_[r];\n\n        compBonus += (double)s * s / (op + 1);\n\n        if (op == 0) {\n            if (s > res.l1) {\n                res.l2 = res.l1;\n                res.l1 = s;\n            } else if (s > res.l2) {\n                res.l2 = s;\n            }\n        }\n    }\n\n    if (res.l2 > 0) res.actual = 1LL * res.l1 * res.l2;\n\n    res.energy =\n        (double)res.actual\n        + 1.50 * res.l1 * res.l1\n        + 1.50 * res.l2 * res.l2\n        + 0.05 * compBonus;\n\n    return res;\n}\n\nint rotateTile(int t, int r) {\n    if (t < 4) return (t + r) & 3;\n    if (t < 6) return 4 + ((t - 4 + r) & 1);\n    return 6 + ((t - 6 + r) & 1);\n}\n\nint outsideCountState(int k, int t) {\n    int i = k / N;\n    int j = k % N;\n\n    bool has[4] = {};\n    for (int p = 0; p < pieceCntOf[t]; p++) {\n        has[A[t][p]] = true;\n        has[B[t][p]] = true;\n    }\n\n    int cnt = 0;\n    for (int d = 0; d < 4; d++) {\n        if (!has[d]) continue;\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) cnt++;\n    }\n    return cnt;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto timeStart = chrono::steady_clock::now();\n\n    string input[30];\n    for (int i = 0; i < N; i++) cin >> input[i];\n\n    uint8_t base[V];\n\n    int dom[V][4], domCnt[V];\n    int initDom[V][4], initDomCnt[V];\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n            int t = input[i][j] - '0';\n            base[k] = t;\n\n            vector<int> states;\n            if (t < 4) {\n                states = {0, 1, 2, 3};\n            } else if (t < 6) {\n                states = {4, 5};\n            } else {\n                states = {6, 7};\n            }\n\n            domCnt[k] = (int)states.size();\n            for (int a = 0; a < domCnt[k]; a++) dom[k][a] = states[a];\n\n            int bestOut = 100;\n            for (int s : states) bestOut = min(bestOut, outsideCountState(k, s));\n\n            initDomCnt[k] = 0;\n            for (int s : states) {\n                if (outsideCountState(k, s) == bestOut) {\n                    initDom[k][initDomCnt[k]++] = s;\n                }\n            }\n        }\n    }\n\n    uint8_t cur[V], best[V], startState[V];\n\n    Eval bestEval;\n    Eval bestEnergyEval;\n    bestEval.actual = -1;\n    bestEnergyEval.energy = -1e100;\n\n    constexpr int INIT_TRIALS = 2500;\n\n    for (int tr = 0; tr < INIT_TRIALS; tr++) {\n        for (int k = 0; k < V; k++) {\n            if ((rng.next() & 15) == 0) {\n                cur[k] = dom[k][rng.nextInt(domCnt[k])];\n            } else {\n                cur[k] = initDom[k][rng.nextInt(initDomCnt[k])];\n            }\n        }\n\n        Eval ev = evaluate(cur);\n\n        if (ev.energy > bestEnergyEval.energy) {\n            bestEnergyEval = ev;\n            memcpy(startState, cur, V);\n        }\n\n        if (\n            ev.actual > bestEval.actual ||\n            (ev.actual == bestEval.actual && ev.energy > bestEval.energy)\n        ) {\n            bestEval = ev;\n            memcpy(best, cur, V);\n        }\n    }\n\n    memcpy(cur, startState, V);\n    Eval curEval = evaluate(cur);\n\n    bool restarted = false;\n\n    const double TL = 1.92;\n    const double T0 = 25000.0;\n    const double T1 = 20.0;\n\n    int iter = 0;\n\n    while (true) {\n        iter++;\n\n        if ((iter & 255) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - timeStart).count();\n            if (elapsed >= TL) break;\n\n            double progress = elapsed / TL;\n            if (!restarted && progress > 0.68) {\n                memcpy(cur, best, V);\n                curEval = evaluate(cur);\n                restarted = true;\n            }\n        }\n\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - timeStart).count();\n        double progress = min(1.0, elapsed / TL);\n        double temp = T0 * pow(T1 / T0, progress);\n\n        int m = 1;\n        int r100 = rng.nextInt(100);\n        if (r100 < 7) m = 2;\n        if (r100 == 0) m = 3;\n\n        int pos[3];\n        uint8_t oldVal[3];\n\n        for (int x = 0; x < m; x++) {\n            while (true) {\n                int k = rng.nextInt(V);\n                bool used = false;\n                for (int y = 0; y < x; y++) {\n                    if (pos[y] == k) used = true;\n                }\n                if (!used) {\n                    pos[x] = k;\n                    break;\n                }\n            }\n\n            int k = pos[x];\n            oldVal[x] = cur[k];\n\n            int nd;\n            do {\n                nd = dom[k][rng.nextInt(domCnt[k])];\n            } while (nd == cur[k]);\n\n            cur[k] = nd;\n        }\n\n        Eval ne = evaluate(cur);\n        double diff = ne.energy - curEval.energy;\n\n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double p = exp(diff / temp);\n            if (rng.nextDouble() < p) accept = true;\n        }\n\n        if (\n            ne.actual > bestEval.actual ||\n            (ne.actual == bestEval.actual && ne.energy > bestEval.energy)\n        ) {\n            bestEval = ne;\n            memcpy(best, cur, V);\n        }\n\n        if (accept) {\n            curEval = ne;\n        } else {\n            for (int x = 0; x < m; x++) {\n                cur[pos[x]] = oldVal[x];\n            }\n        }\n    }\n\n    string ans;\n    ans.reserve(V);\n\n    for (int k = 0; k < V; k++) {\n        int b = base[k];\n        int target = best[k];\n\n        int rr = 0;\n        for (int r = 0; r < 4; r++) {\n            if (rotateTile(b, r) == target) {\n                rr = r;\n                break;\n            }\n        }\n        ans.push_back(char('0' + rr));\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint N, T, M;\nint FULLV;\n\nstruct Eval {\n    int s;        // largest tree component size\n    int maxComp;  // largest connected component size\n    int cyc;      // cycle excess\n};\n\nstruct Node {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    unsigned char prev;\n    ull hash;\n};\n\nstruct Cand {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    short maxComp;\n    short cyc;\n    unsigned char prev;\n    ull hash;\n    long long h;\n};\n\null zob[100][16];\n\ninline int hexval(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\ninline bool edge_adj(const array<unsigned char, 100>& b, int x, int y) {\n    if (y == x - 1) return (b[x] & 1) && (b[y] & 4);\n    if (y == x + 1) return (b[x] & 4) && (b[y] & 1);\n    if (y == x - N) return (b[x] & 2) && (b[y] & 8);\n    if (y == x + N) return (b[x] & 8) && (b[y] & 2);\n    return false;\n}\n\nint local_edges(const array<unsigned char, 100>& b, int a, int c) {\n    int cells[2] = {a, c};\n    int keys[8];\n    int kc = 0;\n    int res = 0;\n\n    for (int ii = 0; ii < 2; ii++) {\n        int x = cells[ii];\n        int r = x / N, col = x % N;\n\n        int neigh[4];\n        int nc = 0;\n        if (r > 0) neigh[nc++] = x - N;\n        if (r + 1 < N) neigh[nc++] = x + N;\n        if (col > 0) neigh[nc++] = x - 1;\n        if (col + 1 < N) neigh[nc++] = x + 1;\n\n        for (int k = 0; k < nc; k++) {\n            int y = neigh[k];\n            int u = min(x, y), v = max(x, y);\n            int key = u * 100 + v;\n\n            bool seen = false;\n            for (int t = 0; t < kc; t++) {\n                if (keys[t] == key) {\n                    seen = true;\n                    break;\n                }\n            }\n            if (seen) continue;\n\n            keys[kc++] = key;\n            if (edge_adj(b, x, y)) res++;\n        }\n    }\n    return res;\n}\n\nint total_edges(const array<unsigned char, 100>& b) {\n    int e = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            if (b[p] == 0) continue;\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) e++;\n            }\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) e++;\n            }\n        }\n    }\n    return e;\n}\n\nstruct DSU {\n    int p[100], sz[100], ed[100];\n\n    void init(const array<unsigned char, 100>& b) {\n        for (int i = 0; i < M; i++) {\n            if (b[i]) {\n                p[i] = i;\n                sz[i] = 1;\n                ed[i] = 0;\n            } else {\n                p[i] = -1;\n                sz[i] = 0;\n                ed[i] = 0;\n            }\n        }\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    void add_edge(int a, int b) {\n        int ra = find(a), rb = find(b);\n        if (ra == rb) {\n            ed[ra]++;\n            return;\n        }\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        ed[ra] += ed[rb] + 1;\n    }\n};\n\nEval eval_board(const array<unsigned char, 100>& b) {\n    DSU d;\n    d.init(b);\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            if (b[p] == 0) continue;\n\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) {\n                    d.add_edge(p, p + 1);\n                }\n            }\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) {\n                    d.add_edge(p, p + N);\n                }\n            }\n        }\n    }\n\n    Eval ev{0, 0, 0};\n\n    for (int i = 0; i < M; i++) {\n        if (b[i] == 0) continue;\n        if (d.find(i) != i) continue;\n\n        ev.maxComp = max(ev.maxComp, d.sz[i]);\n\n        if (d.ed[i] == d.sz[i] - 1) {\n            ev.s = max(ev.s, d.sz[i]);\n        } else if (d.ed[i] >= d.sz[i]) {\n            ev.cyc += d.ed[i] - d.sz[i] + 1;\n        }\n    }\n\n    return ev;\n}\n\ninline long long heuristic_score(const Cand& c) {\n    long long h = 0;\n    h += 20000LL * c.s;\n    h += 7000LL * c.e;\n    h += 500LL * c.maxComp;\n    h -= 10000LL * c.cyc;\n    h += (long long)(c.hash & 1023ULL);\n    return h;\n}\n\nstring restore_path(const vector<Node>& pool, int idx) {\n    string res;\n    while (pool[idx].parent != -1) {\n        res.push_back((char)pool[idx].prev);\n        idx = pool[idx].parent;\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    M = N * N;\n    FULLV = M - 1;\n\n    mt19937_64 rng(123456789);\n    for (int i = 0; i < 100; i++) {\n        for (int v = 0; v < 16; v++) {\n            zob[i][v] = rng();\n        }\n    }\n\n    array<unsigned char, 100> init{};\n    int initBlank = -1;\n    ull initHash = 0;\n\n    for (int r = 0; r < N; r++) {\n        string s;\n        cin >> s;\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            int v = hexval(s[c]);\n            init[p] = (unsigned char)v;\n            if (v == 0) initBlank = p;\n            initHash ^= zob[p][v];\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n\n    int W;\n    if (N == 6) W = 2400;\n    else if (N == 7) W = 1700;\n    else if (N == 8) W = 1150;\n    else if (N == 9) W = 800;\n    else W = 560;\n\n    vector<Node> pool;\n    pool.reserve((size_t)W * (T + 2) + 10);\n\n    Node root;\n    root.b = init;\n    root.parent = -1;\n    root.blank = initBlank;\n    root.e = total_edges(init);\n    root.prev = 0;\n    root.hash = initHash;\n\n    Eval rootEv = eval_board(init);\n    root.s = rootEv.s;\n\n    pool.push_back(root);\n\n    if (rootEv.s == FULLV) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    vector<int> beam;\n    beam.push_back(0);\n\n    int bestIdx = 0;\n    int bestS = rootEv.s;\n\n    const char mvChar[4] = {'U', 'D', 'L', 'R'};\n    const int inv[256] = {\n        0\n    };\n\n    auto inverse_move = [](char c) -> char {\n        if (c == 'U') return 'D';\n        if (c == 'D') return 'U';\n        if (c == 'L') return 'R';\n        if (c == 'R') return 'L';\n        return 0;\n    };\n\n    for (int step = 1; step <= T; step++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 2.85) break;\n\n        vector<Cand> cand;\n        cand.reserve(beam.size() * 3 + 10);\n\n        for (int idx : beam) {\n            const Node& nd = pool[idx];\n            int z = nd.blank;\n            int r = z / N, c = z % N;\n\n            for (int dir = 0; dir < 4; dir++) {\n                char mc = mvChar[dir];\n                if (nd.prev && inverse_move((char)nd.prev) == mc) continue;\n\n                int nz = -1;\n                if (mc == 'U') {\n                    if (r == 0) continue;\n                    nz = z - N;\n                } else if (mc == 'D') {\n                    if (r + 1 == N) continue;\n                    nz = z + N;\n                } else if (mc == 'L') {\n                    if (c == 0) continue;\n                    nz = z - 1;\n                } else {\n                    if (c + 1 == N) continue;\n                    nz = z + 1;\n                }\n\n                Cand x;\n                x.b = nd.b;\n\n                int before = local_edges(x.b, z, nz);\n\n                unsigned char tile = x.b[nz];\n                x.b[z] = tile;\n                x.b[nz] = 0;\n\n                int after = local_edges(x.b, z, nz);\n\n                x.e = nd.e - before + after;\n                x.parent = idx;\n                x.blank = nz;\n                x.prev = (unsigned char)mc;\n                x.s = 0;\n                x.maxComp = 0;\n                x.cyc = 0;\n                x.h = 0;\n\n                ull h = nd.hash;\n                h ^= zob[z][0];\n                h ^= zob[nz][tile];\n                h ^= zob[z][tile];\n                h ^= zob[nz][0];\n                x.hash = h;\n\n                cand.push_back(std::move(x));\n            }\n        }\n\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.hash != b.hash) return a.hash < b.hash;\n            return a.e > b.e;\n        });\n\n        int write = 0;\n        for (int i = 0; i < (int)cand.size();) {\n            int j = i + 1;\n            int best = i;\n            while (j < (int)cand.size() && cand[j].hash == cand[i].hash) {\n                if (cand[j].e > cand[best].e) best = j;\n                j++;\n            }\n            cand[write++] = std::move(cand[best]);\n            i = j;\n        }\n        cand.resize(write);\n\n        int preLimit = min((int)cand.size(), max(W, 2 * W));\n        if ((int)cand.size() > preLimit) {\n            nth_element(cand.begin(), cand.begin() + preLimit, cand.end(),\n                        [](const Cand& a, const Cand& b) {\n                            return a.e > b.e;\n                        });\n            cand.resize(preLimit);\n        }\n\n        for (Cand& x : cand) {\n            Eval ev = eval_board(x.b);\n            x.s = ev.s;\n            x.maxComp = ev.maxComp;\n            x.cyc = ev.cyc;\n            x.h = heuristic_score(x);\n\n            if (x.s > bestS) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n                pool.push_back(tmp);\n                bestIdx = (int)pool.size() - 1;\n                bestS = x.s;\n            }\n\n            if (x.s == FULLV) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n                pool.push_back(tmp);\n                cout << restore_path(pool, (int)pool.size() - 1) << '\\n';\n                return 0;\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.h != b.h) return a.h > b.h;\n            return a.e > b.e;\n        });\n\n        int keep = min(W, (int)cand.size());\n        vector<int> nextBeam;\n        nextBeam.reserve(keep);\n\n        for (int i = 0; i < keep; i++) {\n            Node nd;\n            nd.b = cand[i].b;\n            nd.parent = cand[i].parent;\n            nd.blank = cand[i].blank;\n            nd.e = cand[i].e;\n            nd.s = cand[i].s;\n            nd.prev = cand[i].prev;\n            nd.hash = cand[i].hash;\n\n            pool.push_back(nd);\n            int ni = (int)pool.size() - 1;\n            nextBeam.push_back(ni);\n\n            if (nd.s > bestS) {\n                bestS = nd.s;\n                bestIdx = ni;\n            }\n        }\n\n        beam.swap(nextBeam);\n    }\n\n    cout << restore_path(pool, bestIdx) << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Line {\n    // a*x + b*y = c, usually (a,b) is a unit normal\n    double a, b, c;\n};\n\nstruct EvalResult {\n    int matched;\n    int diff;\n    array<int, 11> hist;\n    long long value() const {\n        return 10000LL * matched - diff;\n    }\n};\n\nstruct Key {\n    uint64_t lo, hi;\n    bool operator==(const Key& other) const {\n        return lo == other.lo && hi == other.hi;\n    }\n};\n\nstruct KeyHash {\n    size_t operator()(const Key& k) const {\n        uint64_t x = k.lo ^ (k.hi + 0x9e3779b97f4a7c15ULL + (k.lo << 6) + (k.lo >> 2));\n        x ^= x >> 30;\n        x *= 0xbf58476d1ce4e5b9ULL;\n        x ^= x >> 27;\n        x *= 0x94d049bb133111ebULL;\n        x ^= x >> 31;\n        return (size_t)x;\n    }\n};\n\nstatic const double PI = acos(-1.0);\nstatic const double R = 10000.0;\n\nint N, K;\narray<int, 11> targetA;\nvector<Point> pts;\n\nchrono::steady_clock::time_point start_time;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\nEvalResult make_eval_from_hist(const array<int, 11>& hist) {\n    EvalResult res;\n    res.hist = hist;\n    res.matched = 0;\n    res.diff = 0;\n    for (int d = 1; d <= 10; d++) {\n        res.matched += min(targetA[d], hist[d]);\n        res.diff += abs(targetA[d] - hist[d]);\n    }\n    return res;\n}\n\nEvalResult eval_grid(double theta, const vector<double>& cutsU, const vector<double>& cutsV) {\n    int gx = (int)cutsU.size() + 1;\n    int gy = (int)cutsV.size() + 1;\n    vector<int> cnt(gx * gy, 0);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double u = p.x * cs + p.y * sn;\n        double v = -p.x * sn + p.y * cs;\n        int ix = int(upper_bound(cutsU.begin(), cutsU.end(), u) - cutsU.begin());\n        int iy = int(upper_bound(cutsV.begin(), cutsV.end(), v) - cutsV.begin());\n        cnt[ix * gy + iy]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n    for (int c : cnt) {\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n    return make_eval_from_hist(hist);\n}\n\nEvalResult eval_lines(const vector<Line>& lines) {\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(pts.size() * 2);\n\n    int L = (int)lines.size();\n\n    for (const auto& p : pts) {\n        uint64_t lo = 0, hi = 0;\n        for (int i = 0; i < L; i++) {\n            const auto& ln = lines[i];\n            double v = ln.a * p.x + ln.b * p.y - ln.c;\n            if (v > 0) {\n                if (i < 64) lo |= (1ULL << i);\n                else hi |= (1ULL << (i - 64));\n            }\n        }\n        mp[{lo, hi}]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n    for (auto& kv : mp) {\n        int c = kv.second;\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n    return make_eval_from_hist(hist);\n}\n\nvector<double> uniform_cuts(int g) {\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n    for (int i = 1; i < g; i++) {\n        cuts.push_back(-R + 2.0 * R * i / g);\n    }\n    return cuts;\n}\n\nvector<double> random_dirichlet_cuts(int g, double alpha, mt19937& rng) {\n    vector<double> w(g);\n    if (alpha > 500.0) {\n        for (int i = 0; i < g; i++) w[i] = 1.0;\n    } else {\n        gamma_distribution<double> gamma(alpha, 1.0);\n        for (int i = 0; i < g; i++) {\n            w[i] = max(1e-9, gamma(rng));\n        }\n    }\n\n    double sum = accumulate(w.begin(), w.end(), 0.0);\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    double cur = -R;\n    for (int i = 0; i + 1 < g; i++) {\n        cur += 2.0 * R * w[i] / sum;\n        cuts.push_back(cur);\n    }\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nvector<Line> build_grid_lines(double theta, const vector<double>& cutsU, const vector<double>& cutsV) {\n    vector<Line> lines;\n    lines.reserve(cutsU.size() + cutsV.size());\n\n    double cs = cos(theta), sn = sin(theta);\n\n    // u = x cos(theta) + y sin(theta)\n    for (double c : cutsU) {\n        lines.push_back({cs, sn, c});\n    }\n\n    // v = -x sin(theta) + y cos(theta)\n    for (double c : cutsV) {\n        lines.push_back({-sn, cs, c});\n    }\n\n    return lines;\n}\n\nint nearest_safe_integer(double x, const unordered_set<int>& forbidden) {\n    int base = (int)llround(x);\n    for (int d = 0; d <= 30000; d++) {\n        int c1 = base + d;\n        if (c1 >= -1000000000 && c1 <= 1000000000 && !forbidden.count(c1)) return c1;\n        int c2 = base - d;\n        if (d && c2 >= -1000000000 && c2 <= 1000000000 && !forbidden.count(c2)) return c2;\n    }\n    return base;\n}\n\nbool collinear_with_any_point(long long x1, long long y1, long long x2, long long y2) {\n    long long dx = x2 - x1;\n    long long dy = y2 - y1;\n    for (const auto& p : pts) {\n        __int128 v = (__int128)dx * (p.y - y1) - (__int128)dy * (p.x - x1);\n        if (v == 0) return true;\n    }\n    return false;\n}\n\narray<long long, 4> line_to_integer_points(\n    const Line& ln,\n    const unordered_set<int>& forbiddenX,\n    const unordered_set<int>& forbiddenY\n) {\n    double a = ln.a, b = ln.b, c = ln.c;\n\n    const long long BIG = 100000000LL;\n\n    long long x1, y1, x2, y2;\n\n    // Exactly vertical-ish / horizontal-ish lines are output safely.\n    if (fabs(b) < 1e-12 && fabs(a) > 0.999999999) {\n        int xi = nearest_safe_integer(c / a, forbiddenX);\n        x1 = xi; y1 = -BIG;\n        x2 = xi; y2 = BIG;\n    } else if (fabs(a) < 1e-12 && fabs(b) > 0.999999999) {\n        int yi = nearest_safe_integer(c / b, forbiddenY);\n        x1 = -BIG; y1 = yi;\n        x2 = BIG; y2 = yi;\n    } else {\n        // Point on line closest to origin: c*(a,b), direction (-b,a)\n        double px = a * c;\n        double py = b * c;\n        double dx = -b;\n        double dy = a;\n\n        x1 = llround(px + BIG * dx);\n        y1 = llround(py + BIG * dy);\n        x2 = llround(px - BIG * dx);\n        y2 = llround(py - BIG * dy);\n    }\n\n    if (x1 == x2 && y1 == y2) x2++;\n\n    // Avoid cutting exactly through a strawberry center.\n    for (int t = 0; t < 20 && collinear_with_any_point(x1, y1, x2, y2); t++) {\n        if (abs(x2 + 1) <= 1000000000LL) x2++;\n        else y2++;\n    }\n\n    x1 = max(-1000000000LL, min(1000000000LL, x1));\n    y1 = max(-1000000000LL, min(1000000000LL, y1));\n    x2 = max(-1000000000LL, min(1000000000LL, x2));\n    y2 = max(-1000000000LL, min(1000000000LL, y2));\n\n    if (x1 == x2 && y1 == y2) {\n        if (x2 < 1000000000LL) x2++;\n        else x2--;\n    }\n\n    return {x1, y1, x2, y2};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    cin >> N >> K;\n    targetA.fill(0);\n\n    int M = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> targetA[d];\n        M += targetA[d];\n    }\n\n    pts.resize(N);\n    unordered_set<int> forbiddenX, forbiddenY;\n    forbiddenX.reserve(N * 2);\n    forbiddenY.reserve(N * 2);\n\n    for (int i = 0; i < N; i++) {\n        cin >> pts[i].x >> pts[i].y;\n        forbiddenX.insert(pts[i].x);\n        forbiddenY.insert(pts[i].y);\n    }\n\n    mt19937 rng(1234567);\n\n    vector<Line> bestLines;\n    long long bestValue = LLONG_MIN;\n\n    auto try_grid = [&](double theta, const vector<double>& cu, const vector<double>& cv) {\n        int k = (int)cu.size() + (int)cv.size();\n        if (k > K) return;\n\n        EvalResult er = eval_grid(theta, cu, cv);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = build_grid_lines(theta, cu, cv);\n        }\n    };\n\n    auto try_lines = [&](const vector<Line>& lines) {\n        if ((int)lines.size() > K) return;\n\n        EvalResult er = eval_lines(lines);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = lines;\n        }\n    };\n\n    // Main expected number of grid intervals.\n    double baseProduct = 4.0 * M / PI;\n\n    vector<double> factors = {0.50, 0.65, 0.80, 1.00, 1.20, 1.50, 1.80, 2.10};\n    vector<double> aspects = {0.55, 0.70, 0.85, 1.00, 1.18, 1.42, 1.80};\n    vector<double> thetas = {0.0, PI / 16, PI / 8, 3 * PI / 16, PI / 4};\n\n    // Deterministic uniform grids.\n    for (double fac : factors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, baseProduct * fac);\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            if (gx < 1 || gy < 1) continue;\n\n            auto cu = uniform_cuts(gx);\n            auto cv = uniform_cuts(gy);\n\n            for (double th : thetas) {\n                try_grid(th, cu, cv);\n            }\n        }\n    }\n\n    // A few 3-direction arrangements.\n    for (int rep = 0; rep < 30 && elapsed_sec() < 2.2; rep++) {\n        double hbase = sqrt(max(1.0, M / 3.0));\n        double scale = 0.70 + 0.04 * rep;\n        int g = max(2, (int)llround(hbase * scale));\n        g = min(g, 34); // 3*(g-1) <= 99\n\n        double th0 = (rep % 10) * PI / 30.0;\n        vector<Line> lines;\n        for (int f = 0; f < 3; f++) {\n            double th = th0 + f * PI / 3.0;\n            double a = cos(th), b = sin(th);\n            auto cuts = uniform_cuts(g);\n            for (double c : cuts) lines.push_back({a, b, c});\n        }\n        try_lines(lines);\n    }\n\n    vector<double> alphaList = {0.30, 0.45, 0.70, 1.00, 1.50, 2.50, 5.00, 1000.0};\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n    uniform_real_distribution<double> urTheta(0.0, PI / 2);\n\n    // Randomized search over non-uniform rotated grids.\n    int iter = 0;\n    while (elapsed_sec() < 2.75) {\n        iter++;\n\n        double logFac = log(0.45) + ur01(rng) * (log(2.30) - log(0.45));\n        double logAsp = log(0.45) + ur01(rng) * (log(2.20) - log(0.45));\n        double fac = exp(logFac);\n        double asp = exp(logAsp);\n\n        double prod = max(1.0, baseProduct * fac);\n        int gx = max(1, (int)llround(sqrt(prod * asp)));\n        int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n        while (gx + gy - 2 > K) {\n            if (gx > gy) gx--;\n            else gy--;\n        }\n\n        if (gx < 1 || gy < 1) continue;\n\n        double alphaX = alphaList[rng() % alphaList.size()];\n        double alphaY = alphaList[rng() % alphaList.size()];\n\n        vector<double> cu = random_dirichlet_cuts(gx, alphaX, rng);\n        vector<double> cv = random_dirichlet_cuts(gy, alphaY, rng);\n\n        double th = urTheta(rng);\n        try_grid(th, cu, cv);\n\n        // Occasionally try 3-direction random non-uniform lines.\n        if (iter % 13 == 0 && elapsed_sec() < 2.55) {\n            double hbase = sqrt(max(1.0, M / 3.0));\n            double sc = exp(log(0.55) + ur01(rng) * (log(1.65) - log(0.55)));\n            int g = max(2, min(34, (int)llround(hbase * sc)));\n\n            vector<Line> lines;\n            double th0 = ur01(rng) * PI / 3.0;\n            double alpha = alphaList[rng() % alphaList.size()];\n\n            for (int f = 0; f < 3; f++) {\n                double thf = th0 + f * PI / 3.0;\n                double a = cos(thf), b = sin(thf);\n                auto cuts = random_dirichlet_cuts(g, alpha, rng);\n                for (double c : cuts) lines.push_back({a, b, c});\n            }\n            try_lines(lines);\n        }\n    }\n\n    if (bestLines.empty()) {\n        // Fallback: simple 25x25 grid.\n        auto cu = uniform_cuts(25);\n        auto cv = uniform_cuts(25);\n        bestLines = build_grid_lines(0.0, cu, cv);\n    }\n\n    if ((int)bestLines.size() > K) bestLines.resize(K);\n\n    cout << bestLines.size() << '\\n';\n    for (const auto& ln : bestLines) {\n        auto e = line_to_integer_points(ln, forbiddenX, forbiddenY);\n        cout << e[0] << ' ' << e[1] << ' ' << e[2] << ' ' << e[3] << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 61;\n\nint N, M;\nint W[MAXN][MAXN];\nvector<pair<int,int>> initialDots;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int mod) {\n        if (mod <= 0) return 0;\n        return (int)(next() % mod);\n    }\n};\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nstruct State {\n    bool dot[MAXN][MAXN];\n    bool seg[4][MAXN][MAXN];\n    vector<Move> ops;\n    long long totalWeight;\n\n    void init() {\n        memset(dot, 0, sizeof(dot));\n        memset(seg, 0, sizeof(seg));\n        ops.clear();\n        ops.reserve(N * N);\n        totalWeight = 0;\n        for (auto [x, y] : initialDots) {\n            dot[x][y] = true;\n            totalWeight += W[x][y];\n        }\n    }\n\n    int segType(int x1, int y1, int x2, int y2, int &sx, int &sy) const {\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n        if (dy == 0) {\n            sx = min(x1, x2);\n            sy = y1;\n            return 0; // horizontal\n        }\n        if (dx == 0) {\n            sx = x1;\n            sy = min(y1, y2);\n            return 1; // vertical\n        }\n        if (dx == dy) {\n            sx = min(x1, x2);\n            sy = min(y1, y2);\n            return 2; // slope +1\n        }\n        sx = min(x1, x2);\n        sy = min(y1, y2);\n        return 3; // slope -1\n    }\n\n    bool unitUsed(int x1, int y1, int x2, int y2) const {\n        int sx, sy;\n        int t = segType(x1, y1, x2, y2, sx, sy);\n        return seg[t][sx][sy];\n    }\n\n    void markUnit(int x1, int y1, int x2, int y2) {\n        int sx, sy;\n        int t = segType(x1, y1, x2, y2, sx, sy);\n        seg[t][sx][sy] = true;\n    }\n\n    bool edgeFree(int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i < len; i++) {\n            int nx = x + dx;\n            int ny = y + dy;\n            if (unitUsed(x, y, nx, ny)) return false;\n            x = nx;\n            y = ny;\n        }\n        return true;\n    }\n\n    void markEdge(int ax, int ay, int bx, int by) {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i < len; i++) {\n            int nx = x + dx;\n            int ny = y + dy;\n            markUnit(x, y, nx, ny);\n            x = nx;\n            y = ny;\n        }\n    }\n\n    bool rectEdgesFree(const Move &m) const {\n        return edgeFree(m.x1, m.y1, m.x2, m.y2)\n            && edgeFree(m.x2, m.y2, m.x3, m.y3)\n            && edgeFree(m.x3, m.y3, m.x4, m.y4)\n            && edgeFree(m.x4, m.y4, m.x1, m.y1);\n    }\n\n    void apply(const Move &m) {\n        markEdge(m.x1, m.y1, m.x2, m.y2);\n        markEdge(m.x2, m.y2, m.x3, m.y3);\n        markEdge(m.x3, m.y3, m.x4, m.y4);\n        markEdge(m.x4, m.y4, m.x1, m.y1);\n\n        dot[m.x1][m.y1] = true;\n        totalWeight += W[m.x1][m.y1];\n        ops.push_back(m);\n    }\n};\n\nstruct Param {\n    int wcoef;\n    int pcoef;\n    int noise;\n};\n\nstruct Result {\n    long long score;\n    vector<Move> ops;\n};\n\nint dx8[8] = {1, 0, -1, 0, 1, -1, -1, 1};\nint dy8[8] = {0, 1, 0, -1, 1, 1, -1, -1};\n\n// Adjacent perpendicular direction pairs.\n// 0:E 1:N 2:W 3:S 4:NE 5:NW 6:SW 7:SE\npair<int,int> dirPairs[8] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0},\n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ninline int enc(int x, int y) {\n    return x * N + y;\n}\n\ninline int stepLen(int ax, int ay, int bx, int by) {\n    return max(abs(ax - bx), abs(ay - by));\n}\n\nResult simulate(const Param &param, uint64_t seed, const Timer &timer, double deadline) {\n    State st;\n    st.init();\n    XorShift rng(seed);\n\n    static short nearestDot[8][MAXN][MAXN];\n\n    while (true) {\n        if (timer.elapsed() > deadline) break;\n\n        // Build nearest visible dot table for 8 directions.\n        for (int d = 0; d < 8; d++) {\n            int xs = dx8[d] > 0 ? N - 1 : 0;\n            int xe = dx8[d] > 0 ? -1 : N;\n            int xi = dx8[d] > 0 ? -1 : 1;\n\n            int ys = dy8[d] > 0 ? N - 1 : 0;\n            int ye = dy8[d] > 0 ? -1 : N;\n            int yi = dy8[d] > 0 ? -1 : 1;\n\n            for (int x = xs; x != xe; x += xi) {\n                for (int y = ys; y != ye; y += yi) {\n                    int nx = x + dx8[d];\n                    int ny = y + dy8[d];\n                    if (!inside(nx, ny)) {\n                        nearestDot[d][x][y] = -1;\n                    } else if (st.dot[nx][ny]) {\n                        nearestDot[d][x][y] = enc(nx, ny);\n                    } else {\n                        nearestDot[d][x][y] = nearestDot[d][nx][ny];\n                    }\n                }\n            }\n        }\n\n        bool found = false;\n        long long bestEval = LLONG_MIN;\n        Move best{};\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                if (st.dot[x][y]) continue;\n\n                for (auto [d1, d2] : dirPairs) {\n                    int e2 = nearestDot[d1][x][y];\n                    int e4 = nearestDot[d2][x][y];\n                    if (e2 < 0 || e4 < 0) continue;\n\n                    int x2 = e2 / N, y2 = e2 % N;\n                    int x4 = e4 / N, y4 = e4 % N;\n\n                    int x3 = x2 + x4 - x;\n                    int y3 = y2 + y4 - y;\n                    if (!inside(x3, y3)) continue;\n                    if (!st.dot[x3][y3]) continue;\n\n                    int e3 = enc(x3, y3);\n                    if (nearestDot[d2][x2][y2] != e3) continue;\n                    if (nearestDot[d1][x4][y4] != e3) continue;\n\n                    Move mv{x, y, x2, y2, x3, y3, x4, y4};\n                    if (!st.rectEdgesFree(mv)) continue;\n\n                    int perim = stepLen(x, y, x2, y2)\n                              + stepLen(x2, y2, x3, y3)\n                              + stepLen(x3, y3, x4, y4)\n                              + stepLen(x4, y4, x, y);\n\n                    long long eval = 1LL * W[x][y] * param.wcoef\n                                   - 1LL * perim * param.pcoef\n                                   + rng.nextInt(param.noise);\n\n                    if (!found || eval > bestEval || (eval == bestEval && rng.nextInt(2))) {\n                        found = true;\n                        bestEval = eval;\n                        best = mv;\n                    }\n                }\n            }\n        }\n\n        if (!found) break;\n        st.apply(best);\n    }\n\n    return Result{st.totalWeight, st.ops};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    initialDots.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initialDots[i].first >> initialDots[i].second;\n    }\n\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            W[x][y] = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n        }\n    }\n\n    Timer timer;\n    const double DEADLINE = 4.75;\n\n    vector<Param> params = {\n        {1000,   0,      0},\n        {1000,  20,  20000},\n        {1000,  80,  50000},\n        {1000, 200, 100000},\n        {1000, -20,  50000},\n        {1000, -80, 100000},\n        {1000,   0, 200000},\n        {1000, 400, 200000},\n    };\n\n    Result best{-1, {}};\n\n    int run = 0;\n    while (timer.elapsed() < DEADLINE) {\n        Param p = params[run % params.size()];\n        uint64_t seed = 123456789ULL + 1000003ULL * run + 998244353ULL * N + M;\n        Result res = simulate(p, seed, timer, DEADLINE);\n\n        if (res.score > best.score) {\n            best = std::move(res);\n        }\n\n        run++;\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (const auto &m : best.ops) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed = 2463534242u) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n};\n\nusing Board = array<unsigned char, 100>;\n\nint F[101];\nint cntFlavor[4];\n\nint anchorR[4], anchorC[4];\nint distCell[4][100];\nint targetCell[100];\n\nconst int cornerR[4] = {0, 0, 9, 9};\nconst int cornerC[4] = {0, 9, 0, 9};\n\nchar dirChar[4] = {'F', 'B', 'L', 'R'};\n\nBoard tiltBoard(const Board& b, int dir) {\n    Board nb{};\n    nb.fill(0);\n\n    if (dir == 0) { // F\n        for (int c = 0; c < 10; c++) {\n            int w = 0;\n            for (int r = 0; r < 10; r++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w++ * 10 + c] = v;\n            }\n        }\n    } else if (dir == 1) { // B\n        for (int c = 0; c < 10; c++) {\n            int w = 9;\n            for (int r = 9; r >= 0; r--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w-- * 10 + c] = v;\n            }\n        }\n    } else if (dir == 2) { // L\n        for (int r = 0; r < 10; r++) {\n            int w = 0;\n            for (int c = 0; c < 10; c++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w++] = v;\n            }\n        }\n    } else { // R\n        for (int r = 0; r < 10; r++) {\n            int w = 9;\n            for (int c = 9; c >= 0; c--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w--] = v;\n            }\n        }\n    }\n\n    return nb;\n}\n\nvoid placeCandy(Board& b, int p, int flavor) {\n    int k = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            k++;\n            if (k == p) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n        }\n    }\n}\n\nlong long componentRawScore(const Board& b) {\n    bool vis[100] = {};\n    long long res = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int q[100];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n            int r = v / 10;\n            int c = v % 10;\n\n            const int dr[4] = {-1, 1, 0, 0};\n            const int dc[4] = {0, 0, -1, 1};\n\n            for (int d = 0; d < 4; d++) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= 10 || nc < 0 || nc >= 10) continue;\n                int ni = nr * 10 + nc;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        res += 1LL * sz * sz;\n    }\n\n    return res;\n}\n\nlong long evalBoard(const Board& b) {\n    bool vis[100] = {};\n    long long comp = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int q[100];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n            int r = v / 10;\n            int c = v % 10;\n\n            const int dr[4] = {-1, 1, 0, 0};\n            const int dc[4] = {0, 0, -1, 1};\n\n            for (int d = 0; d < 4; d++) {\n                int nr = r + dr[d];\n                int nc = c + dc[d];\n                if (nr < 0 || nr >= 10 || nc < 0 || nc >= 10) continue;\n                int ni = nr * 10 + nc;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        comp += 1LL * sz * sz;\n    }\n\n    int sameAdj = 0;\n    int diffAdj = 0;\n    int pref = 0;\n\n    for (int r = 0; r < 10; r++) {\n        for (int c = 0; c < 10; c++) {\n            int id = r * 10 + c;\n            int fl = b[id];\n            if (fl == 0) continue;\n\n            pref += 18 - distCell[fl][id];\n            if (targetCell[id] == fl) pref += 12;\n\n            if (r + 1 < 10) {\n                int fl2 = b[(r + 1) * 10 + c];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n            if (c + 1 < 10) {\n                int fl2 = b[r * 10 + c + 1];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n        }\n    }\n\n    return comp * 100 + sameAdj * 200 - diffAdj * 50 + pref * 30;\n}\n\nvoid buildTarget() {\n    for (int fl = 1; fl <= 3; fl++) {\n        for (int id = 0; id < 100; id++) {\n            int r = id / 10;\n            int c = id % 10;\n            distCell[fl][id] = abs(r - anchorR[fl]) + abs(c - anchorC[fl]);\n        }\n    }\n\n    fill(targetCell, targetCell + 100, 0);\n\n    struct Item {\n        int dist;\n        int fl;\n        int id;\n    };\n\n    vector<Item> items;\n    items.reserve(300);\n\n    for (int id = 0; id < 100; id++) {\n        for (int fl = 1; fl <= 3; fl++) {\n            items.push_back({distCell[fl][id], fl, id});\n        }\n    }\n\n    sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.fl != b.fl) return a.fl < b.fl;\n        return a.id < b.id;\n    });\n\n    int rem[4];\n    for (int fl = 1; fl <= 3; fl++) rem[fl] = cntFlavor[fl];\n\n    for (auto& it : items) {\n        if (targetCell[it.id] == 0 && rem[it.fl] > 0) {\n            targetCell[it.id] = it.fl;\n            rem[it.fl]--;\n        }\n    }\n}\n\nint choosePolicyDir(const Board& b) {\n    int bestDir = 0;\n    long long bestVal = LLONG_MIN;\n\n    for (int d = 0; d < 4; d++) {\n        Board nb = tiltBoard(b, d);\n        long long val = evalBoard(nb);\n        if (val > bestVal) {\n            bestVal = val;\n            bestDir = d;\n        }\n    }\n\n    return bestDir;\n}\n\nlong long simulatePolicyGame(uint32_t seed) {\n    XorShift rng(seed);\n    Board b{};\n    b.fill(0);\n\n    for (int t = 1; t <= 100; t++) {\n        int p = rng.randint(101 - t) + 1;\n        placeCandy(b, p, F[t]);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long simulateRollout(Board b, int nextT, uint32_t seed) {\n    XorShift rng(seed);\n\n    for (int t = nextT; t <= 100; t++) {\n        int p = rng.randint(101 - t) + 1;\n        placeCandy(b, p, F[t]);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nvoid selectCornerAssignment() {\n    double bestScore = -1.0;\n    int bestCorner[4] = {0, 0, 1, 2};\n\n    vector<uint32_t> seeds;\n    for (int i = 0; i < 5; i++) {\n        seeds.push_back(1234567u + i * 1000003u);\n    }\n\n    for (int mask = 0; mask < (1 << 4); mask++) {\n        if (__builtin_popcount((unsigned)mask) != 3) continue;\n\n        vector<int> cs;\n        for (int i = 0; i < 4; i++) {\n            if (mask >> i & 1) cs.push_back(i);\n        }\n\n        sort(cs.begin(), cs.end());\n        do {\n            for (int fl = 1; fl <= 3; fl++) {\n                int cid = cs[fl - 1];\n                anchorR[fl] = cornerR[cid];\n                anchorC[fl] = cornerC[cid];\n            }\n\n            buildTarget();\n\n            long long sum = 0;\n            for (uint32_t seed : seeds) {\n                sum += simulatePolicyGame(seed);\n            }\n\n            double avg = (double)sum / seeds.size();\n\n            if (avg > bestScore) {\n                bestScore = avg;\n                for (int fl = 1; fl <= 3; fl++) {\n                    bestCorner[fl] = cs[fl - 1];\n                }\n            }\n\n        } while (next_permutation(cs.begin(), cs.end()));\n    }\n\n    for (int fl = 1; fl <= 3; fl++) {\n        int cid = bestCorner[fl];\n        anchorR[fl] = cornerR[cid];\n        anchorC[fl] = cornerC[cid];\n    }\n\n    buildTarget();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    for (int i = 1; i <= 100; i++) {\n        cin >> F[i];\n        cntFlavor[F[i]]++;\n    }\n\n    selectCornerAssignment();\n\n    Board board{};\n    board.fill(0);\n\n    XorShift rolloutRng(987654321u);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        placeCandy(board, p, F[t]);\n\n        Board cand[4];\n        long long baseEval[4];\n\n        for (int d = 0; d < 4; d++) {\n            cand[d] = tiltBoard(board, d);\n            baseEval[d] = evalBoard(cand[d]);\n        }\n\n        int rem = 100 - t;\n        int maxSamples = 0;\n\n        if (rem > 0) {\n            if (rem > 75) maxSamples = 4;\n            else if (rem > 50) maxSamples = 7;\n            else if (rem > 25) maxSamples = 12;\n            else maxSamples = 25;\n        }\n\n        long long total[4] = {};\n        int samples = 0;\n\n        const double TIME_LIMIT = 1.85;\n\n        for (; samples < maxSamples; samples++) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > TIME_LIMIT) break;\n\n            uint32_t seed = rolloutRng.next();\n\n            for (int d = 0; d < 4; d++) {\n                total[d] += simulateRollout(cand[d], t + 1, seed);\n            }\n        }\n\n        int bestDir = 0;\n\n        if (samples > 0) {\n            long long bestTotal = LLONG_MIN;\n            for (int d = 0; d < 4; d++) {\n                if (total[d] > bestTotal ||\n                    (total[d] == bestTotal && baseEval[d] > baseEval[bestDir])) {\n                    bestTotal = total[d];\n                    bestDir = d;\n                }\n            }\n        } else {\n            long long bestVal = LLONG_MIN;\n            for (int d = 0; d < 4; d++) {\n                if (baseEval[d] > bestVal) {\n                    bestVal = baseEval[d];\n                    bestDir = d;\n                }\n            }\n        }\n\n        board = cand[bestDir];\n\n        cout << dirChar[bestDir] << endl;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\nusing Row = array<ull, 2>;\n\nstruct FastRNG {\n    uint64_t x;\n    FastRNG(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline bool getBitRow(const vector<Row>& rows, int i, int j) {\n    return (rows[i][j >> 6] >> (j & 63)) & 1ULL;\n}\nstatic inline void setBitRow(vector<Row>& rows, int i, int j) {\n    rows[i][j >> 6] |= 1ULL << (j & 63);\n    rows[j][i >> 6] |= 1ULL << (i & 63);\n}\nstatic inline void setBitVec(vector<ull>& v, int idx) {\n    v[idx >> 6] |= 1ULL << (idx & 63);\n}\nstatic inline int popcountXor(const vector<ull>& a, const vector<ull>& b) {\n    int s = 0;\n    for (size_t i = 0; i < a.size(); i++) s += __builtin_popcountll(a[i] ^ b[i]);\n    return s;\n}\n\nstruct Canon {\n    vector<ull> bits;\n    vector<int> degOrd;\n    vector<Row> rows;\n    string str;\n};\n\nCanon canonicalizeRows(const vector<Row>& rows, int N, bool needStr = true) {\n    int L = N * (N - 1) / 2;\n    int W = (L + 63) >> 6;\n\n    vector<int> deg(N, 0);\n    for (int i = 0; i < N; i++) {\n        deg[i] = __builtin_popcountll(rows[i][0]) + __builtin_popcountll(rows[i][1]);\n    }\n\n    vector<long long> nds(N, 0);\n    for (int i = 0; i < N; i++) {\n        long long s = 0;\n        for (int j = 0; j < N; j++) {\n            if (i != j && getBitRow(rows, i, j)) s += deg[j];\n        }\n        nds[i] = s;\n    }\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        if (nds[a] != nds[b]) return nds[a] < nds[b];\n        return a < b;\n    });\n\n    Canon c;\n    c.bits.assign(W, 0);\n    c.degOrd.resize(N);\n    c.rows.assign(N, Row{0ULL, 0ULL});\n    if (needStr) c.str.reserve(L);\n\n    int idx = 0;\n    for (int a = 0; a < N; a++) {\n        c.degOrd[a] = deg[ord[a]];\n        for (int b = a + 1; b < N; b++, idx++) {\n            bool e = getBitRow(rows, ord[a], ord[b]);\n            if (e) {\n                setBitVec(c.bits, idx);\n                setBitRow(c.rows, a, b);\n                if (needStr) c.str.push_back('1');\n            } else {\n                if (needStr) c.str.push_back('0');\n            }\n        }\n    }\n    return c;\n}\n\nstruct GraphCode {\n    vector<ull> bits;\n    vector<int> degOrd;\n    vector<Row> rows;\n    string out;\n};\n\nstruct Codebook {\n    int mode = 0; // 0: threshold/canonical, 1: edge count\n    int N = 4;\n    int M = 0;\n    double eps = 0.0;\n    double alpha = 0.0;\n\n    vector<GraphCode> code;\n    vector<string> edgeGraphs;\n    vector<int> edgeCnt;\n};\n\nGraphCode makeThresholdCandidate(int N, uint64_t mask, bool fromMask, FastRNG& rng) {\n    vector<Row> rows(N, Row{0ULL, 0ULL});\n    vector<int> bit(N, 0);\n\n    if (fromMask) {\n        for (int j = 1; j < N; j++) bit[j] = (mask >> (j - 1)) & 1ULL;\n    } else {\n        for (int j = 1; j < N; j++) bit[j] = rng.nextInt(2);\n    }\n\n    for (int j = 1; j < N; j++) {\n        if (bit[j]) {\n            for (int i = 0; i < j; i++) setBitRow(rows, i, j);\n        }\n    }\n\n    Canon c = canonicalizeRows(rows, N, true);\n\n    GraphCode g;\n    g.bits = std::move(c.bits);\n    g.degOrd = std::move(c.degOrd);\n    g.rows = std::move(c.rows);\n    g.out = std::move(c.str);\n    return g;\n}\n\nint candidateDistance(const GraphCode& a, const GraphCode& b) {\n    int ham = popcountXor(a.bits, b.bits);\n    int l1 = 0;\n    for (size_t i = 0; i < a.degOrd.size(); i++) {\n        l1 += abs(a.degOrd[i] - b.degOrd[i]);\n    }\n    return ham + l1;\n}\n\nCodebook generateThresholdBook(int M, double eps, int N, FastRNG& rng) {\n    int L = N * (N - 1) / 2;\n\n    vector<GraphCode> pool;\n    int targetK = max(220, 4 * M);\n    targetK = min(targetK, 500);\n\n    unordered_set<string> seen;\n    seen.reserve(targetK * 2 + 10);\n\n    if (N - 1 <= 12) {\n        uint64_t total = 1ULL << (N - 1);\n        for (uint64_t mask = 0; mask < total; mask++) {\n            auto g = makeThresholdCandidate(N, mask, true, rng);\n            if (seen.insert(g.out).second) pool.push_back(std::move(g));\n        }\n    } else {\n        int attempts = 0;\n        while ((int)pool.size() < targetK && attempts < targetK * 40) {\n            attempts++;\n            auto g = makeThresholdCandidate(N, 0, false, rng);\n            if (seen.insert(g.out).second) pool.push_back(std::move(g));\n        }\n    }\n\n    Codebook book;\n    book.mode = 0;\n    book.N = N;\n    book.M = M;\n    book.eps = eps;\n\n    double V = max(1e-9, (N - 1) * eps * (1.0 - eps));\n    double logodds = log((1.0 - eps) / eps);\n    book.alpha = min(0.08, 1.0 / max(1e-9, 2.0 * V * logodds));\n\n    if ((int)pool.size() < M) return book;\n\n    int K = (int)pool.size();\n    vector<char> used(K, 0);\n    vector<int> minD(K, INT_MAX);\n\n    int first = rng.nextInt(K);\n    for (int it = 0; it < M; it++) {\n        int best = -1;\n        if (it == 0) {\n            best = first;\n        } else {\n            int bestVal = -1;\n            for (int i = 0; i < K; i++) {\n                if (!used[i] && minD[i] > bestVal) {\n                    bestVal = minD[i];\n                    best = i;\n                }\n            }\n        }\n\n        used[best] = 1;\n        book.code.push_back(std::move(pool[best]));\n\n        for (int i = 0; i < K; i++) {\n            if (!used[i]) {\n                int d = candidateDistance(book.code.back(), pool[i]);\n                if (d < minD[i]) minD[i] = d;\n            }\n        }\n    }\n\n    return book;\n}\n\nCodebook generateEdgeBook(int M, double eps, int N) {\n    int L = N * (N - 1) / 2;\n\n    Codebook book;\n    book.mode = 1;\n    book.N = N;\n    book.M = M;\n    book.eps = eps;\n    book.edgeGraphs.resize(M);\n    book.edgeCnt.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        int e = (M == 1 ? 0 : (int)llround((long double)k * L / (M - 1)));\n        e = min(e, L);\n        book.edgeCnt[k] = e;\n        string s(L, '0');\n        for (int i = 0; i < e; i++) s[i] = '1';\n        book.edgeGraphs[k] = std::move(s);\n    }\n    return book;\n}\n\nint decodeRowsThreshold(const Codebook& book, const vector<Row>& rows) {\n    int N = book.N;\n    Canon h = canonicalizeRows(rows, N, false);\n\n    int best = 0;\n    double bestScore = 1e100;\n\n    for (int k = 0; k < book.M; k++) {\n        const auto& g = book.code[k];\n        int ham = popcountXor(h.bits, g.bits);\n\n        double sse = 0.0;\n        for (int i = 0; i < N; i++) {\n            double expected = book.eps * (N - 1) + (1.0 - 2.0 * book.eps) * g.degOrd[i];\n            double d = h.degOrd[i] - expected;\n            sse += d * d;\n        }\n\n        double score = ham + book.alpha * sse;\n        if (score < bestScore) {\n            bestScore = score;\n            best = k;\n        }\n    }\n\n    return best;\n}\n\nvector<Row> parseGraphRows(const string& s, int N) {\n    vector<Row> rows(N, Row{0ULL, 0ULL});\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++, idx++) {\n            if (s[idx] == '1') setBitRow(rows, i, j);\n        }\n    }\n    return rows;\n}\n\nint decodeString(const Codebook& book, const string& s) {\n    if (book.mode == 1) {\n        int m = 0;\n        for (char c : s) if (c == '1') m++;\n\n        int L = book.N * (book.N - 1) / 2;\n        int best = 0;\n        double bestDiff = 1e100;\n        for (int k = 0; k < book.M; k++) {\n            double expCnt = book.eps * L + (1.0 - 2.0 * book.eps) * book.edgeCnt[k];\n            double diff = abs(m - expCnt);\n            if (diff < bestDiff) {\n                bestDiff = diff;\n                best = k;\n            }\n        }\n        return best;\n    } else {\n        auto rows = parseGraphRows(s, book.N);\n        return decodeRowsThreshold(book, rows);\n    }\n}\n\nvector<Row> noisyPermutedRows(const GraphCode& g, int N, double eps, FastRNG& rng) {\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    for (int i = N - 1; i >= 1; i--) {\n        int j = rng.nextInt(i + 1);\n        swap(perm[i], perm[j]);\n    }\n\n    vector<Row> h(N, Row{0ULL, 0ULL});\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = getBitRow(g.rows, i, j);\n            if (rng.nextDouble() < eps) e = !e;\n            if (e) setBitRow(h, perm[i], perm[j]);\n        }\n    }\n    return h;\n}\n\nint simulateThresholdErrors(const Codebook& book, int T, FastRNG& rng) {\n    int err = 0;\n    for (int t = 0; t < T; t++) {\n        int s = rng.nextInt(book.M);\n        auto h = noisyPermutedRows(book.code[s], book.N, book.eps, rng);\n        int pred = decodeRowsThreshold(book, h);\n        if (pred != s) err++;\n    }\n    return err;\n}\n\nint simulateEdgeErrors(const Codebook& book, int T, FastRNG& rng) {\n    int L = book.N * (book.N - 1) / 2;\n    int err = 0;\n\n    for (int t = 0; t < T; t++) {\n        int s = rng.nextInt(book.M);\n        int e = book.edgeCnt[s];\n        int cnt = 0;\n\n        for (int i = 0; i < e; i++) {\n            bool bit = true;\n            if (rng.nextDouble() < book.eps) bit = !bit;\n            if (bit) cnt++;\n        }\n        for (int i = e; i < L; i++) {\n            bool bit = false;\n            if (rng.nextDouble() < book.eps) bit = !bit;\n            if (bit) cnt++;\n        }\n\n        int best = 0;\n        double bestDiff = 1e100;\n        for (int k = 0; k < book.M; k++) {\n            double expCnt = book.eps * L + (1.0 - 2.0 * book.eps) * book.edgeCnt[k];\n            double diff = abs(cnt - expCnt);\n            if (diff < bestDiff) {\n                bestDiff = diff;\n                best = k;\n            }\n        }\n        if (best != s) err++;\n    }\n    return err;\n}\n\nint ceilLog2Int(int x) {\n    int p = 1, r = 0;\n    while (p < x) p <<= 1, r++;\n    return r;\n}\n\nint minNForEdges(int M) {\n    for (int n = 4; n <= 100; n++) {\n        if (n * (n - 1) / 2 >= M - 1) return n;\n    }\n    return 100;\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    FastRNG rng(123456789ULL + M * 1009ULL + (int)llround(eps * 100) * 9176ULL);\n\n    Codebook bestBook;\n    double bestValue = -1.0;\n\n    if (eps < 1e-12) {\n        int N = minNForEdges(M);\n        bestBook = generateEdgeBook(M, eps, N);\n    } else {\n        int minTh = max(4, ceilLog2Int(M) + 1);\n        int low = max(minTh, (int)floor(4 + 0.15 * M + 20.0 * eps));\n        low = min(low, 100);\n\n        vector<int> Ns;\n        for (int n = low; n <= 100; n += 5) Ns.push_back(n);\n        if (Ns.empty() || Ns.back() != 100) Ns.push_back(100);\n\n        for (int N : Ns) {\n            Codebook book = generateThresholdBook(M, eps, N, rng);\n            if ((int)book.code.size() != M) continue;\n\n            int T = (M >= 80 ? 70 : 90);\n            int err = simulateThresholdErrors(book, T, rng);\n\n            double p = (err + 1.0) / (T + 2.0);\n            double value = exp(100.0 * log(max(1e-12, 1.0 - 0.1 * p))) / N;\n\n            if (value > bestValue) {\n                bestValue = value;\n                bestBook = std::move(book);\n            }\n        }\n\n        if (eps <= 0.12) {\n            int minE = minNForEdges(M);\n            for (int N = minE; N <= 100; N += 5) {\n                Codebook book = generateEdgeBook(M, eps, N);\n                int T = 180;\n                int err = simulateEdgeErrors(book, T, rng);\n\n                double p = (err + 1.0) / (T + 2.0);\n                double value = exp(100.0 * log(max(1e-12, 1.0 - 0.1 * p))) / N;\n\n                if (value > bestValue) {\n                    bestValue = value;\n                    bestBook = std::move(book);\n                }\n            }\n        }\n\n        if (bestValue < 0) {\n            bestBook = generateThresholdBook(M, eps, 100, rng);\n        }\n    }\n\n    cout << bestBook.N << '\\n';\n    if (bestBook.mode == 1) {\n        for (int k = 0; k < M; k++) cout << bestBook.edgeGraphs[k] << '\\n';\n    } else {\n        for (int k = 0; k < M; k++) cout << bestBook.code[k].out << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n        int ans = decodeString(bestBook, H);\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF = (1LL << 60);\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int root(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = root(a);\n        b = root(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    int mx, my;\n    ll len2;\n};\n\nstruct Adj {\n    int to, w, id;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<vector<Adj>> g;\nvector<int> X, Y;\nvector<int> degv;\nmt19937 rng(1234567);\n\nuint64_t morton_key(int x, int y) {\n    uint64_t r = 0;\n    for (int i = 0; i < 12; i++) {\n        r |= uint64_t((x >> i) & 1) << (2 * i);\n        r |= uint64_t((y >> i) & 1) << (2 * i + 1);\n    }\n    return r;\n}\n\nvoid dijkstra_fill(int s, const vector<int>* assign, int ban_day, vector<ll>& dist) {\n    fill(dist.begin(), dist.end(), INF);\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 [du, u] = pq.top();\n        pq.pop();\n        if (du != dist[u]) continue;\n        for (const auto& e : g[u]) {\n            if (assign && (*assign)[e.id] == ban_day) continue;\n            ll nd = du + e.w;\n            if (nd < dist[e.to]) {\n                dist[e.to] = nd;\n                pq.push({nd, e.to});\n            }\n        }\n    }\n}\n\nbool connected_day(const vector<int>& assign, int day) {\n    if (M - count(assign.begin(), assign.end(), day) < N - 1) return false;\n    DSU uf(N);\n    for (int i = 0; i < M; i++) {\n        if (assign[i] != day) uf.unite(edges[i].u, edges[i].v);\n    }\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n    return true;\n}\n\nbool all_connected(const vector<int>& assign) {\n    for (int d = 0; d < D; d++) {\n        if (!connected_day(assign, d)) return false;\n    }\n    return true;\n}\n\nbool can_add_removal_keep_connected(const vector<int>& assign, int day, int eid) {\n    DSU uf(N);\n    int rem = 0;\n    for (int i = 0; i < M; i++) {\n        if (assign[i] == day || i == eid) {\n            rem++;\n        } else {\n            uf.unite(edges[i].u, edges[i].v);\n        }\n    }\n    if (M - rem < N - 1) return false;\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n    return true;\n}\n\nvoid repair_isolated(vector<int>& assign) {\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n    for (int i = 0; i < M; i++) {\n        int d = assign[i];\n        load[d]++;\n        vc[edges[i].u][d]++;\n        vc[edges[i].v][d]++;\n    }\n\n    bool changed = true;\n    int loop = 0;\n    while (changed && loop++ < 20) {\n        changed = false;\n        for (int v = 0; v < N; v++) {\n            for (int d = 0; d < D; d++) {\n                if (vc[v][d] < degv[v]) continue;\n\n                int eid = -1;\n                for (auto& a : g[v]) {\n                    if (assign[a.id] == d) {\n                        eid = a.id;\n                        break;\n                    }\n                }\n                if (eid == -1) continue;\n\n                int u = edges[eid].u;\n                int w = edges[eid].v;\n                int best = -1;\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == d) continue;\n                    if (load[nd] >= K) continue;\n                    if (vc[u][nd] + 1 >= degv[u]) continue;\n                    if (vc[w][nd] + 1 >= degv[w]) continue;\n                    best = nd;\n                    break;\n                }\n                if (best == -1) {\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd != d && load[nd] < K) {\n                            best = nd;\n                            break;\n                        }\n                    }\n                }\n                if (best != -1) {\n                    assign[eid] = best;\n                    load[d]--;\n                    load[best]++;\n                    vc[u][d]--;\n                    vc[w][d]--;\n                    vc[u][best]++;\n                    vc[w][best]++;\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\nvoid repair_connectivity(vector<int>& assign, const Timer& timer, double limit_time) {\n    vector<int> load(D, 0);\n    for (int x : assign) load[x]++;\n\n    for (int iter = 0; iter < 200 && timer.elapsed() < limit_time; iter++) {\n        bool changed = false;\n\n        for (int day = 0; day < D && timer.elapsed() < limit_time; day++) {\n            DSU uf(N);\n            int rem = 0;\n            for (int i = 0; i < M; i++) {\n                if (assign[i] == day) rem++;\n                else uf.unite(edges[i].u, edges[i].v);\n            }\n            int r0 = uf.root(0);\n            bool ok = true;\n            for (int i = 1; i < N; i++) {\n                if (uf.root(i) != r0) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) continue;\n\n            vector<int> cand;\n            cand.reserve(rem);\n            for (int i = 0; i < M; i++) {\n                if (assign[i] == day && uf.root(edges[i].u) != uf.root(edges[i].v)) {\n                    cand.push_back(i);\n                }\n            }\n            shuffle(cand.begin(), cand.end(), rng);\n\n            bool moved = false;\n            for (int eid : cand) {\n                int best_day = -1;\n                int best_cost = INT_MAX;\n\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == day) continue;\n                    if (load[nd] >= K) continue;\n\n                    int cost = load[nd];\n                    if (!can_add_removal_keep_connected(assign, nd, eid)) {\n                        cost += 1000000;\n                    }\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_day = nd;\n                    }\n                }\n\n                if (best_day != -1) {\n                    assign[eid] = best_day;\n                    load[day]--;\n                    load[best_day]++;\n                    changed = true;\n                    moved = true;\n                    break;\n                }\n            }\n\n            if (moved) break;\n        }\n\n        if (!changed) break;\n        if (all_connected(assign)) break;\n    }\n}\n\nvector<int> make_order(int type) {\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    if (type == 0) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) < morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 1) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) > morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 2) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].mx != edges[b].mx) return edges[a].mx < edges[b].mx;\n            return edges[a].my < edges[b].my;\n        });\n    } else if (type == 3) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].my != edges[b].my) return edges[a].my < edges[b].my;\n            return edges[a].mx < edges[b].mx;\n        });\n    } else if (type == 4) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx + edges[a].my < edges[b].mx + edges[b].my;\n        });\n    } else if (type == 5) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx - edges[a].my < edges[b].mx - edges[b].my;\n        });\n    } else if (type == 6) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].len2 > edges[b].len2;\n        });\n    } else {\n        int A = uniform_int_distribution<int>(-1000, 1000)(rng);\n        int B = uniform_int_distribution<int>(-1000, 1000)(rng);\n        if (A == 0 && B == 0) A = 1;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ll va = 1LL * A * edges[a].mx + 1LL * B * edges[a].my;\n            ll vb = 1LL * A * edges[b].mx + 1LL * B * edges[b].my;\n            if (va != vb) return va < vb;\n            return a < b;\n        });\n    }\n    return ord;\n}\n\nvector<int> construct_cyclic(int type) {\n    vector<int> ord = make_order(type);\n    vector<int> perm(D);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n\n    int shift = uniform_int_distribution<int>(0, D - 1)(rng);\n    vector<int> assign(M);\n    for (int i = 0; i < M; i++) {\n        assign[ord[i]] = perm[(i + shift) % D];\n    }\n    repair_isolated(assign);\n    return assign;\n}\n\nvector<int> construct_greedy(int type) {\n    vector<int> ord;\n    if (type == 100) {\n        ord.resize(M);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n    } else {\n        ord = make_order(type);\n    }\n\n    vector<int> target(D, M / D);\n    for (int i = 0; i < M % D; i++) target[i]++;\n    shuffle(target.begin(), target.end(), rng);\n\n    vector<int> assign(M, -1);\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n\n    const int G = 18;\n    vector<vector<int>> cell(D, vector<int>(G * G, 0));\n\n    auto cid = [&](int eid) {\n        int cx = min(G - 1, max(0, edges[eid].mx * G / 2001));\n        int cy = min(G - 1, max(0, edges[eid].my * G / 2001));\n        return pair<int,int>(cx, cy);\n    };\n\n    for (int eid : ord) {\n        int u = edges[eid].u;\n        int v = edges[eid].v;\n        auto [cx, cy] = cid(eid);\n\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int pass = 0; pass < 2; pass++) {\n            best = -1;\n            best_cost = INT_MAX;\n\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= target[d]) continue;\n\n                if (pass == 0) {\n                    if (vc[u][d] + 1 >= degv[u]) continue;\n                    if (vc[v][d] + 1 >= degv[v]) continue;\n                }\n\n                int near = 0;\n                for (int dx = -1; dx <= 1; dx++) {\n                    for (int dy = -1; dy <= 1; dy++) {\n                        int nx = cx + dx;\n                        int ny = cy + dy;\n                        if (0 <= nx && nx < G && 0 <= ny && ny < G) {\n                            near += cell[d][nx * G + ny];\n                        }\n                    }\n                }\n\n                int cost = 0;\n                cost += (vc[u][d] + vc[v][d]) * 100000;\n                cost += near * 700;\n                cost += load[d] * 5;\n                cost += uniform_int_distribution<int>(0, 999)(rng);\n\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best = d;\n                }\n            }\n\n            if (best != -1) break;\n        }\n\n        if (best == -1) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] < target[d]) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n\n        assign[eid] = best;\n        load[best]++;\n        vc[u][best]++;\n        vc[v][best]++;\n        cell[best][cx * G + cy]++;\n    }\n\n    repair_isolated(assign);\n    return assign;\n}\n\nll evaluate_schedule(\n    const vector<int>& assign,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist\n) {\n    vector<int> load(D, 0);\n    for (int x : assign) {\n        if (x < 0 || x >= D) return (ll)4e18;\n        load[x]++;\n    }\n    for (int d = 0; d < D; d++) {\n        if (load[d] > K) return (ll)4e18;\n    }\n\n    // Connectivity is extremely important because unreachable pairs cost 1e9.\n    if (!all_connected(assign)) {\n        return (ll)3e18;\n    }\n\n    ll score = 0;\n    vector<ll> dist(N);\n\n    for (int day = 0; day < D; day++) {\n        for (int si = 0; si < S; si++) {\n            int s = sources[si];\n            dijkstra_fill(s, &assign, day, dist);\n            const auto& bd = base_dist[si];\n            for (int v = 0; v < N; v++) {\n                if (v == s) continue;\n                if (dist[v] >= INF / 2) {\n                    score += 1000000000LL - bd[v];\n                } else {\n                    score += dist[v] - bd[v];\n                }\n            }\n        }\n    }\n\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> D >> K;\n    edges.resize(M);\n    g.assign(N, {});\n    degv.assign(N, 0);\n\n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        g[u].push_back({v, w, i});\n        g[v].push_back({u, w, i});\n        degv[u]++;\n        degv[v]++;\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> X[i] >> Y[i];\n    }\n\n    for (int i = 0; i < M; i++) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        edges[i].mx = X[u] + X[v];\n        edges[i].my = Y[u] + Y[v];\n        ll dx = X[u] - X[v];\n        ll dy = Y[u] - Y[v];\n        edges[i].len2 = dx * dx + dy * dy;\n    }\n\n    vector<int> vertices(N);\n    iota(vertices.begin(), vertices.end(), 0);\n    shuffle(vertices.begin(), vertices.end(), rng);\n\n    int Smax = min(N, 96);\n    int Ssmall = min(Smax, (D >= 20 ? 24 : 32));\n    int Sfinal = min(Smax, 80);\n\n    vector<int> sources(vertices.begin(), vertices.begin() + Smax);\n\n    vector<vector<ll>> base_dist(Smax, vector<ll>(N));\n    for (int i = 0; i < Smax; i++) {\n        dijkstra_fill(sources[i], nullptr, -1, base_dist[i]);\n    }\n\n    vector<pair<ll, vector<int>>> top;\n\n    auto add_candidate = [&](vector<int> assign) {\n        if (!all_connected(assign) && timer.elapsed() < 4.8) {\n            repair_connectivity(assign, timer, 4.9);\n        }\n\n        ll sc = evaluate_schedule(assign, Ssmall, sources, base_dist);\n\n        if ((int)top.size() < 8) {\n            top.push_back({sc, assign});\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        } else if (sc < top.back().first) {\n            top.back() = {sc, assign};\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        }\n    };\n\n    // Deterministic initial candidates.\n    for (int t = 0; t < 10 && timer.elapsed() < 4.5; t++) {\n        add_candidate(construct_cyclic(t % 8));\n    }\n    for (int t = 0; t < 10 && timer.elapsed() < 4.5; t++) {\n        add_candidate(construct_greedy(t % 8));\n    }\n\n    int iter = 0;\n    while (timer.elapsed() < 4.9) {\n        vector<int> cand;\n        if (iter % 3 == 0) {\n            cand = construct_greedy(100);\n        } else if (iter % 3 == 1) {\n            cand = construct_greedy(8 + iter);\n        } else {\n            cand = construct_cyclic(8 + iter);\n        }\n        add_candidate(std::move(cand));\n        iter++;\n    }\n\n    if (top.empty()) {\n        vector<int> fallback(M);\n        for (int i = 0; i < M; i++) fallback[i] = i % D;\n        repair_isolated(fallback);\n        top.push_back({0, fallback});\n    }\n\n    vector<int> best = top[0].second;\n    ll best_score = top[0].first;\n\n    // Re-evaluate promising candidates with more samples.\n    for (auto& p : top) {\n        if (timer.elapsed() > 5.55) break;\n        ll sc = evaluate_schedule(p.second, Sfinal, sources, base_dist);\n        if (sc < best_score || best_score >= (ll)3e18) {\n            best_score = sc;\n            best = p.second;\n        }\n    }\n\n    // Final emergency repair if possible.\n    if (!all_connected(best) && timer.elapsed() < 5.75) {\n        repair_connectivity(best, timer, 5.85);\n    }\n\n    // Ensure capacity, though constructions should already satisfy it.\n    vector<int> load(D, 0);\n    for (int x : best) load[x]++;\n    for (int i = 0; i < M; i++) {\n        if (load[best[i]] <= K) continue;\n        for (int d = 0; d < D; d++) {\n            if (load[d] < K) {\n                load[best[i]]--;\n                best[i] = d;\n                load[d]++;\n                break;\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << best[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rod {\n    vector<int> cells;\n};\n\nstruct Candidate {\n    vector<Rod> rods;\n    vector<int> lens;\n    int volume = 0;\n};\n\nstruct Params {\n    int extra;\n    int contW;\n    int futW;\n    int randAmp;\n    uint32_t seed;\n};\n\nint D;\nstring f_[2][14], r_[2][14];\n\ninline int idx3(int x, int y, int z) {\n    return x * D * D + y * D + z;\n}\n\nvector<pair<int,int>> solve_min_edge_cover(\n    const vector<int>& X,\n    const vector<int>& Y,\n    int w[14][14]\n) {\n    int nx = (int)X.size();\n    int ny = (int)Y.size();\n    vector<pair<int,int>> res;\n\n    if (nx >= ny) {\n        int A = nx, B = ny;\n        int M = 1 << B;\n        const int NEG = -1e9;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> choice(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n        for (int t = 0; t < A; t++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[t]][Y[j]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[t + 1][nm] = mask;\n                        choice[t + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int t = A; t >= 1; t--) {\n            int j = choice[t][mask];\n            int old = pre[t][mask];\n            res.push_back({X[t - 1], Y[j]});\n            mask = old;\n        }\n    } else {\n        int A = ny, B = nx;\n        int M = 1 << B;\n        const int NEG = -1e9;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> choice(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n        for (int t = 0; t < A; t++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[j]][Y[t]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[t + 1][nm] = mask;\n                        choice[t + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int t = A; t >= 1; t--) {\n            int j = choice[t][mask];\n            int old = pre[t][mask];\n            res.push_back({X[j], Y[t - 1]});\n            mask = old;\n        }\n    }\n\n    return res;\n}\n\nCandidate build_candidate(int id, const Params& param) {\n    mt19937 rng(param.seed);\n\n    vector<char> occ(D * D * D, 0);\n    bool prev[14][14] = {};\n\n    for (int z = 0; z < D; z++) {\n        vector<int> X, Y;\n        for (int x = 0; x < D; x++) {\n            if (f_[id][z][x] == '1') X.push_back(x);\n        }\n        for (int y = 0; y < D; y++) {\n            if (r_[id][z][y] == '1') Y.push_back(y);\n        }\n\n        int w[14][14] = {};\n        for (int x : X) {\n            for (int y : Y) {\n                int val = 0;\n                if (prev[x][y]) val += param.contW;\n                if (z + 1 < D && f_[id][z + 1][x] == '1' && r_[id][z + 1][y] == '1') {\n                    val += param.futW;\n                }\n                if (param.randAmp > 0) val += (int)(rng() % param.randAmp);\n                w[x][y] = val;\n            }\n        }\n\n        auto base = solve_min_edge_cover(X, Y, w);\n\n        bool sel[14][14] = {};\n        int cnt = 0;\n        for (auto [x, y] : base) {\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        int maxEdges = (int)X.size() * (int)Y.size();\n        int target = min(maxEdges, max((int)X.size(), (int)Y.size()) + param.extra);\n\n        vector<tuple<int,int,int>> add;\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) continue;\n                int sc = 0;\n                if (prev[x][y]) sc += 100000;\n                if (z + 1 < D && f_[id][z + 1][x] == '1' && r_[id][z + 1][y] == '1') {\n                    sc += 10000;\n                }\n                sc += (int)(rng() % 1000);\n                add.push_back({sc, x, y});\n            }\n        }\n\n        sort(add.rbegin(), add.rend());\n        for (auto [sc, x, y] : add) {\n            if (cnt >= target) break;\n            sel[x][y] = true;\n            cnt++;\n        }\n\n        memset(prev, 0, sizeof(prev));\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) {\n                    occ[idx3(x, y, z)] = 1;\n                    prev[x][y] = true;\n                }\n            }\n        }\n    }\n\n    Candidate cand;\n\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            int z = 0;\n            while (z < D) {\n                if (!occ[idx3(x, y, z)]) {\n                    z++;\n                    continue;\n                }\n\n                Rod rod;\n                while (z < D && occ[idx3(x, y, z)]) {\n                    rod.cells.push_back(idx3(x, y, z));\n                    z++;\n                }\n\n                cand.volume += (int)rod.cells.size();\n                cand.lens.push_back((int)rod.cells.size());\n                cand.rods.push_back(move(rod));\n            }\n        }\n    }\n\n    return cand;\n}\n\nlong double eval_score(const Candidate& a, const Candidate& b) {\n    priority_queue<int> p, q;\n    for (int x : a.lens) p.push(x);\n    for (int x : b.lens) q.push(x);\n\n    long double score = 0;\n\n    for (int len = D; len >= 1; len--) {\n        while (!p.empty() && !q.empty() && p.top() >= len && q.top() >= len) {\n            int x = p.top(); p.pop();\n            int y = q.top(); q.pop();\n\n            score += 1.0L / len;\n\n            if (x - len > 0) p.push(x - len);\n            if (y - len > 0) q.push(y - len);\n        }\n    }\n\n    while (!p.empty()) {\n        score += p.top();\n        p.pop();\n    }\n    while (!q.empty()) {\n        score += q.top();\n        q.pop();\n    }\n\n    return score;\n}\n\nstruct Piece {\n    int len;\n    int rod;\n    int off;\n\n    bool operator<(const Piece& other) const {\n        if (len != other.len) return len < other.len;\n        if (rod != other.rod) return rod < other.rod;\n        return off < other.off;\n    }\n};\n\nvoid mark_piece(\n    vector<int>& arr,\n    const Candidate& cand,\n    const Piece& p,\n    int useLen,\n    int blockId\n) {\n    const Rod& rod = cand.rods[p.rod];\n    for (int i = 0; i < useLen; i++) {\n        arr[rod.cells[p.off + i]] = blockId;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D;\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) cin >> f_[i][z];\n        for (int z = 0; z < D; z++) cin >> r_[i][z];\n    }\n\n    vector<Params> params;\n    vector<int> extras = {0, 1, 2, 4, 7, 1000};\n\n    uint32_t baseSeed = 123456789;\n    for (int e : extras) {\n        for (int rep = 0; rep < 2; rep++) {\n            Params p;\n            p.extra = e;\n            p.contW = 1000;\n            p.futW = 100;\n            p.randAmp = 50;\n            p.seed = baseSeed + e * 1009 + rep * 9176;\n            params.push_back(p);\n        }\n    }\n\n    vector<Candidate> cand[2];\n    for (int id = 0; id < 2; id++) {\n        for (auto p : params) {\n            p.seed += id * 998244353u;\n            cand[id].push_back(build_candidate(id, p));\n        }\n    }\n\n    int bestA = 0, bestB = 0;\n    long double bestScore = 1e100L;\n\n    for (int i = 0; i < (int)cand[0].size(); i++) {\n        for (int j = 0; j < (int)cand[1].size(); j++) {\n            long double sc = eval_score(cand[0][i], cand[1][j]);\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestA = i;\n                bestB = j;\n            }\n        }\n    }\n\n    const Candidate& A = cand[0][bestA];\n    const Candidate& B = cand[1][bestB];\n\n    vector<int> out1(D * D * D, 0), out2(D * D * D, 0);\n\n    priority_queue<Piece> pq1, pq2;\n    for (int i = 0; i < (int)A.rods.size(); i++) {\n        pq1.push({(int)A.rods[i].cells.size(), i, 0});\n    }\n    for (int i = 0; i < (int)B.rods.size(); i++) {\n        pq2.push({(int)B.rods[i].cells.size(), i, 0});\n    }\n\n    int blockId = 0;\n\n    for (int len = D; len >= 1; len--) {\n        while (!pq1.empty() && !pq2.empty() && pq1.top().len >= len && pq2.top().len >= len) {\n            Piece a = pq1.top(); pq1.pop();\n            Piece b = pq2.top(); pq2.pop();\n\n            blockId++;\n            mark_piece(out1, A, a, len, blockId);\n            mark_piece(out2, B, b, len, blockId);\n\n            if (a.len - len > 0) {\n                pq1.push({a.len - len, a.rod, a.off + len});\n            }\n            if (b.len - len > 0) {\n                pq2.push({b.len - len, b.rod, b.off + len});\n            }\n        }\n    }\n\n    while (!pq1.empty()) {\n        Piece a = pq1.top(); pq1.pop();\n        blockId++;\n        mark_piece(out1, A, a, a.len, blockId);\n    }\n\n    while (!pq2.empty()) {\n        Piece b = pq2.top(); pq2.pop();\n        blockId++;\n        mark_piece(out2, B, b, b.len, blockId);\n    }\n\n    cout << blockId << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << out1[i];\n    }\n    cout << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << out2[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) x = p[x] = p[p[x]];\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstatic const long long INF = (1LL << 60);\n\nint N, M, K;\nvector<int> X, Y;\nvector<Edge> edges;\nvector<int> A, Bp;\n\nvector<vector<int>> cdist; // ceil euclidean distance station-resident\nvector<vector<pair<int,int>>> sortedRes;\n\nvector<vector<long long>> fw;\nvector<vector<int>> nxtv;\nvector<vector<int>> directEdge;\n\nchrono::steady_clock::time_point st_time;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st_time).count();\n}\n\nint ceil_sqrt_ll(long long x) {\n    long long r = sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r > 0 && (r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nvoid add_path_edges(int s, int t, vector<char>& sel) {\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n    }\n}\n\nlong long prune_and_cost(vector<char> sel, const vector<int>& P) {\n    vector<char> terminal(N, 0);\n    terminal[0] = 1;\n    for (int i = 0; i < N; i++) if (P[i] > 0) terminal[i] = 1;\n\n    vector<vector<pair<int,int>>> g(N);\n    vector<int> deg(N, 0);\n    for (int e = 0; e < M; e++) if (sel[e]) {\n        int u = edges[e].u, v = edges[e].v;\n        g[u].push_back({v, e});\n        g[v].push_back({u, e});\n        deg[u]++;\n        deg[v]++;\n    }\n\n    queue<int> q;\n    for (int i = 0; i < N; i++) {\n        if (!terminal[i] && deg[i] <= 1) q.push(i);\n    }\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (terminal[v] || deg[v] != 1) continue;\n\n        for (auto [to, eid] : g[v]) {\n            if (!sel[eid]) continue;\n            sel[eid] = 0;\n            deg[v]--;\n            deg[to]--;\n            if (!terminal[to] && deg[to] == 1) q.push(to);\n            break;\n        }\n    }\n\n    long long cost = 0;\n    for (int e = 0; e < M; e++) if (sel[e]) cost += edges[e].w;\n    return cost;\n}\n\npair<long long, vector<int>> build_best_tree(const vector<int>& P) {\n    long long bestCost = INF;\n    vector<int> bestB(M, 0);\n\n    auto consider = [&](vector<char> sel) {\n        vector<char> terminal(N, 0);\n        terminal[0] = 1;\n        for (int i = 0; i < N; i++) if (P[i] > 0) terminal[i] = 1;\n\n        vector<vector<pair<int,int>>> g(N);\n        vector<int> deg(N, 0);\n        for (int e = 0; e < M; e++) if (sel[e]) {\n            int u = edges[e].u, v = edges[e].v;\n            g[u].push_back({v, e});\n            g[v].push_back({u, e});\n            deg[u]++;\n            deg[v]++;\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (!terminal[i] && deg[i] <= 1) q.push(i);\n        }\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            if (terminal[v] || deg[v] != 1) continue;\n\n            for (auto [to, eid] : g[v]) {\n                if (!sel[eid]) continue;\n                sel[eid] = 0;\n                deg[v]--;\n                deg[to]--;\n                if (!terminal[to] && deg[to] == 1) q.push(to);\n                break;\n            }\n        }\n\n        long long cost = 0;\n        vector<int> B(M, 0);\n        for (int e = 0; e < M; e++) {\n            if (sel[e]) {\n                cost += edges[e].w;\n                B[e] = 1;\n            }\n        }\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestB = B;\n        }\n    };\n\n    // 1. MST on metric closure of terminals\n    {\n        vector<int> terms;\n        terms.push_back(0);\n        for (int i = 1; i < N; i++) if (P[i] > 0) terms.push_back(i);\n\n        vector<char> sel(M, 0);\n        int T = (int)terms.size();\n\n        if (T >= 2) {\n            vector<long long> minD(T, INF);\n            vector<int> par(T, -1);\n            vector<char> used(T, 0);\n            minD[0] = 0;\n\n            for (int it = 0; it < T; it++) {\n                int v = -1;\n                for (int i = 0; i < T; i++) {\n                    if (!used[i] && (v == -1 || minD[i] < minD[v])) v = i;\n                }\n                if (v == -1) break;\n                used[v] = 1;\n\n                if (par[v] != -1) {\n                    add_path_edges(terms[v], terms[par[v]], sel);\n                }\n\n                for (int to = 0; to < T; to++) {\n                    if (!used[to] && fw[terms[v]][terms[to]] < minD[to]) {\n                        minD[to] = fw[terms[v]][terms[to]];\n                        par[to] = v;\n                    }\n                }\n            }\n        }\n        consider(sel);\n    }\n\n    // 2. Union of shortest paths from root\n    {\n        vector<char> sel(M, 0);\n        for (int i = 1; i < N; i++) {\n            if (P[i] > 0) add_path_edges(0, i, sel);\n        }\n        consider(sel);\n    }\n\n    // 3. Ordinary graph MST, then prune\n    {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].w < edges[b].w;\n        });\n\n        DSU dsu(N);\n        vector<char> sel(M, 0);\n        for (int eid : ord) {\n            if (dsu.unite(edges[eid].u, edges[eid].v)) {\n                sel[eid] = 1;\n            }\n        }\n        consider(sel);\n    }\n\n    return {bestCost, bestB};\n}\n\nlong long total_cost(const vector<int>& P) {\n    long long radio = 0;\n    for (int p : P) radio += 1LL * p * p;\n    auto tr = build_best_tree(P);\n    return radio + tr.first;\n}\n\nbool compute_covered(const vector<int>& P, vector<char>& covered) {\n    covered.assign(K, 0);\n    int cnt = 0;\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                covered[k] = 1;\n                cnt++;\n                break;\n            }\n        }\n    }\n    return cnt == K;\n}\n\nvoid reduce_powers(vector<int>& P) {\n    vector<int> coverCnt(K, 0);\n    for (int i = 0; i < N; i++) if (P[i] > 0) {\n        for (int k = 0; k < K; k++) {\n            if (cdist[i][k] <= P[i]) coverCnt[k]++;\n        }\n    }\n\n    bool changed = true;\n    int loop = 0;\n    while (changed && loop < 10) {\n        loop++;\n        changed = false;\n\n        for (int i = 0; i < N; i++) {\n            int old = P[i];\n            if (old == 0) continue;\n\n            int req = 0;\n            for (int k = 0; k < K; k++) {\n                if (cdist[i][k] <= old && coverCnt[k] == 1) {\n                    req = max(req, cdist[i][k]);\n                }\n            }\n\n            if (req < old) {\n                for (int k = 0; k < K; k++) {\n                    if (cdist[i][k] <= old && cdist[i][k] > req) {\n                        coverCnt[k]--;\n                    }\n                }\n                P[i] = req;\n                changed = true;\n            }\n        }\n    }\n}\n\nbool greedy_complete(vector<int>& P, double alpha, int banned = -1) {\n    vector<char> covered(K, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; k++) {\n        bool ok = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                ok = true;\n                break;\n            }\n        }\n        covered[k] = ok;\n        if (!ok) uncovered++;\n    }\n\n    vector<double> connPen(N, 0.0);\n    for (int i = 0; i < N; i++) connPen[i] = alpha * (double)fw[0][i];\n\n    while (uncovered > 0) {\n        int bestI = -1, bestR = -1, bestGain = 0;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            if (i == banned) continue;\n\n            int old = P[i];\n            int gain = 0;\n            const auto& vec = sortedRes[i];\n\n            for (int idx = 0; idx < (int)vec.size();) {\n                int r = vec[idx].first;\n                if (r > 5000) break;\n\n                int add = 0;\n                while (idx < (int)vec.size() && vec[idx].first == r) {\n                    int k = vec[idx].second;\n                    if (r > old && !covered[k]) add++;\n                    idx++;\n                }\n\n                if (r <= old) continue;\n                gain += add;\n                if (gain > 0) {\n                    double delta = (double)r * r - (double)old * old;\n                    if (old == 0) delta += connPen[i];\n                    double score = delta / gain;\n\n                    if (score < bestScore ||\n                        (abs(score - bestScore) < 1e-9 && gain > bestGain)) {\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestGain = gain;\n                    }\n                }\n            }\n        }\n\n        if (bestI == -1) return false;\n\n        P[bestI] = bestR;\n        for (auto [r, k] : sortedRes[bestI]) {\n            if (r > bestR) break;\n            if (!covered[k]) {\n                covered[k] = 1;\n                uncovered--;\n            }\n        }\n    }\n\n    return true;\n}\n\nvector<int> initial_nearest_solution() {\n    vector<int> P(N, 0);\n    for (int k = 0; k < K; k++) {\n        int bi = -1;\n        int bd = 1e9;\n        for (int i = 0; i < N; i++) {\n            if (cdist[i][k] <= 5000 && cdist[i][k] < bd) {\n                bd = cdist[i][k];\n                bi = i;\n            }\n        }\n        if (bi == -1) {\n            for (int i = 0; i < N; i++) {\n                if (cdist[i][k] < bd) {\n                    bd = cdist[i][k];\n                    bi = i;\n                }\n            }\n        }\n        P[bi] = max(P[bi], bd);\n    }\n    reduce_powers(P);\n    return P;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st_time = chrono::steady_clock::now();\n\n    cin >> N >> M >> K;\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n        edges[i] = {u, v, w};\n    }\n\n    A.resize(K);\n    Bp.resize(K);\n    for (int k = 0; k < K; k++) cin >> A[k] >> Bp[k];\n\n    // Floyd-Warshall and path reconstruction\n    fw.assign(N, vector<long long>(N, INF));\n    nxtv.assign(N, vector<int>(N, -1));\n    directEdge.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; i++) {\n        fw[i][i] = 0;\n        nxtv[i][i] = i;\n    }\n\n    for (int e = 0; e < M; e++) {\n        int u = edges[e].u, v = edges[e].v;\n        long long w = edges[e].w;\n        if (w < fw[u][v]) {\n            fw[u][v] = fw[v][u] = w;\n            nxtv[u][v] = v;\n            nxtv[v][u] = u;\n            directEdge[u][v] = directEdge[v][u] = e;\n        }\n    }\n\n    for (int k = 0; k < N; k++) {\n        for (int i = 0; i < N; i++) if (fw[i][k] < INF) {\n            for (int j = 0; j < N; j++) if (fw[k][j] < INF) {\n                long long nd = fw[i][k] + fw[k][j];\n                if (nd < fw[i][j]) {\n                    fw[i][j] = nd;\n                    nxtv[i][j] = nxtv[i][k];\n                }\n            }\n        }\n    }\n\n    // Station-resident distances\n    cdist.assign(N, vector<int>(K));\n    sortedRes.assign(N, {});\n\n    for (int i = 0; i < N; i++) {\n        sortedRes[i].reserve(K);\n        for (int k = 0; k < K; k++) {\n            long long dx = X[i] - A[k];\n            long long dy = Y[i] - Bp[k];\n            int d = ceil_sqrt_ll(dx * dx + dy * dy);\n            cdist[i][k] = d;\n            if (d <= 5000) sortedRes[i].push_back({d, k});\n        }\n        sort(sortedRes[i].begin(), sortedRes[i].end());\n    }\n\n    vector<int> bestP = initial_nearest_solution();\n    long long bestS = total_cost(bestP);\n    double bestAlpha = 0.2;\n\n    vector<double> alphas = {0.0, 0.03, 0.07, 0.12, 0.2, 0.35, 0.6, 1.0, 1.7};\n\n    for (double alpha : alphas) {\n        if (elapsed_sec() > 1.25) break;\n\n        vector<int> P(N, 0);\n        bool ok = greedy_complete(P, alpha, -1);\n        if (!ok) continue;\n\n        reduce_powers(P);\n        long long S = total_cost(P);\n\n        if (S < bestS) {\n            bestS = S;\n            bestP = P;\n            bestAlpha = alpha;\n        }\n    }\n\n    // Local search: remove one active station and repair coverage\n    double repairAlpha = max(0.12, min(0.6, bestAlpha));\n\n    while (elapsed_sec() < 1.82) {\n        bool improved = false;\n        vector<int> candBestP;\n        long long candBestS = bestS;\n\n        vector<int> active;\n        for (int i = 0; i < N; i++) if (bestP[i] > 0) active.push_back(i);\n\n        sort(active.begin(), active.end(), [&](int a, int b) {\n            return bestP[a] < bestP[b];\n        });\n\n        for (int rem : active) {\n            if (elapsed_sec() > 1.86) break;\n\n            vector<int> P = bestP;\n            P[rem] = 0;\n\n            if (!greedy_complete(P, repairAlpha, rem)) continue;\n            reduce_powers(P);\n\n            long long S = total_cost(P);\n            if (S < candBestS) {\n                candBestS = S;\n                candBestP = P;\n                improved = true;\n            }\n        }\n\n        if (improved) {\n            bestS = candBestS;\n            bestP = candBestP;\n        } else {\n            break;\n        }\n    }\n\n    // Safety repair\n    vector<char> covered;\n    if (!compute_covered(bestP, covered)) {\n        greedy_complete(bestP, 0.0, -1);\n        reduce_powers(bestP);\n    }\n\n    auto tree = build_best_tree(bestP);\n    vector<int> ansB = tree.second;\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n\n    for (int e = 0; e < M; e++) {\n        if (e) cout << ' ';\n        cout << ansB[e];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = N * (N + 1) / 2;\n\nstruct Op {\n    int u, v;\n};\n\nint ID[N][N];\nint X[M], Y[M];\n\nvector<pair<int,int>> adjEdges; // all 6-neighbour undirected edges, once\nvector<pair<int,int>> downEdges; // directed condition edges: parent -> child\nvector<vector<int>> incidentDown; // down-edge indices incident to each vertex\n\narray<int, M> initialA;\nint initialE;\n\nint calcE(const array<int, M>& a) {\n    int e = 0;\n    for (auto [p, c] : downEdges) if (a[p] > a[c]) e++;\n    return e;\n}\n\nstruct State {\n    array<int, M> a;\n    vector<Op> ops;\n    int E = 0;\n};\n\nint deltaSwapLocal(const array<int, M>& a, int u, int v) {\n    int ids[16], cnt = 0;\n    auto add = [&](int e) {\n        for (int i = 0; i < cnt; i++) if (ids[i] == e) return;\n        ids[cnt++] = e;\n    };\n    for (int e : incidentDown[u]) add(e);\n    for (int e : incidentDown[v]) add(e);\n\n    int before = 0, after = 0;\n    for (int k = 0; k < cnt; k++) {\n        auto [p, c] = downEdges[ids[k]];\n        before += (a[p] > a[c]);\n\n        int vp = (p == u ? a[v] : (p == v ? a[u] : a[p]));\n        int vc = (c == u ? a[v] : (c == v ? a[u] : a[c]));\n        after += (vp > vc);\n    }\n    // positive means E decreases\n    return before - after;\n}\n\nvoid applySwap(State& s, int u, int v) {\n    int d = deltaSwapLocal(s.a, u, v);\n    s.E -= d;\n    swap(s.a[u], s.a[v]);\n    s.ops.push_back({u, v});\n}\n\nvector<int> yOrder(int x, int type) {\n    vector<int> ys;\n    for (int y = 0; y <= x; y++) ys.push_back(y);\n\n    if (type == 1) {\n        reverse(ys.begin(), ys.end());\n    } else if (type == 2) {\n        if (x & 1) reverse(ys.begin(), ys.end());\n    } else if (type == 3) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da < db;\n            return a < b;\n        });\n    }\n    return ys;\n}\n\n// Floyd-like heap construction on the triangular heap.\nState runHeapify(State s, int yType) {\n    for (int x = N - 2; x >= 0; x--) {\n        auto ys = yOrder(x, yType);\n        for (int sy : ys) {\n            int cx = x, cy = sy;\n            int cur = ID[cx][cy];\n\n            while (cx + 1 < N) {\n                int c1 = ID[cx + 1][cy];\n                int c2 = ID[cx + 1][cy + 1];\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[cur] > s.a[ch]) {\n                    applySwap(s, cur, ch);\n                    cur = ch;\n                    cx = X[cur];\n                    cy = Y[cur];\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n    return s;\n}\n\n// One-step repeated bubbling.\nState runScanBubble(State s, int rowType, int yType, int limitOps) {\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        bool changed = false;\n\n        vector<int> rows;\n        if (rowType == 0) {\n            for (int x = N - 2; x >= 0; x--) rows.push_back(x);\n        } else {\n            for (int x = 0; x <= N - 2; x++) rows.push_back(x);\n        }\n\n        for (int x : rows) {\n            auto ys = yOrder(x, yType);\n            for (int y : ys) {\n                if ((int)s.ops.size() >= limitOps) break;\n\n                int p = ID[x][y];\n                int c1 = ID[x + 1][y];\n                int c2 = ID[x + 1][y + 1];\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[p] > s.a[ch]) {\n                    applySwap(s, p, ch);\n                    changed = true;\n                }\n            }\n        }\n\n        if (!changed) break;\n    }\n    return s;\n}\n\n// Greedy among currently violating parent-child edges.\nState runViolationGreedy(State s, int mode, int limitOps) {\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        int bu = -1, bv = -1;\n        long long bk1 = LLONG_MIN, bk2 = LLONG_MIN, bk3 = LLONG_MIN;\n\n        for (auto [p, c] : downEdges) {\n            if (s.a[p] <= s.a[c]) continue;\n\n            int imp = deltaSwapLocal(s.a, p, c);\n            int diff = s.a[p] - s.a[c];\n\n            long long k1, k2, k3;\n            if (mode == 0) {\n                k1 = imp;\n                k2 = diff;\n                k3 = -X[p];\n            } else if (mode == 1) {\n                k1 = diff;\n                k2 = imp;\n                k3 = -X[p];\n            } else if (mode == 2) {\n                k1 = -s.a[c]; // smaller child value first\n                k2 = imp;\n                k3 = diff;\n            } else {\n                k1 = -X[p]; // upper violations first\n                k2 = imp;\n                k3 = diff;\n            }\n\n            if (k1 > bk1 || (k1 == bk1 && (k2 > bk2 || (k2 == bk2 && k3 > bk3)))) {\n                bk1 = k1;\n                bk2 = k2;\n                bk3 = k3;\n                bu = p;\n                bv = c;\n            }\n        }\n\n        if (bu == -1) break;\n        applySwap(s, bu, bv);\n    }\n    return s;\n}\n\nvector<Op> reduceOps(const vector<Op>& ops) {\n    vector<Op> st;\n    st.reserve(ops.size());\n\n    auto sameEdge = [](const Op& a, const Op& b) {\n        return (a.u == b.u && a.v == b.v) || (a.u == b.v && a.v == b.u);\n    };\n\n    for (auto op : ops) {\n        if (!st.empty() && sameEdge(st.back(), op)) {\n            st.pop_back();\n        } else {\n            st.push_back(op);\n        }\n    }\n    return st;\n}\n\nbool validateOps(const vector<Op>& ops) {\n    if ((int)ops.size() > 10000) return false;\n\n    array<int, M> a = initialA;\n    for (auto [u, v] : ops) {\n        bool ok = false;\n        for (auto [x, y] : adjEdges) {\n            if ((x == u && y == v) || (x == v && y == u)) {\n                ok = true;\n                break;\n            }\n        }\n        if (!ok) return false;\n        swap(a[u], a[v]);\n    }\n    return calcE(a) == 0;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int id = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            ID[x][y] = id;\n            X[id] = x;\n            Y[id] = y;\n            id++;\n        }\n    }\n\n    incidentDown.assign(M, {});\n\n    // Build edges.\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int u = ID[x][y];\n\n            // horizontal\n            if (y + 1 <= x) {\n                int v = ID[x][y + 1];\n                adjEdges.push_back({u, v});\n            }\n\n            // downward two neighbours\n            if (x + 1 < N) {\n                int v1 = ID[x + 1][y];\n                int v2 = ID[x + 1][y + 1];\n\n                adjEdges.push_back({u, v1});\n                adjEdges.push_back({u, v2});\n\n                int e1 = (int)downEdges.size();\n                downEdges.push_back({u, v1});\n                incidentDown[u].push_back(e1);\n                incidentDown[v1].push_back(e1);\n\n                int e2 = (int)downEdges.size();\n                downEdges.push_back({u, v2});\n                incidentDown[u].push_back(e2);\n                incidentDown[v2].push_back(e2);\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> initialA[ID[x][y]];\n        }\n    }\n\n    initialE = calcE(initialA);\n\n    State base;\n    base.a = initialA;\n    base.E = initialE;\n\n    vector<Op> bestOps;\n    bool haveBest = false;\n\n    auto tryCandidate = [&](const State& s) {\n        if (s.E != 0) return;\n\n        vector<Op> ops = reduceOps(s.ops);\n        if ((int)ops.size() > 10000) return;\n\n        // Validation is cheap here and protects against bugs in reduction.\n        if (!validateOps(ops)) return;\n\n        if (!haveBest || ops.size() < bestOps.size()) {\n            bestOps = move(ops);\n            haveBest = true;\n        }\n    };\n\n    // 1. Guaranteed candidates: triangular heapify with several row orders.\n    for (int t = 0; t < 4; t++) {\n        State s = runHeapify(base, t);\n        tryCandidate(s);\n    }\n\n    // Fallback should already exist, but keep safety.\n    if (!haveBest) {\n        State s = runHeapify(base, 0);\n        bestOps = s.ops;\n        haveBest = true;\n    }\n\n    int bestLimit = min(10000, (int)bestOps.size() - 1);\n\n    // 2. Repeated one-step bubble variants.\n    if (bestLimit > 0) {\n        for (int rowType = 0; rowType < 2; rowType++) {\n            for (int yType = 0; yType < 4; yType++) {\n                State s = runScanBubble(base, rowType, yType, bestLimit);\n                tryCandidate(s);\n                bestLimit = min(10000, (int)bestOps.size() - 1);\n                if (bestLimit <= 0) break;\n            }\n            if (bestLimit <= 0) break;\n        }\n    }\n\n    // 3. Greedy among violating vertical edges.\n    bestLimit = min(10000, (int)bestOps.size() - 1);\n    if (bestLimit > 0) {\n        for (int mode = 0; mode < 4; mode++) {\n            State s = runViolationGreedy(base, mode, bestLimit);\n            tryCandidate(s);\n            bestLimit = min(10000, (int)bestOps.size() - 1);\n            if (bestLimit <= 0) break;\n        }\n    }\n\n    // 4. Prefix of local E-reducing swaps over all adjacent edges,\n    //    periodically completed by heapify.\n    bestLimit = min(10000, (int)bestOps.size() - 1);\n    if (bestLimit > 0) {\n        State cur = base;\n        int maxSteps = min(700, bestLimit);\n\n        for (int step = 1; step <= maxSteps; step++) {\n            int bu = -1, bv = -1;\n            int bestImp = 0;\n            long long bestPot = LLONG_MIN;\n            int bestDiff = -1;\n\n            for (auto [u, v] : adjEdges) {\n                int imp = deltaSwapLocal(cur.a, u, v);\n                if (imp <= 0) continue;\n\n                long long pot =\n                    1LL * (X[v] - X[u]) * (cur.a[u] - cur.a[v]);\n                int diff = abs(cur.a[u] - cur.a[v]);\n\n                if (imp > bestImp ||\n                    (imp == bestImp &&\n                     (pot > bestPot || (pot == bestPot && diff > bestDiff)))) {\n                    bestImp = imp;\n                    bestPot = pot;\n                    bestDiff = diff;\n                    bu = u;\n                    bv = v;\n                }\n            }\n\n            if (bu == -1) break;\n\n            applySwap(cur, bu, bv);\n\n            if (cur.E == 0) {\n                tryCandidate(cur);\n                break;\n            }\n\n            if (step <= 30 || step % 20 == 0 || step == maxSteps) {\n                for (int t = 0; t < 4; t++) {\n                    State completed = runHeapify(cur, t);\n                    tryCandidate(completed);\n                }\n                bestLimit = min(10000, (int)bestOps.size() - 1);\n                if ((int)cur.ops.size() >= bestLimit) break;\n            }\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n    for (auto [u, v] : bestOps) {\n        cout << X[u] << ' ' << Y[u] << ' ' << X[v] << ' ' << Y[v] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D, N;\nint ENT;\nvector<int> freeIds;\nbool obstacleCell[100];\nint labelAt[100]; // -1 empty, >=0 occupied label\nint rankOfCell[100];\nbool usedLabel[100];\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nint id_of(int r, int c) {\n    return r * D + c;\n}\n\npair<int,int> rc_of(int id) {\n    return {id / D, id % D};\n}\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nvector<int> neighbors(int id) {\n    auto [r, c] = rc_of(id);\n    vector<int> res;\n    for (int k = 0; k < 4; k++) {\n        int nr = r + dr[k], nc = c + dc[k];\n        if (inside(nr, nc)) res.push_back(id_of(nr, nc));\n    }\n    return res;\n}\n\n// Check whether filling cand keeps all remaining empty cells reachable from entrance.\nbool legal_fill(int cand) {\n    int totalEmptyAfter = 0;\n    for (int id : freeIds) {\n        if (id != cand && labelAt[id] == -1) totalEmptyAfter++;\n    }\n\n    queue<int> q;\n    bool vis[100] = {};\n    vis[ENT] = true;\n    q.push(ENT);\n\n    int reached = 0;\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int to : neighbors(v)) {\n            if (vis[to]) continue;\n            if (obstacleCell[to]) continue;\n            if (to == cand) continue;\n            if (to != ENT && labelAt[to] != -1) continue;\n\n            vis[to] = true;\n            q.push(to);\n            if (to != ENT) reached++;\n        }\n    }\n\n    return reached == totalEmptyAfter;\n}\n\nbool is_accessible_container(int id, const bool emptyCell[]) {\n    for (int to : neighbors(id)) {\n        if (emptyCell[to]) return true;\n    }\n    return false;\n}\n\n// Estimate final inversions if current arriving label t is placed at cand.\n// Future labels are optimistically assigned to remaining empty cells in rank order.\nint evaluate_candidate(\n    int cand,\n    int t,\n    const vector<int>& emptySorted,\n    const vector<int>& remLabels\n) {\n    int val[100];\n    fill(val, val + 100, -1);\n\n    for (int id : freeIds) {\n        if (labelAt[id] >= 0) val[id] = labelAt[id];\n    }\n    val[cand] = t;\n\n    int p = 0;\n    for (int id : emptySorted) {\n        if (id == cand) continue;\n        val[id] = remLabels[p++];\n    }\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    vector<int> seq;\n    seq.reserve(freeIds.size());\n\n    for (int step = 0; step < (int)freeIds.size(); step++) {\n        int best = -1;\n        int bestVal = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (val[id] < bestVal ||\n                (val[id] == bestVal && rankOfCell[id] < rankOfCell[best])) {\n                bestVal = val[id];\n                best = id;\n            }\n        }\n\n        // Should never happen if the graph is connected.\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    bestVal = val[id];\n                    break;\n                }\n            }\n        }\n\n        seq.push_back(bestVal);\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    int inv = 0;\n    int M = seq.size();\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (seq[i] > seq[j]) inv++;\n        }\n    }\n    return inv;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    ENT = id_of(0, (D - 1) / 2);\n\n    fill(obstacleCell, obstacleCell + 100, false);\n    fill(labelAt, labelAt + 100, -1);\n    fill(usedLabel, usedLabel + 100, false);\n\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        obstacleCell[id_of(r, c)] = true;\n    }\n\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            int id = id_of(r, c);\n            if (id == ENT) continue;\n            if (obstacleCell[id]) continue;\n            freeIds.push_back(id);\n        }\n    }\n\n    int M = freeIds.size();\n\n    // Compute BFS distance from entrance.\n    const int INF = 1e9;\n    vector<int> dist(D * D, INF);\n    queue<int> q;\n    dist[ENT] = 0;\n    q.push(ENT);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int to : neighbors(v)) {\n            if (obstacleCell[to]) continue;\n            if (dist[to] != INF) continue;\n            dist[to] = dist[v] + 1;\n            q.push(to);\n        }\n    }\n\n    int center = (D - 1) / 2;\n\n    sort(freeIds.begin(), freeIds.end(), [&](int a, int b) {\n        auto [ra, ca] = rc_of(a);\n        auto [rb, cb] = rc_of(b);\n\n        tuple<int,int,int,int> ka = {\n            dist[a],\n            abs(ca - center),\n            ra,\n            ca\n        };\n        tuple<int,int,int,int> kb = {\n            dist[b],\n            abs(cb - center),\n            rb,\n            cb\n        };\n        return ka < kb;\n    });\n\n    for (int i = 0; i < M; i++) {\n        rankOfCell[freeIds[i]] = i;\n    }\n\n    // Arrival phase.\n    for (int step = 0; step < M; step++) {\n        int t;\n        cin >> t;\n\n        vector<int> emptySorted;\n        for (int id : freeIds) {\n            if (labelAt[id] == -1) emptySorted.push_back(id);\n        }\n        sort(emptySorted.begin(), emptySorted.end(), [&](int a, int b) {\n            return rankOfCell[a] < rankOfCell[b];\n        });\n\n        vector<int> remLabels;\n        for (int x = 0; x < M; x++) {\n            if (!usedLabel[x] && x != t) remLabels.push_back(x);\n        }\n\n        vector<int> legal;\n        for (int id : emptySorted) {\n            if (legal_fill(id)) legal.push_back(id);\n        }\n\n        // Fallback, should not be needed.\n        if (legal.empty()) {\n            legal = emptySorted;\n        }\n\n        int bestCell = legal[0];\n        long long bestScore = (1LL << 60);\n\n        for (int cand : legal) {\n            int inv = evaluate_candidate(cand, t, emptySorted, remLabels);\n\n            long long mismatch = abs(rankOfCell[cand] - t);\n            long long score = inv * 1000LL + mismatch;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestCell = cand;\n            }\n        }\n\n        labelAt[bestCell] = t;\n        usedLabel[t] = true;\n\n        auto [r, c] = rc_of(bestCell);\n        cout << r << ' ' << c << endl; // endl flushes\n    }\n\n    // Removal phase: always remove the smallest currently reachable label.\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    for (int step = 0; step < M; step++) {\n        int best = -1;\n        int bestLabel = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (labelAt[id] < bestLabel) {\n                bestLabel = labelAt[id];\n                best = id;\n            }\n        }\n\n        // Should not happen.\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    break;\n                }\n            }\n        }\n\n        auto [r, c] = rc_of(best);\n        cout << r << ' ' << c << '\\n';\n\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXC = 101;\nstatic const int INF = 1e9;\n\nint n, m;\nbool allowedAdj[MAXC][MAXC];\n\nstruct State {\n    vector<vector<int>> g;\n    int cnt[MAXC]{};\n    int edgeCnt[MAXC][MAXC]{};\n\n    int stamp[MAXN][MAXN]{};\n    int curStamp = 1;\n\n    State() {\n        g.assign(n, vector<int>(n, 0));\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(stamp, 0, sizeof(stamp));\n    }\n\n    static void norm(int &a, int &b) {\n        if (a > b) swap(a, b);\n    }\n\n    void addEdgeCount(int a, int b, int v) {\n        if (a == b) return;\n        norm(a, b);\n        edgeCnt[a][b] += v;\n    }\n\n    void init(const vector<vector<int>> &src) {\n        g = src;\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                cnt[g[i][j]]++;\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = g[i][j];\n\n                if (i == 0) addEdgeCount(c, 0, 1);\n                if (i == n - 1) addEdgeCount(c, 0, 1);\n                if (j == 0) addEdgeCount(c, 0, 1);\n                if (j == n - 1) addEdgeCount(c, 0, 1);\n\n                if (i + 1 < n) addEdgeCount(c, g[i + 1][j], 1);\n                if (j + 1 < n) addEdgeCount(c, g[i][j + 1], 1);\n            }\n        }\n    }\n\n    bool inside(int r, int c) const {\n        return 0 <= r && r < n && 0 <= c && c < n;\n    }\n\n    bool adjacentZeroOrOutside(int r, int c) const {\n        if (r == 0 || r == n - 1 || c == 0 || c == n - 1) return true;\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == 0) return true;\n        }\n        return false;\n    }\n\n    bool oldColorConnectedAfterRemoval(int r, int c, int col) {\n        vector<pair<int, int>> starts;\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) {\n                starts.push_back({nr, nc});\n            }\n        }\n\n        if (starts.size() <= 1) return true;\n\n        curStamp++;\n        if (curStamp == INT_MAX) {\n            memset(stamp, 0, sizeof(stamp));\n            curStamp = 1;\n        }\n\n        queue<pair<int, int>> q;\n        q.push(starts[0]);\n        stamp[starts[0].first][starts[0].second] = curStamp;\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dr[k], ny = y + dc[k];\n                if (!inside(nx, ny)) continue;\n                if (nx == r && ny == c) continue;\n                if (stamp[nx][ny] == curStamp) continue;\n                if (g[nx][ny] != col) continue;\n\n                stamp[nx][ny] = curStamp;\n                q.push({nx, ny});\n            }\n        }\n\n        for (auto [x, y] : starts) {\n            if (stamp[x][y] != curStamp) return false;\n        }\n        return true;\n    }\n\n    struct Delta {\n        int a, b, d;\n    };\n\n    void addDelta(vector<Delta> &ds, int a, int b, int d) const {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n\n        for (auto &x : ds) {\n            if (x.a == a && x.b == b) {\n                x.d += d;\n                return;\n            }\n        }\n        ds.push_back({a, b, d});\n    }\n\n    vector<Delta> makeDelta(int r, int c, int to) const {\n        vector<Delta> ds;\n        int from = g[r][c];\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            int nb = 0;\n            if (0 <= nr && nr < n && 0 <= nc && nc < n) {\n                nb = g[nr][nc];\n            }\n\n            addDelta(ds, from, nb, -1);\n            addDelta(ds, to, nb, +1);\n        }\n\n        return ds;\n    }\n\n    bool validChange(int r, int c, int to) {\n        int from = g[r][c];\n        if (from == to) return false;\n        if (from == 0) return false;\n\n        if (cnt[from] <= 1) return false;\n\n        if (to == 0) {\n            if (!adjacentZeroOrOutside(r, c)) return false;\n        } else {\n            bool touches = false;\n            static int dr[4] = {-1, 1, 0, 0};\n            static int dc[4] = {0, 0, -1, 1};\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (inside(nr, nc) && g[nr][nc] == to) {\n                    touches = true;\n                    break;\n                }\n            }\n            if (!touches) return false;\n        }\n\n        if (!oldColorConnectedAfterRemoval(r, c, from)) return false;\n\n        auto ds = makeDelta(r, c, to);\n        for (auto &x : ds) {\n            int now = edgeCnt[x.a][x.b] + x.d;\n            if (allowedAdj[x.a][x.b]) {\n                if (now <= 0) return false;\n            } else {\n                if (now != 0) return false;\n            }\n        }\n\n        return true;\n    }\n\n    void applyChange(int r, int c, int to) {\n        int from = g[r][c];\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            edgeCnt[x.a][x.b] += x.d;\n        }\n\n        cnt[from]--;\n        cnt[to]++;\n        g[r][c] = to;\n    }\n\n    vector<int> computeDistanceToZero() const {\n        vector<int> dist(n * n, INF);\n        queue<int> q;\n\n        auto id = [&](int r, int c) {\n            return r * n + c;\n        };\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int v = id(i, j);\n                if (g[i][j] == 0) {\n                    dist[v] = 0;\n                    q.push(v);\n                } else if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    dist[v] = 1;\n                    q.push(v);\n                }\n            }\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            int r = v / n, c = v % n;\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!inside(nr, nc)) continue;\n                int nv = id(nr, nc);\n                if (dist[nv] > dist[v] + 1) {\n                    dist[nv] = dist[v] + 1;\n                    q.push(nv);\n                }\n            }\n        }\n\n        return dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    vector<vector<int>> original(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> original[i][j];\n        }\n    }\n\n    memset(allowedAdj, 0, sizeof(allowedAdj));\n\n    auto addAllowed = [&](int a, int b) {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n        allowedAdj[a][b] = true;\n    };\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = original[i][j];\n\n            if (i == 0) addAllowed(c, 0);\n            if (i == n - 1) addAllowed(c, 0);\n            if (j == 0) addAllowed(c, 0);\n            if (j == n - 1) addAllowed(c, 0);\n\n            if (i + 1 < n) addAllowed(c, original[i + 1][j]);\n            if (j + 1 < n) addAllowed(c, original[i][j + 1]);\n        }\n    }\n\n    State st;\n    st.init(original);\n\n    vector<vector<int>> best = st.g;\n    int bestZero = st.cnt[0];\n\n    mt19937 rng(123456789);\n\n    auto startTime = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    vector<int> cells(n * n);\n    iota(cells.begin(), cells.end(), 0);\n\n    auto updateBest = [&]() {\n        if (st.cnt[0] > bestZero) {\n            bestZero = st.cnt[0];\n            best = st.g;\n        }\n    };\n\n    auto peelPass = [&]() {\n        bool changed = false;\n        shuffle(cells.begin(), cells.end(), rng);\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 255) == 0 && elapsed() > 1.85) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n            if (st.g[r][c] == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n            }\n        }\n\n        updateBest();\n        return changed;\n    };\n\n    auto recolorPass = [&]() {\n        bool changed = false;\n        auto dist = st.computeDistanceToZero();\n\n        shuffle(cells.begin(), cells.end(), rng);\n        stable_sort(cells.begin(), cells.end(), [&](int a, int b) {\n            return dist[a] < dist[b];\n        });\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.85) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                int nd = dist[nr * n + nc];\n                int cd = dist[r * n + c];\n\n                if (nd < cd) {\n                    used[to] = true;\n                    cand.push_back({nd, to});\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto randomRecolorPass = [&]() {\n        bool changed = false;\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.85) break;\n            if (applied >= 200) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<int> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n                used[to] = true;\n                cand.push_back(to);\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            for (int to : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    while (elapsed() < 1.85) {\n        bool any = false;\n\n        any |= peelPass();\n        if (elapsed() > 1.85) break;\n\n        any |= recolorPass();\n        if (elapsed() > 1.85) break;\n\n        any |= peelPass();\n        if (elapsed() > 1.85) break;\n\n        updateBest();\n\n        if (!any) {\n            bool r = randomRecolorPass();\n            if (!r) break;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct QueryManager {\n    int N, D, Q;\n    int used = 0;\n\n    QueryManager(int N_, int D_, int Q_) : N(N_), D(D_), Q(Q_) {}\n\n    char query(const vector<int>& L, const vector<int>& R) {\n        if (used >= Q) return '?';\n\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        string s;\n        if (!(cin >> s)) exit(0);\n\n        used++;\n        return s[0];\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query(L, R);\n    }\n};\n\nint ceil_log2_int(int x) {\n    int r = 0;\n    int p = 1;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\nstruct Solver {\n    int N, D, Q;\n    QueryManager qm;\n\n    vector<double> estWeight;\n    vector<int> order;\n\n    vector<vector<int>> bins;\n    vector<double> estSum;\n    vector<int> answer;\n\n    mt19937 rng;\n\n    Solver(int N_, int D_, int Q_)\n        : N(N_), D(D_), Q(Q_), qm(N_, D_, Q_), rng(1234567 + N_ * 1009 + D_ * 917 + Q_) {}\n\n    bool heavier_single(int a, int b) {\n        char c = qm.query_single(a, b);\n        return c == '>';\n    }\n\n    vector<int> merge_sort_rec(const vector<int>& v) {\n        int n = (int)v.size();\n        if (n <= 1) return v;\n\n        int mid = n / 2;\n        vector<int> L(v.begin(), v.begin() + mid);\n        vector<int> R(v.begin() + mid, v.end());\n\n        L = merge_sort_rec(L);\n        R = merge_sort_rec(R);\n\n        vector<int> res;\n        res.reserve(n);\n\n        int i = 0, j = 0;\n        while (i < (int)L.size() && j < (int)R.size()) {\n            if (heavier_single(L[i], R[j])) {\n                res.push_back(L[i++]);\n            } else {\n                res.push_back(R[j++]);\n            }\n        }\n        while (i < (int)L.size()) res.push_back(L[i++]);\n        while (j < (int)R.size()) res.push_back(R[j++]);\n\n        return res;\n    }\n\n    void exact_sort_items() {\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        order = merge_sort_rec(order);\n    }\n\n    void approximate_sort_items(int targetQueries) {\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        vector<int> gaps;\n        for (int g = N / 2; g >= 1; g /= 2) gaps.push_back(g);\n\n        while (qm.used < targetQueries) {\n            bool anySwap = false;\n\n            for (int gap : gaps) {\n                for (int i = gap; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - gap];\n                    int b = order[i];\n\n                    char c = qm.query_single(a, b);\n                    if (c == '<') {\n                        swap(order[i - gap], order[i]);\n                        anySwap = true;\n                    }\n                }\n                if (qm.used >= targetQueries) break;\n            }\n\n            // If it already looks sorted, still spend useful adjacent comparisons.\n            if (!anySwap) {\n                for (int i = 1; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - 1];\n                    int b = order[i];\n                    char c = qm.query_single(a, b);\n                    if (c == '<') swap(order[i - 1], order[i]);\n                }\n            }\n        }\n    }\n\n    void make_estimated_weights() {\n        vector<double> H(N + 1, 0.0);\n        for (int i = 1; i <= N; i++) H[i] = H[i - 1] + 1.0 / i;\n\n        estWeight.assign(N, 0.0);\n\n        // Expected k-th largest value of Exp(1) samples is H_N - H_k.\n        for (int k = 0; k < N; k++) {\n            int item = order[k];\n            estWeight[item] = H[N] - H[k];\n        }\n    }\n\n    int compare_bins_by_est(int a, int b) {\n        const double eps = 1e-12;\n        if (estSum[a] + eps < estSum[b]) return -1;\n        if (estSum[a] > estSum[b] + eps) return 1;\n        return 0;\n    }\n\n    int compare_bins(int a, int b, bool allowQuery = true) {\n        if (a == b) return 0;\n\n        if (allowQuery && qm.used < Q) {\n            char c = qm.query(bins[a], bins[b]);\n            if (c == '<') return -1;\n            if (c == '>') return 1;\n            return 0;\n        } else {\n            return compare_bins_by_est(a, b);\n        }\n    }\n\n    void build_partition() {\n        bins.assign(D, {});\n        estSum.assign(D, 0.0);\n        answer.assign(N, 0);\n\n        for (int i = 0; i < D; i++) {\n            int item = order[i];\n            bins[i].push_back(item);\n            estSum[i] += estWeight[item];\n            answer[item] = i;\n        }\n\n        vector<int> binOrder(D);\n        iota(binOrder.begin(), binOrder.end(), 0);\n\n        sort(binOrder.begin(), binOrder.end(), [&](int a, int b) {\n            return estSum[a] < estSum[b];\n        });\n\n        for (int idx = D; idx < N; idx++) {\n            int item = order[idx];\n\n            int b = binOrder.front();\n            binOrder.erase(binOrder.begin());\n\n            bins[b].push_back(item);\n            estSum[b] += estWeight[item];\n            answer[item] = b;\n\n            int lo = 0, hi = (int)binOrder.size();\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int cmp = compare_bins(b, binOrder[mid], true);\n                if (cmp <= 0) hi = mid;\n                else lo = mid + 1;\n            }\n            binOrder.insert(binOrder.begin() + lo, b);\n        }\n    }\n\n    bool find_min_max_bins(int& mn, int& mx) {\n        if (qm.used + 2 * (D - 1) > Q) return false;\n\n        mn = 0;\n        mx = 0;\n\n        for (int b = 1; b < D; b++) {\n            int c1 = compare_bins(b, mn, true);\n            if (c1 < 0) mn = b;\n\n            int c2 = compare_bins(b, mx, true);\n            if (c2 > 0) mx = b;\n        }\n\n        return true;\n    }\n\n    void local_improve() {\n        int iteration = 0;\n\n        while (qm.used < Q && iteration < 10000) {\n            iteration++;\n\n            int lo, hi;\n            if (!find_min_max_bins(lo, hi)) break;\n            if (lo == hi) break;\n            if ((int)bins[hi].size() <= 1) break;\n\n            vector<int> cand = bins[hi];\n            sort(cand.begin(), cand.end(), [&](int a, int b) {\n                return estWeight[a] > estWeight[b];\n            });\n\n            bool moved = false;\n\n            for (int x : cand) {\n                if (qm.used >= Q) break;\n                if ((int)bins[hi].size() <= 1) break;\n\n                vector<int> leftSet;\n                leftSet.reserve(bins[hi].size() - 1);\n                for (int y : bins[hi]) {\n                    if (y != x) leftSet.push_back(y);\n                }\n\n                if (leftSet.empty()) continue;\n\n                vector<int> rightSet = bins[lo];\n                rightSet.push_back(x);\n\n                char c = qm.query(leftSet, rightSet);\n\n                // If after moving x, the old heavy bin is still not lighter,\n                // this is a safe balancing move.\n                if (c == '>' || c == '=') {\n                    auto it = find(bins[hi].begin(), bins[hi].end(), x);\n                    if (it != bins[hi].end()) bins[hi].erase(it);\n\n                    bins[lo].push_back(x);\n                    estSum[hi] -= estWeight[x];\n                    estSum[lo] += estWeight[x];\n                    answer[x] = lo;\n\n                    moved = true;\n                    break;\n                }\n            }\n\n            if (!moved) break;\n        }\n    }\n\n    void spend_remaining_queries() {\n        while (qm.used < Q) {\n            qm.query_single(0, 1);\n        }\n    }\n\n    void output_answer() {\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << answer[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n\n    void solve() {\n        int lgN = ceil_log2_int(N);\n        int mergeWorst = N * lgN - (1 << lgN) + 1;\n        if (mergeWorst < 0) mergeWorst = N * lgN;\n\n        int lgD = ceil_log2_int(D);\n        int constructionCostApprox = max(0, N - D) * max(1, lgD);\n\n        bool useExactSort = false;\n        if (Q >= mergeWorst + D) useExactSort = true;\n\n        if (useExactSort) {\n            exact_sort_items();\n        } else {\n            int reserve = min(constructionCostApprox, Q / 3);\n            int target = max(0, Q - reserve);\n            approximate_sort_items(target);\n        }\n\n        make_estimated_weights();\n\n        build_partition();\n\n        if (qm.used < Q) {\n            local_improve();\n        }\n\n        spend_remaining_queries();\n\n        output_answer();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    cin >> N >> D >> Q;\n\n    Solver solver(N, D, Q);\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int v, to;\n};\n\nstruct Result {\n    vector<Op> ops;\n    int energy = INT_MAX;\n    bool valid = false;\n};\n\nstatic const int N = 200;\nstatic const int M = 10;\nstatic const int EMPTY_VAL = 1000;\n\nint seg_max(const vector<int>& a) {\n    int mx = 0;\n    for (int x : a) mx = max(mx, x);\n    return mx;\n}\n\nint stack_min_value(const vector<int>& st) {\n    if (st.empty()) return EMPTY_VAL;\n    int mn = EMPTY_VAL;\n    for (int x : st) mn = min(mn, x);\n    return mn;\n}\n\nbool has_good_destination(const vector<vector<int>>& stacks, int src, const vector<int>& vals) {\n    int mx = seg_max(vals);\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n        if (stacks[d].empty()) return true;\n        if (stacks[d].back() > mx) return true;\n    }\n    return false;\n}\n\nint choose_destination(\n    const vector<vector<int>>& stacks,\n    int src,\n    const vector<int>& vals,\n    int policy,\n    mt19937& rng,\n    double noise_amp\n) {\n    int mx = seg_max(vals);\n\n    uniform_real_distribution<double> dist(0.0, noise_amp);\n\n    int best = -1;\n    double best_score = 1e100;\n\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n\n        int h = (int)stacks[d].size();\n        bool empty = stacks[d].empty();\n\n        int top = empty ? EMPTY_VAL : stacks[d].back();\n        int mn = stack_min_value(stacks[d]);\n\n        bool good_top = empty || top > mx;\n        bool good_all = empty || mn > mx;\n\n        double score = 0.0;\n\n        switch (policy % 8) {\n            case 0:\n                // Basic: prefer smallest top larger than block max.\n                if (good_top) score = top * 100.0 + h;\n                else score = 1e6 - top * 100.0 + h;\n                break;\n\n            case 1:\n                // Prefer low height, but still prioritize good destinations.\n                score = (good_top ? 0.0 : 100000.0) + h * 100.0 + top;\n                break;\n\n            case 2:\n                // Stronger condition: all boxes in destination are larger.\n                if (good_all) score = mn * 100.0 + h;\n                else if (good_top) score = 200000.0 + top * 100.0 + h;\n                else score = 1e6 - mn * 50.0 - top * 10.0 + h;\n                break;\n\n            case 3:\n                // Prefer smallest positive gap top - max.\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0;\n                else score = 1e6 + (mx - top) * 100.0 + h;\n                break;\n\n            case 4:\n                // Mostly balance heights.\n                score = h * 100.0 + (good_top ? 0.0 : 10.0);\n                break;\n\n            case 5:\n                // Try using taller stacks if destination is good.\n                if (good_top) score = top * 100.0 - h * 20.0;\n                else score = 1e6 - top * 100.0 - h * 10.0;\n                break;\n\n            case 6:\n                // Prefer large top labels.\n                score = (good_top ? 0.0 : 500000.0) - top * 100.0 + h * 10.0;\n                break;\n\n            case 7:\n                // Prefer destinations whose minimum label is large.\n                score = (good_top ? 0.0 : 300000.0) - mn * 100.0 - top * 10.0 + h;\n                break;\n        }\n\n        if (noise_amp > 0.0) score += dist(rng);\n\n        if (score < best_score) {\n            best_score = score;\n            best = d;\n        }\n    }\n\n    return best;\n}\n\nResult simulate(\n    const vector<vector<int>>& initial,\n    int split_mode,\n    int policy,\n    bool merge_when_no_good,\n    uint32_t seed,\n    double noise_amp\n) {\n    mt19937 rng(seed);\n\n    vector<vector<int>> stacks = initial;\n    vector<Op> ops;\n    int energy = 0;\n\n    for (int cur = 1; cur <= N; cur++) {\n        int s = -1, pos = -1;\n\n        for (int i = 0; i < M; i++) {\n            for (int j = 0; j < (int)stacks[i].size(); j++) {\n                if (stacks[i][j] == cur) {\n                    s = i;\n                    pos = j;\n                }\n            }\n        }\n\n        if (s == -1) {\n            return Result{};\n        }\n\n        while (pos != (int)stacks[s].size() - 1) {\n            if ((int)ops.size() >= 5000) return Result{};\n\n            int h = (int)stacks[s].size();\n            int l;\n\n            bool force_whole = ((int)ops.size() > 4500);\n\n            if (force_whole || split_mode == 0) {\n                // Move the whole suffix above cur.\n                l = pos + 1;\n            } else if (split_mode == 2) {\n                // Move one box at a time.\n                l = h - 1;\n            } else {\n                // Move a maximal decreasing run from the top.\n                l = h - 1;\n                while (l - 1 > pos && stacks[s][l - 1] > stacks[s][l]) {\n                    l--;\n                }\n\n                vector<int> tmp(stacks[s].begin() + l, stacks[s].end());\n\n                if (merge_when_no_good && !has_good_destination(stacks, s, tmp)) {\n                    l = pos + 1;\n                }\n            }\n\n            vector<int> vals(stacks[s].begin() + l, stacks[s].end());\n\n            int d = choose_destination(stacks, s, vals, policy, rng, noise_amp);\n            if (d < 0 || d == s) return Result{};\n\n            ops.push_back({vals.front(), d + 1});\n            energy += (int)vals.size() + 1;\n\n            stacks[s].erase(stacks[s].begin() + l, stacks[s].end());\n            stacks[d].insert(stacks[d].end(), vals.begin(), vals.end());\n\n            if ((int)ops.size() > 5000) return Result{};\n        }\n\n        // Now cur is on top.\n        if (stacks[s].empty() || stacks[s].back() != cur) {\n            return Result{};\n        }\n\n        ops.push_back({cur, 0});\n        stacks[s].pop_back();\n\n        if ((int)ops.size() > 5000) return Result{};\n    }\n\n    Result res;\n    res.ops = move(ops);\n    res.energy = energy;\n    res.valid = true;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> initial(M);\n\n    for (int i = 0; i < M; i++) {\n        initial[i].resize(N / M);\n        for (int j = 0; j < N / M; j++) {\n            cin >> initial[i][j];\n        }\n    }\n\n    uint32_t base_seed = 123456789;\n    for (int i = 0; i < M; i++) {\n        for (int x : initial[i]) {\n            base_seed = base_seed * 1000003u + (uint32_t)x;\n        }\n    }\n\n    Result best;\n\n    auto try_result = [&](const Result& r) {\n        if (!r.valid) return;\n        if ((int)r.ops.size() > 5000) return;\n\n        if (!best.valid ||\n            r.energy < best.energy ||\n            (r.energy == best.energy && r.ops.size() < best.ops.size())) {\n            best = r;\n        }\n    };\n\n    // Deterministic variants.\n    for (int split = 0; split < 3; split++) {\n        for (int policy = 0; policy < 8; policy++) {\n            for (int merge = 0; merge < 2; merge++) {\n                Result r = simulate(\n                    initial,\n                    split,\n                    policy,\n                    merge,\n                    base_seed + split * 1000 + policy * 100 + merge,\n                    0.0\n                );\n                try_result(r);\n            }\n        }\n    }\n\n    // Randomized variants.\n    mt19937 rng(base_seed ^ 0x9e3779b9u);\n\n    for (int t = 0; t < 250; t++) {\n        int split;\n        int r = (int)(rng() % 100);\n        if (r < 20) split = 0;\n        else if (r < 85) split = 1;\n        else split = 2;\n\n        int policy = rng() % 8;\n        bool merge = rng() & 1;\n\n        double noise;\n        int nr = rng() % 5;\n        if (nr == 0) noise = 5.0;\n        else if (nr == 1) noise = 20.0;\n        else if (nr == 2) noise = 100.0;\n        else if (nr == 3) noise = 500.0;\n        else noise = 2000.0;\n\n        Result res = simulate(\n            initial,\n            split,\n            policy,\n            merge,\n            base_seed + 100000u + t * 17u,\n            noise\n        );\n\n        try_result(res);\n    }\n\n    // Fallback should always exist, but just in case.\n    if (!best.valid) {\n        best = simulate(initial, 0, 1, false, base_seed, 0.0);\n    }\n\n    for (const auto& op : best.ops) {\n        cout << op.v << ' ' << op.to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    char c;\n};\n\nstatic const uint16_t INF16 = 65535;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    int N;\n    cin >> N;\n\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    int V = N * N;\n    vector<int> dirt(V);\n    long long sumD = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> dirt[i * N + j];\n            sumD += dirt[i * N + j];\n        }\n    }\n    double avgD = (double)sumD / V;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    vector<vector<Edge>> g(V);\n\n    auto add_edge = [&](int a, int b, char c1, char c2) {\n        g[a].push_back({b, c1});\n        g[b].push_back({a, c2});\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (i + 1 < N && h[i][j] == '0') {\n                add_edge(id(i, j), id(i + 1, j), 'D', 'U');\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                add_edge(id(i, j), id(i, j + 1), 'R', 'L');\n            }\n        }\n    }\n\n    // all-pairs shortest paths\n    vector<uint16_t> dist((size_t)V * V, INF16);\n    vector<int> q(V);\n\n    for (int s = 0; s < V; s++) {\n        uint16_t* ds = &dist[(size_t)s * V];\n        int head = 0, tail = 0;\n        ds[s] = 0;\n        q[tail++] = s;\n\n        while (head < tail) {\n            int cur = q[head++];\n            uint16_t nd = ds[cur] + 1;\n            for (auto &e : g[cur]) {\n                if (ds[e.to] == INF16) {\n                    ds[e.to] = nd;\n                    q[tail++] = e.to;\n                }\n            }\n        }\n    }\n\n    int maxDist = 0;\n    for (int i = 0; i < V; i++) {\n        for (int j = 0; j < V; j++) {\n            maxDist = max(maxDist, (int)dist[(size_t)i * V + j]);\n        }\n    }\n\n    vector<double> alphas = {1.0, 1.5, 2.0, 3.0};\n    vector<vector<double>> denom(alphas.size(), vector<double>(maxDist + 2));\n    for (int a = 0; a < (int)alphas.size(); a++) {\n        for (int d = 0; d <= maxDist + 1; d++) {\n            denom[a][d] = pow((double)d, alphas[a]);\n        }\n    }\n\n    auto score_route = [&](const string &route) -> long double {\n        int L = (int)route.size();\n        if (L == 0 || L > 100000) return 1e100L;\n\n        vector<vector<int>> times(V);\n        int cur = 0;\n        times[0].push_back(0);\n\n        for (int t = 1; t <= L; t++) {\n            char c = route[t - 1];\n            bool moved = false;\n            for (auto &e : g[cur]) {\n                if (e.c == c) {\n                    cur = e.to;\n                    moved = true;\n                    break;\n                }\n            }\n            if (!moved) return 1e100L;\n\n            if (t < L) {\n                times[cur].push_back(t);\n            }\n        }\n\n        if (cur != 0) return 1e100L;\n\n        long double total = 0.0L;\n\n        for (int x = 0; x < V; x++) {\n            if (times[x].empty()) return 1e100L;\n\n            auto &ts = times[x];\n            long long ss = 0;\n\n            for (int k = 0; k + 1 < (int)ts.size(); k++) {\n                long long gap = ts[k + 1] - ts[k];\n                ss += gap * (gap - 1);\n            }\n\n            long long gap = L - ts.back() + ts.front();\n            ss += gap * (gap - 1);\n\n            total += (long double)dirt[x] * ss / (2.0L * L);\n        }\n\n        return total;\n    };\n\n    string bestRoute;\n    long double bestScore = 1e100L;\n\n    auto consider = [&](const string &route) {\n        if (route.empty() || route.size() > 100000) return;\n        long double sc = score_route(route);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n        }\n    };\n\n    // DFS baseline routes\n    for (int mode = 0; mode < 4; mode++) {\n        vector<int> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n\n            vector<Edge> es = g[cur];\n\n            if (mode == 1) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] > dirt[b.to];\n                });\n            } else if (mode == 2) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] < dirt[b.to];\n                });\n            } else if (mode == 3) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return a.c < b.c;\n                });\n            }\n\n            for (auto &e : es) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n\n                    for (auto &r : g[e.to]) {\n                        if (r.to == cur) {\n                            route.push_back(r.c);\n                            break;\n                        }\n                    }\n                }\n            }\n        };\n\n        dfs(0);\n        consider(route);\n    }\n\n    uint32_t rng = 123456789;\n    auto rnd01 = [&]() {\n        rng ^= rng << 13;\n        rng ^= rng >> 17;\n        rng ^= rng << 5;\n        return (rng & 0xffff) / 65536.0;\n    };\n\n    auto generate_route = [&](int cap, int covAlphaIdx, int patAlphaIdx, double coverBiasMul, bool noise) {\n        string route;\n        route.reserve(min(100000, max(cap, V * 2)));\n\n        vector<int> last(V, 0);\n        vector<char> visited(V, 0);\n        int visitedCnt = 1;\n        visited[0] = 1;\n\n        int cur = 0;\n        int t = 0;\n\n        auto append_path = [&](int target) {\n            while (cur != target) {\n                uint16_t dc = dist[(size_t)cur * V + target];\n\n                int bestNext = -1;\n                char bestChar = '?';\n                long long bestVal = LLONG_MIN;\n\n                for (auto &e : g[cur]) {\n                    if (dist[(size_t)e.to * V + target] + 1 == dc) {\n                        long long val = 0;\n                        if (!visited[e.to]) val += (long long)4e18 / 4;\n                        val += (long long)dirt[e.to] * (t - last[e.to] + 1);\n\n                        if (val > bestVal) {\n                            bestVal = val;\n                            bestNext = e.to;\n                            bestChar = e.c;\n                        }\n                    }\n                }\n\n                if (bestNext == -1) return;\n\n                route.push_back(bestChar);\n                cur = bestNext;\n                t++;\n\n                last[cur] = t;\n                if (!visited[cur]) {\n                    visited[cur] = 1;\n                    visitedCnt++;\n                }\n            }\n        };\n\n        double coverBias = avgD * coverBiasMul;\n\n        // Phase 1: visit all cells\n        while (visitedCnt < V) {\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                if (visited[x]) continue;\n\n                int ds = dist[(size_t)cur * V + x];\n                double val = (coverBias + dirt[x]) / denom[covAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.9 + 0.2 * rnd01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n            append_path(target);\n\n            if ((int)route.size() > 100000) break;\n        }\n\n        // Phase 2: patrol high-dirt / long-unvisited cells\n        int limit = cap;\n        if (limit <= 0) limit = (int)route.size();\n\n        int iter = 0;\n        while ((int)route.size() + dist[(size_t)cur * V + 0] < limit &&\n               (int)route.size() < 100000) {\n            if ((++iter & 255) == 0 && elapsed() > 1.82) break;\n\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                int ds = dist[(size_t)cur * V + x];\n                if (ds == 0) continue;\n\n                int ret = dist[(size_t)x * V + 0];\n                if ((int)route.size() + ds + ret > limit) continue;\n                if ((int)route.size() + ds + ret > 100000) continue;\n\n                int age = t - last[x];\n                double val = (double)dirt[x] * (age + 1) / denom[patAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.9 + 0.2 * rnd01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n            append_path(target);\n        }\n\n        append_path(0);\n        return route;\n    };\n\n    struct Param {\n        int cap;\n        int covA;\n        int patA;\n        double bias;\n        bool noise;\n    };\n\n    vector<Param> params;\n\n    // Coverage-only variants\n    params.push_back({0, 3, 1, 20.0, false});\n    params.push_back({0, 2, 1, 20.0, false});\n    params.push_back({0, 2, 1, 0.0, false});\n    params.push_back({0, 1, 1, 0.0, false});\n\n    vector<int> caps = {\n        V * 2,\n        V * 3,\n        V * 5,\n        V * 8,\n        V * 13,\n        30000,\n        60000,\n        100000\n    };\n\n    for (int &x : caps) {\n        x = min(100000, max(1, x));\n    }\n    sort(caps.begin(), caps.end());\n    caps.erase(unique(caps.begin(), caps.end()), caps.end());\n\n    for (int cap : caps) {\n        params.push_back({cap, 2, 1, 10.0, false});\n    }\n\n    params.push_back({30000, 2, 0, 10.0, false});\n    params.push_back({30000, 2, 2, 10.0, false});\n    params.push_back({60000, 2, 0, 10.0, false});\n    params.push_back({100000, 2, 0, 10.0, false});\n\n    params.push_back({60000, 2, 1, 10.0, true});\n    params.push_back({100000, 2, 1, 10.0, true});\n\n    for (auto &p : params) {\n        if (elapsed() > 1.84) break;\n        string r = generate_route(p.cap, p.covA, p.patA, p.bias, p.noise);\n        consider(r);\n    }\n\n    // Absolute safety fallback, should practically never be needed.\n    if (bestRoute.empty()) {\n        vector<int> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n            for (auto &e : g[cur]) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n                    for (auto &r : g[e.to]) {\n                        if (r.to == cur) {\n                            route.push_back(r.c);\n                            break;\n                        }\n                    }\n                }\n            }\n        };\n\n        dfs(0);\n        bestRoute = route;\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\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 nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nint N, M;\nint si, sj;\nvector<string> Agrid;\nvector<string> t;\nvector<pair<int,int>> occ[26];\nint mindist_ch[26][26];\n\nint manhattan(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nint overlap_word(const string& a, const string& b) {\n    for (int k = 4; k >= 1; --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) return k;\n    }\n    return 0;\n}\n\nint overlap_suffix_string(const string& s, const string& w) {\n    int lim = min<int>(4, s.size());\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (s[(int)s.size() - k + i] != w[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nlong long pathCost(const vector<int>& p, const vector<vector<int>>& W, const vector<int>& startCost) {\n    long long c = startCost[p[0]];\n    for (int i = 0; i + 1 < (int)p.size(); ++i) c += W[p[i]][p[i + 1]];\n    return c;\n}\n\nlong long contrib(const vector<int>& p, int idx, const vector<vector<int>>& W, const vector<int>& startCost) {\n    int n = (int)p.size();\n    if (idx == -1) return startCost[p[0]];\n    if (0 <= idx && idx + 1 < n) return W[p[idx]][p[idx + 1]];\n    return 0;\n}\n\nlong long deltaSwap(const vector<int>& p, int a, int b, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (a == b) return 0;\n    if (a > b) swap(a, b);\n\n    vector<int> ids = {-1, a - 1, a, b - 1, b};\n    sort(ids.begin(), ids.end());\n    ids.erase(unique(ids.begin(), ids.end()), ids.end());\n\n    long long oldv = 0, newv = 0;\n    for (int id : ids) oldv += contrib(p, id, W, startCost);\n\n    vector<int> q = p;\n    swap(q[a], q[b]);\n\n    for (int id : ids) newv += contrib(q, id, W, startCost);\n    return newv - oldv;\n}\n\nvector<int> greedyOrder(const vector<vector<int>>& W, const vector<int>& startCost, const vector<vector<int>>& ov) {\n    vector<int> best;\n    long long bestCost = (1LL << 60);\n\n    for (int st = 0; st < M; ++st) {\n        vector<int> p;\n        vector<char> used(M, 0);\n        p.reserve(M);\n        p.push_back(st);\n        used[st] = 1;\n\n        for (int step = 1; step < M; ++step) {\n            int last = p.back();\n            int bj = -1;\n            pair<int,int> bestKey = {INT_MAX, INT_MAX};\n\n            for (int j = 0; j < M; ++j) if (!used[j]) {\n                // primary: estimated cost, secondary: larger overlap\n                pair<int,int> key = {W[last][j], -ov[last][j]};\n                if (key < bestKey) {\n                    bestKey = key;\n                    bj = j;\n                }\n            }\n\n            used[bj] = 1;\n            p.push_back(bj);\n        }\n\n        long long c = pathCost(p, W, startCost);\n        if (c < bestCost) {\n            bestCost = c;\n            best = p;\n        }\n    }\n\n    return best;\n}\n\nstring buildStringFromOrder(const vector<int>& ord) {\n    string s;\n\n    for (int id : ord) {\n        if (s.find(t[id]) != string::npos) continue;\n\n        if (s.empty()) {\n            s = t[id];\n        } else {\n            int k = overlap_suffix_string(s, t[id]);\n            s += t[id].substr(k);\n        }\n    }\n\n    // Safety fallback.\n    for (int i = 0; i < M; ++i) {\n        if (s.find(t[i]) == string::npos) {\n            int k = overlap_suffix_string(s, t[i]);\n            s += t[i].substr(k);\n        }\n    }\n\n    return s;\n}\n\npair<int, vector<pair<int,int>>> solveTypingDP(const string& s) {\n    const int INF = 1e9;\n    int L = (int)s.size();\n\n    vector<vector<int>> par(L);\n    vector<int> dp_prev, dp_cur;\n\n    for (int pos = 0; pos < L; ++pos) {\n        int c = s[pos] - 'A';\n        int C = (int)occ[c].size();\n\n        dp_cur.assign(C, INF);\n        par[pos].assign(C, -1);\n\n        if (pos == 0) {\n            pair<int,int> start = {si, sj};\n            for (int i = 0; i < C; ++i) {\n                dp_cur[i] = manhattan(start, occ[c][i]) + 1;\n            }\n        } else {\n            int pc = s[pos - 1] - 'A';\n            int P = (int)occ[pc].size();\n\n            for (int i = 0; i < C; ++i) {\n                for (int j = 0; j < P; ++j) {\n                    int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                    if (val < dp_cur[i]) {\n                        dp_cur[i] = val;\n                        par[pos][i] = j;\n                    }\n                }\n            }\n        }\n\n        dp_prev.swap(dp_cur);\n    }\n\n    int bestIdx = 0;\n    int bestCost = INF;\n    for (int i = 0; i < (int)dp_prev.size(); ++i) {\n        if (dp_prev[i] < bestCost) {\n            bestCost = dp_prev[i];\n            bestIdx = i;\n        }\n    }\n\n    vector<pair<int,int>> path(L);\n    int idx = bestIdx;\n    for (int pos = L - 1; pos >= 0; --pos) {\n        int c = s[pos] - 'A';\n        path[pos] = occ[c][idx];\n        idx = par[pos][idx];\n    }\n\n    return {bestCost, path};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto timeStart = chrono::steady_clock::now();\n\n    cin >> N >> M;\n    cin >> si >> sj;\n\n    Agrid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> Agrid[i];\n\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            occ[Agrid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) {\n            int best = 1e9;\n            for (auto pa : occ[a]) {\n                for (auto pb : occ[b]) {\n                    best = min(best, manhattan(pa, pb));\n                }\n            }\n            mindist_ch[a][b] = best;\n        }\n    }\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i != j) ov[i][j] = overlap_word(t[i], t[j]);\n        }\n    }\n\n    vector<vector<int>> W(M, vector<int>(M, 1e8));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            int o = ov[i][j];\n            int prev = t[i][4] - 'A';\n            int cost = 0;\n            for (int k = o; k < 5; ++k) {\n                int c = t[j][k] - 'A';\n                cost += mindist_ch[prev][c] + 1;\n                prev = c;\n            }\n            W[i][j] = cost;\n        }\n    }\n\n    vector<int> startCost(M, 0);\n    pair<int,int> startPos = {si, sj};\n    for (int i = 0; i < M; ++i) {\n        int cost = 1e9;\n        int c0 = t[i][0] - 'A';\n        for (auto p : occ[c0]) {\n            cost = min(cost, manhattan(startPos, p) + 1);\n        }\n        for (int k = 1; k < 5; ++k) {\n            int a = t[i][k - 1] - 'A';\n            int b = t[i][k] - 'A';\n            cost += mindist_ch[a][b] + 1;\n        }\n        startCost[i] = cost;\n    }\n\n    vector<int> perm = greedyOrder(W, startCost, ov);\n    long long curCost = pathCost(perm, W, startCost);\n    vector<int> bestPerm = perm;\n    long long bestCost = curCost;\n\n    // Additional pure-overlap candidate.\n    vector<vector<int>> Wover(M, vector<int>(M, 1000000));\n    vector<int> zeroStart(M, 0);\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            Wover[i][j] = 5 - ov[i][j];\n        }\n    }\n    vector<int> overlapPerm = greedyOrder(Wover, zeroStart, ov);\n\n    // Simulated annealing / local search on estimated typing cost.\n    XorShift rng;\n    vector<int> np;\n    np.reserve(M);\n\n    const double TL = 1.78;\n    int iter = 0;\n    while (true) {\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - timeStart).count();\n            if (elapsed > TL) break;\n        }\n        ++iter;\n\n        double progress = min(1.0, chrono::duration<double>(chrono::steady_clock::now() - timeStart).count() / TL);\n        double temp = 18.0 * pow(0.03 / 18.0, progress);\n\n        if (rng.nextInt(100) < 55) {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            long long d = deltaSwap(perm, a, b, W, startCost);\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                swap(perm[a], perm[b]);\n                curCost += d;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        } else {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            np = perm;\n            int val = np[a];\n            np.erase(np.begin() + a);\n            np.insert(np.begin() + b, val);\n\n            long long ncost = pathCost(np, W, startCost);\n            long long d = ncost - curCost;\n\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                perm.swap(np);\n                curCost = ncost;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        }\n    }\n\n    vector<string> candidates;\n    candidates.push_back(buildStringFromOrder(bestPerm));\n    candidates.push_back(buildStringFromOrder(overlapPerm));\n\n    // A simple lexicographic-order fallback, surprisingly useful in rare cases.\n    vector<int> lexPerm(M);\n    iota(lexPerm.begin(), lexPerm.end(), 0);\n    candidates.push_back(buildStringFromOrder(lexPerm));\n\n    int answerCost = INT_MAX;\n    vector<pair<int,int>> answerPath;\n\n    sort(candidates.begin(), candidates.end());\n    candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n    for (const string& s : candidates) {\n        auto res = solveTypingDP(s);\n        if (res.first < answerCost) {\n            answerCost = res.first;\n            answerPath = move(res.second);\n        }\n    }\n\n    if ((int)answerPath.size() > 5000) {\n        answerPath.resize(5000);\n    }\n\n    for (auto [i, j] : answerPath) {\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXC = 400;\n\nint N, M, C;\ndouble EPSV;\nint MAX_OPS;\nint op_cnt = 0;\n\nstruct Placement {\n    vector<int> cells;\n    bitset<MAXC> mask;\n};\n\nstruct Obs {\n    bitset<MAXC> mask;\n    int k;\n    double target;\n    double weight;\n    bool drill;\n    int cell;\n    int value;\n};\n\nstruct State {\n    vector<int> pos;\n    double score;\n    bitset<MAXC> uni;\n};\n\nvector<vector<pair<int,int>>> shapes;\nvector<vector<Placement>> placements;\nvector<Obs> observations;\n\nvector<int> drilled; // -1 unknown, otherwise exact v(i,j)\n\nmt19937 rng(1234567);\nauto time_start = chrono::steady_clock::now();\n\ndouble elapsed_ms() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double, milli>(now - time_start).count();\n}\n\nint id_of(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> coord_of(int id) {\n    return {id / N, id % N};\n}\n\nint ask_query(const vector<int>& cells) {\n    cout << \"q \" << cells.size();\n    for (int id : cells) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n    return res;\n}\n\nbool ask_answer(bitset<MAXC> mask) {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] > 0) mask.set(id);\n    }\n\n    vector<int> ans;\n    for (int id = 0; id < C; id++) {\n        if (mask.test(id)) ans.push_back(id);\n    }\n\n    cout << \"a \" << ans.size();\n    for (int id : ans) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n    if (res == 1) exit(0);\n    return false;\n}\n\nvoid add_divination_observation(const vector<int>& cells, int y) {\n    Obs obs;\n    obs.mask.reset();\n    for (int id : cells) obs.mask.set(id);\n    obs.k = (int)cells.size();\n    obs.drill = false;\n    obs.cell = -1;\n    obs.value = -1;\n\n    double a = 1.0 - 2.0 * EPSV;\n    double target = (y - obs.k * EPSV) / max(1e-9, a);\n    target = max(0.0, min(target, (double)M * obs.k));\n\n    double var = obs.k * EPSV * (1.0 - EPSV) + 0.35;\n    double weight = a * a / max(1e-9, var);\n\n    obs.target = target;\n    obs.weight = weight;\n    observations.push_back(obs);\n}\n\nvoid add_drill_observation(int cell, int val) {\n    Obs obs;\n    obs.mask.reset();\n    obs.mask.set(cell);\n    obs.k = 1;\n    obs.target = val;\n    obs.weight = 10000.0;\n    obs.drill = true;\n    obs.cell = cell;\n    obs.value = val;\n    observations.push_back(obs);\n}\n\nvoid do_divination(const vector<int>& cells) {\n    if ((int)cells.size() < 2) return;\n    int y = ask_query(cells);\n    add_divination_observation(cells, y);\n}\n\nint do_drill(int cell) {\n    vector<int> q = {cell};\n    int v = ask_query(q);\n    drilled[cell] = v;\n    add_drill_observation(cell, v);\n    return v;\n}\n\nvoid build_placements() {\n    placements.assign(M, {});\n\n    for (int m = 0; m < M; m++) {\n        int imax = 0, jmax = 0;\n        for (auto [i, j] : shapes[m]) {\n            imax = max(imax, i);\n            jmax = max(jmax, j);\n        }\n\n        for (int di = 0; di + imax < N; di++) {\n            for (int dj = 0; dj + jmax < N; dj++) {\n                Placement p;\n                p.mask.reset();\n                for (auto [i, j] : shapes[m]) {\n                    int id = id_of(di + i, dj + j);\n                    p.cells.push_back(id);\n                    p.mask.set(id);\n                }\n                placements[m].push_back(p);\n            }\n        }\n    }\n}\n\nvoid initial_queries() {\n    // Whole grid: almost free and gives total amount.\n    vector<int> all;\n    for (int id = 0; id < C; id++) all.push_back(id);\n    do_divination(all);\n\n    // Rows.\n    for (int i = 0; i < N; i++) {\n        vector<int> cells;\n        for (int j = 0; j < N; j++) cells.push_back(id_of(i, j));\n        do_divination(cells);\n    }\n\n    // Columns.\n    for (int j = 0; j < N; j++) {\n        vector<int> cells;\n        for (int i = 0; i < N; i++) cells.push_back(id_of(i, j));\n        do_divination(cells);\n    }\n\n    // Coarse blocks.\n    int B = 4;\n    for (int si = 0; si < N; si += B) {\n        for (int sj = 0; sj < N; sj += B) {\n            vector<int> cells;\n            for (int i = si; i < min(N, si + B); i++) {\n                for (int j = sj; j < min(N, sj + B); j++) {\n                    cells.push_back(id_of(i, j));\n                }\n            }\n            if ((int)cells.size() >= 2) do_divination(cells);\n        }\n    }\n\n    // Random half-grid masks. Cheap global linear measurements.\n    int R = (N <= 10 ? 18 : 30);\n    vector<int> ids(C);\n    iota(ids.begin(), ids.end(), 0);\n    for (int r = 0; r < R; r++) {\n        shuffle(ids.begin(), ids.end(), rng);\n        vector<int> cells;\n        int sz = max(2, C / 2);\n        for (int t = 0; t < sz; t++) cells.push_back(ids[t]);\n        do_divination(cells);\n    }\n}\n\nbitset<MAXC> union_of_state(const vector<int>& pos) {\n    bitset<MAXC> res;\n    res.reset();\n    for (int m = 0; m < M; m++) {\n        res |= placements[m][pos[m]].mask;\n    }\n    return res;\n}\n\nbool union_consistent_with_drills(const bitset<MAXC>& mask) {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) continue;\n        if (drilled[id] == 0 && mask.test(id)) return false;\n        if (drilled[id] > 0 && !mask.test(id)) return false;\n    }\n    return true;\n}\n\nstring mask_key(const bitset<MAXC>& mask) {\n    string s;\n    s.reserve(C);\n    for (int id = 0; id < C; id++) s.push_back(mask.test(id) ? '1' : '0');\n    return s;\n}\n\nvector<State> find_candidates(int want, int time_ms) {\n    int O = observations.size();\n\n    vector<vector<vector<unsigned char>>> contrib(M);\n    for (int m = 0; m < M; m++) {\n        int P = placements[m].size();\n        contrib[m].assign(P, vector<unsigned char>(O, 0));\n        for (int p = 0; p < P; p++) {\n            for (int o = 0; o < O; o++) {\n                bitset<MAXC> b = placements[m][p].mask & observations[o].mask;\n                contrib[m][p][o] = (unsigned char)b.count();\n            }\n        }\n    }\n\n    auto score_of_sums = [&](const vector<int>& sums) {\n        double sc = 0.0;\n        for (int o = 0; o < O; o++) {\n            double e = sums[o] - observations[o].target;\n            sc += observations[o].weight * e * e;\n        }\n        return sc;\n    };\n\n    vector<State> result;\n    auto deadline = chrono::steady_clock::now() + chrono::milliseconds(max(5, time_ms));\n\n    int restarts = 0;\n    while (restarts < 3 || chrono::steady_clock::now() < deadline) {\n        restarts++;\n\n        vector<int> pos(M);\n        for (int m = 0; m < M; m++) {\n            uniform_int_distribution<int> dist(0, (int)placements[m].size() - 1);\n            pos[m] = dist(rng);\n        }\n\n        vector<int> sums(O, 0);\n        for (int m = 0; m < M; m++) {\n            for (int o = 0; o < O; o++) {\n                sums[o] += contrib[m][pos[m]][o];\n            }\n        }\n\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n\n        for (int sweep = 0; sweep < 7; sweep++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool changed = false;\n\n            for (int mm = 0; mm < M; mm++) {\n                int m = order[mm];\n                int oldp = pos[m];\n\n                for (int o = 0; o < O; o++) {\n                    sums[o] -= contrib[m][oldp][o];\n                }\n\n                int bestp = oldp;\n                double bestsc = numeric_limits<double>::infinity();\n\n                int P = placements[m].size();\n                for (int p = 0; p < P; p++) {\n                    double sc = 0.0;\n                    for (int o = 0; o < O; o++) {\n                        double v = sums[o] + contrib[m][p][o];\n                        double e = v - observations[o].target;\n                        sc += observations[o].weight * e * e;\n                        if (sc >= bestsc) break;\n                    }\n                    if (sc < bestsc) {\n                        bestsc = sc;\n                        bestp = p;\n                    }\n                }\n\n                pos[m] = bestp;\n                for (int o = 0; o < O; o++) {\n                    sums[o] += contrib[m][bestp][o];\n                }\n\n                if (bestp != oldp) changed = true;\n            }\n\n            if (!changed) break;\n        }\n\n        State st;\n        st.pos = pos;\n        st.score = score_of_sums(sums);\n        st.uni = union_of_state(pos);\n        result.push_back(st);\n\n        if (elapsed_ms() > 2700.0) break;\n    }\n\n    sort(result.begin(), result.end(), [](const State& a, const State& b) {\n        return a.score < b.score;\n    });\n\n    vector<State> uniq;\n    unordered_set<string> seen;\n    for (auto &st : result) {\n        string key = mask_key(st.uni);\n        if (seen.insert(key).second) {\n            uniq.push_back(st);\n            if ((int)uniq.size() >= want) break;\n        }\n    }\n\n    return uniq;\n}\n\nint choose_drill_cell(const vector<State>& cand, int wrong_same_count) {\n    int K = cand.size();\n    vector<int> freq(C, 0);\n\n    for (auto &st : cand) {\n        for (int id = 0; id < C; id++) {\n            if (st.uni.test(id)) freq[id]++;\n        }\n    }\n\n    int best = -1;\n    int bestScore = -1;\n\n    // Prefer uncertain cells among candidate unions.\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] != -1) continue;\n        int f = freq[id];\n        if (f == 0 || f == K) continue;\n        int score = min(f, K - f);\n        if (score > bestScore) {\n            bestScore = score;\n            best = id;\n        }\n    }\n\n    if (best != -1) return best;\n\n    // If all candidates agree, verify predicted positives and nearby negatives.\n    if (!cand.empty()) {\n        const bitset<MAXC>& mask = cand[0].uni;\n\n        if (wrong_same_count % 2 == 0) {\n            for (int id = 0; id < C; id++) {\n                if (drilled[id] == -1 && mask.test(id)) return id;\n            }\n        }\n\n        // Boundary negatives.\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] != -1 || mask.test(id)) continue;\n            int i = id / N, j = id % N;\n            bool near = false;\n            const int di[4] = {-1, 1, 0, 0};\n            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 (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    if (mask.test(id_of(ni, nj))) near = true;\n                }\n            }\n            if (near) return id;\n        }\n\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] == -1 && !mask.test(id)) return id;\n        }\n    }\n\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) return id;\n    }\n\n    return -1;\n}\n\nvoid fallback_drill_all_and_answer() {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) {\n            do_drill(id);\n        }\n    }\n\n    bitset<MAXC> ans;\n    ans.reset();\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] > 0) ans.set(id);\n    }\n\n    ask_answer(ans);\n    exit(0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> EPSV;\n    C = N * N;\n    MAX_OPS = 2 * C;\n\n    shapes.resize(M);\n    for (int m = 0; m < M; m++) {\n        int d;\n        cin >> d;\n        shapes[m].resize(d);\n        for (int k = 0; k < d; k++) {\n            cin >> shapes[m][k].first >> shapes[m][k].second;\n        }\n    }\n\n    drilled.assign(C, -1);\n    build_placements();\n\n    initial_queries();\n\n    unordered_set<string> guessed;\n    int heuristic_drills = 0;\n    int guesses = 0;\n    int wrong_same_count = 0;\n\n    while (true) {\n        int unknown = 0;\n        for (int id = 0; id < C; id++) if (drilled[id] == -1) unknown++;\n\n        // Keep enough operations to drill everything and submit.\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        if (elapsed_ms() > 2700.0 || heuristic_drills >= 55) {\n            fallback_drill_all_and_answer();\n        }\n\n        int tlim = 90;\n        if (heuristic_drills == 0) tlim = 350;\n        if (elapsed_ms() > 2200.0) tlim = 20;\n\n        vector<State> cand = find_candidates(10, tlim);\n        if (cand.empty()) {\n            fallback_drill_all_and_answer();\n        }\n\n        bitset<MAXC> bestMask = cand[0].uni;\n        string key = mask_key(bestMask);\n\n        bool can_try_answer =\n            guesses < 25 &&\n            op_cnt + unknown + 2 <= MAX_OPS &&\n            guessed.find(key) == guessed.end() &&\n            union_consistent_with_drills(bestMask);\n\n        if (can_try_answer) {\n            guessed.insert(key);\n            guesses++;\n            bool ok = ask_answer(bestMask);\n            if (ok) return 0;\n            wrong_same_count++;\n        }\n\n        unknown = 0;\n        for (int id = 0; id < C; id++) if (drilled[id] == -1) unknown++;\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        int cell = choose_drill_cell(cand, wrong_same_count);\n        if (cell == -1) {\n            fallback_drill_all_and_answer();\n        }\n\n        do_drill(cell);\n        heuristic_drills++;\n    }\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int W = 1000;\nusing ll = long long;\nusing ull = unsigned long long;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nstruct Option {\n    int l, r;          // inclusive\n    int h;\n    ll cost;\n    bool stat;\n};\n\nint D, N;\nvector<vector<int>> A;\nvector<int> maxA;\n\ninline int ceil_div(int x, int y) {\n    return (x + y - 1) / y;\n}\n\nstruct Scorer {\n    int HN = 999 * 1000;\n    int VN = 1000 * 999;\n    int HW, VW;\n\n    Scorer() {\n        HW = (HN + 63) >> 6;\n        VW = (VN + 63) >> 6;\n    }\n\n    inline void setbit(vector<ull>& b, int idx) const {\n        b[idx >> 6] |= 1ULL << (idx & 63);\n    }\n\n    ll score(const vector<vector<Rect>>& sol) const {\n        vector<ull> prevH(HW, 0), prevV(VW, 0), curH(HW), curV(VW);\n        ll total = 0;\n\n        for (int d = 0; d < D; d++) {\n            fill(curH.begin(), curH.end(), 0);\n            fill(curV.begin(), curV.end(), 0);\n\n            for (int k = 0; k < N; k++) {\n                const Rect& r = sol[d][k];\n\n                ll area = 1LL * (r.i1 - r.i0) * (r.j1 - r.j0);\n                if (area < A[d][k]) total += 100LL * (A[d][k] - area);\n\n                if (r.i0 > 0) {\n                    int row = r.i0 - 1;\n                    for (int x = r.j0; x < r.j1; x++) {\n                        setbit(curH, row * 1000 + x);\n                    }\n                }\n                if (r.i1 < W) {\n                    int row = r.i1 - 1;\n                    for (int x = r.j0; x < r.j1; x++) {\n                        setbit(curH, row * 1000 + x);\n                    }\n                }\n                if (r.j0 > 0) {\n                    int col = r.j0 - 1;\n                    for (int y = r.i0; y < r.i1; y++) {\n                        setbit(curV, y * 999 + col);\n                    }\n                }\n                if (r.j1 < W) {\n                    int col = r.j1 - 1;\n                    for (int y = r.i0; y < r.i1; y++) {\n                        setbit(curV, y * 999 + col);\n                    }\n                }\n            }\n\n            if (d > 0) {\n                for (int i = 0; i < HW; i++) total += __builtin_popcountll(prevH[i] ^ curH[i]);\n                for (int i = 0; i < VW; i++) total += __builtin_popcountll(prevV[i] ^ curV[i]);\n            }\n\n            prevH.swap(curH);\n            prevV.swap(curV);\n        }\n\n        return total;\n    }\n};\n\nvector<vector<Rect>> make_empty_solution() {\n    return vector<vector<Rect>>(D, vector<Rect>(N));\n}\n\nvector<vector<Rect>> stable_shelf_dp() {\n    int K = N + 1;\n    int HD = 1001;\n\n    vector<int> pref(HD * D * K, 0);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) {\n                P(h, d, k + 1) = P(h, d, k) + ceil_div(A[d][k], h);\n            }\n        }\n    }\n\n    vector<int> prefMax(HD * K, 0);\n    auto PM = [&](int h, int k) -> int& {\n        return prefMax[h * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        PM(h, 0) = 0;\n        for (int k = 0; k < N; k++) {\n            PM(h, k + 1) = PM(h, k) + ceil_div(maxA[k], h);\n        }\n    }\n\n    auto dyn_feasible = [&](int l, int r, int h) {\n        for (int d = 0; d < D; d++) {\n            int s = P(h, d, r + 1) - P(h, d, l);\n            if (s > W) return false;\n        }\n        return true;\n    };\n\n    auto stat_feasible = [&](int l, int r, int h) {\n        int s = PM(h, r + 1) - PM(h, l);\n        return s <= W;\n    };\n\n    auto dyn_cost = [&](int l, int r, int h) -> ll {\n        int m = r - l + 1;\n        if (m <= 1) return 0;\n\n        ll res = 0;\n        vector<int> a, b;\n        a.reserve(m - 1);\n        b.reserve(m - 1);\n\n        for (int d = 1; d < D; d++) {\n            a.clear();\n            b.clear();\n\n            for (int t = l; t < r; t++) {\n                a.push_back(P(h, d - 1, t + 1) - P(h, d - 1, l));\n                b.push_back(P(h, d, t + 1) - P(h, d, l));\n            }\n\n            int i = 0, j = 0, common = 0;\n            while (i < (int)a.size() && j < (int)b.size()) {\n                if (a[i] == b[j]) {\n                    common++;\n                    i++;\n                    j++;\n                } else if (a[i] < b[j]) {\n                    i++;\n                } else {\n                    j++;\n                }\n            }\n\n            int sym = 2 * (m - 1) - 2 * common;\n            res += 1LL * sym * h;\n        }\n\n        return res;\n    };\n\n    vector<Option> opts;\n    vector<vector<int>> byStart(N);\n\n    for (int l = 0; l < N; l++) {\n        for (int r = l; r < N; r++) {\n            int hmin = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (dyn_feasible(l, r, h)) {\n                    hmin = h;\n                    break;\n                }\n            }\n            if (hmin == -1) continue;\n\n            vector<Option> tmp;\n\n            auto add_dyn = [&](int h) {\n                if (h < hmin || h > 1000) return;\n                if (!dyn_feasible(l, r, h)) return;\n                tmp.push_back({l, r, h, dyn_cost(l, r, h), false});\n            };\n\n            add_dyn(hmin);\n            for (int x = 1; x <= 5; x++) add_dyn(hmin + x);\n\n            vector<pair<int,int>> fs = {\n                {11,10}, {6,5}, {5,4}, {4,3}, {3,2},\n                {2,1}, {5,2}, {3,1}, {4,1}, {5,1}\n            };\n            for (auto [num, den] : fs) {\n                int h = (hmin * num + den - 1) / den;\n                add_dyn(h);\n            }\n\n            int hs = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (stat_feasible(l, r, h)) {\n                    hs = h;\n                    break;\n                }\n            }\n            if (hs != -1) tmp.push_back({l, r, hs, 0, true});\n\n            sort(tmp.begin(), tmp.end(), [](const Option& a, const Option& b) {\n                if (a.h != b.h) return a.h < b.h;\n                if (a.cost != b.cost) return a.cost < b.cost;\n                return a.stat > b.stat;\n            });\n\n            vector<Option> uniq;\n            for (auto &op : tmp) {\n                if (uniq.empty() || uniq.back().h != op.h) {\n                    uniq.push_back(op);\n                } else if (op.cost < uniq.back().cost) {\n                    uniq.back() = op;\n                }\n            }\n\n            ll best = (1LL << 60);\n            for (auto &op : uniq) {\n                if (op.cost < best) {\n                    best = op.cost;\n                    int id = (int)opts.size();\n                    opts.push_back(op);\n                    byStart[l].push_back(id);\n                }\n            }\n        }\n    }\n\n    const ll INF = (1LL << 60);\n    vector<vector<ll>> dp(N + 1, vector<ll>(1001, INF));\n    vector<vector<int>> parH(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parK(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parO(N + 1, vector<int>(1001, -1));\n\n    dp[0][0] = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int used = 0; used <= 1000; used++) {\n            if (dp[i][used] == INF) continue;\n\n            for (int id : byStart[i]) {\n                const Option& op = opts[id];\n                int nu = used + op.h;\n                if (nu > 1000) continue;\n\n                int ni = op.r + 1;\n                ll nv = dp[i][used] + op.cost;\n                if (nv < dp[ni][nu]) {\n                    dp[ni][nu] = nv;\n                    parH[ni][nu] = used;\n                    parK[ni][nu] = i;\n                    parO[ni][nu] = id;\n                }\n            }\n        }\n    }\n\n    int bestH = -1;\n    ll bestV = INF;\n    for (int h = 0; h <= 1000; h++) {\n        if (dp[N][h] < bestV) {\n            bestV = dp[N][h];\n            bestH = h;\n        }\n    }\n\n    if (bestH == -1 || bestV == INF) return {};\n\n    vector<Option> rows;\n    int curK = N, curH = bestH;\n    while (curK > 0) {\n        int id = parO[curK][curH];\n        if (id < 0) return {};\n        rows.push_back(opts[id]);\n\n        int pk = parK[curK][curH];\n        int ph = parH[curK][curH];\n        curK = pk;\n        curH = ph;\n    }\n\n    reverse(rows.begin(), rows.end());\n\n    auto sol = make_empty_solution();\n\n    int y = 0;\n    for (auto &op : rows) {\n        int l = op.l, r = op.r, h = op.h;\n\n        if (op.stat) {\n            vector<int> widths(r - l + 1);\n            int sum = 0;\n            for (int k = l; k < r; k++) {\n                widths[k - l] = ceil_div(maxA[k], h);\n                sum += widths[k - l];\n            }\n            widths[r - l] = W - sum;\n\n            for (int d = 0; d < D; d++) {\n                int x = 0;\n                for (int k = l; k <= r; k++) {\n                    int w = widths[k - l];\n                    sol[d][k] = {y, x, y + h, x + w};\n                    x += w;\n                }\n            }\n        } else {\n            for (int d = 0; d < D; d++) {\n                vector<int> widths(r - l + 1);\n                int sum = 0;\n                for (int k = l; k < r; k++) {\n                    widths[k - l] = ceil_div(A[d][k], h);\n                    sum += widths[k - l];\n                }\n                widths[r - l] = W - sum;\n\n                int x = 0;\n                for (int k = l; k <= r; k++) {\n                    int w = widths[k - l];\n                    sol[d][k] = {y, x, y + h, x + w};\n                    x += w;\n                }\n            }\n        }\n\n        y += h;\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> day_shelf_solution() {\n    int K = N + 1;\n    int HD = 1001;\n\n    vector<int> pref(HD * D * K, 0);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) {\n                P(h, d, k + 1) = P(h, d, k) + ceil_div(A[d][k], h);\n            }\n        }\n    }\n\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        vector<vector<int>> hmin(N, vector<int>(N, -1));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l; r < N; r++) {\n                for (int h = 1; h <= 1000; h++) {\n                    int s = P(h, d, r + 1) - P(h, d, l);\n                    if (s <= W) {\n                        hmin[l][r] = h;\n                        break;\n                    }\n                }\n            }\n        }\n\n        const int INF = 1e9;\n        vector<int> dp(N + 1, INF), par(N + 1, -1);\n        dp[0] = 0;\n\n        for (int i = 0; i < N; i++) {\n            if (dp[i] == INF) continue;\n            for (int r = i; r < N; r++) {\n                int h = hmin[i][r];\n                if (h < 0) continue;\n                if (dp[i] + h < dp[r + 1]) {\n                    dp[r + 1] = dp[i] + h;\n                    par[r + 1] = i;\n                }\n            }\n        }\n\n        if (dp[N] > 1000) return {};\n\n        vector<pair<int,int>> rows;\n        int cur = N;\n        while (cur > 0) {\n            int p = par[cur];\n            if (p < 0) return {};\n            rows.push_back({p, cur - 1});\n            cur = p;\n        }\n        reverse(rows.begin(), rows.end());\n\n        int y = 0;\n        for (auto [l, r] : rows) {\n            int h = hmin[l][r];\n\n            int x = 0;\n            for (int k = l; k < r; k++) {\n                int w = ceil_div(A[d][k], h);\n                sol[d][k] = {y, x, y + h, x + w};\n                x += w;\n            }\n            sol[d][r] = {y, x, y + h, W};\n\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\nvector<int> allocate_single_day_heights(int d) {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) -> int {\n        int rem = A[d][k] - h[k] * W;\n        if (rem <= 0) return 0;\n        return min(W, rem);\n    };\n\n    priority_queue<pair<int,int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n        if (b <= 0) break;\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<int> allocate_static_heights() {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) -> int {\n        int res = 0;\n        for (int d = 0; d < D; d++) {\n            int rem = A[d][k] - h[k] * W;\n            if (rem > 0) res += min(W, rem);\n        }\n        return res;\n    };\n\n    priority_queue<pair<int,int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n        if (b <= 0) break;\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<vector<Rect>> singleton_dynamic_solution() {\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        vector<int> h = allocate_single_day_heights(d);\n        int y = 0;\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> singleton_static_solution() {\n    auto sol = make_empty_solution();\n    vector<int> h = allocate_static_heights();\n\n    for (int d = 0; d < D; d++) {\n        int y = 0;\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nbool valid_solution(const vector<vector<Rect>>& sol) {\n    if ((int)sol.size() != D) return false;\n    for (int d = 0; d < D; d++) {\n        if ((int)sol[d].size() != N) return false;\n        for (int k = 0; k < N; k++) {\n            auto r = sol[d][k];\n            if (!(0 <= r.i0 && r.i0 < r.i1 && r.i1 <= W)) return false;\n            if (!(0 <= r.j0 && r.j0 < r.j1 && r.j1 <= W)) return false;\n        }\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inputW;\n    cin >> inputW >> D >> N;\n\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    maxA.assign(N, 0);\n    for (int k = 0; k < N; k++) {\n        for (int d = 0; d < D; d++) maxA[k] = max(maxA[k], A[d][k]);\n    }\n\n    vector<vector<vector<Rect>>> candidates;\n\n    {\n        auto s = stable_shelf_dp();\n        if (valid_solution(s)) candidates.push_back(move(s));\n    }\n    {\n        auto s = day_shelf_solution();\n        if (valid_solution(s)) candidates.push_back(move(s));\n    }\n    {\n        auto s = singleton_dynamic_solution();\n        if (valid_solution(s)) candidates.push_back(move(s));\n    }\n    {\n        auto s = singleton_static_solution();\n        if (valid_solution(s)) candidates.push_back(move(s));\n    }\n\n    Scorer scorer;\n    ll bestScore = (1LL << 62);\n    int bestId = 0;\n\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        ll sc = scorer.score(candidates[i]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestId = i;\n        }\n    }\n\n    const auto& ans = candidates[bestId];\n\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            const Rect& r = ans[d][k];\n            cout << r.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 NN = 9;\nstatic constexpr int POS = 7;\nstatic constexpr int KK = 81;\nstatic constexpr int MOD = 998244353;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int nextInt(int n) {\n        return int(next() % n);\n    }\n\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstruct Action {\n    int m, p, q;\n    int cell[9];\n    int val[9];\n};\n\nstruct State {\n    array<int, 81> board;\n    array<int, 81> seq;\n    long long score;\n};\n\nclass Solver {\nprivate:\n    int N, M, K;\n    int S[20][3][3];\n\n    vector<Action> actions;\n    int DUMMY;\n\n    array<int, 81> initialBoard;\n    long long initialScore = 0;\n\n    chrono::steady_clock::time_point startTime;\n    const double TIME_LIMIT = 1.85;\n\n    XorShift rng;\n\n    double elapsed() const {\n        auto now = chrono::steady_clock::now();\n        return chrono::duration<double>(now - startTime).count();\n    }\n\n    bool timeOver() const {\n        return elapsed() >= TIME_LIMIT;\n    }\n\n    inline long long gainAdd(const array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long gain = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv + a.val[k];\n            if (nv >= MOD) nv -= MOD;\n            gain += (long long)nv - oldv;\n        }\n\n        return gain;\n    }\n\n    inline long long applyAdd(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv + a.val[k];\n            if (nv >= MOD) nv -= MOD;\n            board[c] = nv;\n            diff += (long long)nv - oldv;\n        }\n\n        return diff;\n    }\n\n    inline long long applyRemove(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv - a.val[k];\n            if (nv < 0) nv += MOD;\n            board[c] = nv;\n            diff += (long long)nv - oldv;\n        }\n\n        return diff;\n    }\n\n    State makeEmptyState() const {\n        State st;\n        st.board = initialBoard;\n        st.score = initialScore;\n        st.seq.fill(DUMMY);\n        return st;\n    }\n\n    State makeGreedyState() {\n        State st = makeEmptyState();\n\n        for (int t = 0; t < KK; t++) {\n            long long bestGain = 0;\n            int bestAct = DUMMY;\n\n            for (int id = 0; id < DUMMY; id++) {\n                long long g = gainAdd(st.board, id);\n                if (g > bestGain) {\n                    bestGain = g;\n                    bestAct = id;\n                }\n            }\n\n            st.seq[t] = bestAct;\n            if (bestAct != DUMMY) {\n                st.score += applyAdd(st.board, bestAct);\n            }\n        }\n\n        return st;\n    }\n\n    State makeRandomState() {\n        State st = makeEmptyState();\n\n        for (int t = 0; t < KK; t++) {\n            int id = rng.nextInt(DUMMY);\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    void shuffleOrder(array<int, 81>& ord) {\n        for (int i = KK - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    void coordinateDescent(State& st, int maxPass) {\n        array<int, 81> ord;\n        for (int i = 0; i < KK; i++) ord[i] = i;\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            if (timeOver()) return;\n\n            shuffleOrder(ord);\n            bool changed = false;\n\n            for (int oi = 0; oi < KK; oi++) {\n                if ((oi & 7) == 0 && timeOver()) return;\n\n                int idx = ord[oi];\n                int oldAct = st.seq[idx];\n\n                if (oldAct != DUMMY) {\n                    st.score += applyRemove(st.board, oldAct);\n                }\n\n                long long bestGain = 0;\n                int bestAct = DUMMY;\n\n                for (int id = 0; id < DUMMY; id++) {\n                    long long g = gainAdd(st.board, id);\n                    if (g > bestGain) {\n                        bestGain = g;\n                        bestAct = id;\n                    }\n                }\n\n                st.seq[idx] = bestAct;\n                if (bestAct != DUMMY) {\n                    st.score += applyAdd(st.board, bestAct);\n                }\n\n                if (bestAct != oldAct) changed = true;\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void perturb(State& st, int strength) {\n        for (int r = 0; r < strength; r++) {\n            int idx = rng.nextInt(KK);\n            int oldAct = st.seq[idx];\n\n            if (oldAct != DUMMY) {\n                st.score += applyRemove(st.board, oldAct);\n            }\n\n            int newAct = rng.nextInt(DUMMY);\n            st.seq[idx] = newAct;\n            st.score += applyAdd(st.board, newAct);\n        }\n    }\n\npublic:\n    void readInput() {\n        cin >> N >> M >> K;\n\n        uint64_t seed = 123456789;\n\n        for (int i = 0; i < NN; i++) {\n            for (int j = 0; j < NN; j++) {\n                int x;\n                cin >> x;\n                initialBoard[i * NN + j] = x;\n                initialScore += x;\n                seed ^= uint64_t(x + 1) * 1000003ULL;\n                seed = seed * 11995408973635179863ULL + 101;\n            }\n        }\n\n        for (int m = 0; m < M; m++) {\n            for (int i = 0; i < 3; i++) {\n                for (int j = 0; j < 3; j++) {\n                    cin >> S[m][i][j];\n                    seed ^= uint64_t(S[m][i][j] + 7) * 1000000007ULL;\n                    seed = seed * 1000003ULL + 97;\n                }\n            }\n        }\n\n        rng = XorShift(seed);\n    }\n\n    void buildActions() {\n        actions.clear();\n\n        for (int p = 0; p <= NN - 3; p++) {\n            for (int q = 0; q <= NN - 3; q++) {\n                for (int m = 0; m < M; m++) {\n                    Action a;\n                    a.m = m;\n                    a.p = p;\n                    a.q = q;\n\n                    int idx = 0;\n                    for (int di = 0; di < 3; di++) {\n                        for (int dj = 0; dj < 3; dj++) {\n                            a.cell[idx] = (p + di) * NN + (q + dj);\n                            a.val[idx] = S[m][di][dj];\n                            idx++;\n                        }\n                    }\n\n                    actions.push_back(a);\n                }\n            }\n        }\n\n        DUMMY = (int)actions.size();\n    }\n\n    void solve() {\n        startTime = chrono::steady_clock::now();\n\n        buildActions();\n\n        State best = makeGreedyState();\n        coordinateDescent(best, 1000);\n\n        int iter = 0;\n\n        while (!timeOver()) {\n            State cand;\n\n            if (iter % 10 == 9) {\n                cand = makeRandomState();\n                coordinateDescent(cand, 40);\n            } else {\n                cand = best;\n\n                int strength;\n                if (iter % 20 == 19) {\n                    strength = 14 + rng.nextInt(8);\n                } else {\n                    strength = 2 + (iter % 8);\n                }\n\n                perturb(cand, strength);\n                coordinateDescent(cand, 30);\n            }\n\n            if (cand.score > best.score) {\n                best = cand;\n            }\n\n            iter++;\n        }\n\n        vector<tuple<int, int, int>> answer;\n\n        for (int i = 0; i < KK; i++) {\n            int id = best.seq[i];\n            if (id == DUMMY) continue;\n\n            const Action& a = actions[id];\n            answer.emplace_back(a.m, a.p, a.q);\n        }\n\n        cout << answer.size() << '\\n';\n        for (auto [m, p, q] : answer) {\n            cout << m << ' ' << p << ' ' << q << '\\n';\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\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static constexpr int N = 5;\n\n    vector<vector<int>> A;\n    int grid[N][N];\n    int idx[N];\n\n    int cr = 0, cc = 0;\n    int hold = -1;\n\n    vector<string> S;\n    bool first_step = true;\n\n    vector<int> nextNeed;\n    vector<int> delivered;\n    int deliveredCnt = 0;\n\n    Solver(const vector<vector<int>>& A_) : A(A_) {\n        memset(grid, -1, sizeof(grid));\n        memset(idx, 0, sizeof(idx));\n        S.assign(N, \"\");\n        nextNeed.resize(N);\n        delivered.assign(N * N, 0);\n        for (int g = 0; g < N; g++) nextNeed[g] = g * N;\n    }\n\n    int dist(pair<int,int> a, pair<int,int> b) {\n        return abs(a.first - b.first) + abs(a.second - b.second);\n    }\n\n    void step(char act) {\n        // 1. arrivals\n        for (int r = 0; r < N; r++) {\n            bool blocked_by_holding_crane = (hold != -1 && cr == r && cc == 0);\n            if (idx[r] < N && grid[r][0] == -1 && !blocked_by_holding_crane) {\n                grid[r][0] = A[r][idx[r]];\n                idx[r]++;\n            }\n        }\n\n        // output operation\n        S[0].push_back(act);\n        for (int i = 1; i < N; i++) {\n            if (first_step) S[i].push_back('B');\n            else S[i].push_back('.');\n        }\n        first_step = false;\n\n        // 2. action of the large crane\n        if (act == 'P') {\n            hold = grid[cr][cc];\n            grid[cr][cc] = -1;\n        } else if (act == 'Q') {\n            grid[cr][cc] = hold;\n            hold = -1;\n        } else if (act == 'U') {\n            cr--;\n        } else if (act == 'D') {\n            cr++;\n        } else if (act == 'L') {\n            cc--;\n        } else if (act == 'R') {\n            cc++;\n        }\n\n        // 3. dispatch\n        for (int r = 0; r < N; r++) {\n            if (grid[r][N - 1] != -1) {\n                grid[r][N - 1] = -1;\n            }\n        }\n    }\n\n    void moveTo(int r, int c) {\n        while (cr < r) step('D');\n        while (cr > r) step('U');\n        while (cc < c) step('R');\n        while (cc > c) step('L');\n    }\n\n    void pickAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('P');\n    }\n\n    void releaseAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('Q');\n    }\n\n    void markDelivered(int id) {\n        if (!delivered[id]) {\n            delivered[id] = 1;\n            deliveredCnt++;\n        }\n        int g = id / N;\n        while (nextNeed[g] < (g + 1) * N && delivered[nextNeed[g]]) {\n            nextNeed[g]++;\n        }\n    }\n\n    optional<pair<int,int>> findAccessible(int id) {\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (grid[r][c] == id) return pair<int,int>{r, c};\n            }\n        }\n\n        // A hidden next container at an empty receiving gate is accessible:\n        // it will appear at the beginning of the next turn.\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == id) {\n                return pair<int,int>{r, 0};\n            }\n        }\n\n        return nullopt;\n    }\n\n    int frontId(int r) {\n        if (grid[r][0] != -1) return grid[r][0];\n        if (idx[r] < N) return A[r][idx[r]];\n        return -1;\n    }\n\n    vector<pair<int,int>> freeStorageCells() {\n        vector<pair<int,int>> res;\n\n        // Main storage: inner 15 cells.\n        for (int r = 0; r < N; r++) {\n            for (int c = 1; c <= 3; c++) {\n                if (grid[r][c] == -1) res.push_back({r, c});\n            }\n        }\n\n        // Receiving gates whose input has already been exhausted are also safe storage.\n        for (int r = 0; r < N; r++) {\n            if (idx[r] >= N && grid[r][0] == -1) {\n                res.push_back({r, 0});\n            }\n        }\n\n        return res;\n    }\n\n    pair<int,int> chooseStorageCell(pair<int,int> from) {\n        auto cells = freeStorageCells();\n        pair<int,int> best = cells[0];\n        int bestCost = 1e9;\n\n        for (auto p : cells) {\n            int cost = dist(from, p);\n            if (cost < bestCost) {\n                bestCost = cost;\n                best = p;\n            }\n        }\n\n        return best;\n    }\n\n    void dispatchContainer(int id) {\n        auto srcOpt = findAccessible(id);\n        if (!srcOpt) return;\n\n        auto src = *srcOpt;\n        pickAt(src);\n\n        int g = id / N;\n        releaseAt({g, N - 1});\n\n        markDelivered(id);\n    }\n\n    void storeFrontContainer(int r) {\n        int id = frontId(r);\n        if (id == -1) return;\n\n        pair<int,int> src = {r, 0};\n        auto dst = chooseStorageCell(src);\n\n        pickAt(src);\n        releaseAt(dst);\n    }\n\n    int depthToNeeded(int r) {\n        set<int> need;\n        for (int g = 0; g < N; g++) {\n            if (nextNeed[g] < (g + 1) * N) need.insert(nextNeed[g]);\n        }\n\n        int d = 0;\n\n        if (grid[r][0] != -1) {\n            if (need.count(grid[r][0])) return 0;\n            d = 1;\n        }\n\n        for (int k = idx[r]; k < N; k++, d++) {\n            if (need.count(A[r][k])) return d;\n        }\n\n        return 100;\n    }\n\n    int chooseRowToDig() {\n        int bestRow = -1;\n        int bestDepth = 1e9;\n        int bestDist = 1e9;\n\n        for (int r = 0; r < N; r++) {\n            int f = frontId(r);\n            if (f == -1) continue;\n\n            // If this row has no hidden future containers, digging it does not unlock much.\n            if (idx[r] >= N && grid[r][0] != -1) continue;\n\n            int dep = depthToNeeded(r);\n            int dcur = abs(cr - r) + cc;\n\n            if (dep < bestDepth || (dep == bestDepth && dcur < bestDist)) {\n                bestDepth = dep;\n                bestDist = dcur;\n                bestRow = r;\n            }\n        }\n\n        if (bestRow != -1) return bestRow;\n\n        // Fallback: any row with a front container.\n        for (int r = 0; r < N; r++) {\n            if (frontId(r) != -1) return r;\n        }\n\n        return -1;\n    }\n\n    vector<pair<int,pair<int,int>>> accessibleCandidates() {\n        vector<pair<int,pair<int,int>>> res;\n        bool seen[N * N] = {};\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                int id = grid[r][c];\n                if (id != -1 && !delivered[id] && !seen[id]) {\n                    seen[id] = true;\n                    res.push_back({id, {r, c}});\n                }\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N) {\n                int id = A[r][idx[r]];\n                if (!delivered[id] && !seen[id]) {\n                    seen[id] = true;\n                    res.push_back({id, {r, 0}});\n                }\n            }\n        }\n\n        return res;\n    }\n\n    int missingSmallerInGroup(int id) {\n        int g = id / N;\n        int cnt = 0;\n        for (int x = g * N; x < id; x++) {\n            if (!delivered[x]) cnt++;\n        }\n        return cnt;\n    }\n\n    int chooseFallbackDispatch() {\n        auto cand = accessibleCandidates();\n\n        int bestId = -1;\n        tuple<int,int,int> best = {1e9, 1e9, 1e9};\n\n        for (auto [id, pos] : cand) {\n            int g = id / N;\n            int invRisk = missingSmallerInGroup(id);\n            int cost = dist({cr, cc}, pos) + dist(pos, {g, N - 1});\n\n            tuple<int,int,int> key = {invRisk, cost, id};\n            if (key < best) {\n                best = key;\n                bestId = id;\n            }\n        }\n\n        return bestId;\n    }\n\n    void solve() {\n        while (deliveredCnt < N * N && (int)S[0].size() < 9500) {\n            int bestId = -1;\n            pair<int,int> bestSrc;\n            int bestCost = 1e9;\n\n            // Prefer dispatching the exact next needed container for some gate.\n            for (int g = 0; g < N; g++) {\n                if (nextNeed[g] >= (g + 1) * N) continue;\n\n                int id = nextNeed[g];\n                auto srcOpt = findAccessible(id);\n                if (!srcOpt) continue;\n\n                auto src = *srcOpt;\n                int cost = dist({cr, cc}, src) + dist(src, {g, N - 1});\n\n                if (cost < bestCost) {\n                    bestCost = cost;\n                    bestId = id;\n                    bestSrc = src;\n                }\n            }\n\n            if (bestId != -1) {\n                dispatchContainer(bestId);\n                continue;\n            }\n\n            // Otherwise, store a blocking front container if possible.\n            auto freeCells = freeStorageCells();\n            if (!freeCells.empty()) {\n                int r = chooseRowToDig();\n                if (r != -1) {\n                    storeFrontContainer(r);\n                    continue;\n                }\n            }\n\n            // Storage full: dispatch something out of order but to its correct gate.\n            int id = chooseFallbackDispatch();\n            if (id != -1) {\n                dispatchContainer(id);\n                continue;\n            }\n\n            // Should not happen, but keep output valid.\n            step('.');\n        }\n\n        // If all containers are not delivered due to some unexpected situation,\n        // keep the output valid. Usually this is unnecessary.\n        if (S[0].empty()) step('.');\n    }\n\n    void output() {\n        int T = 0;\n        for (auto &s : S) T = max(T, (int)s.size());\n\n        for (auto &s : S) {\n            while ((int)s.size() < T) s.push_back('.');\n        }\n\n        for (int i = 0; i < N; i++) {\n            cout << S[i] << '\\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\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> A[i][j];\n    }\n\n    Solver solver(A);\n    solver.solve();\n    solver.output();\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int B = 10;\nstatic const int V = N * N;\n\nint hval[V];\nlong long base_cost = 0;\n\nint dr[4] = {-1, 0, 1, 0};\nint dc[4] = {0, 1, 0, -1};\nchar mvchar[4] = {'U', 'R', 'D', 'L'};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int a, b;\n};\n\nstruct Best {\n    long long cost = (1LL << 60);\n    vector<int> order;\n};\n\nint id20(int r, int c) {\n    return r * N + c;\n}\n\nint dir_between(int a, int b) {\n    int ar = a / N, ac = a % N;\n    int br = b / N, bc = b % N;\n    for (int d = 0; d < 4; d++) {\n        if (ar + dr[d] == br && ac + dc[d] == bc) return d;\n    }\n    return -1;\n}\n\nvoid add_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n    if (d < 0 || e < 0) return;\n    mask[a] |= (1u << d);\n    mask[b] |= (1u << e);\n}\n\nvoid remove_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n    if (d < 0 || e < 0) return;\n    mask[a] &= ~(1u << d);\n    mask[b] &= ~(1u << e);\n}\n\nbool build_cycle_from_tree(const vector<Edge>& tree_edges, vector<int>& cyc) {\n    array<unsigned char, V> mask;\n    mask.fill(0);\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int a = id20(2 * r, 2 * c);\n            int b = id20(2 * r, 2 * c + 1);\n            int e = id20(2 * r + 1, 2 * c + 1);\n            int d = id20(2 * r + 1, 2 * c);\n\n            add_edge_cell(mask, a, b);\n            add_edge_cell(mask, b, e);\n            add_edge_cell(mask, e, d);\n            add_edge_cell(mask, d, a);\n        }\n    }\n\n    for (auto ed : tree_edges) {\n        int ar = ed.a / B, ac = ed.a % B;\n        int br = ed.b / B, bc = ed.b % B;\n\n        if (ar == br) {\n            int r = ar;\n            int c = min(ac, bc);\n\n            int a1 = id20(2 * r, 2 * c + 1);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r, 2 * c + 2);\n            int b2 = id20(2 * r + 1, 2 * c + 2);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        } else {\n            int r = min(ar, br);\n            int c = ac;\n\n            int a1 = id20(2 * r + 1, 2 * c);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r + 2, 2 * c);\n            int b2 = id20(2 * r + 2, 2 * c + 1);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        }\n    }\n\n    for (int i = 0; i < V; i++) {\n        if (__builtin_popcount((int)mask[i]) != 2) return false;\n    }\n\n    cyc.clear();\n    int start = 0;\n    int cur = start;\n    int prev = -1;\n\n    while (true) {\n        cyc.push_back(cur);\n\n        int nxt = -1;\n        for (int d = 0; d < 4; d++) {\n            if (!(mask[cur] & (1u << d))) continue;\n            int r = cur / N + dr[d];\n            int c = cur % N + dc[d];\n            int nb = id20(r, c);\n            if (nb != prev) {\n                nxt = nb;\n                break;\n            }\n        }\n\n        if (nxt < 0) return false;\n\n        prev = cur;\n        cur = nxt;\n\n        if (cur == start) break;\n        if ((int)cyc.size() > V) return false;\n    }\n\n    return (int)cyc.size() == V;\n}\n\nvoid evaluate_cycle_order(const vector<int>& cyc, Best& best) {\n    const int L = V;\n    vector<int> pref(L + 1, 0);\n    for (int i = 0; i < L; i++) {\n        pref[i + 1] = pref[i] + hval[cyc[i]];\n    }\n\n    int mn = pref[0];\n    for (int i = 0; i < L; i++) mn = min(mn, pref[i]);\n\n    for (int k = 0; k < L; k++) {\n        if (pref[k] != mn) continue;\n\n        long long load = 0;\n        long long load_move_cost = 0;\n        bool ok = true;\n\n        for (int t = 0; t < L; t++) {\n            int id = cyc[(k + t) % L];\n            load += hval[id];\n            if (load < 0) {\n                ok = false;\n                break;\n            }\n            if (t != L - 1) load_move_cost += load;\n        }\n\n        if (!ok || load != 0) continue;\n\n        int st = cyc[k];\n        int sr = st / N;\n        int sc = st % N;\n        int empty_dist = sr + sc;\n\n        long long cost = base_cost + 100LL * (empty_dist + L - 1) + load_move_cost;\n\n        if (cost < best.cost) {\n            best.cost = cost;\n            best.order.clear();\n            best.order.reserve(L);\n            for (int t = 0; t < L; t++) {\n                best.order.push_back(cyc[(k + t) % L]);\n            }\n        }\n    }\n}\n\nvoid evaluate_cycle(const vector<int>& cyc, Best& best) {\n    evaluate_cycle_order(cyc, best);\n\n    vector<int> rev = cyc;\n    reverse(rev.begin(), rev.end());\n    evaluate_cycle_order(rev, best);\n}\n\nvector<Edge> make_row_tree(int col) {\n    vector<Edge> res;\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c + 1 < B; c++) {\n            res.push_back({r * B + c, r * B + c + 1});\n        }\n    }\n\n    for (int r = 0; r + 1 < B; r++) {\n        res.push_back({r * B + col, (r + 1) * B + col});\n    }\n\n    return res;\n}\n\nvector<Edge> make_col_tree(int row) {\n    vector<Edge> res;\n\n    for (int c = 0; c < B; c++) {\n        for (int r = 0; r + 1 < B; r++) {\n            res.push_back({r * B + c, (r + 1) * B + c});\n        }\n    }\n\n    for (int c = 0; c + 1 < B; c++) {\n        res.push_back({row * B + c, row * B + c + 1});\n    }\n\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            hval[id20(i, j)] = x;\n            base_cost += abs(x);\n        }\n    }\n\n    if (base_cost == 0) {\n        return 0;\n    }\n\n    Best best;\n\n    vector<int> cyc;\n\n    for (int c = 0; c < B; c++) {\n        auto tr = make_row_tree(c);\n        if (build_cycle_from_tree(tr, cyc)) evaluate_cycle(cyc, best);\n    }\n\n    for (int r = 0; r < B; r++) {\n        auto tr = make_col_tree(r);\n        if (build_cycle_from_tree(tr, cyc)) evaluate_cycle(cyc, best);\n    }\n\n    vector<Edge> all_edges;\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int v = r * B + c;\n            if (r + 1 < B) all_edges.push_back({v, (r + 1) * B + c});\n            if (c + 1 < B) all_edges.push_back({v, r * B + c + 1});\n        }\n    }\n\n    vector<int> perm(all_edges.size());\n    iota(perm.begin(), perm.end(), 0);\n\n    mt19937 rng(123456789);\n\n    auto start_time = chrono::steady_clock::now();\n    int iter = 0;\n\n    while (true) {\n        if ((iter & 255) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > 1.75) break;\n        }\n        iter++;\n\n        shuffle(perm.begin(), perm.end(), rng);\n\n        DSU dsu(B * B);\n        vector<Edge> tree;\n        tree.reserve(B * B - 1);\n\n        for (int idx : perm) {\n            Edge e = all_edges[idx];\n            if (dsu.unite(e.a, e.b)) {\n                tree.push_back(e);\n                if ((int)tree.size() == B * B - 1) break;\n            }\n        }\n\n        if ((int)tree.size() != B * B - 1) continue;\n\n        if (build_cycle_from_tree(tree, cyc)) {\n            evaluate_cycle(cyc, best);\n        }\n    }\n\n    if (best.order.empty()) {\n        return 0;\n    }\n\n    vector<string> ans;\n\n    int first = best.order[0];\n    int tr = first / N;\n    int tc = first % N;\n\n    for (int i = 0; i < tr; i++) ans.push_back(\"D\");\n    for (int j = 0; j < tc; j++) ans.push_back(\"R\");\n\n    long long load = 0;\n\n    for (int idx = 0; idx < (int)best.order.size(); idx++) {\n        int id = best.order[idx];\n        int v = hval[id];\n\n        if (v > 0) {\n            ans.push_back(\"+\" + to_string(v));\n            load += v;\n        } else if (v < 0) {\n            ans.push_back(\"-\" + to_string(-v));\n            load += v;\n        }\n\n        if (idx + 1 < (int)best.order.size()) {\n            int a = best.order[idx];\n            int b = best.order[idx + 1];\n            int d = dir_between(a, b);\n            ans.push_back(string(1, mvchar[d]));\n        }\n    }\n\n    for (const string& s : ans) {\n        cout << s << '\\n';\n    }\n\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    int randint(int n) {\n        return (int)(next_u32() % n);\n    }\n\n    double uniform01() {\n        return (next_u32() >> 8) * (1.0 / 16777216.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int G = N * N;\n    const int K = 2 * N * (N - 1);\n\n    vector<vector<int>> X(K, vector<int>(M));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    vector<int> initialMax(M, 0);\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) {\n            initialMax[j] = max(initialMax[j], X[i][j]);\n        }\n    }\n\n    vector<pair<int, int>> edges;\n    vector<vector<int>> incident(G);\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j + 1 < N; j++) {\n            int a = id(i, j);\n            int b = id(i, j + 1);\n            int e = (int)edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n        }\n    }\n\n    for (int i = 0; i + 1 < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = id(i, j);\n            int b = id(i + 1, j);\n            int e = (int)edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n        }\n    }\n\n    vector<int> posOrder(G);\n    iota(posOrder.begin(), posOrder.end(), 0);\n    sort(posOrder.begin(), posOrder.end(), [&](int a, int b) {\n        int da = (int)incident[a].size();\n        int db = (int)incident[b].size();\n        if (da != db) return da > db;\n\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n        double ca = abs(ai - (N - 1) / 2.0) + abs(aj - (N - 1) / 2.0);\n        double cb = abs(bi - (N - 1) / 2.0) + abs(bj - (N - 1) / 2.0);\n        return ca < cb;\n    });\n\n    XorShift rng;\n\n    auto calc_delta = [&](const vector<int>& slots,\n                          const vector<vector<double>>& W,\n                          int a,\n                          int b) -> double {\n        if (a == b) return 0.0;\n        if (a >= G && b >= G) return 0.0;\n\n        double delta = 0.0;\n\n        for (auto [u, v] : edges) {\n            if (u != a && u != b && v != a && v != b) continue;\n\n            int su = slots[u];\n            int sv = slots[v];\n\n            int nsu = su;\n            int nsv = sv;\n\n            if (u == a) nsu = slots[b];\n            else if (u == b) nsu = slots[a];\n\n            if (v == a) nsv = slots[b];\n            else if (v == b) nsv = slots[a];\n\n            delta += W[nsu][nsv] - W[su][sv];\n        }\n\n        return delta;\n    };\n\n    auto total_score = [&](const vector<int>& slots,\n                           const vector<vector<double>>& W) -> double {\n        double s = 0.0;\n        for (auto [u, v] : edges) {\n            s += W[slots[u]][slots[v]];\n        }\n        return s;\n    };\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> sumValue(K, 0);\n        for (int i = 0; i < K; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) s += X[i][j];\n            sumValue[i] = s;\n        }\n\n        double progress = (T == 1 ? 1.0 : (double)turn / (T - 1));\n\n        // Earlier: more coordinate-wise potential.\n        // Later: more immediate high-tail potential.\n        double alpha = 0.45 * (1.0 - progress) + 0.08 * progress;\n        double tailCoef = 0.55 * (1.0 - progress) + 1.30 * progress;\n        double geneCoef = 0.08 * (1.0 - progress) + 0.02 * progress;\n\n        vector<vector<double>> W(K, vector<double>(K, 0.0));\n\n        for (int i = 0; i < K; i++) {\n            for (int j = i + 1; j < K; j++) {\n                double mu = 0.5 * (sumValue[i] + sumValue[j]);\n\n                double cmax = 0.0;\n                double diff2 = 0.0;\n                double gene = 0.0;\n\n                for (int l = 0; l < M; l++) {\n                    int a = X[i][l];\n                    int b = X[j][l];\n                    int mx = max(a, b);\n                    int d = a - b;\n\n                    cmax += mx;\n                    diff2 += (double)d * d;\n\n                    int den = max(1, initialMax[l]);\n                    gene += (double)mx * mx / den;\n                }\n\n                double sigma = 0.5 * sqrt(diff2);\n\n                double score = mu;\n                score += alpha * (cmax - mu);\n                score += tailCoef * sigma;\n                score += geneCoef * gene;\n\n                W[i][j] = W[j][i] = score;\n            }\n        }\n\n        // Seed potential: sum of good possible mating scores.\n        vector<pair<double, int>> potential;\n        potential.reserve(K);\n\n        for (int i = 0; i < K; i++) {\n            vector<double> v;\n            v.reserve(K - 1);\n            for (int j = 0; j < K; j++) {\n                if (i != j) v.push_back(W[i][j]);\n            }\n\n            nth_element(v.begin(), v.begin() + 8, v.end(), greater<double>());\n\n            double p = 0.0;\n            for (int k = 0; k < 8 && k < (int)v.size(); k++) p += v[k];\n\n            p += 0.20 * sumValue[i];\n            potential.push_back({p, i});\n        }\n\n        sort(potential.begin(), potential.end(), greater<pair<double, int>>());\n\n        vector<int> slots(K, -1);\n        vector<int> used(K, 0);\n\n        for (int k = 0; k < G; k++) {\n            int seed = potential[k].second;\n            int pos = posOrder[k];\n            slots[pos] = seed;\n            used[seed] = 1;\n        }\n\n        int ptr = G;\n        for (int i = 0; i < K; i++) {\n            if (!used[i]) {\n                slots[ptr++] = i;\n            }\n        }\n\n        double curScore = total_score(slots, W);\n\n        // Simulated annealing.\n        const int ITER = 90000;\n        const double T0 = 80.0;\n        const double T1 = 0.05;\n\n        for (int it = 0; it < ITER; it++) {\n            int a, b;\n\n            if (rng.randint(100) < 65) {\n                a = rng.randint(G);\n                b = rng.randint(K);\n            } else {\n                a = rng.randint(K);\n                b = rng.randint(K);\n            }\n\n            if (a == b) continue;\n            if (a >= G && b >= G) continue;\n\n            double delta = calc_delta(slots, W, a, b);\n\n            double ratio = (double)it / ITER;\n            double temp = T0 * (1.0 - ratio) + T1 * ratio;\n\n            bool accept = false;\n            if (delta >= 0.0) {\n                accept = true;\n            } else {\n                double prob = exp(delta / temp);\n                if (rng.uniform01() < prob) accept = true;\n            }\n\n            if (accept) {\n                swap(slots[a], slots[b]);\n                curScore += delta;\n            }\n        }\n\n        // Final greedy improvement.\n        for (int pass = 0; pass < 3; pass++) {\n            bool improved = false;\n\n            for (int a = 0; a < K; a++) {\n                for (int b = a + 1; b < K; b++) {\n                    if (a >= G && b >= G) continue;\n\n                    double delta = calc_delta(slots, W, a, b);\n                    if (delta > 1e-9) {\n                        swap(slots[a], slots[b]);\n                        curScore += delta;\n                        improved = true;\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n\n        // Output grid.\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << slots[id(i, j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // Read generated seeds.\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < M; j++) {\n                if (!(cin >> X[i][j])) return 0;\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nint manhattan(const Pos& a, const Pos& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    const int INF = 1e9;\n\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            int delta = INF;\n            int j1 = 0;\n\n            for (int j = 1; j <= n; j++) {\n                if (used[j]) continue;\n\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    vector<int> assignment(n, -1);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] != 0) {\n            assignment[p[j] - 1] = j - 1;\n        }\n    }\n\n    return assignment;\n}\n\nlong long eval_plan(\n    const vector<pair<int, int>>& plan,\n    const vector<Pos>& src,\n    const vector<Pos>& dst\n) {\n    if (plan.empty()) return 0;\n\n    long long cost = 0;\n\n    for (int i = 0; i < (int)plan.size(); i++) {\n        int s = plan[i].first;\n        int t = plan[i].second;\n\n        if (i > 0) {\n            int pt = plan[i - 1].second;\n            cost += manhattan(dst[pt], src[s]);\n        }\n\n        cost += manhattan(src[s], dst[t]);\n    }\n\n    return cost;\n}\n\nvector<pair<int, int>> plan_greedy_pair(\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    int alpha_num\n) {\n    int n = (int)src.size();\n\n    vector<int> remS(n), remT(n);\n    iota(remS.begin(), remS.end(), 0);\n    iota(remT.begin(), remT.end(), 0);\n\n    vector<pair<int, int>> plan;\n    bool has_cur = false;\n    Pos cur{0, 0};\n\n    while (!remS.empty()) {\n        long long best_score = (1LL << 60);\n        int best_si = -1;\n        int best_ti = -1;\n        int best_dcur = 0;\n        int best_dtr = 0;\n\n        for (int ai = 0; ai < (int)remS.size(); ai++) {\n            int s = remS[ai];\n            int dcur = has_cur ? manhattan(cur, src[s]) : 0;\n\n            for (int bi = 0; bi < (int)remT.size(); bi++) {\n                int t = remT[bi];\n                int dtr = manhattan(src[s], dst[t]);\n\n                long long score = 1LL * alpha_num * dcur + 2LL * dtr;\n\n                if (\n                    score < best_score ||\n                    (score == best_score && make_pair(dcur, dtr) < make_pair(best_dcur, best_dtr))\n                ) {\n                    best_score = score;\n                    best_si = ai;\n                    best_ti = bi;\n                    best_dcur = dcur;\n                    best_dtr = dtr;\n                }\n            }\n        }\n\n        int s = remS[best_si];\n        int t = remT[best_ti];\n\n        plan.push_back({s, t});\n        cur = dst[t];\n        has_cur = true;\n\n        remS[best_si] = remS.back();\n        remS.pop_back();\n\n        remT[best_ti] = remT.back();\n        remT.pop_back();\n    }\n\n    return plan;\n}\n\nvector<pair<int, int>> plan_greedy_nearest(\n    const vector<Pos>& src,\n    const vector<Pos>& dst\n) {\n    int n = (int)src.size();\n\n    vector<int> remS(n), remT(n);\n    iota(remS.begin(), remS.end(), 0);\n    iota(remT.begin(), remT.end(), 0);\n\n    vector<pair<int, int>> plan;\n    bool has_cur = false;\n    Pos cur{0, 0};\n\n    while (!remS.empty()) {\n        int best_si = -1;\n        int best_ti = -1;\n\n        if (!has_cur) {\n            int best = 1e9;\n\n            for (int ai = 0; ai < (int)remS.size(); ai++) {\n                int s = remS[ai];\n\n                for (int bi = 0; bi < (int)remT.size(); bi++) {\n                    int t = remT[bi];\n                    int d = manhattan(src[s], dst[t]);\n\n                    if (d < best) {\n                        best = d;\n                        best_si = ai;\n                        best_ti = bi;\n                    }\n                }\n            }\n        } else {\n            int best_source_dist = 1e9;\n            int best_source_nearest_target = 1e9;\n\n            for (int ai = 0; ai < (int)remS.size(); ai++) {\n                int s = remS[ai];\n                int dcur = manhattan(cur, src[s]);\n\n                int nearest_target = 1e9;\n                for (int t : remT) {\n                    nearest_target = min(nearest_target, manhattan(src[s], dst[t]));\n                }\n\n                if (\n                    dcur < best_source_dist ||\n                    (dcur == best_source_dist && nearest_target < best_source_nearest_target)\n                ) {\n                    best_source_dist = dcur;\n                    best_source_nearest_target = nearest_target;\n                    best_si = ai;\n                }\n            }\n\n            int s = remS[best_si];\n            int best = 1e9;\n\n            for (int bi = 0; bi < (int)remT.size(); bi++) {\n                int t = remT[bi];\n                int d = manhattan(src[s], dst[t]);\n\n                if (d < best) {\n                    best = d;\n                    best_ti = bi;\n                }\n            }\n        }\n\n        int s = remS[best_si];\n        int t = remT[best_ti];\n\n        plan.push_back({s, t});\n        cur = dst[t];\n        has_cur = true;\n\n        remS[best_si] = remS.back();\n        remS.pop_back();\n\n        remT[best_ti] = remT.back();\n        remT.pop_back();\n    }\n\n    return plan;\n}\n\nvector<pair<int, int>> plan_hungarian_ordered(\n    const vector<Pos>& src,\n    const vector<Pos>& dst\n) {\n    int n = (int)src.size();\n\n    vector<vector<int>> cost(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cost[i][j] = manhattan(src[i], dst[j]);\n        }\n    }\n\n    vector<int> assign = hungarian(cost);\n\n    vector<pair<int, int>> best_plan;\n    long long best_cost = (1LL << 60);\n\n    for (int st = 0; st < n; st++) {\n        vector<unsigned char> used(n, 0);\n        vector<pair<int, int>> plan;\n        plan.reserve(n);\n\n        int curS = st;\n        used[curS] = 1;\n        plan.push_back({curS, assign[curS]});\n\n        Pos cur = dst[assign[curS]];\n\n        for (int step = 1; step < n; step++) {\n            int best = -1;\n            int best_d = 1e9;\n            int best_tr = 1e9;\n\n            for (int i = 0; i < n; i++) {\n                if (used[i]) continue;\n\n                int d = manhattan(cur, src[i]);\n                int tr = manhattan(src[i], dst[assign[i]]);\n\n                if (d < best_d || (d == best_d && tr < best_tr)) {\n                    best_d = d;\n                    best_tr = tr;\n                    best = i;\n                }\n            }\n\n            used[best] = 1;\n            plan.push_back({best, assign[best]});\n            cur = dst[assign[best]];\n        }\n\n        long long c = eval_plan(plan, src, dst);\n\n        if (c < best_cost) {\n            best_cost = c;\n            best_plan = move(plan);\n        }\n    }\n\n    return best_plan;\n}\n\nvoid append_move(\n    vector<string>& ops,\n    Pos& cur,\n    const Pos& to,\n    bool action_on_arrival\n) {\n    vector<char> moves;\n\n    while (cur.x < to.x) {\n        moves.push_back('D');\n        cur.x++;\n    }\n    while (cur.x > to.x) {\n        moves.push_back('U');\n        cur.x--;\n    }\n    while (cur.y < to.y) {\n        moves.push_back('R');\n        cur.y++;\n    }\n    while (cur.y > to.y) {\n        moves.push_back('L');\n        cur.y--;\n    }\n\n    if (moves.empty()) {\n        if (action_on_arrival) {\n            ops.push_back(\".P\");\n        }\n        return;\n    }\n\n    for (int i = 0; i < (int)moves.size(); i++) {\n        string op = \"..\";\n        op[0] = moves[i];\n\n        if (i == (int)moves.size() - 1 && action_on_arrival) {\n            op[1] = 'P';\n        }\n\n        ops.push_back(op);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<Pos> src, dst;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                src.push_back({i, j});\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    int D = (int)src.size();\n\n    vector<pair<int, int>> best_plan;\n    long long best_cost = (1LL << 60);\n\n    auto consider = [&](vector<pair<int, int>> plan) {\n        long long c = eval_plan(plan, src, dst);\n        if (c < best_cost) {\n            best_cost = c;\n            best_plan = move(plan);\n        }\n    };\n\n    if (D > 0) {\n        consider(plan_greedy_nearest(src, dst));\n        consider(plan_greedy_pair(src, dst, 0));\n        consider(plan_greedy_pair(src, dst, 1));\n        consider(plan_greedy_pair(src, dst, 2));\n        consider(plan_greedy_pair(src, dst, 4));\n\n        consider(plan_hungarian_ordered(src, dst));\n    }\n\n    Pos root{0, 0};\n    vector<string> ops;\n\n    if (D > 0) {\n        root = src[best_plan[0].first];\n\n        // First pickup.\n        ops.push_back(\".P\");\n\n        for (int i = 0; i < D; i++) {\n            int si = best_plan[i].first;\n            int ti = best_plan[i].second;\n\n            if (i > 0) {\n                append_move(ops, root, src[si], true); // pickup\n            }\n\n            append_move(ops, root, dst[ti], true); // place\n        }\n    }\n\n    // Robot arm: one vertex, the root itself is a fingertip.\n    cout << 1 << '\\n';\n    cout << root.x << ' ' << root.y << '\\n';\n\n    for (const string& op : ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Fish {\n    int x, y, w;\n};\n\nstruct PolyCand {\n    int diff = -1000000000;\n    vector<pair<int,int>> poly;\n};\n\nstruct EvalResult {\n    bool ok = false;\n    int diff = -1000000000;\n    vector<char> mask;\n    vector<pair<int,int>> poly;\n};\n\nstatic const int LIM = 100000;\nstatic const int MAX_PERIM = 400000;\nstatic const int MAX_VERT = 1000;\n\nint N;\nvector<Fish> fishes;\nPolyCand bestAns;\n\nstatic inline int id(int x, int y, int G) {\n    return y * G + x;\n}\n\nint exactDiffRect(int x1, int y1, int x2, int y2) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) s += p.w;\n    }\n    return s;\n}\n\nvoid updateBest(const vector<pair<int,int>>& poly, int diff) {\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return;\n    if (diff > bestAns.diff) {\n        bestAns.diff = diff;\n        bestAns.poly = poly;\n    }\n}\n\nbool pointInsideMask(const vector<char>& mask, int G, int L, int px, int py) {\n    int xs[2], ys[2];\n    int nx = 0, ny = 0;\n\n    if (px == LIM) xs[nx++] = G - 1;\n    else xs[nx++] = px / L;\n    if (px > 0 && px % L == 0) xs[nx++] = px / L - 1;\n\n    if (py == LIM) ys[ny++] = G - 1;\n    else ys[ny++] = py / L;\n    if (py > 0 && py % L == 0) ys[ny++] = py / L - 1;\n\n    for (int i = 0; i < nx; i++) {\n        for (int j = 0; j < ny; j++) {\n            int x = xs[i], y = ys[j];\n            if (0 <= x && x < G && 0 <= y && y < G && mask[id(x,y,G)]) return true;\n        }\n    }\n    return false;\n}\n\nint exactDiffMask(const vector<char>& mask, int G, int L) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (pointInsideMask(mask, G, L, p.x, p.y)) s += p.w;\n    }\n    return s;\n}\n\nbool isConnected(const vector<char>& mask, int G) {\n    int st = -1, cnt = 0;\n    for (int i = 0; i < G * G; i++) {\n        if (mask[i]) {\n            cnt++;\n            if (st == -1) st = i;\n        }\n    }\n    if (cnt == 0) return false;\n\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    q.push(st);\n    vis[st] = 1;\n    int got = 0;\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        got++;\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n            int ni = id(nx,ny,G);\n            if (!mask[ni] || vis[ni]) continue;\n            vis[ni] = 1;\n            q.push(ni);\n        }\n    }\n    return got == cnt;\n}\n\nvoid fillHoles(vector<char>& mask, int G) {\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n\n    auto push_empty = [&](int x, int y) {\n        if (x < 0 || x >= G || y < 0 || y >= G) return;\n        int v = id(x,y,G);\n        if (!mask[v] && !vis[v]) {\n            vis[v] = 1;\n            q.push(v);\n        }\n    };\n\n    for (int i = 0; i < G; i++) {\n        push_empty(i, 0);\n        push_empty(i, G - 1);\n        push_empty(0, i);\n        push_empty(G - 1, i);\n    }\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            push_empty(x + dx[d], y + dy[d]);\n        }\n    }\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] && !vis[i]) mask[i] = 1;\n    }\n}\n\nvoid normalizeMask(vector<char>& mask, int G, const vector<int>& cellW) {\n    fillHoles(mask, G);\n\n    for (int iter = 0; iter < G * G; iter++) {\n        bool changed = false;\n        for (int y = 0; y + 1 < G; y++) {\n            for (int x = 0; x + 1 < G; x++) {\n                int a = id(x,y,G);\n                int b = id(x+1,y,G);\n                int c = id(x,y+1,G);\n                int d = id(x+1,y+1,G);\n\n                if (mask[a] && mask[d] && !mask[b] && !mask[c]) {\n                    if (cellW[b] >= cellW[c]) mask[b] = 1;\n                    else mask[c] = 1;\n                    changed = true;\n                }\n                if (mask[b] && mask[c] && !mask[a] && !mask[d]) {\n                    if (cellW[a] >= cellW[d]) mask[a] = 1;\n                    else mask[d] = 1;\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n        fillHoles(mask, G);\n    }\n}\n\nint calcPerimCells(const vector<char>& mask, int G) {\n    int per = 0;\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n            if (x == 0 || !mask[id(x-1,y,G)]) per++;\n            if (x == G-1 || !mask[id(x+1,y,G)]) per++;\n            if (y == 0 || !mask[id(x,y-1,G)]) per++;\n            if (y == G-1 || !mask[id(x,y+1,G)]) per++;\n        }\n    }\n    return per;\n}\n\nvector<pair<int,int>> extractPolygon(const vector<char>& mask, int G, int L) {\n    int V = (G + 1) * (G + 1);\n    vector<int> nxt(V, -1), indeg(V, 0);\n    bool bad = false;\n    int edgeCnt = 0;\n\n    auto vid = [&](int x, int y) {\n        return y * (G + 1) + x;\n    };\n\n    auto addEdge = [&](int x1, int y1, int x2, int y2) {\n        int u = vid(x1,y1), v = vid(x2,y2);\n        if (nxt[u] != -1) bad = true;\n        nxt[u] = v;\n        indeg[v]++;\n        if (indeg[v] > 1) bad = true;\n        edgeCnt++;\n    };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n\n            if (y == 0 || !mask[id(x,y-1,G)]) {\n                addEdge(x, y, x+1, y);\n            }\n            if (x == G-1 || !mask[id(x+1,y,G)]) {\n                addEdge(x+1, y, x+1, y+1);\n            }\n            if (y == G-1 || !mask[id(x,y+1,G)]) {\n                addEdge(x+1, y+1, x, y+1);\n            }\n            if (x == 0 || !mask[id(x-1,y,G)]) {\n                addEdge(x, y+1, x, y);\n            }\n        }\n    }\n\n    if (bad || edgeCnt == 0) return {};\n\n    int st = -1;\n    for (int i = 0; i < V; i++) {\n        if (nxt[i] != -1) {\n            st = i;\n            break;\n        }\n    }\n\n    vector<char> used(V, 0);\n    vector<pair<int,int>> poly;\n    int cur = st;\n\n    for (int step = 0; step <= edgeCnt; step++) {\n        if (cur == -1) return {};\n        if (cur == st && step > 0) break;\n        if (used[cur]) return {};\n        used[cur] = 1;\n\n        int gx = cur % (G + 1);\n        int gy = cur / (G + 1);\n        poly.push_back({gx * L, gy * L});\n\n        cur = nxt[cur];\n    }\n\n    if (cur != st) return {};\n\n    int usedEdges = 0;\n    for (int i = 0; i < V; i++) if (used[i]) usedEdges++;\n    if ((int)poly.size() != edgeCnt) {\n        // This usually means multiple cycles or invalid touching.\n        // Collinear vertices are counted here, so size should equal boundary edges.\n        return {};\n    }\n\n    auto collinear = [](pair<int,int> a, pair<int,int> b, pair<int,int> c) {\n        return (a.first == b.first && b.first == c.first) ||\n               (a.second == b.second && b.second == c.second);\n    };\n\n    bool changed = true;\n    while (changed && poly.size() >= 4) {\n        changed = false;\n        vector<pair<int,int>> np;\n        int m = (int)poly.size();\n        for (int i = 0; i < m; i++) {\n            auto a = poly[(i - 1 + m) % m];\n            auto b = poly[i];\n            auto c = poly[(i + 1) % m];\n            if (collinear(a,b,c)) {\n                changed = true;\n            } else {\n                np.push_back(b);\n            }\n        }\n        poly.swap(np);\n    }\n\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return {};\n\n    set<pair<int,int>> ss(poly.begin(), poly.end());\n    if (ss.size() != poly.size()) return {};\n\n    return poly;\n}\n\nEvalResult evalMask(vector<char> mask, int G, int L, const vector<int>& cellW) {\n    EvalResult res;\n    normalizeMask(mask, G, cellW);\n\n    if (!isConnected(mask, G)) return res;\n\n    int perCells = calcPerimCells(mask, G);\n    if (perCells * L > MAX_PERIM) return res;\n\n    auto poly = extractPolygon(mask, G, L);\n    if (poly.empty()) return res;\n\n    int diff = exactDiffMask(mask, G, L);\n\n    res.ok = true;\n    res.diff = diff;\n    res.mask = std::move(mask);\n    res.poly = std::move(poly);\n    return res;\n}\n\nvector<int> buildGridWeight(int G, int L) {\n    vector<int> w(G * G, 0);\n    for (auto &p : fishes) {\n        int x = min(G - 1, p.x / L);\n        int y = min(G - 1, p.y / L);\n        w[id(x,y,G)] += p.w;\n    }\n    return w;\n}\n\nvoid tryTinyBaseline() {\n    for (int i = 0; i < N; i++) {\n        int x = fishes[i].x;\n        int y = fishes[i].y;\n        int x1, x2, y1, y2;\n\n        if (x < LIM) x1 = x, x2 = x + 1;\n        else x1 = x - 1, x2 = x;\n\n        if (y < LIM) y1 = y, y2 = y + 1;\n        else y1 = y - 1, y2 = y;\n\n        int diff = exactDiffRect(x1,y1,x2,y2);\n        vector<pair<int,int>> poly = {\n            {x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}\n        };\n        updateBest(poly, diff);\n    }\n}\n\nvoid tryBestRectangle(int G, int L, const vector<int>& cellW) {\n    int maxSideSum = MAX_PERIM / (2 * L);\n\n    int bestVal = -1000000000;\n    int bx1 = 0, by1 = 0, bx2 = 1, by2 = 1;\n\n    vector<int> arr(G), pref(G + 1);\n\n    for (int xl = 0; xl < G; xl++) {\n        fill(arr.begin(), arr.end(), 0);\n\n        for (int xr = xl; xr < G; xr++) {\n            for (int y = 0; y < G; y++) {\n                arr[y] += cellW[id(xr,y,G)];\n            }\n\n            int width = xr - xl + 1;\n            int maxH = maxSideSum - width;\n            if (maxH <= 0) continue;\n            maxH = min(maxH, G);\n\n            pref[0] = 0;\n            for (int y = 0; y < G; y++) pref[y+1] = pref[y] + arr[y];\n\n            deque<int> dq;\n            for (int e = 1; e <= G; e++) {\n                int sNew = e - 1;\n                while (!dq.empty() && pref[dq.back()] >= pref[sNew]) dq.pop_back();\n                dq.push_back(sNew);\n\n                while (!dq.empty() && dq.front() < e - maxH) dq.pop_front();\n\n                int s = dq.front();\n                int val = pref[e] - pref[s];\n                if (val > bestVal) {\n                    bestVal = val;\n                    bx1 = xl;\n                    bx2 = xr + 1;\n                    by1 = s;\n                    by2 = e;\n                }\n            }\n        }\n    }\n\n    int x1 = bx1 * L;\n    int x2 = bx2 * L;\n    int y1 = by1 * L;\n    int y2 = by2 * L;\n\n    int diff = exactDiffRect(x1,y1,x2,y2);\n    vector<pair<int,int>> poly = {\n        {x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}\n    };\n    updateBest(poly, diff);\n}\n\nstruct Comp {\n    int score = 0;\n    int size = 0;\n    long long sx = 0, sy = 0;\n    vector<int> cells;\n};\n\nvector<Comp> getComponents(const vector<char>& mask, int G, const vector<int>& cellW) {\n    vector<Comp> comps;\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] || vis[i]) continue;\n\n        Comp c;\n        vis[i] = 1;\n        q.push(i);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            int x = v % G, y = v / G;\n\n            c.cells.push_back(v);\n            c.score += cellW[v];\n            c.size++;\n            c.sx += x;\n            c.sy += y;\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n                int ni = id(nx,ny,G);\n                if (!mask[ni] || vis[ni]) continue;\n                vis[ni] = 1;\n                q.push(ni);\n            }\n        }\n\n        if (c.size > 0) comps.push_back(std::move(c));\n    }\n\n    sort(comps.begin(), comps.end(), [](const Comp& a, const Comp& b) {\n        return a.score > b.score;\n    });\n\n    return comps;\n}\n\nvector<char> makeCompMask(const Comp& c, int G) {\n    vector<char> m(G * G, 0);\n    for (int v : c.cells) m[v] = 1;\n    return m;\n}\n\nvoid addPath(vector<char>& m, int G, int x1, int y1, int x2, int y2, bool hv) {\n    if (hv) {\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y1,G)] = 1;\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x2,y,G)] = 1;\n    } else {\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x1,y,G)] = 1;\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y2,G)] = 1;\n    }\n}\n\nvoid tryGreedyUnion(vector<Comp>& comps, int G, int L, const vector<int>& cellW) {\n    vector<Comp> pos;\n    for (auto &c : comps) {\n        if (c.score > 0) pos.push_back(c);\n        if ((int)pos.size() >= 20) break;\n    }\n    if (pos.empty()) return;\n\n    vector<char> cur = makeCompMask(pos[0], G);\n    auto er0 = evalMask(cur, G, L, cellW);\n    if (!er0.ok) return;\n\n    updateBest(er0.poly, er0.diff);\n    cur = er0.mask;\n    int curDiff = er0.diff;\n\n    for (int ci = 1; ci < (int)pos.size(); ci++) {\n        const Comp& c = pos[ci];\n\n        int cx = (int)(c.sx / max(1, c.size));\n        int cy = (int)(c.sy / max(1, c.size));\n\n        int ax = -1, ay = -1, bestD = INT_MAX;\n        for (int y = 0; y < G; y++) {\n            for (int x = 0; x < G; x++) {\n                if (!cur[id(x,y,G)]) continue;\n                int d = abs(x - cx) + abs(y - cy);\n                if (d < bestD) {\n                    bestD = d;\n                    ax = x;\n                    ay = y;\n                }\n            }\n        }\n\n        int bx = -1, by = -1;\n        bestD = INT_MAX;\n        for (int v : c.cells) {\n            int x = v % G, y = v / G;\n            int d = abs(x - ax) + abs(y - ay);\n            if (d < bestD) {\n                bestD = d;\n                bx = x;\n                by = y;\n            }\n        }\n\n        vector<char> base = cur;\n        for (int v : c.cells) base[v] = 1;\n\n        vector<char> m1 = base, m2 = base;\n        addPath(m1, G, ax, ay, bx, by, true);\n        addPath(m2, G, ax, ay, bx, by, false);\n\n        auto e1 = evalMask(m1, G, L, cellW);\n        auto e2 = evalMask(m2, G, L, cellW);\n\n        EvalResult bestE;\n        if (e1.ok) bestE = e1;\n        if (e2.ok && (!bestE.ok || e2.diff > bestE.diff)) bestE = e2;\n\n        if (bestE.ok) {\n            updateBest(bestE.poly, bestE.diff);\n            if (bestE.diff > curDiff) {\n                curDiff = bestE.diff;\n                cur = bestE.mask;\n            }\n        }\n    }\n}\n\nvector<int> boxSmooth(const vector<int>& w, int G, int r) {\n    vector<int> pref((G+1)*(G+1), 0);\n    auto pid = [&](int x, int y) { return y * (G + 1) + x; };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            pref[pid(x+1,y+1)] =\n                pref[pid(x+1,y)] + pref[pid(x,y+1)] - pref[pid(x,y)] + w[id(x,y,G)];\n        }\n    }\n\n    vector<int> sm(G * G, 0);\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            int x1 = max(0, x - r);\n            int y1 = max(0, y - r);\n            int x2 = min(G, x + r + 1);\n            int y2 = min(G, y + r + 1);\n            int val =\n                pref[pid(x2,y2)] - pref[pid(x1,y2)] -\n                pref[pid(x2,y1)] + pref[pid(x1,y1)];\n            sm[id(x,y,G)] = val;\n        }\n    }\n    return sm;\n}\n\nvoid processGrid(int L) {\n    int G = LIM / L;\n    vector<int> cellW = buildGridWeight(G, L);\n\n    tryBestRectangle(G, L, cellW);\n\n    vector<int> radii;\n    if (L == 500) radii = {0,1,2,3,5,8,12};\n    else if (L == 1000) radii = {0,1,2,3,5,8};\n    else if (L == 2000) radii = {0,1,2,3,4};\n    else radii = {0,1,2,3};\n\n    for (int r : radii) {\n        vector<int> sm = boxSmooth(cellW, G, r);\n\n        vector<int> thresholds;\n        if (r == 0) thresholds = {0};\n        else thresholds = {-1, 0, 1, 2, 4};\n\n        for (int th : thresholds) {\n            vector<char> mask(G * G, 0);\n            for (int i = 0; i < G * G; i++) {\n                if (sm[i] > th) mask[i] = 1;\n            }\n\n            auto comps = getComponents(mask, G, cellW);\n\n            int cnt = 0;\n            for (auto &c : comps) {\n                if (c.score <= 0) continue;\n                auto cm = makeCompMask(c, G);\n                auto er = evalMask(cm, G, L, cellW);\n                if (er.ok) updateBest(er.poly, er.diff);\n\n                cnt++;\n                if (cnt >= 30) break;\n            }\n\n            tryGreedyUnion(comps, G, L, cellW);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    fishes.reserve(2 * N);\n\n    for (int i = 0; i < 2 * N; i++) {\n        int x, y;\n        cin >> x >> y;\n        int w = (i < N ? 1 : -1);\n        fishes.push_back({x,y,w});\n    }\n\n    tryTinyBaseline();\n\n    vector<int> Ls = {500, 1000, 2000, 2500, 4000, 5000};\n    for (int L : Ls) {\n        processGrid(L);\n    }\n\n    if (bestAns.poly.empty()) {\n        // Absolute fallback.\n        cout << 4 << '\\n';\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << bestAns.poly.size() << '\\n';\n    for (auto [x,y] : bestAns.poly) {\n        x = max(0, min(LIM, x));\n        y = max(0, min(LIM, y));\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Op {\n    int p, r;\n    char d;\n    int b;\n};\n\nstruct RectPlaced {\n    ll x, y, w, h;\n};\n\nstruct Solution {\n    vector<Op> ops;\n    ll estScore;\n};\n\nstatic inline bool overlap(ll l1, ll r1, ll l2, ll r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstruct Solver {\n    int N, T;\n    ll sigma;\n    vector<ll> w, h;\n    vector<Solution> sols;\n    unordered_set<string> seen;\n    chrono::steady_clock::time_point st;\n    mt19937 rng;\n\n    Solver() : rng(1234567) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    pair<ll, ll> simulate(const vector<Op>& ops) const {\n        vector<ll> X(N), Y(N), W(N), H(N);\n        vector<char> used(N, 0);\n        ll BW = 0, BH = 0;\n\n        for (auto &op : ops) {\n            int p = op.p;\n            ll rw = op.r ? h[p] : w[p];\n            ll rh = op.r ? w[p] : h[p];\n            ll x = 0, y = 0;\n\n            if (op.d == 'U') {\n                x = (op.b == -1 ? 0 : X[op.b] + W[op.b]);\n                y = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap(x, x + rw, X[j], X[j] + W[j])) {\n                        y = max(y, Y[j] + H[j]);\n                    }\n                }\n            } else {\n                y = (op.b == -1 ? 0 : Y[op.b] + H[op.b]);\n                x = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap(y, y + rh, Y[j], Y[j] + H[j])) {\n                        x = max(x, X[j] + W[j]);\n                    }\n                }\n            }\n\n            X[p] = x;\n            Y[p] = y;\n            W[p] = rw;\n            H[p] = rh;\n            used[p] = 1;\n            BW = max(BW, x + rw);\n            BH = max(BH, y + rh);\n        }\n        return {BW, BH};\n    }\n\n    string makeKey(const vector<Op>& ops) const {\n        string s;\n        s.reserve(ops.size() * 3);\n        for (auto &op : ops) {\n            s.push_back(char(op.r));\n            s.push_back(op.d);\n            s.push_back(char(op.b + 1));\n        }\n        return s;\n    }\n\n    void addSolution(const vector<Op>& ops) {\n        if ((int)ops.size() != N) return;\n        string key = makeKey(ops);\n        if (seen.find(key) != seen.end()) return;\n        seen.insert(key);\n        auto [W0, H0] = simulate(ops);\n        sols.push_back({ops, W0 + H0});\n    }\n\n    struct SegInfo {\n        bool ok = false;\n        ll rowH = 0;\n        ll rowW = 0;\n        vector<int> rot;\n    };\n\n    SegInfo calcSegment(int l, int r, ll limitW, bool needRot) const {\n        vector<ll> cand;\n        cand.reserve((r - l) * 2);\n        for (int i = l; i < r; i++) {\n            cand.push_back(h[i]); // non-rotated height\n            cand.push_back(w[i]); // rotated height\n        }\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        SegInfo best;\n\n        for (ll HH : cand) {\n            ll sumW = 0;\n            bool ok = true;\n            vector<int> rots;\n            if (needRot) rots.reserve(r - l);\n\n            for (int i = l; i < r; i++) {\n                const ll INF = (1LL << 60);\n                ll bw = INF;\n                int br = -1;\n\n                if (h[i] <= HH) {\n                    bw = w[i];\n                    br = 0;\n                }\n                if (w[i] <= HH) {\n                    if (h[i] < bw) {\n                        bw = h[i];\n                        br = 1;\n                    }\n                }\n\n                if (br == -1) {\n                    ok = false;\n                    break;\n                }\n\n                sumW += bw;\n                if (sumW > limitW) {\n                    ok = false;\n                    break;\n                }\n                if (needRot) rots.push_back(br);\n            }\n\n            if (ok) {\n                best.ok = true;\n                best.rowH = HH;\n                best.rowW = sumW;\n                if (needRot) best.rot = move(rots);\n                return best;\n            }\n        }\n        return best;\n    }\n\n    void generateShelf(ll limitW) {\n        const ll INF = (1LL << 60);\n\n        vector<vector<ll>> segH(N, vector<ll>(N + 1, INF));\n        vector<vector<ll>> segW(N, vector<ll>(N + 1, INF));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l + 1; r <= N; r++) {\n                SegInfo si = calcSegment(l, r, limitW, false);\n                if (si.ok) {\n                    segH[l][r] = si.rowH;\n                    segW[l][r] = si.rowW;\n                }\n            }\n        }\n\n        vector<ll> dpH(N + 1, INF), dpMaxW(N + 1, INF);\n        vector<int> prv(N + 1, -1);\n        dpH[0] = 0;\n        dpMaxW[0] = 0;\n\n        for (int i = 1; i <= N; i++) {\n            for (int l = 0; l < i; l++) {\n                if (dpH[l] == INF || segH[l][i] == INF) continue;\n                ll nh = dpH[l] + segH[l][i];\n                ll nw = max(dpMaxW[l], segW[l][i]);\n                if (nh < dpH[i] || (nh == dpH[i] && nw < dpMaxW[i])) {\n                    dpH[i] = nh;\n                    dpMaxW[i] = nw;\n                    prv[i] = l;\n                }\n            }\n        }\n\n        if (prv[N] == -1) return;\n\n        vector<pair<int,int>> rows;\n        int cur = N;\n        while (cur > 0) {\n            int l = prv[cur];\n            rows.push_back({l, cur});\n            cur = l;\n        }\n        reverse(rows.begin(), rows.end());\n\n        vector<int> rot(N, 0);\n        for (auto [l, r] : rows) {\n            SegInfo si = calcSegment(l, r, limitW, true);\n            if (!si.ok) return;\n            for (int k = l; k < r; k++) {\n                rot[k] = si.rot[k - l];\n            }\n        }\n\n        vector<Op> ops;\n        ops.reserve(N);\n\n        int prevAnchor = -1;\n\n        for (int row = 0; row < (int)rows.size(); row++) {\n            auto [l, r] = rows[row];\n            int b = (row == 0 ? -1 : prevAnchor);\n\n            for (int i = l; i < r; i++) {\n                ops.push_back({i, rot[i], 'L', b});\n            }\n\n            ll bestH = -1;\n            int anchor = l;\n            for (int i = l; i < r; i++) {\n                ll hh = rot[i] ? w[i] : h[i];\n                if (hh > bestH) {\n                    bestH = hh;\n                    anchor = i;\n                }\n            }\n            prevAnchor = anchor;\n        }\n\n        addSolution(ops);\n    }\n\n    void generateSimpleRows() {\n        // One horizontal row, several rotation policies.\n        for (int policy = 0; policy < 4; policy++) {\n            vector<Op> ops;\n            ops.reserve(N);\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (policy == 1) r = 1;\n                else if (policy == 2) r = (h[i] < w[i]); // smaller width\n                else if (policy == 3) r = (w[i] < h[i]); // smaller height\n                ops.push_back({i, r, 'L', -1});\n            }\n            addSolution(ops);\n        }\n\n        // One vertical column.\n        for (int policy = 0; policy < 4; policy++) {\n            vector<Op> ops;\n            ops.reserve(N);\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (policy == 1) r = 1;\n                else if (policy == 2) r = (h[i] < w[i]);\n                else if (policy == 3) r = (w[i] < h[i]);\n                ops.push_back({i, r, 'U', -1});\n            }\n            addSolution(ops);\n        }\n    }\n\n    void generateGreedy(double wp, double wa, double wb, double noiseCoef) {\n        vector<Op> ops;\n        ops.reserve(N);\n\n        vector<ll> X(N), Y(N), RW(N), RH(N);\n        vector<char> used(N, 0);\n        ll curW = 0, curH = 0;\n\n        long double area = 0;\n        for (int i = 0; i < N; i++) area += (long double)w[i] * h[i];\n        double scale = max(1.0, sqrt((double)area));\n\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        for (int i = 0; i < N; i++) {\n            double bestCost = 1e100;\n            Op bestOp{i, 0, 'L', -1};\n            ll bestX = 0, bestY = 0, bestRW = w[i], bestRH = h[i];\n            ll bestBW = 0, bestBH = 0;\n\n            for (int r = 0; r < 2; r++) {\n                ll rw = r ? h[i] : w[i];\n                ll rh = r ? w[i] : h[i];\n\n                for (int d0 = 0; d0 < 2; d0++) {\n                    char d = d0 ? 'L' : 'U';\n\n                    for (int b = -1; b < i; b++) {\n                        ll x = 0, y = 0;\n\n                        if (d == 'U') {\n                            x = (b == -1 ? 0 : X[b] + RW[b]);\n                            y = 0;\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (overlap(x, x + rw, X[j], X[j] + RW[j])) {\n                                    y = max(y, Y[j] + RH[j]);\n                                }\n                            }\n                        } else {\n                            y = (b == -1 ? 0 : Y[b] + RH[b]);\n                            x = 0;\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (overlap(y, y + rh, Y[j], Y[j] + RH[j])) {\n                                    x = max(x, X[j] + RW[j]);\n                                }\n                            }\n                        }\n\n                        ll BW = max(curW, x + rw);\n                        ll BH = max(curH, y + rh);\n\n                        double cost = 0.0;\n                        cost += wp * (double)(BW + BH);\n                        cost += wa * ((double)BW * (double)BH / scale);\n                        cost += wb * (double)llabs(BW - BH);\n                        cost += noiseCoef * scale * ud(rng);\n\n                        // Slight preference for compact coordinates.\n                        cost += 0.0001 * (double)(x + y);\n\n                        if (cost < bestCost) {\n                            bestCost = cost;\n                            bestOp = {i, r, d, b};\n                            bestX = x;\n                            bestY = y;\n                            bestRW = rw;\n                            bestRH = rh;\n                            bestBW = BW;\n                            bestBH = BH;\n                        }\n                    }\n                }\n            }\n\n            ops.push_back(bestOp);\n            X[i] = bestX;\n            Y[i] = bestY;\n            RW[i] = bestRW;\n            RH[i] = bestRH;\n            used[i] = 1;\n            curW = bestBW;\n            curH = bestBH;\n        }\n\n        addSolution(ops);\n    }\n\n    void generateAll() {\n        st = chrono::steady_clock::now();\n\n        generateSimpleRows();\n\n        long double area = 0;\n        ll minSingleW = 1;\n        for (int i = 0; i < N; i++) {\n            area += (long double)w[i] * h[i];\n            minSingleW = max(minSingleW, min(w[i], h[i]));\n        }\n        double sqrtA = sqrt((double)area);\n\n        vector<ll> limits;\n        for (int k = 0; k < 48; k++) {\n            double f = 0.55 + (2.45 - 0.55) * k / 47.0;\n            ll L = max<ll>(minSingleW, (ll)llround(sqrtA * f));\n            limits.push_back(L);\n        }\n        sort(limits.begin(), limits.end());\n        limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n        for (ll L : limits) {\n            if (elapsed() > 1.65) break;\n            generateShelf(L);\n        }\n\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        int greedyTrials = 0;\n        while (elapsed() < 2.45 && greedyTrials < 500) {\n            greedyTrials++;\n\n            double wp = 1.0;\n            double wa = pow(10.0, -0.4 + 1.2 * ud(rng)); // about 0.4 to 6.3\n            double wb = 0.05 + 1.2 * ud(rng);\n            double nz = 0.0;\n\n            if (greedyTrials % 3 == 0) nz = 0.01 * ud(rng);\n            if (greedyTrials % 7 == 0) nz = 0.05 * ud(rng);\n\n            generateGreedy(wp, wa, wb, nz);\n        }\n\n        if (sols.empty()) {\n            vector<Op> ops;\n            for (int i = 0; i < N; i++) ops.push_back({i, 0, 'L', -1});\n            addSolution(ops);\n        }\n\n        sort(sols.begin(), sols.end(), [](const Solution& a, const Solution& b) {\n            return a.estScore < b.estScore;\n        });\n    }\n\n    void run() {\n        cin >> N >> T >> sigma;\n        w.resize(N);\n        h.resize(N);\n        for (int i = 0; i < N; i++) cin >> w[i] >> h[i];\n\n        generateAll();\n\n        for (int t = 0; t < T; t++) {\n            const vector<Op>& ops = sols[t % sols.size()].ops;\n\n            cout << ops.size() << '\\n';\n            for (auto &op : ops) {\n                cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n            }\n            cout.flush();\n\n            ll Wobs, Hobs;\n            if (!(cin >> Wobs >> Hobs)) return;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.run();\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int NMAX = 1000;\nstatic constexpr int H = 10;\nstatic constexpr long long NEG = -(1LL << 60);\n\nstruct Edge {\n    int u, v;\n    long long len2;\n};\n\nstruct Solver {\n    int N, M, HH;\n    vector<int> A;\n    vector<Edge> edges;\n    vector<vector<int>> adj;\n    vector<int> xs, ys;\n\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n\n    vector<array<long long, 11>> dp_no, dp_need;\n    vector<vector<int>> children;\n\n    vector<int> orderHigh, orderLow;\n\n    Solver() : rng(1234567) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    long long scoreLabels(const vector<int>& d) const {\n        long long s = 0;\n        for (int i = 0; i < N; i++) s += 1LL * (d[i] + 1) * A[i];\n        return s;\n    }\n\n    long long keyPrim(int mode, int from, int to) {\n        long long noise = (long long)(rng() % 100000);\n        long long len2 = 0;\n        long long dx = xs[from] - xs[to];\n        long long dy = ys[from] - ys[to];\n        len2 = dx * dx + dy * dy;\n\n        if (mode == 0) return 1LL * A[to] * 100000 + noise;              // low beauty first\n        if (mode == 1) return 1LL * (101 - A[to]) * 100000 + noise;        // high beauty first\n        if (mode == 2) return (long long)(rng() & 0x7fffffff);             // random\n        if (mode == 3) return len2 * 1000 + noise;                         // short edges first\n        if (mode == 4) return (2000000LL - min(len2, 2000000LL)) * 1000 + noise; // long edges first\n        return 1LL * A[to] * 50000 + len2 + noise;\n    }\n\n    vector<int> makePrimTree(int mode) {\n        vector<int> par(N, -2), used(N, 0);\n\n        int start = 0;\n        if (mode == 0 || mode == 5) {\n            start = min_element(A.begin(), A.end()) - A.begin();\n        } else if (mode == 1) {\n            start = max_element(A.begin(), A.end()) - A.begin();\n        } else {\n            start = rng() % N;\n        }\n\n        using T = tuple<long long, int, int>;\n        priority_queue<T, vector<T>, greater<T>> pq;\n\n        used[start] = 1;\n        par[start] = -1;\n        int cnt = 1;\n\n        for (int to : adj[start]) {\n            pq.emplace(keyPrim(mode, start, to), start, to);\n        }\n\n        while (cnt < N && !pq.empty()) {\n            auto [key, from, v] = pq.top();\n            pq.pop();\n            if (used[v]) continue;\n            used[v] = 1;\n            par[v] = from;\n            cnt++;\n            for (int to : adj[v]) {\n                if (!used[to]) pq.emplace(keyPrim(mode, v, to), v, to);\n            }\n        }\n\n        return par;\n    }\n\n    vector<int> makeDFSTree(int mode) {\n        vector<vector<pair<long long, int>>> ord(N);\n        for (int v = 0; v < N; v++) {\n            for (int to : adj[v]) {\n                long long noise = (long long)(rng() % 100000);\n                long long key;\n                if (mode == 0) key = 1LL * A[to] * 100000 + noise;\n                else if (mode == 1) key = 1LL * (101 - A[to]) * 100000 + noise;\n                else key = (long long)(rng() & 0x7fffffff);\n                ord[v].push_back({key, to});\n            }\n            sort(ord[v].begin(), ord[v].end());\n        }\n\n        int start;\n        if (mode == 0) start = min_element(A.begin(), A.end()) - A.begin();\n        else if (mode == 1) start = max_element(A.begin(), A.end()) - A.begin();\n        else start = rng() % N;\n\n        vector<int> par(N, -2), used(N, 0), idx(N, 0);\n        vector<int> stk;\n        stk.push_back(start);\n        used[start] = 1;\n        par[start] = -1;\n        int cnt = 1;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n            while (idx[v] < (int)ord[v].size() && used[ord[v][idx[v]].second]) idx[v]++;\n            if (idx[v] == (int)ord[v].size()) {\n                stk.pop_back();\n                continue;\n            }\n            int to = ord[v][idx[v]++].second;\n            used[to] = 1;\n            par[to] = v;\n            cnt++;\n            stk.push_back(to);\n        }\n\n        // Should not happen because graph is connected, but repair just in case.\n        if (cnt < N) {\n            for (int v = 0; v < N; v++) {\n                if (used[v]) continue;\n                for (int to : adj[v]) {\n                    if (used[to]) {\n                        used[v] = 1;\n                        par[v] = to;\n                        break;\n                    }\n                }\n            }\n        }\n\n        return par;\n    }\n\n    long long childVal(int c, int childLabel, int parentLabel) const {\n        if (childLabel == 0 || parentLabel == childLabel - 1) {\n            return dp_no[c][childLabel];\n        } else {\n            return dp_need[c][childLabel];\n        }\n    }\n\n    vector<int> solveOnTree(const vector<int>& treePar) {\n        vector<vector<int>> tadj(N);\n        for (int v = 0; v < N; v++) {\n            if (treePar[v] >= 0) {\n                tadj[v].push_back(treePar[v]);\n                tadj[treePar[v]].push_back(v);\n            }\n        }\n\n        children.assign(N, {});\n        vector<int> parent(N, -1), order;\n        order.reserve(N);\n\n        vector<int> stk = {0};\n        parent[0] = -2;\n        while (!stk.empty()) {\n            int v = stk.back();\n            stk.pop_back();\n            order.push_back(v);\n            for (int to : tadj[v]) {\n                if (to == parent[v]) continue;\n                parent[to] = v;\n                children[v].push_back(to);\n                stk.push_back(to);\n            }\n        }\n\n        dp_no.assign(N, {});\n        dp_need.assign(N, {});\n\n        for (int ii = N - 1; ii >= 0; ii--) {\n            int v = order[ii];\n\n            for (int l = 0; l <= H; l++) {\n                long long base = 1LL * (l + 1) * A[v];\n                vector<long long> bestChild;\n                bestChild.reserve(children[v].size());\n\n                bool ok = true;\n                long long sum = base;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n                    for (int lc = 0; lc <= H; lc++) {\n                        best = max(best, childVal(c, lc, l));\n                    }\n                    if (best <= NEG / 2) ok = false;\n                    sum += best;\n                    bestChild.push_back(best);\n                }\n\n                dp_no[v][l] = ok ? sum : NEG;\n\n                if (l == 0 || !ok) {\n                    dp_need[v][l] = NEG;\n                } else {\n                    int forcedLabel = l - 1;\n                    long long bestDelta = NEG;\n                    for (int idx = 0; idx < (int)children[v].size(); idx++) {\n                        int c = children[v][idx];\n                        long long fv = childVal(c, forcedLabel, l);\n                        if (fv <= NEG / 2) continue;\n                        bestDelta = max(bestDelta, fv - bestChild[idx]);\n                    }\n                    if (bestDelta <= NEG / 2) dp_need[v][l] = NEG;\n                    else dp_need[v][l] = sum + bestDelta;\n                }\n            }\n        }\n\n        int rootLabel = 0;\n        bool rootNeed = false;\n        long long bestRoot = dp_no[0][0];\n\n        for (int l = 1; l <= H; l++) {\n            if (dp_need[0][l] > bestRoot) {\n                bestRoot = dp_need[0][l];\n                rootLabel = l;\n                rootNeed = true;\n            }\n        }\n\n        vector<int> label(N, 0);\n\n        function<void(int, int, bool)> rec = [&](int v, int l, bool needSupportChild) {\n            label[v] = l;\n\n            int forcedChild = -1;\n            if (needSupportChild) {\n                int forcedLabel = l - 1;\n                long long bestDelta = NEG;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n                    for (int lc = 0; lc <= H; lc++) best = max(best, childVal(c, lc, l));\n\n                    long long fv = childVal(c, forcedLabel, l);\n                    if (fv <= NEG / 2) continue;\n\n                    long long delta = fv - best;\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        forcedChild = c;\n                    }\n                }\n            }\n\n            for (int c : children[v]) {\n                int lcBest = 0;\n                long long valBest = NEG;\n\n                if (c == forcedChild) {\n                    lcBest = l - 1;\n                } else {\n                    for (int lc = 0; lc <= H; lc++) {\n                        long long val = childVal(c, lc, l);\n                        if (val > valBest) {\n                            valBest = val;\n                            lcBest = lc;\n                        }\n                    }\n                }\n\n                bool childNeed = !(lcBest == 0 || l == lcBest - 1);\n                rec(c, lcBest, childNeed);\n            }\n        };\n\n        rec(0, rootLabel, rootNeed);\n        return label;\n    }\n\n    vector<int> calcCnt(const vector<int>& d) const {\n        vector<int> cnt(N, 0);\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) continue;\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) cnt[v]++;\n            }\n        }\n        return cnt;\n    }\n\n    bool canMove(const vector<int>& d, const vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n        if (old == nl) return false;\n\n        if (nl > 0) {\n            bool has = false;\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) {\n                    has = true;\n                    break;\n                }\n            }\n            if (!has) return false;\n        }\n\n        for (int to : adj[v]) {\n            if (d[to] > 0 && d[to] - 1 == old && cnt[to] == 1) {\n                // This vertex would lose its only lower neighbour.\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    void applyMove(vector<int>& d, vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n\n        for (int to : adj[v]) {\n            if (d[to] > 0) {\n                if (old == d[to] - 1) cnt[to]--;\n                if (nl == d[to] - 1) cnt[to]++;\n            }\n        }\n\n        d[v] = nl;\n\n        if (nl == 0) {\n            cnt[v] = 0;\n        } else {\n            int c = 0;\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) c++;\n            }\n            cnt[v] = c;\n        }\n    }\n\n    void greedyImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 20; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int old = d[v];\n                for (int nl = H; nl > old; nl--) {\n                    if (canMove(d, cnt, v, nl)) {\n                        applyMove(d, cnt, v, nl);\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void lowPerturbAndImprove(vector<int>& d) const {\n        vector<int> best = d;\n        long long bestScore = scoreLabels(d);\n\n        vector<int> cur = d;\n        vector<int> cnt = calcCnt(cur);\n\n        int tried = 0;\n        for (int v : orderLow) {\n            if (++tried > 250) break;\n\n            int old = cur[v];\n            if (old == 0) continue;\n\n            int chosen = -1;\n            for (int nl = 0; nl < old; nl++) {\n                if (!canMove(cur, cnt, v, nl)) continue;\n\n                long long loss = 1LL * A[v] * (old - nl);\n                long long pot = 0;\n                for (int to : adj[v]) {\n                    if (cur[to] == nl + 1) pot += A[to];\n                }\n\n                if (loss <= 80 + pot) {\n                    chosen = nl;\n                    break;\n                }\n            }\n\n            if (chosen != -1) applyMove(cur, cnt, v, chosen);\n        }\n\n        greedyImprove(cur);\n\n        long long sc = scoreLabels(cur);\n        if (sc > bestScore) d = cur;\n    }\n\n    bool checkFeasible(const vector<int>& d) const {\n        for (int v = 0; v < N; v++) {\n            if (d[v] < 0 || d[v] > H) return false;\n            if (d[v] == 0) continue;\n            bool ok = false;\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n            if (!ok) return false;\n        }\n        return true;\n    }\n\n    vector<int> buildParents(const vector<int>& d) const {\n        vector<int> p(N, -1);\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) {\n                p[v] = -1;\n            } else {\n                int best = -1;\n                int bestA = 1e9;\n                for (int to : adj[v]) {\n                    if (d[to] == d[v] - 1) {\n                        if (A[to] < bestA) {\n                            bestA = A[to];\n                            best = to;\n                        }\n                    }\n                }\n                p[v] = best;\n            }\n        }\n        return p;\n    }\n\n    void run() {\n        cin >> N >> M >> HH;\n\n        A.resize(N);\n        for (int i = 0; i < N; i++) cin >> A[i];\n\n        edges.resize(M);\n        adj.assign(N, {});\n\n        for (int i = 0; i < M; i++) {\n            int u, v;\n            cin >> u >> v;\n            edges[i] = {u, v, 0};\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n\n        xs.resize(N);\n        ys.resize(N);\n        for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n        for (auto& e : edges) {\n            long long dx = xs[e.u] - xs[e.v];\n            long long dy = ys[e.u] - ys[e.v];\n            e.len2 = dx * dx + dy * dy;\n        }\n\n        orderHigh.resize(N);\n        orderLow.resize(N);\n        iota(orderHigh.begin(), orderHigh.end(), 0);\n        iota(orderLow.begin(), orderLow.end(), 0);\n\n        sort(orderHigh.begin(), orderHigh.end(), [&](int a, int b) {\n            return A[a] > A[b];\n        });\n        sort(orderLow.begin(), orderLow.end(), [&](int a, int b) {\n            return A[a] < A[b];\n        });\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestLabel(N, 0);\n        long long bestScore = scoreLabels(bestLabel);\n\n        int iter = 0;\n        while (elapsed() < 1.85) {\n            vector<int> treePar;\n\n            if (iter % 5 == 0) {\n                treePar = makeDFSTree((iter / 5) % 3);\n            } else {\n                treePar = makePrimTree(iter % 6);\n            }\n\n            vector<int> label = solveOnTree(treePar);\n\n            greedyImprove(label);\n\n            if (iter % 3 == 0) {\n                lowPerturbAndImprove(label);\n            }\n\n            long long sc = scoreLabels(label);\n            if (sc > bestScore && checkFeasible(label)) {\n                bestScore = sc;\n                bestLabel = label;\n            }\n\n            iter++;\n        }\n\n        if (!checkFeasible(bestLabel)) {\n            fill(bestLabel.begin(), bestLabel.end(), 0);\n        }\n\n        vector<int> parent = buildParents(bestLabel);\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << parent[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.run();\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nchar opposite_dir(char d) {\n    if (d == 'L') return 'R';\n    if (d == 'R') return 'L';\n    if (d == 'U') return 'D';\n    return 'U';\n}\n\nbool apply_shift(vector<string>& b, char d, int p) {\n    if (d == 'L') {\n        if (b[p][0] == 'o') return false;\n        for (int j = 0; j + 1 < N; j++) b[p][j] = b[p][j + 1];\n        b[p][N - 1] = '.';\n    } else if (d == 'R') {\n        if (b[p][N - 1] == 'o') return false;\n        for (int j = N - 1; j >= 1; j--) b[p][j] = b[p][j - 1];\n        b[p][0] = '.';\n    } else if (d == 'U') {\n        if (b[0][p] == 'o') return false;\n        for (int i = 0; i + 1 < N; i++) b[i][p] = b[i + 1][p];\n        b[N - 1][p] = '.';\n    } else {\n        if (b[N - 1][p] == 'o') return false;\n        for (int i = N - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n    return true;\n}\n\nint count_oni(const vector<string>& b) {\n    int c = 0;\n    for (auto& s : b) for (char ch : s) if (ch == 'x') c++;\n    return c;\n}\n\nbool validate_solution(const vector<string>& init, const vector<Op>& ops) {\n    if ((int)ops.size() > 4 * N * N) return false;\n    vector<string> b = init;\n    for (auto [d, p] : ops) {\n        if (p < 0 || p >= N) return false;\n        if (!apply_shift(b, d, p)) return false;\n    }\n    return count_oni(b) == 0;\n}\n\n/* -------------------- Restoring set-cover solver -------------------- */\n\nstruct Cand {\n    char d;\n    int p;\n    int s;\n    uint64_t mask;\n};\n\nint eval_cover(const vector<int>& sel, const vector<Cand>& cand, uint64_t allmask) {\n    uint64_t u = 0;\n    int sum = 0, mx = 0;\n    for (int id : sel) {\n        u |= cand[id].mask;\n        sum += cand[id].s;\n        mx = max(mx, cand[id].s);\n    }\n    if (u != allmask) return 1e9;\n    return 2 * sum - mx;\n}\n\nvoid prune_cover(vector<int>& sel, const vector<Cand>& cand, uint64_t allmask, mt19937& rng) {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        shuffle(sel.begin(), sel.end(), rng);\n        for (int k = 0; k < (int)sel.size(); k++) {\n            uint64_t u = 0;\n            for (int t = 0; t < (int)sel.size(); t++) {\n                if (t != k) u |= cand[sel[t]].mask;\n            }\n            if (u == allmask) {\n                sel.erase(sel.begin() + k);\n                changed = true;\n                break;\n            }\n        }\n    }\n}\n\nvector<Op> build_ops_from_cover(const vector<int>& sel, const vector<Cand>& cand) {\n    vector<Op> ops;\n    if (sel.empty()) return ops;\n\n    int last_pos = 0;\n    for (int i = 1; i < (int)sel.size(); i++) {\n        if (cand[sel[i]].s > cand[sel[last_pos]].s) last_pos = i;\n    }\n\n    for (int k = 0; k < (int)sel.size(); k++) {\n        const Cand& c = cand[sel[k]];\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        if (k != last_pos) {\n            char od = opposite_dir(c.d);\n            for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n        }\n    }\n    return ops;\n}\n\nvector<Op> solve_set_cover(const vector<string>& init, mt19937& rng) {\n    int id[N][N];\n    memset(id, -1, sizeof(id));\n    vector<pair<int,int>> oni;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (init[i][j] == 'x') {\n                id[i][j] = (int)oni.size();\n                oni.push_back({i, j});\n            }\n        }\n    }\n    int Mx = oni.size();\n    uint64_t allmask = (Mx == 64 ? ~0ULL : ((1ULL << Mx) - 1));\n\n    vector<Cand> cand;\n\n    auto add_cand = [&](char d, int p, int s, uint64_t mask) {\n        if (mask) cand.push_back({d, p, s, mask});\n    };\n\n    for (int i = 0; i < N; i++) {\n        int first_o = N;\n        for (int j = 0; j < N; j++) if (init[i][j] == 'o') { first_o = j; break; }\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int j = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('L', i, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int j = N - 1; j >= 0; j--) if (init[i][j] == 'o') { last_o = j; break; }\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int j = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('R', i, s, mask);\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int first_o = N;\n        for (int i = 0; i < N; i++) if (init[i][j] == 'o') { first_o = i; break; }\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int i = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('U', j, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int i = N - 1; i >= 0; i--) if (init[i][j] == 'o') { last_o = i; break; }\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int i = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('D', j, s, mask);\n            }\n        }\n    }\n\n    // Remove dominated candidates.\n    int C = cand.size();\n    vector<int> alive(C, 1);\n    for (int i = 0; i < C; i++) {\n        for (int j = 0; j < C; j++) if (i != j) {\n            bool subset = (cand[i].mask & ~cand[j].mask) == 0;\n            if (subset && (cand[j].s < cand[i].s || (cand[j].s == cand[i].s && j < i))) {\n                alive[i] = 0;\n                break;\n            }\n        }\n    }\n    vector<Cand> nc;\n    for (int i = 0; i < C; i++) if (alive[i]) nc.push_back(cand[i]);\n    cand.swap(nc);\n\n    vector<int> best_sel;\n\n    // Guaranteed baseline: choose the cheapest candidate for every Oni.\n    {\n        vector<int> sel;\n        for (int k = 0; k < Mx; k++) {\n            int best = -1;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                if ((cand[i].mask >> k) & 1ULL) {\n                    if (best == -1 || cand[i].s < cand[best].s) best = i;\n                }\n            }\n            if (best != -1) sel.push_back(best);\n        }\n        sort(sel.begin(), sel.end());\n        sel.erase(unique(sel.begin(), sel.end()), sel.end());\n        prune_cover(sel, cand, allmask, rng);\n        best_sel = sel;\n    }\n\n    int best_score = eval_cover(best_sel, cand, allmask);\n\n    // Randomized greedy set cover.\n    for (int iter = 0; iter < 5000; iter++) {\n        uint64_t covered = 0;\n        vector<int> sel;\n        double alpha = 1.0 + (rng() % 1200) / 1000.0; // 1.0 .. 2.2\n\n        while (covered != allmask) {\n            vector<pair<double,int>> v;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                uint64_t nw = cand[i].mask & ~covered;\n                if (!nw) continue;\n                int cnt = __builtin_popcountll(nw);\n                double noise = 0.85 + (rng() % 3000) / 10000.0; // 0.85..1.15\n                double sc = cand[i].s / pow((double)cnt, alpha) * noise;\n                v.push_back({sc, i});\n            }\n            if (v.empty()) break;\n            sort(v.begin(), v.end());\n            int K = min<int>((int)v.size(), 3 + (rng() % 8));\n            int pos = rng() % K;\n            int chosen = v[pos].second;\n            sel.push_back(chosen);\n            covered |= cand[chosen].mask;\n        }\n\n        if (covered != allmask) continue;\n        prune_cover(sel, cand, allmask, rng);\n        int sc = eval_cover(sel, cand, allmask);\n        if (sc < best_score) {\n            best_score = sc;\n            best_sel = sel;\n        }\n    }\n\n    return build_ops_from_cover(best_sel, cand);\n}\n\n/* -------------------- Dynamic one-way / bounce greedy solver -------------------- */\n\nstruct DynCand {\n    char d;\n    int p;\n    int s;\n    int rem;\n    bool bounce;\n};\n\nvoid add_dyn_cands_for_line(vector<DynCand>& res, const vector<string>& b, bool bounce_allowed) {\n    for (int i = 0; i < N; i++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[i][s - 1] != 'o'; s++) {\n            if (b[i][s - 1] == 'x') {\n                rem++;\n                res.push_back({'L', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'L', i, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[i][N - s] != 'o'; s++) {\n            if (b[i][N - s] == 'x') {\n                rem++;\n                res.push_back({'R', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'R', i, s, rem, true});\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[s - 1][j] != 'o'; s++) {\n            if (b[s - 1][j] == 'x') {\n                rem++;\n                res.push_back({'U', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'U', j, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[N - s][j] != 'o'; s++) {\n            if (b[N - s][j] == 'x') {\n                rem++;\n                res.push_back({'D', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'D', j, s, rem, true});\n            }\n        }\n    }\n}\n\nbool apply_dyn(vector<string>& b, vector<Op>& ops, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n        ops.push_back({c.d, c.p});\n    }\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n            ops.push_back({od, c.p});\n        }\n    }\n    return true;\n}\n\nvector<Op> dynamic_trial(const vector<string>& init, mt19937& rng, int mode) {\n    vector<string> b = init;\n    vector<Op> ops;\n\n    double alpha = 1.0 + (rng() % 1400) / 1000.0;\n    bool bounce_allowed = (mode != 0);\n\n    for (int step = 0; step < 45; step++) {\n        int oni = count_oni(b);\n        if (oni == 0) return ops;\n        if ((int)ops.size() > 4 * N * N) return {};\n\n        vector<DynCand> cs;\n        add_dyn_cands_for_line(cs, b, bounce_allowed);\n        if (cs.empty()) return {};\n\n        vector<pair<double,int>> rank;\n        for (int i = 0; i < (int)cs.size(); i++) {\n            int cost = cs[i].s * (cs[i].bounce ? 2 : 1);\n            double sc = cost / pow((double)cs[i].rem, alpha);\n\n            if (mode == 0 && cs[i].bounce) continue;\n            if (mode == 1 && cs[i].bounce) sc *= 1.15;\n            if (mode == 2 && !cs[i].bounce) sc *= 0.85;\n            if (mode == 3 && cs[i].bounce) sc *= 0.85;\n\n            double noise = 0.80 + (rng() % 4000) / 10000.0; // 0.80..1.20\n            sc *= noise;\n            rank.push_back({sc, i});\n        }\n\n        if (rank.empty()) return {};\n        sort(rank.begin(), rank.end());\n\n        int K;\n        if (mode == 4) K = 1;\n        else K = min<int>((int)rank.size(), 3 + (rng() % 8));\n\n        int chosen_pos = (K == 1 ? 0 : (int)(rng() % K));\n        DynCand chosen = cs[rank[chosen_pos].second];\n\n        if (!apply_dyn(b, ops, chosen)) return {};\n    }\n\n    if (count_oni(b) == 0) return ops;\n    return {};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<string> init(N);\n    for (int i = 0; i < N; i++) cin >> init[i];\n\n    mt19937 rng(1234567);\n\n    auto start = chrono::steady_clock::now();\n\n    vector<Op> best = solve_set_cover(init, rng);\n    if (!validate_solution(init, best)) best.clear();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int trial = 0;\n    while (elapsed() < 1.85) {\n        int mode;\n        if (trial == 0) mode = 4;          // deterministic-ish\n        else if (trial == 1) mode = 0;     // one-way only\n        else mode = rng() % 5;\n\n        vector<Op> ops = dynamic_trial(init, rng, mode);\n        if (!ops.empty() && (best.empty() || ops.size() < best.size())) {\n            if (validate_solution(init, ops)) best = ops;\n        }\n        trial++;\n    }\n\n    // Absolute safety fallback.\n    if (best.empty() || !validate_solution(init, best) || (int)best.size() > 4 * N * N) {\n        rng.seed(42);\n        best = solve_set_cover(init, rng);\n    }\n\n    for (auto [d, p] : best) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T;\nmt19937 rng(1234567);\n\nstruct Graph {\n    array<int, MAXN> a{}, b{}, cnt{};\n    int err = INT_MAX;\n};\n\ndouble elapsed_sec() {\n    static auto st = chrono::steady_clock::now();\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - st).count();\n}\n\nGraph evaluate(const array<int, MAXN>& a, const array<int, MAXN>& b) {\n    Graph g;\n    g.a = a;\n    g.b = b;\n    g.cnt.fill(0);\n\n    int cur = 0;\n    g.cnt[cur] = 1;\n\n    for (int step = 1; step < L; step++) {\n        int c = g.cnt[cur];\n        cur = (c & 1) ? a[cur] : b[cur];\n        g.cnt[cur]++;\n    }\n\n    long long e = 0;\n    for (int i = 0; i < N; i++) e += llabs((long long)g.cnt[i] - T[i]);\n    g.err = (int)e;\n    return g;\n}\n\nint calc_stationary_cost(const array<long long, MAXN>& in) {\n    long long c = 0;\n    for (int i = 0; i < N; i++) {\n        c += llabs(in[i] - 2LL * T[i]);\n    }\n    return (int)c;\n}\n\nGraph make_cycle_candidate(int id) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    sort(active.begin(), active.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    if (id == 1) {\n        reverse(active.begin(), active.end());\n    } else if (id >= 2) {\n        int m = (int)active.size();\n        int swaps = (id % 7 + 1) * m / 18;\n        for (int k = 0; k < swaps; k++) {\n            int p = rng() % m;\n            int q = rng() % m;\n            swap(active[p], active[q]);\n        }\n    }\n\n    int m = (int)active.size();\n\n    vector<int> succ(N, root);\n    array<long long, MAXN> in{};\n    in.fill(0);\n\n    for (int k = 0; k < m; k++) {\n        int v = active[k];\n        int to = active[(k + 1) % m];\n        succ[v] = to;\n        in[to] += T[v];\n    }\n\n    vector<int> sources = active;\n    sort(sources.begin(), sources.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    vector<int> assigned(N, root);\n\n    for (int s : sources) {\n        long long w = T[s];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(m);\n\n        for (int d : active) {\n            long long before = llabs(in[d] - 2LL * T[d]);\n            long long after = llabs(in[d] + w - 2LL * T[d]);\n            cand.push_back({after - before, d});\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int choose = 0;\n        if (id >= 2) {\n            int lim = min(4, (int)cand.size());\n            choose = rng() % lim;\n        }\n\n        int d = cand[choose].second;\n        assigned[s] = d;\n        in[d] += w;\n    }\n\n    // Local improvement of the \"stationary flow\" approximation.\n    for (int it = 0; it < 35; it++) {\n        long long best_delta = 0;\n        int best_s = -1, best_d = -1;\n\n        for (int s : sources) {\n            int old = assigned[s];\n            long long w = T[s];\n\n            for (int d : active) {\n                if (d == old) continue;\n\n                long long cur =\n                    llabs(in[old] - 2LL * T[old]) +\n                    llabs(in[d] - 2LL * T[d]);\n\n                long long nxt =\n                    llabs(in[old] - w - 2LL * T[old]) +\n                    llabs(in[d] + w - 2LL * T[d]);\n\n                long long delta = nxt - cur;\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_s = s;\n                    best_d = d;\n                }\n            }\n        }\n\n        if (best_s == -1) break;\n\n        int old = assigned[best_s];\n        long long w = T[best_s];\n        in[old] -= w;\n        in[best_d] += w;\n        assigned[best_s] = best_d;\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            a[i] = succ[i];\n            b[i] = assigned[i];\n\n            if (id >= 2 && (rng() & 1)) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nint weighted_pick(const vector<int>& v, const vector<int>& w) {\n    long long sum = 0;\n    for (int x : w) sum += x;\n    if (sum <= 0) return v[rng() % v.size()];\n\n    long long r = rng() % sum;\n    for (int i = 0; i < (int)v.size(); i++) {\n        if (r < w[i]) return v[i];\n        r -= w[i];\n    }\n    return v.back();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    uint64_t seed = 88172645463325252ULL;\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n        seed ^= (uint64_t)(T[i] + 10007) * (i + 911);\n        seed ^= seed << 7;\n        seed ^= seed >> 9;\n    }\n    rng.seed((uint32_t)seed);\n\n    Graph best;\n    best.err = INT_MAX;\n\n    // Generate several strongly-connected rotor graphs.\n    int initial_candidates = 45;\n    for (int id = 0; id < initial_candidates; id++) {\n        if (elapsed_sec() > 0.70) break;\n        Graph g = make_cycle_candidate(id);\n        if (g.err < best.err) best = g;\n    }\n\n    Graph cur = best;\n\n    // Phase optimization: swap a_i and b_i.\n    for (int pass = 0; pass < 3; pass++) {\n        bool improved = false;\n\n        for (int i = 0; i < N; i++) {\n            if (elapsed_sec() > 1.35) break;\n            if (cur.a[i] == cur.b[i]) continue;\n\n            swap(cur.a[i], cur.b[i]);\n            Graph ng = evaluate(cur.a, cur.b);\n\n            if (ng.err <= cur.err) {\n                cur = ng;\n                improved = true;\n                if (cur.err < best.err) best = cur;\n            } else {\n                swap(cur.a[i], cur.b[i]);\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    cur = best;\n\n    // Actual-score local search.\n    while (elapsed_sec() < 1.88) {\n        vector<int> over, under, wover, wunder;\n        for (int i = 0; i < N; i++) {\n            int d = cur.cnt[i] - T[i];\n            if (d > 0) {\n                over.push_back(i);\n                wover.push_back(d);\n            } else if (d < 0) {\n                under.push_back(i);\n                wunder.push_back(-d);\n            }\n        }\n\n        if (over.empty() || under.empty()) break;\n\n        int typ = rng() % 100;\n        array<int, MAXN> na = cur.a, nb = cur.b;\n\n        if (typ < 25) {\n            int i = rng() % N;\n            if (na[i] == nb[i]) continue;\n            swap(na[i], nb[i]);\n        } else if (typ < 80) {\n            int v = weighted_pick(over, wover);\n            int u = weighted_pick(under, wunder);\n\n            vector<pair<int, int>> edges;\n            for (int i = 0; i < N; i++) {\n                if (na[i] == v) edges.push_back({i, 0});\n                if (nb[i] == v) edges.push_back({i, 1});\n            }\n            if (edges.empty()) continue;\n\n            auto [s, slot] = edges[rng() % edges.size()];\n            if (slot == 0) na[s] = u;\n            else nb[s] = u;\n        } else {\n            int s = weighted_pick(over, wover);\n            int u = weighted_pick(under, wunder);\n\n            if (rng() & 1) na[s] = u;\n            else nb[s] = u;\n        }\n\n        Graph ng = evaluate(na, nb);\n\n        bool accept = false;\n        if (ng.err <= cur.err) accept = true;\n        else {\n            double e = elapsed_sec();\n            int temp = max(1, (int)(1200.0 * max(0.0, 1.88 - e) / 1.88));\n            int diff = ng.err - cur.err;\n            if (diff < temp && (int)(rng() % temp) < temp - diff) accept = true;\n        }\n\n        if (accept) {\n            cur = ng;\n            if (cur.err < best.err) best = cur;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), 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\nint N, M, Q, L, W;\nvector<int> G;\nvector<double> cx, cy;\n\ninline double edist(int a, int b) {\n    double dx = cx[a] - cx[b];\n    double dy = cy[a] - cy[b];\n    return sqrt(dx * dx + dy * dy);\n}\n\ninline unsigned long long ekey(int a, int b) {\n    if (a > b) swap(a, b);\n    return (unsigned long long)a << 32 | (unsigned int)b;\n}\n\ninline pair<int,int> decode_key(unsigned long long k) {\n    int a = (int)(k >> 32);\n    int b = (int)(k & 0xffffffffu);\n    return {a, b};\n}\n\n// Hilbert order for 0 <= x,y < 2^bits\nlong long hilbert_index(int x, int y, int bits = 14) {\n    long long d = 0;\n    int n = 1 << bits;\n    for (int s = n >> 1; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += 1LL * s * s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = n - 1 - x;\n                y = n - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\nstruct Evaluator {\n    vector<int> ord;\n    unordered_map<int, double> cache;\n\n    Evaluator() {}\n    Evaluator(const vector<int>& o): ord(o) {\n        cache.reserve(20000);\n    }\n\n    double interval_cost(int s, int len) {\n        if (len <= 1) return 0.0;\n        if (len == 2) return edist(ord[s], ord[s + 1]);\n\n        int key = s * 1000 + len;\n        auto it = cache.find(key);\n        if (it != cache.end()) return it->second;\n\n        vector<double> minv(len, 1e100);\n        vector<char> used(len, 0);\n        minv[0] = 0;\n        double res = 0;\n\n        for (int itn = 0; itn < len; itn++) {\n            int v = -1;\n            double best = 1e100;\n            for (int i = 0; i < len; i++) {\n                if (!used[i] && minv[i] < best) {\n                    best = minv[i];\n                    v = i;\n                }\n            }\n            used[v] = 1;\n            res += best;\n            int cv = ord[s + v];\n            for (int u = 0; u < len; u++) {\n                if (!used[u]) {\n                    double d = edist(cv, ord[s + u]);\n                    if (d < minv[u]) minv[u] = d;\n                }\n            }\n        }\n\n        cache[key] = res;\n        return res;\n    }\n\n    double block_cost(int s, int len) {\n        if (len <= 1) return 0.0;\n        if (len <= L) return interval_cost(s, len);\n\n        double res = 0;\n        int end = s + len;\n        int cur = s;\n        while (cur < end - 1) {\n            int e = min(end, cur + L);\n            res += interval_cost(cur, e - cur);\n            if (e == end) break;\n            cur = e - 1;\n        }\n        return res;\n    }\n\n    double sequence_cost(const vector<int>& perm) {\n        double res = 0;\n        int pos = 0;\n        for (int id : perm) {\n            res += block_cost(pos, G[id]);\n            pos += G[id];\n        }\n        return res;\n    }\n};\n\nvector<pair<int,int>> prim_edges(const vector<int>& verts) {\n    int n = (int)verts.size();\n    vector<pair<int,int>> ret;\n    if (n <= 1) return ret;\n    if (n == 2) {\n        ret.push_back({verts[0], verts[1]});\n        return ret;\n    }\n\n    vector<double> minv(n, 1e100);\n    vector<int> par(n, -1);\n    vector<char> used(n, 0);\n    minv[0] = 0;\n\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n        used[v] = 1;\n        if (par[v] != -1) ret.push_back({verts[v], verts[par[v]]});\n\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(verts[v], verts[u]);\n                if (d < minv[u]) {\n                    minv[u] = d;\n                    par[u] = v;\n                }\n            }\n        }\n    }\n    return ret;\n}\n\nstring subset_key(vector<int> v) {\n    sort(v.begin(), v.end());\n    string s;\n    s.reserve(v.size() * 5);\n    for (int x : v) {\n        s += to_string(x);\n        s += ',';\n    }\n    return s;\n}\n\nvector<pair<int,int>> do_query(const vector<int>& c) {\n    cout << \"? \" << c.size();\n    for (int v : c) cout << ' ' << v;\n    cout << endl;\n    cout.flush();\n\n    vector<pair<int,int>> ret;\n    for (int i = 0; i < (int)c.size() - 1; i++) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        ret.push_back({a, b});\n    }\n    return ret;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    cx.resize(N);\n    cy.resize(N);\n    for (int i = 0; i < N; i++) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cx[i] = (lx + rx) * 0.5;\n        cy[i] = (ly + ry) * 0.5;\n    }\n\n    vector<vector<int>> city_orders;\n\n    for (int t = 0; t < 8; t++) {\n        vector<pair<long long,int>> v;\n        for (int i = 0; i < N; i++) {\n            double x = cx[i], y = cy[i];\n            double X = x, Y = y;\n            if (t == 0) { X = x; Y = y; }\n            if (t == 1) { X = y; Y = x; }\n            if (t == 2) { X = 10000 - x; Y = y; }\n            if (t == 3) { X = x; Y = 10000 - y; }\n            if (t == 4) { X = 10000 - x; Y = 10000 - y; }\n            if (t == 5) { X = y; Y = 10000 - x; }\n            if (t == 6) { X = 10000 - y; Y = x; }\n            if (t == 7) { X = 10000 - y; Y = 10000 - x; }\n\n            int xi = min(16383, max(0, (int)llround(X * 16383.0 / 10000.0)));\n            int yi = min(16383, max(0, (int)llround(Y * 16383.0 / 10000.0)));\n            v.push_back({hilbert_index(xi, yi), i});\n        }\n        sort(v.begin(), v.end());\n        vector<int> ord;\n        for (auto [d, i] : v) ord.push_back(i);\n        city_orders.push_back(ord);\n    }\n\n    auto make_perm_variants = [&]() {\n        vector<vector<int>> vars;\n\n        vector<int> p0(M);\n        iota(p0.begin(), p0.end(), 0);\n        vars.push_back(p0);\n\n        vector<int> p1 = p0;\n        reverse(p1.begin(), p1.end());\n        vars.push_back(p1);\n\n        vector<int> asc = p0;\n        sort(asc.begin(), asc.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] < G[b];\n            return a < b;\n        });\n        vars.push_back(asc);\n\n        vector<int> desc = p0;\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] > G[b];\n            return a < b;\n        });\n        vars.push_back(desc);\n\n        return vars;\n    };\n\n    double best_score = 1e100;\n    vector<int> best_order, best_perm;\n\n    for (const auto& ord : city_orders) {\n        Evaluator ev(ord);\n        auto vars = make_perm_variants();\n        for (auto& perm : vars) {\n            double sc = ev.sequence_cost(perm);\n            if (sc < best_score) {\n                best_score = sc;\n                best_order = ord;\n                best_perm = perm;\n            }\n        }\n    }\n\n    // Local adjacent-swap improvement on the best order.\n    {\n        Evaluator ev(best_order);\n        vector<int> perm = best_perm;\n        double cur = ev.sequence_cost(perm);\n\n        for (int pass = 0; pass < 30; pass++) {\n            bool changed = false;\n            int pos = 0;\n            vector<int> pref(M + 1, 0);\n            for (int i = 0; i < M; i++) pref[i + 1] = pref[i] + G[perm[i]];\n\n            for (int i = 0; i + 1 < M; i++) {\n                int s = pref[i];\n                int a = perm[i], b = perm[i + 1];\n\n                double oldc = ev.block_cost(s, G[a])\n                            + ev.block_cost(s + G[a], G[b]);\n                double newc = ev.block_cost(s, G[b])\n                            + ev.block_cost(s + G[b], G[a]);\n\n                if (newc + 1e-9 < oldc) {\n                    swap(perm[i], perm[i + 1]);\n                    cur += newc - oldc;\n                    changed = true;\n                    // Prefix after i+1 is unchanged, but pref[i+1] changes.\n                    pref[i + 1] = pref[i] + G[perm[i]];\n                }\n            }\n            if (!changed) break;\n        }\n\n        if (cur < best_score) {\n            best_score = cur;\n            best_perm = perm;\n        }\n    }\n\n    vector<vector<int>> groups(M);\n    {\n        int pos = 0;\n        for (int id : best_perm) {\n            groups[id].assign(best_order.begin() + pos, best_order.begin() + pos + G[id]);\n            pos += G[id];\n        }\n    }\n\n    vector<vector<pair<int,int>>> final_edges(M);\n    vector<unordered_map<unsigned long long,int>> oracle_edges(M);\n\n    struct PlannedQuery {\n        int gid;\n        vector<int> cities;\n        bool exact_small;\n    };\n    vector<PlannedQuery> queries;\n    unordered_set<string> used_subset;\n    used_subset.reserve(2000);\n\n    auto add_query = [&](int gid, const vector<int>& c, bool exact_small) {\n        if ((int)queries.size() >= Q) return false;\n        if ((int)c.size() < 2 || (int)c.size() > L) return false;\n        string key = subset_key(c);\n        if (used_subset.count(key)) return false;\n        used_subset.insert(key);\n        queries.push_back({gid, c, exact_small});\n        return true;\n    };\n\n    // Base queries, guaranteeing connectivity for groups with size >= 3.\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n        if (g <= 2) continue;\n\n        if (g <= L) {\n            add_query(gid, groups[gid], true);\n        } else {\n            int cur = 0;\n            while (cur < g - 1) {\n                int e = min(g, cur + L);\n                vector<int> sub(groups[gid].begin() + cur, groups[gid].begin() + e);\n                add_query(gid, sub, false);\n                if (e == g) break;\n                cur = e - 1;\n            }\n        }\n    }\n\n    // Extra nearest-neighbor queries for large groups.\n    vector<int> large_ids;\n    for (int gid = 0; gid < M; gid++) {\n        if ((int)groups[gid].size() > L) large_ids.push_back(gid);\n    }\n    sort(large_ids.begin(), large_ids.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    int round = 0;\n    while ((int)queries.size() < Q && !large_ids.empty()) {\n        bool any = false;\n        for (int gid : large_ids) {\n            if ((int)queries.size() >= Q) break;\n            int g = groups[gid].size();\n            if (round >= g) continue;\n\n            int seed = groups[gid][round];\n            vector<pair<double,int>> near;\n            near.reserve(g);\n            for (int v : groups[gid]) {\n                near.push_back({edist(seed, v), v});\n            }\n            sort(near.begin(), near.end());\n\n            vector<int> sub;\n            for (int i = 0; i < min(L, g); i++) sub.push_back(near[i].second);\n\n            if (add_query(gid, sub, false)) any = true;\n        }\n        round++;\n        if (!any && round > N) break;\n    }\n\n    // Perform queries.\n    for (auto& qu : queries) {\n        auto ret = do_query(qu.cities);\n        int gid = qu.gid;\n\n        for (auto [a, b] : ret) {\n            oracle_edges[gid][ekey(a, b)]++;\n        }\n\n        if (qu.exact_small) {\n            final_edges[gid] = ret;\n        }\n    }\n\n    // Construct final edges.\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n\n        if (g <= 1) {\n            final_edges[gid].clear();\n        } else if (g == 2) {\n            final_edges[gid] = {{groups[gid][0], groups[gid][1]}};\n        } else if (g <= L) {\n            // Already exact MST from whole-group query.\n            if ((int)final_edges[gid].size() != g - 1) {\n                final_edges[gid] = prim_edges(groups[gid]);\n            }\n        } else {\n            struct CE {\n                double w;\n                int a, b;\n            };\n            vector<CE> cand;\n\n            for (auto &kv : oracle_edges[gid]) {\n                auto [a, b] = decode_key(kv.first);\n                int cnt = kv.second;\n                double factor = 0.75 - 0.05 * min(3, cnt - 1);\n                cand.push_back({edist(a, b) * factor, a, b});\n            }\n\n            // Estimated MST backup.\n            auto backup = prim_edges(groups[gid]);\n            for (auto [a, b] : backup) {\n                cand.push_back({edist(a, b) * 0.95, a, b});\n            }\n\n            sort(cand.begin(), cand.end(), [](const CE& x, const CE& y) {\n                if (x.w != y.w) return x.w < y.w;\n                if (x.a != y.a) return x.a < y.a;\n                return x.b < y.b;\n            });\n\n            DSU dsu(N);\n            vector<pair<int,int>> tree;\n            tree.reserve(g - 1);\n\n            for (auto &e : cand) {\n                if (dsu.unite(e.a, e.b)) {\n                    tree.push_back({e.a, e.b});\n                    if ((int)tree.size() == g - 1) break;\n                }\n            }\n\n            // Very unlikely fallback.\n            if ((int)tree.size() != g - 1) {\n                tree = prim_edges(groups[gid]);\n            }\n\n            final_edges[gid] = tree;\n        }\n    }\n\n    cout << \"!\" << '\\n';\n    for (int gid = 0; gid < M; gid++) {\n        for (int i = 0; i < (int)groups[gid].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[gid][i];\n        }\n        cout << '\\n';\n\n        for (auto [a, b] : final_edges[gid]) {\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 Act {\n    char a, d;\n};\n\nconst int MAXC = 400;\nconst int INF = 1e9;\n\nint N, M;\nvector<int> pos_id;\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\ninline int id(int r, int c) { return r * N + c; }\ninline int rr(int x) { return x / N; }\ninline int cc(int x) { return x % N; }\ninline bool inside(int r, int c) { return 0 <= r && r < N && 0 <= c && c < N; }\n\nstruct BFSRes {\n    array<int, MAXC> dist;\n    array<int, MAXC> par;\n    array<char, MAXC> pact;\n    array<char, MAXC> pdir;\n};\n\nbool blocked(const bitset<MAXC>& g, int r, int c) {\n    if (!inside(r, c)) return true;\n    return g[id(r, c)];\n}\n\nint slide_stop(const bitset<MAXC>& g, int s, int dir) {\n    int r = rr(s), c = cc(s);\n    while (true) {\n        int nr = r + dr[dir], nc = c + dc[dir];\n        if (blocked(g, nr, nc)) break;\n        r = nr;\n        c = nc;\n    }\n    return id(r, c);\n}\n\n// forbid_stop: this cell must not be stopped on / moved onto as an intermediate target.\n// Sliding over it is allowed.\nBFSRes forward_bfs(const bitset<MAXC>& g, int start, int forbid_stop = -1) {\n    BFSRes res;\n    res.dist.fill(INF);\n    res.par.fill(-1);\n    res.pact.fill(0);\n    res.pdir.fill(0);\n\n    queue<int> q;\n    res.dist[start] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            // Move\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (to != forbid_stop && res.dist[to] == INF) {\n                    res.dist[to] = res.dist[v] + 1;\n                    res.par[to] = v;\n                    res.pact[to] = 'M';\n                    res.pdir[to] = dch[d];\n                    q.push(to);\n                }\n            }\n\n            // Slide\n            int to = slide_stop(g, v, d);\n            if (to != v && to != forbid_stop && res.dist[to] == INF) {\n                res.dist[to] = res.dist[v] + 1;\n                res.par[to] = v;\n                res.pact[to] = 'S';\n                res.pdir[to] = dch[d];\n                q.push(to);\n            }\n        }\n    }\n\n    return res;\n}\n\narray<int, MAXC> reverse_bfs_dist(const bitset<MAXC>& g, int target) {\n    array<int, MAXC> dist;\n    dist.fill(INF);\n    if (g[target]) return dist;\n\n    queue<int> q;\n    dist[target] = 0;\n    q.push(target);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            // Reverse of Move d: predecessor is v - d\n            int pr = r - dr[d], pc = c - dc[d];\n            if (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n            }\n\n            // Reverse of Slide d.\n            // v can be a slide stop in direction d only if the next cell is blocked/outside.\n            int br = r + dr[d], bc = c + dc[d];\n            if (!blocked(g, br, bc)) continue;\n\n            pr = r - dr[d];\n            pc = c - dc[d];\n            while (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n                pr -= dr[d];\n                pc -= dc[d];\n            }\n        }\n    }\n\n    return dist;\n}\n\nvector<Act> restore_forward(const BFSRes& bfs, int start, int goal) {\n    vector<Act> rev;\n    int cur = goal;\n    while (cur != start) {\n        rev.push_back({bfs.pact[cur], bfs.pdir[cur]});\n        cur = bfs.par[cur];\n        if (cur < 0) return {};\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nvector<Act> restore_by_reverse_dist(const bitset<MAXC>& g, const array<int, MAXC>& dist, int start, int target) {\n    vector<Act> ret;\n    int cur = start;\n\n    while (cur != target) {\n        bool found = false;\n        int cd = dist[cur];\n\n        for (int d = 0; d < 4 && !found; d++) {\n            int r = rr(cur), c = cc(cur);\n\n            // Move\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (dist[to] == cd - 1) {\n                    ret.push_back({'M', dch[d]});\n                    cur = to;\n                    found = true;\n                    break;\n                }\n            }\n\n            // Slide\n            int to = slide_stop(g, cur, d);\n            if (to != cur && dist[to] == cd - 1) {\n                ret.push_back({'S', dch[d]});\n                cur = to;\n                found = true;\n                break;\n            }\n        }\n\n        if (!found) {\n            // Should not happen.\n            ret.clear();\n            return ret;\n        }\n    }\n\n    return ret;\n}\n\nint dir_from_to(int p, int b) {\n    int pr = rr(p), pc = cc(p);\n    int br = rr(b), bc = cc(b);\n    for (int d = 0; d < 4; d++) {\n        if (pr + dr[d] == br && pc + dc[d] == bc) return d;\n    }\n    return -1;\n}\n\nstruct State {\n    bitset<MAXC> grid;\n    int cost;\n    vector<Act> acts;\n};\n\nstruct Option {\n    int cost;\n    int b;\n    int p;\n};\n\nvector<State> expand_state(\n    const State& st,\n    int start,\n    int target,\n    const bitset<MAXC>& future_target_mask\n) {\n    constexpr int TOP_K = 5;\n    constexpr int ALLOW_EXTRA = 4;\n\n    vector<State> res;\n\n    BFSRes bfs_normal = forward_bfs(st.grid, start, -1);\n    BFSRes bfs_avoid = forward_bfs(st.grid, start, target);\n\n    int base_cost = bfs_normal.dist[target];\n\n    // Baseline: no alteration.\n    if (base_cost < INF) {\n        State ns;\n        ns.grid = st.grid;\n        ns.acts = st.acts;\n        auto path = restore_forward(bfs_normal, start, target);\n        ns.acts.insert(ns.acts.end(), path.begin(), path.end());\n        ns.cost = (int)ns.acts.size();\n        res.push_back(std::move(ns));\n    }\n\n    vector<Option> opts;\n\n    for (int b = 0; b < N * N; b++) {\n        bool is_block = st.grid[b];\n\n        // Avoid placing a new block on current/future target squares.\n        if (!is_block && future_target_mask[b]) continue;\n\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(b);\n        if (g2[target]) continue;\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n\n        int best_cost = INF;\n        int best_p = -1;\n\n        int br = rr(b), bc = cc(b);\n        for (int d = 0; d < 4; d++) {\n            int pr = br - dr[d], pc = bc - dc[d];\n            if (!inside(pr, pc)) continue;\n\n            int p = id(pr, pc);\n            if (p == b) continue;\n            if (st.grid[p]) continue;\n            if (g2[p]) continue;\n            if (bfs_avoid.dist[p] >= INF) continue;\n            if (dist_to_target[p] >= INF) continue;\n\n            int cand = bfs_avoid.dist[p] + 1 + dist_to_target[p];\n            if (cand < best_cost) {\n                best_cost = cand;\n                best_p = p;\n            }\n        }\n\n        if (best_p == -1) continue;\n        if (base_cost < INF && best_cost > base_cost + ALLOW_EXTRA) continue;\n\n        opts.push_back({best_cost, b, best_p});\n    }\n\n    sort(opts.begin(), opts.end(), [](const Option& x, const Option& y) {\n        return x.cost < y.cost;\n    });\n    if ((int)opts.size() > TOP_K) opts.resize(TOP_K);\n\n    for (const auto& op : opts) {\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(op.b);\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n        if (dist_to_target[op.p] >= INF) continue;\n\n        State ns;\n        ns.grid = g2;\n        ns.acts = st.acts;\n\n        auto path1 = restore_forward(bfs_avoid, start, op.p);\n        ns.acts.insert(ns.acts.end(), path1.begin(), path1.end());\n\n        int ad = dir_from_to(op.p, op.b);\n        if (ad < 0) continue;\n        ns.acts.push_back({'A', dch[ad]});\n\n        auto path2 = restore_by_reverse_dist(g2, dist_to_target, op.p, target);\n        if (path2.empty() && op.p != target) continue;\n        ns.acts.insert(ns.acts.end(), path2.begin(), path2.end());\n\n        ns.cost = (int)ns.acts.size();\n        res.push_back(std::move(ns));\n    }\n\n    return res;\n}\n\nvector<Act> simple_fallback() {\n    vector<Act> ret;\n    int cur = pos_id[0];\n\n    for (int k = 1; k < M; k++) {\n        int t = pos_id[k];\n\n        int r = rr(cur), c = cc(cur);\n        int tr = rr(t), tc = cc(t);\n\n        while (r < tr) {\n            ret.push_back({'M', 'D'});\n            r++;\n        }\n        while (r > tr) {\n            ret.push_back({'M', 'U'});\n            r--;\n        }\n        while (c < tc) {\n            ret.push_back({'M', 'R'});\n            c++;\n        }\n        while (c > tc) {\n            ret.push_back({'M', 'L'});\n            c--;\n        }\n\n        cur = t;\n    }\n\n    return ret;\n}\n\nbool simulate(const vector<Act>& acts) {\n    if ((int)acts.size() > 2 * N * M) return false;\n\n    bitset<MAXC> g;\n    int cur = pos_id[0];\n    int nxt = 1;\n\n    auto dir_index = [](char c) {\n        if (c == 'U') return 0;\n        if (c == 'D') return 1;\n        if (c == 'L') return 2;\n        return 3;\n    };\n\n    for (auto [a, ch] : acts) {\n        int d = dir_index(ch);\n        int r = rr(cur), c = cc(cur);\n\n        if (a == 'M') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n            int to = id(nr, nc);\n            if (g[to]) return false;\n            cur = to;\n\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'S') {\n            while (true) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (!inside(nr, nc) || g[id(nr, nc)]) break;\n                r = nr;\n                c = nc;\n            }\n            cur = id(r, c);\n\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'A') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n            int b = id(nr, nc);\n            g.flip(b);\n        } else {\n            return false;\n        }\n    }\n\n    return nxt == M;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    pos_id.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        int r, c;\n        cin >> r >> c;\n        pos_id[k] = id(r, c);\n    }\n\n    vector<bitset<MAXC>> future_mask(M + 1);\n    for (int k = M - 1; k >= 0; k--) {\n        future_mask[k] = future_mask[k + 1];\n        future_mask[k].set(pos_id[k]);\n    }\n\n    constexpr int BEAM_W = 4;\n\n    vector<State> beam;\n    State init;\n    init.grid.reset();\n    init.cost = 0;\n    beam.push_back(init);\n\n    for (int leg = 1; leg < M; leg++) {\n        int start = pos_id[leg - 1];\n        int target = pos_id[leg];\n\n        vector<State> nxt_states;\n\n        for (const auto& st : beam) {\n            auto ex = expand_state(st, start, target, future_mask[leg]);\n            for (auto& ns : ex) nxt_states.push_back(std::move(ns));\n        }\n\n        sort(nxt_states.begin(), nxt_states.end(), [](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        vector<State> nb;\n        for (auto& st : nxt_states) {\n            bool dup = false;\n            for (const auto& kept : nb) {\n                if (kept.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (dup) continue;\n\n            nb.push_back(std::move(st));\n            if ((int)nb.size() >= BEAM_W) break;\n        }\n\n        if (nb.empty()) {\n            auto fb = simple_fallback();\n            for (auto [a, d] : fb) cout << a << ' ' << d << '\\n';\n            return 0;\n        }\n\n        beam = std::move(nb);\n    }\n\n    vector<Act> ans = beam[0].acts;\n\n    if (!simulate(ans)) {\n        ans = simple_fallback();\n    }\n\n    for (auto [a, d] : ans) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"},"2":{"ahc001":"#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 Rect {\n    int a, b, c, d;\n};\n\nstruct Blocker {\n    int id;\n    int gap;\n    int limit;\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\nvector<long double> wt;\nmt19937 rng(1234567);\nTimer timer_;\n\nlong long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\ndouble score_area(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    double q = (double)min(s, r) / (double)max(s, r);\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble evaluate(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; i++) {\n        const Rect& e = rects[i];\n        if (e.a <= xs[i] && xs[i] + 1 <= e.c && e.b <= ys[i] && ys[i] + 1 <= e.d) {\n            sum += score_area(area(e), rs[i]);\n        }\n    }\n    return sum;\n}\n\nbool overlap1d(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\n/* ---------- slicing construction ---------- */\n\nstruct SplitCand {\n    int axis;\n    int k;\n    int cut;\n    double cost;\n};\n\nvoid build_rec(const vector<int>& ids, int L, int B, int R, int T, vector<Rect>& out, int topK) {\n    int m = (int)ids.size();\n\n    if (m == 1) {\n        out[ids[0]] = {L, B, R, T};\n        return;\n    }\n\n    long double totalTarget = 0;\n    for (int id : ids) totalTarget += wt[id];\n\n    long long regionArea = 1LL * (R - L) * (T - B);\n    vector<SplitCand> cands;\n\n    for (int axis = 0; axis < 2; axis++) {\n        vector<int> v = ids;\n\n        if (axis == 0) {\n            sort(v.begin(), v.end(), [&](int p, int q) {\n                if (xs[p] != xs[q]) return xs[p] < xs[q];\n                return ys[p] < ys[q];\n            });\n        } else {\n            sort(v.begin(), v.end(), [&](int p, int q) {\n                if (ys[p] != ys[q]) return ys[p] < ys[q];\n                return xs[p] < xs[q];\n            });\n        }\n\n        vector<long double> pref(m + 1, 0);\n        for (int i = 0; i < m; i++) pref[i + 1] = pref[i] + wt[v[i]];\n\n        for (int k = 1; k < m; k++) {\n            int coordL = (axis == 0 ? xs[v[k - 1]] : ys[v[k - 1]]);\n            int coordR = (axis == 0 ? xs[v[k]] : ys[v[k]]);\n            if (coordL >= coordR) continue;\n\n            int start = (axis == 0 ? L : B);\n            int end = (axis == 0 ? R : T);\n            int otherLen = (axis == 0 ? T - B : R - L);\n            int len = end - start;\n\n            int lo = max(coordL + 1, start + 1);\n            int hi = min(coordR, end - 1);\n            if (lo > hi) continue;\n\n            long double ratio = pref[k] / totalTarget;\n            int desired = (int)llround((long double)start + ratio * len);\n            int cut = min(max(desired, lo), hi);\n\n            long long leftArea = 1LL * (cut - start) * otherLen;\n            long long rightArea = regionArea - leftArea;\n\n            long double leftTarget = pref[k];\n            long double rightTarget = totalTarget - leftTarget;\n            long double scale = (long double)regionArea / totalTarget;\n\n            double er1 = fabs((double)((long double)leftArea / leftTarget - scale));\n            double er2 = fabs((double)((long double)rightArea / rightTarget - scale));\n            double cost = er1 * (double)(leftTarget / totalTarget)\n                        + er2 * (double)(rightTarget / totalTarget);\n\n            if (k == 1) {\n                int id = v[0];\n                cost += 0.08 * (1.0 - score_area(leftArea, rs[id]));\n            }\n            if (m - k == 1) {\n                int id = v[m - 1];\n                cost += 0.08 * (1.0 - score_area(rightArea, rs[id]));\n            }\n\n            cands.push_back({axis, k, cut, cost});\n        }\n    }\n\n    if (cands.empty()) {\n        vector<int> v = ids;\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (xs[p] != xs[q]) return xs[p] < xs[q];\n            return ys[p] < ys[q];\n        });\n\n        int k = m / 2;\n        int cut = (L + R) / 2;\n        cut = min(max(cut, L + 1), R - 1);\n\n        vector<int> A(v.begin(), v.begin() + k), C(v.begin() + k, v.end());\n        build_rec(A, L, B, cut, T, out, topK);\n        build_rec(C, cut, B, R, T, out, topK);\n        return;\n    }\n\n    sort(cands.begin(), cands.end(), [](const SplitCand& x, const SplitCand& y) {\n        return x.cost < y.cost;\n    });\n\n    int pick = 0;\n    if (topK > 1) {\n        int lim = min<int>(topK, cands.size());\n        double u = uniform_real_distribution<double>(0.0, 1.0)(rng);\n        pick = min(lim - 1, (int)(u * u * lim));\n    }\n\n    SplitCand ch = cands[pick];\n\n    vector<int> v = ids;\n    if (ch.axis == 0) {\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (xs[p] != xs[q]) return xs[p] < xs[q];\n            return ys[p] < ys[q];\n        });\n    } else {\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (ys[p] != ys[q]) return ys[p] < ys[q];\n            return xs[p] < xs[q];\n        });\n    }\n\n    vector<int> left(v.begin(), v.begin() + ch.k);\n    vector<int> right(v.begin() + ch.k, v.end());\n\n    if (ch.axis == 0) {\n        build_rec(left, L, B, ch.cut, T, out, topK);\n        build_rec(right, ch.cut, B, R, T, out, topK);\n    } else {\n        build_rec(left, L, B, R, ch.cut, out, topK);\n        build_rec(right, L, ch.cut, R, T, out, topK);\n    }\n}\n\nvector<Rect> build_slicing(int topK, double noise) {\n    wt.assign(n, 0);\n    if (noise <= 0) {\n        for (int i = 0; i < n; i++) wt[i] = rs[i];\n    } else {\n        normal_distribution<double> nd(0.0, noise);\n        for (int i = 0; i < n; i++) {\n            double mul = exp(nd(rng));\n            mul = min(1.45, max(0.70, mul));\n            wt[i] = (long double)rs[i] * mul;\n        }\n    }\n\n    vector<Rect> res(n);\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    build_rec(ids, 0, 0, 10000, 10000, res, topK);\n    return res;\n}\n\n/* ---------- local search ---------- */\n\nbool shrink_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect cur = rects[id];\n        long long A = area(cur);\n        double curScore = score_area(A, rs[id]);\n\n        Rect best = cur;\n        double bestGain = 1e-15;\n\n        auto try_delta = [&](int dir, int maxd) {\n            if (maxd <= 0) return;\n\n            int len = (dir < 2 ? cur.d - cur.b : cur.c - cur.a);\n            vector<int> ds;\n\n            long long excess = A - rs[id];\n            if (excess > 0) {\n                long long q = excess / len;\n                for (long long z : {q - 2, q - 1, q, q + 1, q + 2}) {\n                    if (1 <= z && z <= maxd) ds.push_back((int)z);\n                }\n            }\n\n            ds.push_back(1);\n            ds.push_back(maxd);\n            sort(ds.begin(), ds.end());\n            ds.erase(unique(ds.begin(), ds.end()), ds.end());\n\n            for (int dlt : ds) {\n                Rect nr = cur;\n                if (dir == 0) nr.a += dlt;\n                if (dir == 1) nr.c -= dlt;\n                if (dir == 2) nr.b += dlt;\n                if (dir == 3) nr.d -= dlt;\n\n                if (!(nr.a < nr.c && nr.b < nr.d)) continue;\n                if (!(nr.a <= xs[id] && xs[id] + 1 <= nr.c && nr.b <= ys[id] && ys[id] + 1 <= nr.d)) continue;\n\n                double ns = score_area(area(nr), rs[id]);\n                double gain = ns - curScore;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = nr;\n                }\n            }\n        };\n\n        try_delta(0, xs[id] - cur.a);\n        try_delta(1, cur.c - (xs[id] + 1));\n        try_delta(2, ys[id] - cur.b);\n        try_delta(3, cur.d - (ys[id] + 1));\n\n        if (bestGain > 1e-14) {\n            rects[id] = best;\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nint max_expand_delta(const vector<Rect>& rects, int id, int dir) {\n    const Rect& r = rects[id];\n    int lim;\n\n    if (dir == 0) {\n        lim = r.a;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.b, r.d, o.b, o.d) && o.c <= r.a) lim = min(lim, r.a - o.c);\n        }\n    } else if (dir == 1) {\n        lim = 10000 - r.c;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.b, r.d, o.b, o.d) && o.a >= r.c) lim = min(lim, o.a - r.c);\n        }\n    } else if (dir == 2) {\n        lim = r.b;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.a, r.c, o.a, o.c) && o.d <= r.b) lim = min(lim, r.b - o.d);\n        }\n    } else {\n        lim = 10000 - r.d;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.a, r.c, o.a, o.c) && o.b >= r.d) lim = min(lim, o.b - r.d);\n        }\n    }\n\n    return lim;\n}\n\nbool expand_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect cur = rects[id];\n        long long A = area(cur);\n        double curScore = score_area(A, rs[id]);\n\n        Rect best = cur;\n        double bestGain = 1e-15;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int maxd = max_expand_delta(rects, id, dir);\n            if (maxd <= 0) continue;\n\n            int len = (dir < 2 ? cur.d - cur.b : cur.c - cur.a);\n            vector<int> ds;\n\n            long long need = rs[id] - A;\n            if (need > 0) {\n                long long q = need / len;\n                for (long long z : {q - 2, q - 1, q, q + 1, q + 2}) {\n                    if (1 <= z && z <= maxd) ds.push_back((int)z);\n                }\n            }\n\n            ds.push_back(1);\n            ds.push_back(maxd);\n            sort(ds.begin(), ds.end());\n            ds.erase(unique(ds.begin(), ds.end()), ds.end());\n\n            for (int dlt : ds) {\n                Rect nr = cur;\n                if (dir == 0) nr.a -= dlt;\n                if (dir == 1) nr.c += dlt;\n                if (dir == 2) nr.b -= dlt;\n                if (dir == 3) nr.d += dlt;\n\n                double gain = score_area(area(nr), rs[id]) - curScore;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = nr;\n                }\n            }\n        }\n\n        if (bestGain > 1e-14) {\n            rects[id] = best;\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\n/*\n   Steal move:\n   Expand rectangle i in one direction by delta.\n   Rectangles blocking that strip are shrunk from the opposite side.\n   Accept if total score of all affected rectangles improves.\n*/\nbool steal_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect r = rects[id];\n        long long Ai = area(r);\n        double oldSi = score_area(Ai, rs[id]);\n\n        int bestDir = -1;\n        int bestD = 0;\n        double bestGain = 1e-13;\n\n        for (int dir = 0; dir < 4; dir++) {\n            vector<Blocker> bs;\n            int maxD;\n            int lenI = (dir < 2 ? r.d - r.b : r.c - r.a);\n\n            if (dir == 0) {\n                maxD = r.a;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.b, r.d, o.b, o.d) && o.c <= r.a) {\n                        int gap = r.a - o.c;\n                        int lim = r.a - (xs[j] + 1);\n                        if (lim >= gap) {\n                            bs.push_back({j, gap, lim});\n                            maxD = min(maxD, lim);\n                        }\n                    }\n                }\n            } else if (dir == 1) {\n                maxD = 10000 - r.c;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.b, r.d, o.b, o.d) && o.a >= r.c) {\n                        int gap = o.a - r.c;\n                        int lim = xs[j] - r.c;\n                        if (lim >= gap) {\n                            bs.push_back({j, gap, lim});\n                            maxD = min(maxD, lim);\n                        }\n                    }\n                }\n            } else if (dir == 2) {\n                maxD = r.b;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.a, r.c, o.a, o.c) && o.d <= r.b) {\n                        int gap = r.b - o.d;\n                        int lim = r.b - (ys[j] + 1);\n                        if (lim >= gap) {\n                            bs.push_back({j, gap, lim});\n                            maxD = min(maxD, lim);\n                        }\n                    }\n                }\n            } else {\n                maxD = 10000 - r.d;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.a, r.c, o.a, o.c) && o.b >= r.d) {\n                        int gap = o.b - r.d;\n                        int lim = ys[j] - r.d;\n                        if (lim >= gap) {\n                            bs.push_back({j, gap, lim});\n                            maxD = min(maxD, lim);\n                        }\n                    }\n                }\n            }\n\n            if (maxD <= 0) continue;\n\n            vector<int> cand;\n            auto addcand = [&](long long x) {\n                for (long long y : {x - 2, x - 1, x, x + 1, x + 2}) {\n                    if (1 <= y && y <= maxD) cand.push_back((int)y);\n                }\n            };\n\n            cand.push_back(1);\n            cand.push_back(maxD);\n\n            long long needI = rs[id] - Ai;\n            if (needI > 0) addcand(needI / lenI);\n\n            for (auto bl : bs) {\n                cand.push_back(bl.gap + 1);\n                cand.push_back(bl.limit);\n\n                int j = bl.id;\n                const Rect& o = rects[j];\n                int lenJ = (dir < 2 ? o.d - o.b : o.c - o.a);\n                long long Aj = area(o);\n\n                if (Aj > rs[j]) {\n                    long long red = Aj - rs[j];\n                    addcand(bl.gap + red / lenJ);\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n            for (int delta : cand) {\n                if (delta <= 0 || delta > maxD) continue;\n\n                double gain = score_area(Ai + 1LL * delta * lenI, rs[id]) - oldSi;\n\n                for (auto bl : bs) {\n                    if (delta <= bl.gap) continue;\n\n                    int j = bl.id;\n                    const Rect& o = rects[j];\n                    long long Aj = area(o);\n                    int lenJ = (dir < 2 ? o.d - o.b : o.c - o.a);\n                    long long nAj = Aj - 1LL * (delta - bl.gap) * lenJ;\n                    gain += score_area(nAj, rs[j]) - score_area(Aj, rs[j]);\n                }\n\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestDir = dir;\n                    bestD = delta;\n                }\n            }\n        }\n\n        if (bestDir != -1) {\n            Rect old = rects[id];\n\n            if (bestDir == 0) rects[id].a -= bestD;\n            if (bestDir == 1) rects[id].c += bestD;\n            if (bestDir == 2) rects[id].b -= bestD;\n            if (bestDir == 3) rects[id].d += bestD;\n\n            for (int j = 0; j < n; j++) if (j != id) {\n                Rect& o = rects[j];\n\n                if (bestDir == 0) {\n                    if (overlap1d(old.b, old.d, o.b, o.d) && o.c <= old.a) {\n                        int gap = old.a - o.c;\n                        if (bestD > gap) o.c = old.a - bestD;\n                    }\n                } else if (bestDir == 1) {\n                    if (overlap1d(old.b, old.d, o.b, o.d) && o.a >= old.c) {\n                        int gap = o.a - old.c;\n                        if (bestD > gap) o.a = old.c + bestD;\n                    }\n                } else if (bestDir == 2) {\n                    if (overlap1d(old.a, old.c, o.a, o.c) && o.d <= old.b) {\n                        int gap = old.b - o.d;\n                        if (bestD > gap) o.d = old.b - bestD;\n                    }\n                } else {\n                    if (overlap1d(old.a, old.c, o.a, o.c) && o.b >= old.d) {\n                        int gap = o.b - old.d;\n                        if (bestD > gap) o.b = old.d + bestD;\n                    }\n                }\n            }\n\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nvoid shrink_only(vector<Rect>& rects, double deadline) {\n    for (int it = 0; it < 20 && timer_.elapsed() < deadline; it++) {\n        if (!shrink_pass(rects, false, deadline)) break;\n    }\n}\n\nvoid improve_solution(vector<Rect>& rects, double deadline) {\n    for (int it = 0; timer_.elapsed() < deadline; it++) {\n        bool moved = false;\n        moved |= shrink_pass(rects, true, deadline);\n        moved |= steal_pass(rects, true, deadline);\n        moved |= expand_pass(rects, true, deadline);\n        if (!moved) break;\n    }\n}\n\n/* ---------- main ---------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n\n    for (int i = 0; i < n; i++) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    vector<Rect> best(n);\n    for (int i = 0; i < n; i++) {\n        best[i] = {xs[i], ys[i], xs[i] + 1, ys[i] + 1};\n    }\n\n    double bestScore = evaluate(best);\n\n    auto consider_best = [&](const vector<Rect>& sol) {\n        double sc = evaluate(sol);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = sol;\n        }\n    };\n\n    vector<pair<double, vector<Rect>>> tops;\n\n    auto insert_top = [&](vector<Rect> sol) {\n        double sc = evaluate(sol);\n        tops.push_back({sc, sol});\n        sort(tops.begin(), tops.end(), [](const auto& p, const auto& q) {\n            return p.first > q.first;\n        });\n        if ((int)tops.size() > 8) tops.pop_back();\n        consider_best(sol);\n    };\n\n    int cnt = 0;\n\n    while (timer_.elapsed() < 2.85) {\n        int topK;\n        if (cnt == 0) topK = 1;\n        else if (cnt % 5 == 0) topK = 3;\n        else if (cnt % 5 == 1) topK = 5;\n        else topK = 10;\n\n        double noise = 0.0;\n        if (cnt > 0) {\n            if (cnt % 3 == 0) noise = 0.06;\n            else if (cnt % 3 == 1) noise = 0.10;\n            else noise = 0.14;\n        }\n\n        vector<Rect> sol = build_slicing(topK, noise);\n        shrink_only(sol, 2.85);\n        insert_top(sol);\n        cnt++;\n    }\n\n    sort(tops.begin(), tops.end(), [](const auto& p, const auto& q) {\n        return p.first > q.first;\n    });\n\n    int m = (int)tops.size();\n    for (int i = 0; i < m && timer_.elapsed() < 4.78; i++) {\n        vector<Rect> sol = tops[i].second;\n        double remain = 4.78 - timer_.elapsed();\n        double deadline = timer_.elapsed() + remain / max(1, m - i);\n        improve_solution(sol, deadline);\n        consider_best(sol);\n    }\n\n    if (timer_.elapsed() < 4.92) {\n        vector<Rect> sol(n);\n        for (int i = 0; i < n; i++) {\n            sol[i] = {xs[i], ys[i], xs[i] + 1, ys[i] + 1};\n        }\n        improve_solution(sol, 4.92);\n        consider_best(sol);\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' ' << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int V = N * N;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\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\nstruct Path {\n    int score = 0;\n    vector<int> cells;\n    string moves;\n};\n\nstruct Params {\n    double wp;\n    double wd;\n    double w1;\n    double w2;\n    double noise;\n    double randomMoveProb;\n};\n\nint si, sj;\nint tile_id[V];\nint point_val[V];\nint nb[V][4];\nchar nb_dir[V][4];\n\nPath best_path;\nvector<Path> pool;\n\nParams make_params(XorShift &rng) {\n    Params p;\n    int mode = rng.nextInt(10);\n\n    if (mode == 0) {\n        p = {1.8, 4.0, 0.22, 0.08, 30.0, 0.02};\n    } else if (mode == 1) {\n        p = {1.0, -24.0, 0.12, 0.05, 45.0, 0.03};\n    } else if (mode == 2) {\n        p = {1.2, 8.0, 0.36, 0.11, 55.0, 0.04};\n    } else if (mode == 3) {\n        p = {1.0, 0.0, 0.16, 0.05, 120.0, 0.12};\n    } else if (mode == 4) {\n        p = {0.85, -34.0, 0.07, 0.03, 60.0, 0.04};\n    } else if (mode == 5) {\n        p = {1.0, 18.0, 0.46, 0.15, 45.0, 0.02};\n    } else if (mode == 6) {\n        p = {2.4, -8.0, 0.26, 0.08, 40.0, 0.02};\n    } else if (mode == 7) {\n        p = {0.9, 2.0, 0.12, 0.04, 160.0, 0.15};\n    } else if (mode == 8) {\n        p = {1.5, -16.0, 0.28, 0.12, 35.0, 0.02};\n    } else {\n        p = {1.1, 26.0, 0.35, 0.20, 65.0, 0.05};\n    }\n\n    p.wp *= 0.75 + rng.nextDouble() * 0.70;\n    p.wd *= 0.75 + rng.nextDouble() * 0.70;\n    p.w1 *= 0.70 + rng.nextDouble() * 0.80;\n    p.w2 *= 0.70 + rng.nextDouble() * 0.80;\n    p.noise *= 0.70 + rng.nextDouble() * 0.80;\n\n    return p;\n}\n\ninline int legal_degree_after(int to, const vector<int> &seen, int mark) {\n    int tid_to = tile_id[to];\n    int d = 0;\n    for (int k = 0; k < 4; k++) {\n        int v = nb[to][k];\n        if (v < 0) continue;\n        int tid = tile_id[v];\n        if (tid == tid_to) continue;\n        if (seen[tid] == mark) continue;\n        d++;\n    }\n    return d;\n}\n\ndouble eval_move(int to, const vector<int> &seen, int mark, const Params &par, XorShift &rng) {\n    int tid_to = tile_id[to];\n\n    int degree1 = 0;\n    int best_next_point = 0;\n    double best_look2 = 0.0;\n\n    for (int k = 0; k < 4; k++) {\n        int v1 = nb[to][k];\n        if (v1 < 0) continue;\n\n        int tid1 = tile_id[v1];\n        if (tid1 == tid_to) continue;\n        if (seen[tid1] == mark) continue;\n\n        degree1++;\n        best_next_point = max(best_next_point, point_val[v1]);\n\n        int degree2 = 0;\n        int best_p2 = 0;\n\n        for (int l = 0; l < 4; l++) {\n            int v2 = nb[v1][l];\n            if (v2 < 0) continue;\n\n            int tid2 = tile_id[v2];\n            if (tid2 == tid_to || tid2 == tid1) continue;\n            if (seen[tid2] == mark) continue;\n\n            degree2++;\n            best_p2 = max(best_p2, point_val[v2]);\n        }\n\n        double look2 = point_val[v1] + 8.0 * degree2 + 0.25 * best_p2;\n        best_look2 = max(best_look2, look2);\n    }\n\n    double e = 0.0;\n    e += par.wp * point_val[to];\n    e += par.wd * degree1;\n    e += par.w1 * best_next_point;\n    e += par.w2 * best_look2;\n    e += par.noise * (rng.nextDouble() - 0.5);\n    return e;\n}\n\nint choose_next(\n    int pos,\n    const vector<int> &seen,\n    int mark,\n    const Params &par,\n    XorShift &rng,\n    char &out_dir\n) {\n    int cand[4];\n    char cdir[4];\n    int cnt = 0;\n\n    for (int k = 0; k < 4; k++) {\n        int to = nb[pos][k];\n        if (to < 0) continue;\n\n        int tid = tile_id[to];\n        if (seen[tid] == mark) continue;\n\n        cand[cnt] = to;\n        cdir[cnt] = nb_dir[pos][k];\n        cnt++;\n    }\n\n    if (cnt == 0) return -1;\n\n    if (cnt == 1) {\n        out_dir = cdir[0];\n        return cand[0];\n    }\n\n    if (rng.nextDouble() < par.randomMoveProb) {\n        int id = rng.nextInt(cnt);\n        out_dir = cdir[id];\n        return cand[id];\n    }\n\n    double best_eval = -1e100;\n    int best_id = 0;\n\n    for (int i = 0; i < cnt; i++) {\n        double e = eval_move(cand[i], seen, mark, par, rng);\n        if (e > best_eval) {\n            best_eval = e;\n            best_id = i;\n        }\n    }\n\n    out_dir = cdir[best_id];\n    return cand[best_id];\n}\n\nvoid consider_path(const Path &p) {\n    if (p.score > best_path.score) {\n        best_path = p;\n    }\n\n    constexpr int POOL_SIZE = 24;\n\n    if ((int)pool.size() < POOL_SIZE) {\n        pool.push_back(p);\n    } else {\n        int worst = 0;\n        for (int i = 1; i < (int)pool.size(); i++) {\n            if (pool[i].score < pool[worst].score) worst = i;\n        }\n        if (p.score > pool[worst].score) {\n            pool[worst] = p;\n        }\n    }\n}\n\nPath build_greedy_from_prefix(\n    const Path *base,\n    int prefix_len,\n    vector<int> &seen,\n    int mark,\n    XorShift &rng\n) {\n    Path cur;\n    cur.cells.reserve(V);\n    cur.moves.reserve(V);\n\n    if (base == nullptr) {\n        int st = si * N + sj;\n        cur.cells.push_back(st);\n        cur.score = point_val[st];\n        seen[tile_id[st]] = mark;\n    } else {\n        prefix_len = max(prefix_len, 1);\n        prefix_len = min(prefix_len, (int)base->cells.size());\n\n        cur.cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n        cur.moves.assign(base->moves.begin(), base->moves.begin() + prefix_len - 1);\n\n        cur.score = 0;\n        for (int c : cur.cells) {\n            cur.score += point_val[c];\n            seen[tile_id[c]] = mark;\n        }\n    }\n\n    Params par = make_params(rng);\n\n    while (true) {\n        int pos = cur.cells.back();\n        char d = '?';\n        int nxt = choose_next(pos, seen, mark, par, rng, d);\n\n        if (nxt < 0) break;\n\n        seen[tile_id[nxt]] = mark;\n        cur.cells.push_back(nxt);\n        cur.moves.push_back(d);\n        cur.score += point_val[nxt];\n    }\n\n    return cur;\n}\n\nstruct DFSSearcher {\n    vector<int> &seen;\n    int mark;\n    XorShift &rng;\n    Timer &timer;\n    double time_limit;\n    Params par;\n\n    vector<int> cur_cells;\n    string cur_moves;\n\n    int nodes = 0;\n    int node_limit = 50000;\n\n    DFSSearcher(\n        vector<int> &seen_,\n        int mark_,\n        XorShift &rng_,\n        Timer &timer_,\n        double time_limit_\n    )\n        : seen(seen_),\n          mark(mark_),\n          rng(rng_),\n          timer(timer_),\n          time_limit(time_limit_) {\n        par = make_params(rng);\n        par.noise *= 0.45;\n        par.randomMoveProb = 0.0;\n    }\n\n    bool time_or_budget_over() {\n        if ((nodes & 2047) == 0) {\n            if (timer.elapsed() > time_limit) return true;\n        }\n        return nodes >= node_limit;\n    }\n\n    bool dfs(int pos, int score) {\n        nodes++;\n\n        if (score > best_path.score) {\n            best_path.score = score;\n            best_path.cells = cur_cells;\n            best_path.moves = cur_moves;\n        }\n\n        if (time_or_budget_over()) return true;\n\n        struct Cand {\n            int to;\n            char dir;\n            double e;\n        };\n\n        Cand cand[4];\n        int cnt = 0;\n\n        for (int k = 0; k < 4; k++) {\n            int to = nb[pos][k];\n            if (to < 0) continue;\n\n            int tid = tile_id[to];\n            if (seen[tid] == mark) continue;\n\n            cand[cnt++] = {to, nb_dir[pos][k], eval_move(to, seen, mark, par, rng)};\n        }\n\n        if (cnt == 0) return false;\n\n        sort(cand, cand + cnt, [](const Cand &a, const Cand &b) {\n            return a.e > b.e;\n        });\n\n        // Occasionally diversify the top choices.\n        if (cnt >= 2 && rng.nextInt(100) < 18) {\n            swap(cand[0], cand[rng.nextInt(cnt)]);\n        }\n\n        for (int i = 0; i < cnt; i++) {\n            int to = cand[i].to;\n            int tid = tile_id[to];\n\n            seen[tid] = mark;\n            cur_cells.push_back(to);\n            cur_moves.push_back(cand[i].dir);\n\n            bool stop = dfs(to, score + point_val[to]);\n\n            cur_moves.pop_back();\n            cur_cells.pop_back();\n            seen[tid] = 0;\n\n            if (stop) return true;\n        }\n\n        return false;\n    }\n\n    void run_from_prefix(const Path *base, int prefix_len) {\n        cur_cells.clear();\n        cur_moves.clear();\n        cur_cells.reserve(V);\n        cur_moves.reserve(V);\n\n        int score = 0;\n\n        if (base == nullptr) {\n            int st = si * N + sj;\n            cur_cells.push_back(st);\n            cur_moves.clear();\n            score = point_val[st];\n            seen[tile_id[st]] = mark;\n        } else {\n            prefix_len = max(prefix_len, 1);\n            prefix_len = min(prefix_len, (int)base->cells.size());\n\n            cur_cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n            cur_moves.assign(base->moves.begin(), base->moves.begin() + prefix_len - 1);\n\n            score = 0;\n            for (int c : cur_cells) {\n                score += point_val[c];\n                seen[tile_id[c]] = mark;\n            }\n        }\n\n        if (score > best_path.score) {\n            best_path.score = score;\n            best_path.cells = cur_cells;\n            best_path.moves = cur_moves;\n        }\n\n        int pos = cur_cells.back();\n\n        dfs(pos, score);\n    }\n};\n\nint select_prefix_len(const Path &p, XorShift &rng) {\n    int L = (int)p.cells.size();\n    if (L <= 1) return 1;\n\n    double u = rng.nextDouble();\n    double x;\n    int typ = rng.nextInt(100);\n\n    if (typ < 45) {\n        // Rebuild the tail.\n        x = sqrt(u);\n    } else if (typ < 75) {\n        // Medium cut.\n        x = u;\n    } else if (typ < 92) {\n        // Early decision change.\n        x = u * u;\n    } else {\n        // Very late local search.\n        x = 0.82 + 0.18 * u;\n    }\n\n    int prefix_len = 1 + (int)(x * (L - 1));\n    prefix_len = min(prefix_len, L - 1);\n    prefix_len = max(prefix_len, 1);\n    return prefix_len;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tid = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            int id = i * N + j;\n            tile_id[id] = x;\n            max_tid = max(max_tid, x);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> point_val[i * N + j];\n        }\n    }\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    for (int i = 0; i < V; i++) {\n        for (int k = 0; k < 4; k++) {\n            nb[i][k] = -1;\n            nb_dir[i][k] = '?';\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            for (int k = 0; k < 4; k++) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    nb[id][k] = ni * N + nj;\n                    nb_dir[id][k] = dc[k];\n                }\n            }\n        }\n    }\n\n    uint64_t seed = 123456789;\n    seed ^= (uint64_t)(si * 51 + sj + 1) * 1000003ULL;\n\n    for (int i = 0; i < V; i++) {\n        seed ^= (uint64_t)(tile_id[i] + 1) * 11995408973635179863ULL;\n        seed ^= (uint64_t)(point_val[i] + 7) * 10150724397891781847ULL;\n        seed = seed * 6364136223846793005ULL + 1442695040888963407ULL;\n    }\n\n    XorShift rng(seed);\n    Timer timer;\n\n    vector<int> seen(max_tid + 1, 0);\n    int mark = 1;\n\n    {\n        int st = si * N + sj;\n        best_path.score = point_val[st];\n        best_path.cells = {st};\n        best_path.moves = \"\";\n    }\n\n    const double TIME_LIMIT = 1.92;\n    const double GREEDY_PHASE = 0.62;\n\n    // Phase 1: randomized greedy rollouts.\n    while (timer.elapsed() < GREEDY_PHASE) {\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        Path cur;\n\n        bool fresh = pool.empty() || rng.nextInt(100) < 24;\n\n        if (fresh) {\n            cur = build_greedy_from_prefix(nullptr, 0, seen, mark, rng);\n        } else {\n            const Path *base;\n\n            if (rng.nextInt(100) < 68) {\n                base = &best_path;\n            } else {\n                base = &pool[rng.nextInt((int)pool.size())];\n            }\n\n            int prefix_len = select_prefix_len(*base, rng);\n            cur = build_greedy_from_prefix(base, prefix_len, seen, mark, rng);\n        }\n\n        consider_path(cur);\n    }\n\n    // Phase 2: DFS/local tail search from promising prefixes.\n    while (timer.elapsed() < TIME_LIMIT) {\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        const Path *base = nullptr;\n        int prefix_len = 1;\n\n        int mode = rng.nextInt(100);\n\n        if (mode < 15 || pool.empty()) {\n            base = nullptr;\n            prefix_len = 1;\n        } else if (mode < 78) {\n            base = &best_path;\n            prefix_len = select_prefix_len(*base, rng);\n        } else {\n            base = &pool[rng.nextInt((int)pool.size())];\n            prefix_len = select_prefix_len(*base, rng);\n        }\n\n        DFSSearcher dfs(seen, mark, rng, timer, TIME_LIMIT);\n\n        // Smaller budget gives more restarts; larger budget gives deeper local optimization.\n        int L = (base == nullptr ? 1 : (int)base->cells.size());\n        if (base != nullptr && prefix_len > L * 3 / 4) {\n            dfs.node_limit = 35000 + rng.nextInt(50000);\n        } else {\n            dfs.node_limit = 18000 + rng.nextInt(45000);\n        }\n\n        dfs.run_from_prefix(base, prefix_len);\n\n        // Occasionally keep DFS result in the pool as well.\n        if (rng.nextInt(100) < 25) {\n            consider_path(best_path);\n        }\n    }\n\n    cout << best_path.moves << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HEDGE = 30 * 29;\nstatic constexpr int VEDGE = 29 * 30;\nstatic constexpr int E = HEDGE + VEDGE;\nstatic constexpr int VAR = 60;\n\nstruct Obs {\n    array<int, VAR> x;\n    vector<int> edges;\n    long long y;\n};\n\nvector<Obs> observations;\n\ndouble hcost[N], vcost[N];\ndouble edge_est[E];\nbool edge_ready = false;\n\nuint64_t rng_state = 88172645463325252ull;\n\nuint64_t xorshift() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\ndouble clamp_double(double x, double lo, double hi) {\n    return max(lo, min(hi, x));\n}\n\nint hid(int i, int j) {\n    return i * 29 + j;\n}\n\nint vid(int i, int j) {\n    return HEDGE + i * 30 + j;\n}\n\ndouble base_weight(int id) {\n    if (id < HEDGE) {\n        int i = id / 29;\n        return hcost[i];\n    } else {\n        int x = id - HEDGE;\n        int j = x % 30;\n        return vcost[j];\n    }\n}\n\nvoid solve_row_col_model() {\n    static double a[VAR][VAR + 1];\n\n    for (int i = 0; i < VAR; i++) {\n        for (int j = 0; j <= VAR; j++) {\n            a[i][j] = 0.0;\n        }\n    }\n\n    const double lambda = 80.0;\n\n    for (int i = 0; i < VAR; i++) {\n        a[i][i] += lambda;\n    }\n\n    for (const auto& ob : observations) {\n        vector<pair<int, int>> nz;\n        int len = 0;\n\n        for (int i = 0; i < VAR; i++) {\n            if (ob.x[i]) {\n                nz.push_back({i, ob.x[i]});\n                len += ob.x[i];\n            }\n        }\n\n        if (len == 0) continue;\n\n        double w = 400.0 / ((double)len * len);\n        double r = (double)ob.y - 5000.0 * len;\n\n        for (auto [i, xi] : nz) {\n            a[i][VAR] += w * xi * r;\n            for (auto [j, xj] : nz) {\n                a[i][j] += w * (double)xi * xj;\n            }\n        }\n    }\n\n    for (int col = 0; col < VAR; col++) {\n        int piv = col;\n        for (int row = col + 1; row < VAR; row++) {\n            if (fabs(a[row][col]) > fabs(a[piv][col])) {\n                piv = row;\n            }\n        }\n\n        if (piv != col) {\n            for (int j = col; j <= VAR; j++) {\n                swap(a[piv][j], a[col][j]);\n            }\n        }\n\n        double div = a[col][col];\n        if (fabs(div) < 1e-12) continue;\n\n        for (int j = col; j <= VAR; j++) {\n            a[col][j] /= div;\n        }\n\n        for (int row = 0; row < VAR; row++) {\n            if (row == col) continue;\n\n            double factor = a[row][col];\n            if (fabs(factor) < 1e-12) continue;\n\n            for (int j = col; j <= VAR; j++) {\n                a[row][j] -= factor * a[col][j];\n            }\n        }\n    }\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = clamp_double(5000.0 + a[i][VAR], 1000.0, 9000.0);\n    }\n\n    for (int j = 0; j < 30; j++) {\n        vcost[j] = clamp_double(5000.0 + a[30 + j][VAR], 1000.0, 9000.0);\n    }\n}\n\nvoid smooth_edge_est(double strength) {\n    static double nxt[E];\n\n    for (int id = 0; id < E; id++) {\n        nxt[id] = edge_est[id];\n    }\n\n    for (int i = 0; i < 30; i++) {\n        for (int j = 0; j < 29; j++) {\n            int id = hid(i, j);\n            double sum = edge_est[id] * 2.0;\n            double den = 2.0;\n\n            if (j > 0) {\n                int nid = hid(i, j - 1);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            if (j + 1 < 29) {\n                int nid = hid(i, j + 1);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            double avg = sum / den;\n            nxt[id] = edge_est[id] * (1.0 - strength) + avg * strength;\n        }\n    }\n\n    for (int i = 0; i < 29; i++) {\n        for (int j = 0; j < 30; j++) {\n            int id = vid(i, j);\n            double sum = edge_est[id] * 2.0;\n            double den = 2.0;\n\n            if (i > 0) {\n                int nid = vid(i - 1, j);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            if (i + 1 < 29) {\n                int nid = vid(i + 1, j);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            double avg = sum / den;\n            nxt[id] = edge_est[id] * (1.0 - strength) + avg * strength;\n        }\n    }\n\n    for (int id = 0; id < E; id++) {\n        edge_est[id] = clamp_double(nxt[id], 800.0, 9500.0);\n    }\n}\n\nvoid rebuild_edge_model(int turn) {\n    for (int id = 0; id < E; id++) {\n        edge_est[id] = base_weight(id);\n    }\n\n    if (observations.empty()) {\n        edge_ready = true;\n        return;\n    }\n\n    int epochs;\n    if (turn < 200) epochs = 2;\n    else if (turn < 650) epochs = 3;\n    else epochs = 4;\n\n    double eta;\n    if (turn < 250) eta = 0.050;\n    else if (turn < 650) eta = 0.045;\n    else eta = 0.040;\n\n    for (int ep = 0; ep < epochs; ep++) {\n        for (const auto& ob : observations) {\n            int len = (int)ob.edges.size();\n            if (len == 0) continue;\n\n            double pred = 0.0;\n            for (int id : ob.edges) {\n                pred += edge_est[id];\n            }\n\n            double err = (double)ob.y - pred;\n            double clip = max(6000.0, 0.18 * pred);\n            err = clamp_double(err, -clip, clip);\n\n            double delta = eta * err / len;\n\n            for (int id : ob.edges) {\n                edge_est[id] += delta;\n            }\n        }\n\n        for (int id = 0; id < E; id++) {\n            double b = base_weight(id);\n            double pull = (turn < 300 ? 0.045 : 0.030);\n            edge_est[id] = edge_est[id] * (1.0 - pull) + b * pull;\n            edge_est[id] = clamp_double(edge_est[id], 800.0, 9500.0);\n        }\n\n        smooth_edge_est(turn < 300 ? 0.06 : 0.09);\n    }\n\n    edge_ready = true;\n}\n\nvoid online_edge_update(long long y, const vector<int>& edges) {\n    if (!edge_ready || edges.empty()) return;\n\n    double pred = 0.0;\n    for (int id : edges) {\n        pred += edge_est[id];\n    }\n\n    double err = (double)y - pred;\n    double clip = max(5000.0, 0.15 * pred);\n    err = clamp_double(err, -clip, clip);\n\n    double delta = 0.015 * err / (double)edges.size();\n\n    for (int id : edges) {\n        edge_est[id] += delta;\n        edge_est[id] = clamp_double(edge_est[id], 800.0, 9500.0);\n    }\n}\n\ndouble learned_weight_raw(int id, int turn) {\n    double b = base_weight(id);\n\n    if (!edge_ready) {\n        return b;\n    }\n\n    double edge_mix = ((double)turn - 120.0) / 600.0;\n    edge_mix = clamp_double(edge_mix, 0.0, 0.65);\n\n    double w = b * (1.0 - edge_mix) + edge_est[id] * edge_mix;\n    return clamp_double(w, 800.0, 9500.0);\n}\n\ndouble model_weight_for_search(int id, int turn) {\n    double learned = learned_weight_raw(id, turn);\n\n    double rel = ((double)turn - 30.0) / 520.0;\n    rel = clamp_double(rel, 0.0, 1.0);\n\n    double w = 5000.0 * (1.0 - rel) + learned * rel;\n    return clamp_double(w, 800.0, 9500.0);\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool horizontal_first) {\n    string res;\n\n    auto add_vertical = [&]() {\n        if (si < ti) {\n            while (si < ti) {\n                res.push_back('D');\n                si++;\n            }\n        } else {\n            while (si > ti) {\n                res.push_back('U');\n                si--;\n            }\n        }\n    };\n\n    auto add_horizontal = [&]() {\n        if (sj < tj) {\n            while (sj < tj) {\n                res.push_back('R');\n                sj++;\n            }\n        } else {\n            while (sj > tj) {\n                res.push_back('L');\n                sj--;\n            }\n        }\n    };\n\n    if (horizontal_first) {\n        add_horizontal();\n        add_vertical();\n    } else {\n        add_vertical();\n        add_horizontal();\n    }\n\n    return res;\n}\n\nvoid extract_features(\n    int si,\n    int sj,\n    const string& path,\n    array<int, VAR>& feat,\n    vector<int>& edges\n) {\n    feat.fill(0);\n    edges.clear();\n\n    int i = si;\n    int j = sj;\n\n    for (char c : path) {\n        if (c == 'R') {\n            int id = hid(i, j);\n            edges.push_back(id);\n            feat[i]++;\n            j++;\n        } else if (c == 'L') {\n            int id = hid(i, j - 1);\n            edges.push_back(id);\n            feat[i]++;\n            j--;\n        } else if (c == 'D') {\n            int id = vid(i, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i++;\n        } else if (c == 'U') {\n            int id = vid(i - 1, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i--;\n        }\n    }\n}\n\ndouble estimated_path_cost(int si, int sj, const string& path, int turn) {\n    int i = si;\n    int j = sj;\n    double cost = 0.0;\n\n    for (char c : path) {\n        if (c == 'R') {\n            cost += model_weight_for_search(hid(i, j), turn);\n            j++;\n        } else if (c == 'L') {\n            cost += model_weight_for_search(hid(i, j - 1), turn);\n            j--;\n        } else if (c == 'D') {\n            cost += model_weight_for_search(vid(i, j), turn);\n            i++;\n        } else {\n            cost += model_weight_for_search(vid(i - 1, j), turn);\n            i--;\n        }\n    }\n\n    return cost;\n}\n\nstring choose_early_path(int si, int sj, int ti, int tj, int turn) {\n    string p1 = manhattan_path(si, sj, ti, tj, true);\n    string p2 = manhattan_path(si, sj, ti, tj, false);\n\n    if (p1 == p2) return p1;\n\n    if (turn < 45) {\n        return (xorshift() & 1) ? p1 : p2;\n    }\n\n    double c1 = estimated_path_cost(si, sj, p1, turn);\n    double c2 = estimated_path_cost(si, sj, p2, turn);\n\n    int eps = (turn < 100 ? 18 : 7);\n    if ((int)(xorshift() % 100) < eps) {\n        return (c1 < c2) ? p2 : p1;\n    }\n\n    return (c1 < c2) ? p1 : p2;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    const double INF = 1e100;\n\n    vector<double> dist(900, INF);\n    vector<int> parent(900, -1);\n    vector<char> pchar(900, '?');\n\n    auto node = [](int i, int j) {\n        return i * 30 + j;\n    };\n\n    priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n\n    int s = node(si, sj);\n    int t = node(ti, tj);\n\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\n        if (d != dist[u]) continue;\n        if (u == t) break;\n\n        int i = u / 30;\n        int j = u % 30;\n\n        auto relax = [&](int ni, int nj, char c, int eid) {\n            int v = node(ni, nj);\n            double nd = d + model_weight_for_search(eid, turn);\n\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                pchar[v] = c;\n                pq.push({nd, v});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, 'U', vid(i - 1, j));\n        if (i + 1 < 30) relax(i + 1, j, 'D', vid(i, j));\n        if (j > 0) relax(i, j - 1, 'L', hid(i, j - 1));\n        if (j + 1 < 30) relax(i, j + 1, 'R', hid(i, j));\n    }\n\n    string res;\n    int cur = t;\n\n    while (cur != s) {\n        res.push_back(pchar[cur]);\n        cur = parent[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = 5000.0;\n        vcost[i] = 5000.0;\n    }\n\n    for (int i = 0; i < E; i++) {\n        edge_est[i] = 5000.0;\n    }\n\n    for (int turn = 0; turn < 1000; turn++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0;\n        }\n\n        string path;\n\n        if (turn < 100) {\n            path = choose_early_path(si, sj, ti, tj, turn);\n        } else {\n            path = dijkstra_path(si, sj, ti, tj, turn);\n        }\n\n        array<int, VAR> feat;\n        vector<int> edges;\n        extract_features(si, sj, path, feat, edges);\n\n        cout << path << endl;\n        cout.flush();\n\n        long long result;\n        if (!(cin >> result)) {\n            return 0;\n        }\n\n        Obs ob;\n        ob.x = feat;\n        ob.edges = edges;\n        ob.y = result;\n        observations.push_back(ob);\n\n        if (turn < 260 || turn % 5 == 4 || turn >= 850) {\n            solve_row_col_model();\n        }\n\n        if (turn >= 60) {\n            bool do_rebuild = false;\n\n            if (turn < 300) {\n                do_rebuild = (turn % 10 == 9);\n            } else if (turn < 800) {\n                do_rebuild = (turn % 20 == 19);\n            } else {\n                do_rebuild = (turn % 10 == 9);\n            }\n\n            if (do_rebuild) {\n                rebuild_edge_model(turn);\n            }\n        }\n\n        online_edge_update(result, edges);\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int C = 400;\nstatic constexpr int ALPHA = 8;\nstatic constexpr long long BIG = 2000000000LL;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) { return (int)(next() % n); }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstruct KmerScorer {\n    int maxQ = 2;\n    vector<vector<int>> dense;\n    vector<unordered_map<unsigned long long, int>> sparse;\n    int mult[13] = {0, 0, 1, 2, 5, 12, 30, 80, 200, 500, 1200, 2500, 5000};\n\n    KmerScorer() {\n        dense.resize(13);\n        sparse.resize(13);\n    }\n\n    void build(const vector<string>& s) {\n        maxQ = 2;\n        for (auto& t : s) maxQ = max(maxQ, min(12, (int)t.size()));\n\n        for (int q = 2; q <= min(8, maxQ); q++) {\n            dense[q].assign(1 << (3 * q), 0);\n        }\n\n        for (auto& t : s) {\n            int L = (int)t.size();\n            vector<int> a(L);\n            for (int i = 0; i < L; i++) a[i] = t[i] - 'A';\n\n            for (int q = 2; q <= min(12, L); q++) {\n                for (int l = 0; l + q <= L; l++) {\n                    unsigned long long code = 0;\n                    for (int p = 0; p < q; p++) code = (code << 3) | a[l + p];\n\n                    int w = mult[q];\n                    if (q <= 8) dense[q][(int)code] += w;\n                    else sparse[q][code] += w;\n                }\n            }\n        }\n    }\n\n    inline int getWeight(int q, unsigned long long code) const {\n        if (q <= 8) return dense[q][(int)code];\n        auto it = sparse[q].find(code);\n        if (it == sparse[q].end()) return 0;\n        return it->second;\n    }\n\n    unsigned long long codeWindow(const vector<unsigned char>& board, int i, int j, int dir, int q,\n                                  int overrideCell = -1, int overrideVal = 0) const {\n        unsigned long long code = 0;\n        for (int p = 0; p < q; p++) {\n            int ni = i, nj = j;\n            if (dir == 0) nj = (j + p) % N;\n            else ni = (i + p) % N;\n            int cell = ni * N + nj;\n            int v = (cell == overrideCell ? overrideVal : board[cell]);\n            if (v < 0 || v >= 8) return ULLONG_MAX;\n            code = (code << 3) | (unsigned)v;\n        }\n        return code;\n    }\n\n    long long score(const vector<unsigned char>& board) const {\n        long long res = 0;\n        for (int q = 2; q <= maxQ; q++) {\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    auto c1 = codeWindow(board, i, j, 0, q);\n                    if (c1 != ULLONG_MAX) res += getWeight(q, c1);\n                    auto c2 = codeWindow(board, i, j, 1, q);\n                    if (c2 != ULLONG_MAX) res += getWeight(q, c2);\n                }\n            }\n        }\n        return res;\n    }\n\n    long long delta(const vector<unsigned char>& board, int cell, int nc) const {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        int i = cell / N;\n        int j = cell % N;\n        long long d = 0;\n\n        for (int q = 2; q <= maxQ; q++) {\n            for (int off = 0; off < q; off++) {\n                int sj = (j - off + N) % N;\n                auto oldCode = codeWindow(board, i, sj, 0, q);\n                auto newCode = codeWindow(board, i, sj, 0, q, cell, nc);\n                if (oldCode != ULLONG_MAX) d -= getWeight(q, oldCode);\n                if (newCode != ULLONG_MAX) d += getWeight(q, newCode);\n\n                int si = (i - off + N) % N;\n                oldCode = codeWindow(board, si, j, 1, q);\n                newCode = codeWindow(board, si, j, 1, q, cell, nc);\n                if (oldCode != ULLONG_MAX) d -= getWeight(q, oldCode);\n                if (newCode != ULLONG_MAX) d += getWeight(q, newCode);\n            }\n        }\n        return d;\n    }\n};\n\nstruct Evaluator {\n    int M;\n    vector<string> s;\n    vector<unsigned char> board;\n\n    vector<unsigned char> mis;\n    vector<array<unsigned short, 13>> hist;\n    vector<long long> val;\n    vector<vector<int>> inc;\n\n    long long obj = 0;\n    int covered = 0;\n\n    long long nearTable[13] = {\n        0,\n        1000000,\n        300000,\n        100000,\n        30000,\n        10000,\n        3000,\n        1000,\n        300,\n        100,\n        30,\n        10,\n        0\n    };\n\n    Evaluator() {}\n\n    Evaluator(const vector<string>& _s, const vector<unsigned char>& _board) {\n        s = _s;\n        M = (int)s.size();\n        board = _board;\n        build();\n    }\n\n    inline int placementCell(int sid, int idx, int p) const {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    }\n\n    inline long long calcVal(int sid) const {\n        if (hist[sid][0] > 0) return BIG + min<int>(hist[sid][0], 1000);\n        for (int d = 1; d <= 12; d++) {\n            if (hist[sid][d] > 0) return nearTable[d] + min<int>(hist[sid][d], 1000);\n        }\n        return 0;\n    }\n\n    void build() {\n        int P = M * 800;\n        mis.assign(P, 0);\n        hist.assign(M, {});\n        val.assign(M, 0);\n        inc.assign(C, {});\n\n        int reservePerCell = max(1, M * 2 * 12);\n        for (int c = 0; c < C; c++) inc[c].reserve(reservePerCell);\n\n        for (int sid = 0; sid < M; sid++) {\n            int len = (int)s[sid].size();\n            for (int idx = 0; idx < 800; idx++) {\n                int pid = sid * 800 + idx;\n                int mm = 0;\n                for (int p = 0; p < len; p++) {\n                    int cell = placementCell(sid, idx, p);\n                    int req = s[sid][p] - 'A';\n                    if (board[cell] != req) mm++;\n                    inc[cell].push_back(pid * 8 + req);\n                }\n                mis[pid] = (unsigned char)mm;\n                hist[sid][mm]++;\n            }\n        }\n\n        obj = 0;\n        covered = 0;\n        for (int sid = 0; sid < M; sid++) {\n            val[sid] = calcVal(sid);\n            obj += val[sid];\n            if (hist[sid][0] > 0) covered++;\n        }\n    }\n\n    long long applyChange(int cell, int nc) {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        long long deltaObj = 0;\n\n        for (int code : inc[cell]) {\n            int req = code & 7;\n            if (req != oc && req != nc) continue;\n\n            int pid = code >> 3;\n            int sid = pid / 800;\n\n            long long oldVal = val[sid];\n            bool oldCov = hist[sid][0] > 0;\n\n            int oldMis = mis[pid];\n            hist[sid][oldMis]--;\n\n            int nm = oldMis;\n            if (req == oc) nm++;\n            if (req == nc) nm--;\n\n            mis[pid] = (unsigned char)nm;\n            hist[sid][nm]++;\n\n            bool newCov = hist[sid][0] > 0;\n            if (oldCov && !newCov) covered--;\n            if (!oldCov && newCov) covered++;\n\n            long long newVal = calcVal(sid);\n            val[sid] = newVal;\n            deltaObj += newVal - oldVal;\n        }\n\n        board[cell] = (unsigned char)nc;\n        obj += deltaObj;\n        return deltaObj;\n    }\n\n    int minMismatchOfString(int sid) const {\n        for (int d = 0; d <= 12; d++) if (hist[sid][d] > 0) return d;\n        return 13;\n    }\n\n    int bestPlacementIndex(int sid, XorShift& rng) const {\n        int best = 100, cnt = 0, bestIdx = 0;\n        int base = sid * 800;\n        for (int idx = 0; idx < 800; idx++) {\n            int mm = mis[base + idx];\n            if (mm < best) {\n                best = mm;\n                cnt = 1;\n                bestIdx = idx;\n            } else if (mm == best) {\n                cnt++;\n                if (rng.nextInt(cnt) == 0) bestIdx = idx;\n            }\n        }\n        return bestIdx;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    int inputN, M;\n    cin >> inputN >> M;\n\n    vector<string> s(M);\n    for (int i = 0; i < M; i++) cin >> s[i];\n\n    XorShift rng(123456789);\n\n    auto elapsedSec = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    KmerScorer ksc;\n    ksc.build(s);\n\n    vector<int> freq(ALPHA, 1);\n    for (auto& t : s) for (char ch : t) freq[ch - 'A']++;\n    vector<int> pref(ALPHA);\n    pref[0] = freq[0];\n    for (int i = 1; i < ALPHA; i++) pref[i] = pref[i - 1] + freq[i];\n    int fsum = pref.back();\n\n    auto randomChar = [&]() {\n        int r = rng.nextInt(fsum);\n        return (unsigned char)(lower_bound(pref.begin(), pref.end(), r + 1) - pref.begin());\n    };\n\n    auto placementCellRaw = [&](int idx, int p) {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    };\n\n    // Candidate 1: greedy stamping.\n    vector<unsigned char> boardStamp(C);\n    for (int i = 0; i < C; i++) boardStamp[i] = randomChar();\n\n    auto conflictOfPlacement = [&](const vector<unsigned char>& b, const string& t, int idx) {\n        int conf = 0;\n        int len = (int)t.size();\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            int req = t[p] - 'A';\n            if (b[cell] != req) conf++;\n        }\n        return conf;\n    };\n\n    auto stampRaw = [&](vector<unsigned char>& b, const string& t, int idx) {\n        int len = (int)t.size();\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            b[cell] = (unsigned char)(t[p] - 'A');\n        }\n    };\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n\n    for (int pass = 0; pass < 6; pass++) {\n        if (pass == 5) {\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return s[a].size() < s[b].size();\n            });\n        } else {\n            shuffle(order.begin(), order.end(), mt19937((unsigned)rng.next()));\n        }\n\n        for (int sid : order) {\n            int bestConf = 100, bestIdx = 0, cnt = 0;\n            for (int idx = 0; idx < 800; idx++) {\n                int conf = conflictOfPlacement(boardStamp, s[sid], idx);\n                if (conf < bestConf) {\n                    bestConf = conf;\n                    bestIdx = idx;\n                    cnt = 1;\n                } else if (conf == bestConf) {\n                    cnt++;\n                    if (rng.nextInt(cnt) == 0) bestIdx = idx;\n                }\n            }\n            stampRaw(boardStamp, s[sid], bestIdx);\n        }\n    }\n\n    // Candidate 2: pure k-mer hill climbing from random board.\n    vector<unsigned char> boardKmer(C);\n    for (int i = 0; i < C; i++) boardKmer[i] = randomChar();\n\n    long long kScore = ksc.score(boardKmer);\n    double kmerLimit = 0.65;\n\n    int kIter = 0;\n    while (elapsedSec() < kmerLimit) {\n        int cell = rng.nextInt(C);\n        int old = boardKmer[cell];\n\n        long long bestD = 0;\n        int bestC = old;\n\n        for (int nc = 0; nc < ALPHA; nc++) {\n            if (nc == old) continue;\n            long long d = ksc.delta(boardKmer, cell, nc);\n            if (d > bestD) {\n                bestD = d;\n                bestC = nc;\n            }\n        }\n\n        if (bestC != old) {\n            boardKmer[cell] = (unsigned char)bestC;\n            kScore += bestD;\n        } else if ((kIter & 3) == 0) {\n            int nc = rng.nextInt(ALPHA);\n            if (nc == old) nc = (nc + 1) % ALPHA;\n            long long d = ksc.delta(boardKmer, cell, nc);\n            double temp = 30.0;\n            if (d >= 0 || rng.nextDouble() < exp((double)d / temp)) {\n                boardKmer[cell] = (unsigned char)nc;\n                kScore += d;\n            }\n        }\n\n        kIter++;\n    }\n\n    Evaluator evStamp(s, boardStamp);\n    Evaluator evKmer(s, boardKmer);\n\n    Evaluator ev;\n    if (evKmer.covered > evStamp.covered ||\n        (evKmer.covered == evStamp.covered && evKmer.obj + 200LL * ksc.score(evKmer.board) > evStamp.obj + 200LL * ksc.score(evStamp.board))) {\n        ev = std::move(evKmer);\n    } else {\n        ev = std::move(evStamp);\n    }\n\n    long long curK = ksc.score(ev.board);\n\n    const double searchLimit = 2.82;\n    int iter = 0;\n\n    vector<pair<int, int>> changed;\n\n    while (true) {\n        if ((iter & 7) == 0 && elapsedSec() > searchLimit) break;\n\n        double progress = min(1.0, elapsedSec() / searchLimit);\n        double temp = 1500000.0 * (1.0 - progress) + 20000.0 * progress;\n\n        long long kScale = (ev.covered < M ? 250 : 40);\n\n        if (ev.covered < M && iter % 5 == 0) {\n            int bestSid = -1;\n            int bestMM = 100;\n            int cnt = 0;\n\n            for (int sid = 0; sid < M; sid++) {\n                if (ev.hist[sid][0] == 0) {\n                    int mm = ev.minMismatchOfString(sid);\n                    if (mm < bestMM) {\n                        bestMM = mm;\n                        bestSid = sid;\n                        cnt = 1;\n                    } else if (mm == bestMM) {\n                        cnt++;\n                        if (rng.nextInt(cnt) == 0) bestSid = sid;\n                    }\n                }\n            }\n\n            if (bestSid != -1) {\n                int idx = ev.bestPlacementIndex(bestSid, rng);\n\n                changed.clear();\n                long long oldObj = ev.obj;\n                long long oldK = curK;\n\n                int len = (int)s[bestSid].size();\n                for (int p = 0; p < len; p++) {\n                    int cell = ev.placementCell(bestSid, idx, p);\n                    int req = s[bestSid][p] - 'A';\n                    if (ev.board[cell] != req) {\n                        int old = ev.board[cell];\n                        changed.push_back({cell, old});\n                        long long kd = ksc.delta(ev.board, cell, req);\n                        curK += kd;\n                        ev.applyChange(cell, req);\n                    }\n                }\n\n                long long exactD = ev.obj - oldObj;\n                long long kD = curK - oldK;\n                long long combD = exactD + kScale * kD;\n\n                bool accept = false;\n                if (combD >= 0) accept = true;\n                else if (exactD > -BIG / 2) {\n                    if (rng.nextDouble() < exp((double)combD / temp)) accept = true;\n                }\n\n                if (!accept) {\n                    for (int i = (int)changed.size() - 1; i >= 0; i--) {\n                        int cell = changed[i].first;\n                        int old = changed[i].second;\n                        long long kd = ksc.delta(ev.board, cell, old);\n                        curK += kd;\n                        ev.applyChange(cell, old);\n                    }\n                }\n            }\n        } else {\n            int cell = rng.nextInt(C);\n            int old = ev.board[cell];\n\n            long long bestComb = 0;\n            long long bestExact = 0;\n            long long bestK = 0;\n            int bestChar = old;\n\n            for (int nc = 0; nc < ALPHA; nc++) {\n                if (nc == old) continue;\n\n                long long kd = ksc.delta(ev.board, cell, nc);\n                long long ed = ev.applyChange(cell, nc);\n                ev.applyChange(cell, old);\n\n                long long cd = ed + kScale * kd;\n                if (cd > bestComb) {\n                    bestComb = cd;\n                    bestExact = ed;\n                    bestK = kd;\n                    bestChar = nc;\n                }\n            }\n\n            if (bestChar != old) {\n                curK += bestK;\n                ev.applyChange(cell, bestChar);\n            } else {\n                int nc = rng.nextInt(ALPHA);\n                if (nc == old) nc = (nc + 1) % ALPHA;\n\n                long long kd = ksc.delta(ev.board, cell, nc);\n                long long ed = ev.applyChange(cell, nc);\n                long long cd = ed + kScale * kd;\n\n                bool accept = false;\n                if (cd >= 0) accept = true;\n                else if (ed > -BIG / 2 && rng.nextDouble() < exp((double)cd / temp)) accept = true;\n\n                if (accept) {\n                    curK += kd;\n                } else {\n                    ev.applyChange(cell, old);\n                }\n            }\n        }\n\n        iter++;\n    }\n\n    // If perfect coverage is achieved, remove unnecessary cells.\n    if (ev.covered == M) {\n        vector<int> cells(C);\n        iota(cells.begin(), cells.end(), 0);\n        shuffle(cells.begin(), cells.end(), mt19937((unsigned)rng.next()));\n\n        for (int cell : cells) {\n            int old = ev.board[cell];\n            if (old == 8) continue;\n\n            ev.applyChange(cell, 8);\n            if (ev.covered < M) ev.applyChange(cell, old);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        string out;\n        for (int j = 0; j < N; j++) {\n            int v = ev.board[i * N + j];\n            if (v == 8) out.push_back('.');\n            else out.push_back(char('A' + v));\n        }\n        cout << out << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<int> ri, rj, cost;\n    int R = 0;\n    int startRid = -1;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R++;\n                ri.push_back(i);\n                rj.push_back(j);\n                cost.push_back(grid[i][j] - '0');\n                if (i == si && j == sj) startRid = id[i][j];\n            }\n        }\n    }\n\n    int W = (R + 63) >> 6;\n\n    vector<int> hid(R), vid(R);\n    vector<vector<int>> hCells, vCells;\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            vector<int> cells;\n            while (j < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                j++;\n            }\n            int h = (int)hCells.size();\n            for (int x : cells) hid[x] = h;\n            hCells.push_back(cells);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            vector<int> cells;\n            while (i < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                i++;\n            }\n            int v = (int)vCells.size();\n            for (int x : cells) vid[x] = v;\n            vCells.push_back(cells);\n        }\n    }\n\n    vector<uint64_t> coverBits((ll)R * W, 0);\n\n    for (int x = 0; x < R; x++) {\n        uint64_t* bs = &coverBits[(ll)x * W];\n        for (int y : hCells[hid[x]]) bs[y >> 6] |= 1ULL << (y & 63);\n        for (int y : vCells[vid[x]]) bs[y >> 6] |= 1ULL << (y & 63);\n    }\n\n    vector<uint64_t> fullMask(W, 0);\n    for (int x = 0; x < R; x++) fullMask[x >> 6] |= 1ULL << (x & 63);\n\n    auto pop_and = [&](const uint64_t* a, const vector<uint64_t>& b) -> int {\n        int res = 0;\n        for (int w = 0; w < W; w++) res += __builtin_popcountll(a[w] & b[w]);\n        return res;\n    };\n\n    auto erase_cover_from_uncovered = [&](vector<uint64_t>& uncovered, int x) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W; w++) uncovered[w] &= ~bs[w];\n    };\n\n    vector<uint64_t> uncovered = fullMask;\n    erase_cover_from_uncovered(uncovered, startRid);\n\n    vector<char> selectedFlag(R, 0);\n    vector<int> selected;\n\n    auto anyUncovered = [&]() -> bool {\n        for (uint64_t x : uncovered) if (x) return true;\n        return false;\n    };\n\n    while (anyUncovered()) {\n        int best = -1;\n        int bestGain = -1;\n        int bestTie = -1;\n\n        for (int x = 0; x < R; x++) {\n            if (selectedFlag[x]) continue;\n\n            const uint64_t* bs = &coverBits[(ll)x * W];\n            int gain = pop_and(bs, uncovered);\n            if (gain <= 0) continue;\n\n            int hLen = (int)hCells[hid[x]].size();\n            int vLen = (int)vCells[vid[x]].size();\n\n            // Tie-breaker: prefer intersections with large future visibility and slightly central/start-near cells.\n            int tie =\n                10 * (hLen + vLen)\n                - abs(ri[x] - si)\n                - abs(rj[x] - sj);\n\n            if (gain > bestGain || (gain == bestGain && tie > bestTie)) {\n                bestGain = gain;\n                bestTie = tie;\n                best = x;\n            }\n        }\n\n        if (best == -1) break;\n        selectedFlag[best] = 1;\n        selected.push_back(best);\n        erase_cover_from_uncovered(uncovered, best);\n    }\n\n    // Remove redundant selected cells using coverage counts.\n    vector<int> cnt(R, 0);\n\n    auto addCoverCount = [&](int x, int delta) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W; w++) {\n            uint64_t v = bs[w];\n            while (v) {\n                int b = __builtin_ctzll(v);\n                int y = (w << 6) + b;\n                if (y < R) cnt[y] += delta;\n                v &= v - 1;\n            }\n        }\n    };\n\n    addCoverCount(startRid, 1);\n    for (int x : selected) addCoverCount(x, 1);\n\n    vector<int> selected2;\n    for (int idx = (int)selected.size() - 1; idx >= 0; idx--) {\n        int x = selected[idx];\n        bool removable = true;\n\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W && removable; w++) {\n            uint64_t v = bs[w];\n            while (v) {\n                int b = __builtin_ctzll(v);\n                int y = (w << 6) + b;\n                if (y < R && cnt[y] <= 1) {\n                    removable = false;\n                    break;\n                }\n                v &= v - 1;\n            }\n        }\n\n        if (removable) {\n            addCoverCount(x, -1);\n        } else {\n            selected2.push_back(x);\n        }\n    }\n    reverse(selected2.begin(), selected2.end());\n    selected.swap(selected2);\n\n    vector<int> nodeRid;\n    nodeRid.push_back(startRid);\n    for (int x : selected) {\n        if (x != startRid) nodeRid.push_back(x);\n    }\n\n    int M = (int)nodeRid.size();\n\n    vector<vector<pair<int,int>>> adj(R);\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n\n    for (int x = 0; x < R; x++) {\n        int i = ri[x], j = rj[x];\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && id[ni][nj] != -1) {\n                int y = id[ni][nj];\n                adj[x].push_back({y, cost[y]});\n            }\n        }\n    }\n\n    const int INF = 1e9;\n    vector<vector<int>> distMat(M, vector<int>(M, INF));\n    vector<vector<short>> prevNode(M, vector<short>(R, -1));\n\n    for (int s = 0; s < M; s++) {\n        int src = nodeRid[s];\n        vector<int> dist(R, INF);\n        vector<short> pre(R, -1);\n\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        dist[src] = 0;\n        pq.push({0, src});\n\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top();\n            pq.pop();\n            if (cd != dist[v]) continue;\n\n            for (auto [to, w] : adj[v]) {\n                int nd = cd + w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pre[to] = (short)v;\n                    pq.push({nd, to});\n                }\n            }\n        }\n\n        prevNode[s].swap(pre);\n        for (int t = 0; t < M; t++) {\n            distMat[s][t] = dist[nodeRid[t]];\n        }\n    }\n\n    auto cycleCost = [&](const vector<int>& cyc) -> ll {\n        ll res = 0;\n        int m = (int)cyc.size();\n        for (int i = 0; i < m; i++) {\n            res += distMat[cyc[i]][cyc[(i + 1) % m]];\n        }\n        return res;\n    };\n\n    vector<int> cycle;\n\n    if (M == 1) {\n        cycle = {0};\n    } else if (M <= 420) {\n        // Cheapest insertion.\n        cycle = {0};\n        vector<int> unused;\n        for (int i = 1; i < M; i++) unused.push_back(i);\n\n        while (!unused.empty()) {\n            int bestUIdx = -1;\n            int bestPos = -1;\n            int bestDelta = INF;\n\n            for (int ui = 0; ui < (int)unused.size(); ui++) {\n                int x = unused[ui];\n                int m = (int)cycle.size();\n\n                for (int p = 0; p < m; p++) {\n                    int a = cycle[p];\n                    int b = cycle[(p + 1) % m];\n                    int delta = distMat[a][x] + distMat[x][b] - distMat[a][b];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestUIdx = ui;\n                        bestPos = p;\n                    }\n                }\n            }\n\n            int x = unused[bestUIdx];\n            cycle.insert(cycle.begin() + bestPos + 1, x);\n            unused.erase(unused.begin() + bestUIdx);\n        }\n    } else {\n        vector<char> used(M, 0);\n        cycle = {0};\n        used[0] = 1;\n        int cur = 0;\n\n        for (int step = 1; step < M; step++) {\n            int best = -1;\n            int bd = INF;\n            for (int x = 1; x < M; x++) {\n                if (!used[x] && distMat[cur][x] < bd) {\n                    bd = distMat[cur][x];\n                    best = x;\n                }\n            }\n            used[best] = 1;\n            cycle.push_back(best);\n            cur = best;\n        }\n    }\n\n    ll curCost = cycleCost(cycle);\n\n    vector<int> nodeCost(M);\n    for (int i = 0; i < M; i++) nodeCost[i] = cost[nodeRid[i]];\n\n    auto symDist = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        return distMat[a][b] + nodeCost[a];\n    };\n\n    // 2-opt + relocation local search.\n    // 2-opt is valid because dist(u,v)+cost(u) is symmetric.\n    if ((int)cycle.size() <= 720) {\n        while (timer.elapsed() < 1.95) {\n            int m = (int)cycle.size();\n\n            ll bestDelta = 0;\n            int bestType = 0;\n            int bestL = -1, bestR = -1;\n            int bestI = -1, bestPos = -1;\n\n            // 2-opt reversal, keeping start node at index 0.\n            for (int l = 1; l < m - 1; l++) {\n                if ((l & 15) == 0 && timer.elapsed() >= 1.95) break;\n                for (int r = l + 1; r < m; r++) {\n                    int a = cycle[l - 1];\n                    int b = cycle[l];\n                    int c = cycle[r];\n                    int d = cycle[(r + 1) % m];\n\n                    ll delta =\n                        (ll)symDist(a, c) + symDist(b, d)\n                        - symDist(a, b) - symDist(c, d);\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 1;\n                        bestL = l;\n                        bestR = r;\n                    }\n                }\n            }\n\n            // Single-node relocation.\n            for (int i = 1; i < m; i++) {\n                if ((i & 15) == 0 && timer.elapsed() >= 1.95) break;\n\n                int x = cycle[i];\n                int a = cycle[i - 1];\n                int b = cycle[(i + 1) % m];\n\n                ll removeDelta = (ll)distMat[a][b] - distMat[a][x] - distMat[x][b];\n\n                for (int pos = 0; pos < m; pos++) {\n                    if (pos == i || pos == i - 1) continue;\n\n                    int c = cycle[pos];\n                    int d = cycle[(pos + 1) % m];\n\n                    ll delta =\n                        removeDelta\n                        + (ll)distMat[c][x] + distMat[x][d]\n                        - distMat[c][d];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 2;\n                        bestI = i;\n                        bestPos = pos;\n                    }\n                }\n            }\n\n            if (bestType == 0) break;\n\n            if (bestType == 1) {\n                reverse(cycle.begin() + bestL, cycle.begin() + bestR + 1);\n            } else {\n                int x = cycle[bestI];\n                cycle.erase(cycle.begin() + bestI);\n\n                int insertIdx;\n                if (bestPos < bestI) insertIdx = bestPos + 1;\n                else insertIdx = bestPos;\n\n                cycle.insert(cycle.begin() + insertIdx, x);\n            }\n\n            curCost += bestDelta;\n        }\n    }\n\n    auto reconstructPath = [&](int srcNode, int dstNode) {\n        vector<int> path;\n        int src = nodeRid[srcNode];\n        int dst = nodeRid[dstNode];\n\n        int cur = dst;\n        while (cur != src) {\n            path.push_back(cur);\n            cur = prevNode[srcNode][cur];\n            if (cur < 0) break;\n        }\n        path.push_back(src);\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    struct EdgeCache {\n        int M, W, R;\n        const vector<int>& nodeRid;\n        const vector<vector<short>>& prevNode;\n        const vector<uint64_t>& coverBits;\n        vector<uint64_t> data;\n        vector<unsigned char> done;\n\n        EdgeCache(\n            int M_,\n            int W_,\n            int R_,\n            const vector<int>& nodeRid_,\n            const vector<vector<short>>& prevNode_,\n            const vector<uint64_t>& coverBits_\n        )\n            : M(M_), W(W_), R(R_), nodeRid(nodeRid_),\n              prevNode(prevNode_), coverBits(coverBits_) {\n            data.assign((ll)M * M * W, 0);\n            done.assign((ll)M * M, 0);\n        }\n\n        uint64_t* get(int a, int b) {\n            ll idx = (ll)a * M + b;\n            uint64_t* ret = &data[idx * W];\n            if (done[idx]) return ret;\n            done[idx] = 1;\n\n            int src = nodeRid[a];\n            int dst = nodeRid[b];\n\n            vector<int> path;\n            int cur = dst;\n            while (cur != src) {\n                path.push_back(cur);\n                cur = prevNode[a][cur];\n                if (cur < 0) break;\n            }\n            path.push_back(src);\n\n            for (int x : path) {\n                const uint64_t* bs = &coverBits[(ll)x * W];\n                for (int w = 0; w < W; w++) ret[w] |= bs[w];\n            }\n            return ret;\n        }\n    };\n\n    // Remove redundant waypoints if visibility of the actual shortest-path route remains complete.\n    // Do not run TSP reordering after this, because route-path visibility may become essential.\n    if (M <= 540 && timer.elapsed() < 2.20) {\n        EdgeCache cache(M, W, R, nodeRid, prevNode, coverBits);\n\n        while ((int)cycle.size() > 1 && timer.elapsed() < 2.78) {\n            int m = (int)cycle.size();\n\n            vector<uint64_t> pref((ll)(m + 1) * W, 0);\n            vector<uint64_t> suff((ll)(m + 1) * W, 0);\n\n            for (int e = 0; e < m; e++) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n                for (int w = 0; w < W; w++) {\n                    pref[(ll)(e + 1) * W + w] = pref[(ll)e * W + w] | ec[w];\n                }\n            }\n\n            for (int e = m - 1; e >= 0; e--) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n                for (int w = 0; w < W; w++) {\n                    suff[(ll)e * W + w] = suff[(ll)(e + 1) * W + w] | ec[w];\n                }\n            }\n\n            int bestP = -1;\n            ll bestSave = 0;\n            vector<uint64_t> tmp(W);\n\n            for (int p = 1; p < m; p++) {\n                int prv = cycle[p - 1];\n                int x = cycle[p];\n                int nxt = cycle[(p + 1) % m];\n\n                ll save = (ll)distMat[prv][x] + distMat[x][nxt] - distMat[prv][nxt];\n                if (save <= bestSave) continue;\n\n                uint64_t* ec = cache.get(prv, nxt);\n\n                for (int w = 0; w < W; w++) {\n                    tmp[w] =\n                        pref[(ll)(p - 1) * W + w] |\n                        suff[(ll)(p + 1) * W + w] |\n                        ec[w];\n                }\n\n                bool ok = true;\n                for (int w = 0; w < W; w++) {\n                    if ((tmp[w] & fullMask[w]) != fullMask[w]) {\n                        ok = false;\n                        break;\n                    }\n                }\n\n                if (ok) {\n                    bestSave = save;\n                    bestP = p;\n                }\n            }\n\n            if (bestP == -1) break;\n            cycle.erase(cycle.begin() + bestP);\n            curCost -= bestSave;\n        }\n    }\n\n    string ans;\n\n    auto moveChar = [&](int a, int b) -> char {\n        int da = ri[b] - ri[a];\n        int db = rj[b] - rj[a];\n        if (da == -1) return 'U';\n        if (da == 1) return 'D';\n        if (db == -1) return 'L';\n        return 'R';\n    };\n\n    int m = (int)cycle.size();\n    for (int e = 0; e < m; e++) {\n        int a = cycle[e];\n        int b = cycle[(e + 1) % m];\n        vector<int> path = reconstructPath(a, b);\n\n        for (int k = 1; k < (int)path.size(); k++) {\n            ans.push_back(moveChar(path[k - 1], path[k]));\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Record {\n    int task;\n    int dur;\n};\n\nint N, M, K, R;\nvector<vector<int>> D;\nvector<vector<int>> children_;\nvector<int> remdep;\nvector<int> status_; // -1:not started, 0:running, 1:done\n\nvector<vector<int>> skill_est;\nvector<vector<Record>> records_;\nvector<int> member_task;\nvector<int> member_start;\n\nvector<double> bottom_priority;\nvector<double> min_cost, avg_cost;\nvector<double> reach_score;\n\nconst int MAX_SKILL = 70;\n\ndouble base_skill;\nconst double PRIOR_COMP = 0.008;\nconst double PRIOR_NORM = 0.003;\nconst double NORM_TARGET = 40.0;\n\ninline double obsPenalty(int w, int t) {\n    static const double p1[5] = {\n        0.0,\n        -log(4.0 / 7.0),\n        -log(3.0 / 7.0),\n        -log(2.0 / 7.0),\n        -log(1.0 / 7.0)\n    };\n\n    if (t == 1) {\n        if (w <= 4) return p1[w];\n        double x = w - 4;\n        return 3.0 + 2.0 * x * x;\n    } else {\n        if (w == 0) {\n            return 5.0 + 1.0 * t * t;\n        }\n        int lo = max(1, t - 3);\n        int hi = t + 3;\n        if (w < lo) {\n            double x = lo - w;\n            return 2.0 * x * x;\n        }\n        if (w > hi) {\n            double x = w - hi;\n            return 2.0 * x * x;\n        }\n        return 1.0 + 0.05 * abs(w - t);\n    }\n}\n\ninline int calcWTaskSkill(int task, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; k++) {\n        if (D[task][k] > s[k]) w += D[task][k] - s[k];\n    }\n    return w;\n}\n\ninline double expectedDurationFromW(int w) {\n    if (w == 0) return 1.0;\n    if (w == 1) return 13.0 / 7.0;\n    if (w == 2) return 17.0 / 7.0;\n    if (w == 3) return 22.0 / 7.0;\n    return (double)w;\n}\n\ninline double expectedDuration(int task, int mem) {\n    int w = 0;\n    const auto& s = skill_est[mem];\n    for (int k = 0; k < K; k++) {\n        if (D[task][k] > s[k]) w += D[task][k] - s[k];\n    }\n    return expectedDurationFromW(w);\n}\n\nvoid optimizeMember(int mem) {\n    auto& recs = records_[mem];\n    if (recs.empty()) return;\n\n    vector<int>& s = skill_est[mem];\n    int Rm = (int)recs.size();\n\n    vector<int> curW(Rm, 0);\n    for (int r = 0; r < Rm; r++) {\n        curW[r] = calcWTaskSkill(recs[r].task, s);\n    }\n\n    double sumsq = 0.0;\n    for (int k = 0; k < K; k++) sumsq += 1.0 * s[k] * s[k];\n\n    int passes = 3;\n    for (int pass = 0; pass < passes; pass++) {\n        bool changed_any = false;\n\n        for (int k = 0; k < K; k++) {\n            int old = s[k];\n\n            double bestObj = 1e100;\n            int bestVal = old;\n\n            double oldCompPrior = PRIOR_COMP * (old - base_skill) * (old - base_skill);\n\n            for (int val = 0; val <= MAX_SKILL; val++) {\n                double obj = 0.0;\n\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    int oldContrib = max(0, D[task][k] - old);\n                    int newContrib = max(0, D[task][k] - val);\n                    int nw = curW[r] - oldContrib + newContrib;\n                    obj += obsPenalty(nw, recs[r].dur);\n                }\n\n                double compPrior = PRIOR_COMP * (val - base_skill) * (val - base_skill);\n\n                double nsumsq = sumsq - 1.0 * old * old + 1.0 * val * val;\n                double norm = sqrt(nsumsq);\n                double normPrior = PRIOR_NORM * (norm - NORM_TARGET) * (norm - NORM_TARGET);\n\n                obj += compPrior + normPrior;\n\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestVal = val;\n                }\n            }\n\n            if (bestVal != old) {\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    curW[r] -= max(0, D[task][k] - old);\n                    curW[r] += max(0, D[task][k] - bestVal);\n                }\n                sumsq = sumsq - 1.0 * old * old + 1.0 * bestVal * bestVal;\n                s[k] = bestVal;\n                changed_any = true;\n            }\n        }\n\n        if (!changed_any) break;\n    }\n}\n\nvoid precomputeReachScore() {\n    vector<double> dp(N, 0.0);\n    for (int i = N - 1; i >= 0; i--) {\n        double v = 0.0;\n        for (int c : children_[i]) {\n            v += 1.0 + dp[c];\n            if (v > 1e6) {\n                v = 1e6;\n                break;\n            }\n        }\n        dp[i] = v;\n    }\n\n    reach_score.assign(N, 0.0);\n    for (int i = 0; i < N; i++) {\n        reach_score[i] = log1p(dp[i]);\n    }\n}\n\nvoid recomputePriorities() {\n    min_cost.assign(N, 0.0);\n    avg_cost.assign(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        if (status_[i] == 1) {\n            min_cost[i] = avg_cost[i] = 0.0;\n            continue;\n        }\n\n        double mn = 1e100;\n        double sum = 0.0;\n        for (int j = 0; j < M; j++) {\n            double e = expectedDuration(i, j);\n            mn = min(mn, e);\n            sum += e;\n        }\n        min_cost[i] = mn;\n        avg_cost[i] = sum / M;\n    }\n\n    bottom_priority.assign(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        if (status_[i] == 1) {\n            bottom_priority[i] = 0.0;\n            continue;\n        }\n\n        double nodeCost = 0.7 * min_cost[i] + 0.3 * avg_cost[i];\n        double mx = 0.0;\n        for (int c : children_[i]) {\n            mx = max(mx, bottom_priority[c]);\n        }\n        bottom_priority[i] = nodeCost + mx;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K >> R;\n\n    D.assign(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) cin >> D[i][k];\n    }\n\n    children_.assign(N, {});\n    remdep.assign(N, 0);\n\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        children_[u].push_back(v);\n        remdep[v]++;\n    }\n\n    base_skill = 35.0 / sqrt((double)K);\n    int init_skill = max(0, (int)round(base_skill));\n\n    skill_est.assign(M, vector<int>(K, init_skill));\n    records_.assign(M, {});\n\n    status_.assign(N, -1);\n    member_task.assign(M, -1);\n    member_start.assign(M, -1);\n\n    precomputeReachScore();\n\n    for (int day = 1; day <= 2000; day++) {\n        recomputePriorities();\n\n        vector<int> free_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready;\n        for (int i = 0; i < N; i++) {\n            if (status_[i] == -1 && remdep[i] == 0) ready.push_back(i);\n        }\n\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (bottom_priority[a] != bottom_priority[b]) {\n                return bottom_priority[a] > bottom_priority[b];\n            }\n            if (reach_score[a] != reach_score[b]) {\n                return reach_score[a] > reach_score[b];\n            }\n            return a < b;\n        });\n\n        vector<pair<int, int>> assignments;\n\n        while (!free_members.empty()) {\n            int bestFi = -1;\n            int bestTask = -1;\n            double bestScore = -1e100;\n\n            int limit = min((int)ready.size(), 300);\n\n            for (int fi = 0; fi < (int)free_members.size(); fi++) {\n                int mem = free_members[fi];\n\n                for (int idx = 0; idx < limit; idx++) {\n                    int task = ready[idx];\n                    if (status_[task] != -1) continue;\n\n                    double pred = expectedDuration(task, mem);\n\n                    double score =\n                        bottom_priority[task]\n                        + 0.15 * reach_score[task]\n                        - 0.70 * pred\n                        + 0.20 * (avg_cost[task] - pred);\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestFi = fi;\n                        bestTask = task;\n                    }\n                }\n            }\n\n            if (bestFi == -1) break;\n\n            int mem = free_members[bestFi];\n\n            status_[bestTask] = 0;\n            member_task[mem] = bestTask;\n            member_start[mem] = day;\n\n            assignments.push_back({mem, bestTask});\n\n            free_members.erase(free_members.begin() + bestFi);\n        }\n\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << mem + 1 << ' ' << task + 1;\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        for (int i = 0; i < cnt; i++) {\n            int f;\n            cin >> f;\n            --f;\n\n            int task = member_task[f];\n            if (task < 0) continue;\n\n            int dur = day - member_start[f] + 1;\n\n            status_[task] = 1;\n            member_task[f] = -1;\n            member_start[f] = -1;\n\n            records_[f].push_back({task, dur});\n            optimizeMember(f);\n\n            for (int c : children_[task]) {\n                remdep[c]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int ax, ay, cx, cy;\n    int score;\n};\n\nstruct Node {\n    int x, y;\n    int id;   // -1 depot\n    int type; // 0 pickup, 1 delivery\n};\n\nstruct InsertInfo {\n    int cost;\n    int pgap;\n    int dgap;\n};\n\nstruct State {\n    vector<Node> route;\n    vector<int> selected;\n    vector<char> used;\n    int cost;\n};\n\nstatic const int N = 1000;\nstatic const int K = 50;\nstatic const int DEP = 400;\nstatic const int INF = 1e9;\n\nvector<Order> ords;\nchrono::steady_clock::time_point start_time;\n\ninline double elapsed() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - start_time).count();\n}\n\ninline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline int ndist(const Node& a, const Node& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\ninline Node pickupNode(int id) {\n    return Node{ords[id].ax, ords[id].ay, id, 0};\n}\n\ninline Node deliveryNode(int id) {\n    return Node{ords[id].cx, ords[id].cy, id, 1};\n}\n\nint routeCost(const vector<Node>& route) {\n    int res = 0;\n    for (int i = 0; i + 1 < (int)route.size(); i++) {\n        res += ndist(route[i], route[i + 1]);\n    }\n    return res;\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    double nextDouble() {\n        return (next() + 0.5) / 4294967296.0;\n    }\n\n    int randint(int l, int r) {\n        return l + (int)(next() % (uint32_t)(r - l + 1));\n    }\n};\n\nXorShift rng;\n\nInsertInfo bestInsert(const vector<Node>& route, int oid) {\n    const int L = (int)route.size();\n\n    const int px = ords[oid].ax;\n    const int py = ords[oid].ay;\n    const int dx = ords[oid].cx;\n    const int dy = ords[oid].cy;\n\n    int best = INF;\n    int bestP = -1;\n    int bestD = -1;\n\n    for (int i = 0; i <= L - 2; i++) {\n        const Node& A = route[i];\n        const Node& B = route[i + 1];\n\n        int directAB = ndist(A, B);\n\n        // pickup and delivery inserted into the same gap\n        int val = mdist(A.x, A.y, px, py)\n                + mdist(px, py, dx, dy)\n                + mdist(dx, dy, B.x, B.y)\n                - directAB;\n\n        if (val < best) {\n            best = val;\n            bestP = i;\n            bestD = i;\n        }\n\n        int addPickup = mdist(A.x, A.y, px, py)\n                      + mdist(px, py, B.x, B.y)\n                      - directAB;\n\n        for (int j = i + 1; j <= L - 2; j++) {\n            const Node& C = route[j];\n            const Node& D = route[j + 1];\n\n            int addDelivery = mdist(C.x, C.y, dx, dy)\n                            + mdist(dx, dy, D.x, D.y)\n                            - ndist(C, D);\n\n            val = addPickup + addDelivery;\n\n            if (val < best) {\n                best = val;\n                bestP = i;\n                bestD = j;\n            }\n        }\n    }\n\n    return InsertInfo{best, bestP, bestD};\n}\n\nvoid applyInsert(vector<Node>& route, int oid, const InsertInfo& ins) {\n    vector<Node> nr;\n    nr.reserve(route.size() + 2);\n\n    Node P = pickupNode(oid);\n    Node D = deliveryNode(oid);\n\n    for (int i = 0; i < (int)route.size(); i++) {\n        nr.push_back(route[i]);\n\n        if (i == ins.pgap) {\n            nr.push_back(P);\n            if (ins.dgap == ins.pgap) {\n                nr.push_back(D);\n            }\n        }\n\n        if (ins.dgap > ins.pgap && i == ins.dgap) {\n            nr.push_back(D);\n        }\n    }\n\n    route.swap(nr);\n}\n\nvector<Node> removeOrder(const vector<Node>& route, int oid) {\n    vector<Node> nr;\n    nr.reserve(route.size() - 2);\n    for (const auto& v : route) {\n        if (v.id != oid) nr.push_back(v);\n    }\n    return nr;\n}\n\nbool feasibleReverse(const vector<Node>& route, int l, int r) {\n    static int p[N], d[N];\n    fill(p, p + N, -1);\n    fill(d, d + N, -1);\n\n    int n = (int)route.size();\n\n    for (int i = 1; i <= n - 2; i++) {\n        int ni = i;\n        if (l <= i && i <= r) ni = l + r - i;\n\n        const Node& v = route[i];\n        if (v.type == 0) p[v.id] = ni;\n        else d[v.id] = ni;\n    }\n\n    for (int i = 1; i <= n - 2; i++) {\n        int id = route[i].id;\n        if (p[id] != -1 && d[id] != -1 && p[id] > d[id]) {\n            return false;\n        }\n    }\n\n    return true;\n}\n\nbool feasibleSwap(const vector<Node>& route, int a, int b) {\n    static int p[N], d[N];\n    fill(p, p + N, -1);\n    fill(d, d + N, -1);\n\n    int n = (int)route.size();\n\n    for (int i = 1; i <= n - 2; i++) {\n        int ni = i;\n        if (i == a) ni = b;\n        else if (i == b) ni = a;\n\n        const Node& v = route[i];\n        if (v.type == 0) p[v.id] = ni;\n        else d[v.id] = ni;\n    }\n\n    for (int i = 1; i <= n - 2; i++) {\n        int id = route[i].id;\n        if (p[id] != -1 && d[id] != -1 && p[id] > d[id]) {\n            return false;\n        }\n    }\n\n    return true;\n}\n\nbool pairReinsertOptimize(State& st, double limitTime, int maxPass = 4) {\n    bool any = false;\n\n    for (int pass = 0; pass < maxPass && elapsed() < limitTime; pass++) {\n        bool improved = false;\n\n        for (int oid : st.selected) {\n            if (elapsed() >= limitTime) break;\n\n            vector<Node> rem = removeOrder(st.route, oid);\n            int remCost = routeCost(rem);\n\n            InsertInfo ins = bestInsert(rem, oid);\n            int newCost = remCost + ins.cost;\n\n            if (newCost < st.cost) {\n                st.route.swap(rem);\n                applyInsert(st.route, oid, ins);\n                st.cost = newCost;\n                improved = true;\n                any = true;\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nbool twoOptOptimize(State& st, double limitTime) {\n    bool any = false;\n    int n = (int)st.route.size();\n\n    while (elapsed() < limitTime) {\n        int bestDelta = 0;\n        int bestL = -1;\n        int bestR = -1;\n\n        for (int l = 1; l <= n - 3; l++) {\n            for (int r = l + 1; r <= n - 2; r++) {\n                int delta = ndist(st.route[l - 1], st.route[r])\n                          + ndist(st.route[l], st.route[r + 1])\n                          - ndist(st.route[l - 1], st.route[l])\n                          - ndist(st.route[r], st.route[r + 1]);\n\n                if (delta < bestDelta && feasibleReverse(st.route, l, r)) {\n                    bestDelta = delta;\n                    bestL = l;\n                    bestR = r;\n                }\n            }\n        }\n\n        if (bestDelta >= 0) break;\n\n        reverse(st.route.begin() + bestL, st.route.begin() + bestR + 1);\n        st.cost += bestDelta;\n        any = true;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nbool swapOptimize(State& st, double limitTime) {\n    bool any = false;\n    int n = (int)st.route.size();\n\n    while (elapsed() < limitTime) {\n        int bestDelta = 0;\n        int bestI = -1;\n        int bestJ = -1;\n\n        for (int i = 1; i <= n - 3; i++) {\n            for (int j = i + 1; j <= n - 2; j++) {\n                int delta;\n\n                if (i + 1 == j) {\n                    delta = ndist(st.route[i - 1], st.route[j])\n                          + ndist(st.route[j], st.route[i])\n                          + ndist(st.route[i], st.route[j + 1])\n                          - ndist(st.route[i - 1], st.route[i])\n                          - ndist(st.route[i], st.route[j])\n                          - ndist(st.route[j], st.route[j + 1]);\n                } else {\n                    delta = ndist(st.route[i - 1], st.route[j])\n                          + ndist(st.route[j], st.route[i + 1])\n                          + ndist(st.route[j - 1], st.route[i])\n                          + ndist(st.route[i], st.route[j + 1])\n                          - ndist(st.route[i - 1], st.route[i])\n                          - ndist(st.route[i], st.route[i + 1])\n                          - ndist(st.route[j - 1], st.route[j])\n                          - ndist(st.route[j], st.route[j + 1]);\n                }\n\n                if (delta < bestDelta && feasibleSwap(st.route, i, j)) {\n                    bestDelta = delta;\n                    bestI = i;\n                    bestJ = j;\n                }\n            }\n        }\n\n        if (bestDelta >= 0) break;\n\n        swap(st.route[bestI], st.route[bestJ]);\n        st.cost += bestDelta;\n        any = true;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nvoid routeLocalOptimize(State& st, double limitTime, bool heavy) {\n    while (elapsed() < limitTime) {\n        int before = st.cost;\n\n        pairReinsertOptimize(st, limitTime, 3);\n        twoOptOptimize(st, limitTime);\n\n        if (heavy) {\n            swapOptimize(st, limitTime);\n            twoOptOptimize(st, limitTime);\n            pairReinsertOptimize(st, limitTime, 2);\n        }\n\n        st.cost = routeCost(st.route);\n\n        if (st.cost >= before) break;\n    }\n}\n\nState constructGreedy(const vector<int>& pool, int randomTop) {\n    Node depot{DEP, DEP, -1, -1};\n\n    State st;\n    st.route = {depot, depot};\n    st.used.assign(N, 0);\n    st.selected.clear();\n    st.cost = 0;\n\n    struct Choice {\n        int cost;\n        int oid;\n        InsertInfo ins;\n    };\n\n    for (int step = 0; step < K; step++) {\n        vector<Choice> top;\n        top.reserve(randomTop);\n\n        for (int oid : pool) {\n            if (st.used[oid]) continue;\n\n            InsertInfo ins = bestInsert(st.route, oid);\n            Choice ch{ins.cost, oid, ins};\n\n            if ((int)top.size() < randomTop) {\n                top.push_back(ch);\n            } else {\n                int worst = 0;\n                for (int i = 1; i < (int)top.size(); i++) {\n                    if (top[i].cost > top[worst].cost) worst = i;\n                }\n                if (ch.cost < top[worst].cost) top[worst] = ch;\n            }\n        }\n\n        sort(top.begin(), top.end(), [](const Choice& a, const Choice& b) {\n            return a.cost < b.cost;\n        });\n\n        int idx = 0;\n        if (randomTop > 1 && (int)top.size() > 1) {\n            int lim = (int)top.size();\n            double u = rng.nextDouble();\n            idx = min(lim - 1, (int)(u * u * lim));\n        }\n\n        Choice ch = top[idx];\n\n        applyInsert(st.route, ch.oid, ch.ins);\n        st.used[ch.oid] = 1;\n        st.selected.push_back(ch.oid);\n        st.cost += ch.ins.cost;\n    }\n\n    st.cost = routeCost(st.route);\n    return st;\n}\n\nvector<int> makeClusterPool(int cx, int cy, int M) {\n    vector<pair<int, int>> v;\n    v.reserve(N);\n\n    for (int i = 0; i < N; i++) {\n        int cluster = mdist(ords[i].ax, ords[i].ay, cx, cy)\n                    + mdist(ords[i].cx, ords[i].cy, cx, cy);\n\n        int center = mdist(ords[i].ax, ords[i].ay, DEP, DEP)\n                   + mdist(ords[i].cx, ords[i].cy, DEP, DEP);\n\n        int paird = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        int sc = cluster * 10 + center * 3 + paird;\n        v.push_back({sc, i});\n    }\n\n    if (M < N) {\n        nth_element(v.begin(), v.begin() + M, v.end());\n        v.resize(M);\n    }\n\n    sort(v.begin(), v.end());\n\n    vector<int> pool;\n    pool.reserve(v.size());\n    for (auto [_, id] : v) pool.push_back(id);\n\n    return pool;\n}\n\nvoid replaceOptimize(State& st, const vector<int>& candList, double limitTime) {\n    while (elapsed() < limitTime) {\n        int bestNewCost = st.cost;\n        int bestRemove = -1;\n        int bestAdd = -1;\n\n        int checks = 0;\n        bool timeout = false;\n\n        for (int remOid : st.selected) {\n            vector<Node> remRoute = removeOrder(st.route, remOid);\n            int remCost = routeCost(remRoute);\n\n            for (int addOid : candList) {\n                if (st.used[addOid]) continue;\n\n                InsertInfo ins = bestInsert(remRoute, addOid);\n                int newCost = remCost + ins.cost;\n\n                if (newCost < bestNewCost) {\n                    bestNewCost = newCost;\n                    bestRemove = remOid;\n                    bestAdd = addOid;\n                }\n\n                if ((++checks & 255) == 0 && elapsed() > limitTime) {\n                    timeout = true;\n                    break;\n                }\n            }\n\n            if (timeout) break;\n        }\n\n        if (bestRemove == -1) break;\n\n        vector<Node> remRoute = removeOrder(st.route, bestRemove);\n        InsertInfo ins = bestInsert(remRoute, bestAdd);\n\n        st.route.swap(remRoute);\n        applyInsert(st.route, bestAdd, ins);\n\n        st.used[bestRemove] = 0;\n        st.used[bestAdd] = 1;\n\n        for (int& x : st.selected) {\n            if (x == bestRemove) {\n                x = bestAdd;\n                break;\n            }\n        }\n\n        st.cost = routeCost(st.route);\n        routeLocalOptimize(st, min(limitTime, elapsed() + 0.08), false);\n\n        if (timeout) break;\n    }\n\n    st.cost = routeCost(st.route);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    ords.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> ords[i].ax >> ords[i].ay >> ords[i].cx >> ords[i].cy;\n\n        int centerSum = mdist(DEP, DEP, ords[i].ax, ords[i].ay)\n                      + mdist(DEP, DEP, ords[i].cx, ords[i].cy);\n        int pairDist = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        ords[i].score = centerSum + pairDist / 2;\n    }\n\n    vector<int> allIds(N);\n    iota(allIds.begin(), allIds.end(), 0);\n\n    vector<int> sortedIds = allIds;\n    sort(sortedIds.begin(), sortedIds.end(), [](int a, int b) {\n        return ords[a].score < ords[b].score;\n    });\n\n    State best = constructGreedy(allIds, 1);\n    routeLocalOptimize(best, 0.35, true);\n\n    vector<int> centerPool;\n    int centerPoolSize = 700;\n    for (int i = 0; i < centerPoolSize; i++) centerPool.push_back(sortedIds[i]);\n\n    int iter = 0;\n\n    while (elapsed() < 1.05) {\n        vector<int> pool;\n\n        if (iter % 4 == 0) {\n            int base = sortedIds[rng.randint(0, 499)];\n            int cx = (ords[base].ax + ords[base].cx) / 2 + rng.randint(-80, 80);\n            int cy = (ords[base].ay + ords[base].cy) / 2 + rng.randint(-80, 80);\n            cx = max(150, min(650, cx));\n            cy = max(150, min(650, cy));\n\n            pool = makeClusterPool(cx, cy, 420);\n        } else if (iter % 4 == 1) {\n            pool = makeClusterPool(\n                400 + rng.randint(-160, 160),\n                400 + rng.randint(-160, 160),\n                420\n            );\n        } else {\n            pool = centerPool;\n        }\n\n        State cur = constructGreedy(pool, 7);\n        routeLocalOptimize(cur, min(1.20, elapsed() + 0.05), false);\n\n        if (cur.cost < best.cost) {\n            best = cur;\n        }\n\n        iter++;\n    }\n\n    routeLocalOptimize(best, 1.35, true);\n\n    vector<int> replaceCand;\n    int replaceSize = 850;\n    for (int i = 0; i < replaceSize; i++) replaceCand.push_back(sortedIds[i]);\n\n    replaceOptimize(best, replaceCand, 1.82);\n\n    routeLocalOptimize(best, 1.95, true);\n\n    cout << K;\n    for (int oid : best.selected) {\n        cout << ' ' << oid + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (const Node& v : best.route) {\n        cout << ' ' << v.x << ' ' << v.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 400;\nstatic constexpr int M = 1995;\nstatic constexpr int SAMPLES = 24;\nstatic constexpr long long INF = (1LL << 60);\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n};\n\nstruct DSU {\n    int p[N];\n    int sz[N];\n\n    void init() {\n        for (int i = 0; i < N; i++) {\n            p[i] = i;\n            sz[i] = 1;\n        }\n    }\n\n    int find(int x) const {\n        while (p[x] != x) x = p[x];\n        return x;\n    }\n\n    bool same(int a, int b) const {\n        return find(a) == find(b);\n    }\n\n    bool unite(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n        if (ra == rb) return false;\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<int> u(M), v(M), d(M);\n    for (int i = 0; i < M; i++) {\n        cin >> u[i] >> v[i];\n\n        long long dx = x[u[i]] - x[v[i]];\n        long long dy = y[u[i]] - y[v[i]];\n        d[i] = int(floor(sqrt(double(dx * dx + dy * dy)) + 0.5));\n    }\n\n    XorShift rng;\n\n    vector<vector<int>> sampled_w(SAMPLES, vector<int>(M));\n    vector<vector<int>> order(SAMPLES, vector<int>(M));\n\n    for (int s = 0; s < SAMPLES; s++) {\n        for (int i = 0; i < M; i++) {\n            sampled_w[s][i] = rng.randint(d[i], 3 * d[i]);\n            order[s][i] = i;\n        }\n\n        sort(order[s].begin(), order[s].end(), [&](int a, int b) {\n            if (sampled_w[s][a] != sampled_w[s][b]) {\n                return sampled_w[s][a] < sampled_w[s][b];\n            }\n            return a < b;\n        });\n    }\n\n    DSU accepted;\n    accepted.init();\n\n    int accepted_edges = 0;\n\n    for (int cur = 0; cur < M; cur++) {\n        int len;\n        cin >> len;\n\n        int answer = 0;\n\n        if (!accepted.same(u[cur], v[cur])) {\n            int base_components = N - accepted_edges;\n\n            long long sum_delta = 0;\n            bool reject_impossible = false;\n\n            for (int s = 0; s < SAMPLES; s++) {\n                DSU dsu_reject = accepted;\n                DSU dsu_accept = accepted;\n\n                int comp_reject = base_components;\n                int comp_accept = base_components;\n\n                long long cost_reject = 0;\n                long long cost_accept = len;\n\n                if (dsu_accept.unite(u[cur], v[cur])) {\n                    comp_accept--;\n                }\n\n                for (int pos = 0; pos < M; pos++) {\n                    if (comp_reject == 1 && comp_accept == 1) break;\n\n                    int e = order[s][pos];\n                    if (e <= cur) continue;\n\n                    int a = u[e];\n                    int b = v[e];\n                    int w = sampled_w[s][e];\n\n                    if (comp_reject > 1 && dsu_reject.unite(a, b)) {\n                        cost_reject += w;\n                        comp_reject--;\n                    }\n\n                    if (comp_accept > 1 && dsu_accept.unite(a, b)) {\n                        cost_accept += w;\n                        comp_accept--;\n                    }\n                }\n\n                if (comp_reject > 1) {\n                    reject_impossible = true;\n                    break;\n                }\n\n                if (comp_accept > 1) {\n                    cost_accept = INF;\n                }\n\n                sum_delta += cost_accept - cost_reject;\n            }\n\n            if (reject_impossible || sum_delta < 0) {\n                answer = 1;\n                accepted.unite(u[cur], v[cur]);\n                accepted_edges++;\n            }\n        }\n\n        cout << answer << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct Task {\n    int sx, sy; // standing cell\n    int wx, wy; // wall cell\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\n\nbool wall_[31][31];\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char mvChar[4] = {'U', 'D', 'L', 'R'};\nconst char buildChar[4] = {'u', 'd', 'l', 'r'};\n\nint ori_, S_;\nint x1_, x2_, y1_, y2_;\nvector<Task> tasks;\n\nbool inBoard(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nbool insideRegion(int x, int y) {\n    return x1_ <= x && x <= x2_ && y1_ <= y && y <= y2_;\n}\n\nbool passable(int x, int y) {\n    return inBoard(x, y) && !wall_[x][y];\n}\n\npair<int,int> regionRangeX(int ori, int S) {\n    if (ori == 0 || ori == 1) return {1, S};\n    return {31 - S, 30};\n}\n\npair<int,int> regionRangeY(int ori, int S) {\n    if (ori == 0 || ori == 2) return {1, S};\n    return {31 - S, 30};\n}\n\nbool insideRegionParam(int x, int y, int ori, int S) {\n    auto rx = regionRangeX(ori, S);\n    auto ry = regionRangeY(ori, S);\n    return rx.first <= x && x <= rx.second && ry.first <= y && y <= ry.second;\n}\n\nint distToRegion(int x, int y, int ori, int S) {\n    auto rx = regionRangeX(ori, S);\n    auto ry = regionRangeY(ori, S);\n    int dx = 0, dy = 0;\n    if (x < rx.first) dx = rx.first - x;\n    if (x > rx.second) dx = x - rx.second;\n    if (y < ry.first) dy = ry.first - y;\n    if (y > ry.second) dy = y - ry.second;\n    return dx + dy;\n}\n\nvoid selectRegion() {\n    double bestVal = -1e100;\n    int bestOri = 0, bestS = 10;\n\n    for (int ori = 0; ori < 4; ori++) {\n        for (int S = 8; S <= 18; S++) {\n            int pcnt = 0;\n            for (auto &p : pets) {\n                if (insideRegionParam(p.x, p.y, ori, S)) pcnt++;\n            }\n\n            double avgDist = 0;\n            for (auto &h : humans) {\n                avgDist += distToRegion(h.x, h.y, ori, S);\n            }\n            avgDist /= M;\n\n            double expected = (double)(S * S) / 900.0 * pow(0.5, pcnt);\n            double val = expected - 0.002 * avgDist - 0.0005 * S;\n\n            if (val > bestVal) {\n                bestVal = val;\n                bestOri = ori;\n                bestS = S;\n            }\n        }\n    }\n\n    ori_ = bestOri;\n    S_ = bestS;\n\n    auto rx = regionRangeX(ori_, S_);\n    auto ry = regionRangeY(ori_, S_);\n    x1_ = rx.first;\n    x2_ = rx.second;\n    y1_ = ry.first;\n    y2_ = ry.second;\n}\n\nvoid makeTasks() {\n    tasks.clear();\n\n    int S = S_;\n\n    if (ori_ == 0) {\n        // top-left\n        for (int c = 1; c <= S; c++) {\n            tasks.push_back({S, c, S + 1, c});\n        }\n        for (int r = 1; r <= S; r++) {\n            tasks.push_back({r, S, r, S + 1});\n        }\n    } else if (ori_ == 1) {\n        // top-right\n        int L = 31 - S;\n        for (int c = L; c <= 30; c++) {\n            tasks.push_back({S, c, S + 1, c});\n        }\n        for (int r = 1; r <= S; r++) {\n            tasks.push_back({r, L, r, L - 1});\n        }\n    } else if (ori_ == 2) {\n        // bottom-left\n        int U = 31 - S;\n        for (int c = 1; c <= S; c++) {\n            tasks.push_back({U, c, U - 1, c});\n        }\n        for (int r = U; r <= 30; r++) {\n            tasks.push_back({r, S, r, S + 1});\n        }\n    } else {\n        // bottom-right\n        int U = 31 - S;\n        int L = 31 - S;\n        for (int c = L; c <= 30; c++) {\n            tasks.push_back({U, c, U - 1, c});\n        }\n        for (int r = U; r <= 30; r++) {\n            tasks.push_back({r, L, r, L - 1});\n        }\n    }\n}\n\nbool allHumansInside() {\n    for (auto &h : humans) {\n        if (!insideRegion(h.x, h.y)) return false;\n    }\n    return true;\n}\n\nint petsInside() {\n    int cnt = 0;\n    for (auto &p : pets) {\n        if (insideRegion(p.x, p.y)) cnt++;\n    }\n    return cnt;\n}\n\nbool allTasksDone() {\n    for (auto &t : tasks) {\n        if (!wall_[t.wx][t.wy]) return false;\n    }\n    return true;\n}\n\nchar dirFromTo(int x1, int y1, int x2, int y2, bool build) {\n    for (int d = 0; d < 4; d++) {\n        if (x1 + dx[d] == x2 && y1 + dy[d] == y2) {\n            return build ? buildChar[d] : mvChar[d];\n        }\n    }\n    return '.';\n}\n\nbool validBuildTarget(\n    int x,\n    int y,\n    const bool occH[31][31],\n    const bool occP[31][31]\n) {\n    if (!inBoard(x, y)) return false;\n    if (occH[x][y]) return false;\n    if (occP[x][y]) return false;\n\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (inBoard(nx, ny) && occP[nx][ny]) return false;\n    }\n\n    return true;\n}\n\nchar bfsMove(\n    int sx,\n    int sy,\n    const vector<pair<int,int>> &targets,\n    const bool avoid[31][31],\n    bool restrictInside\n) {\n    if (targets.empty()) return '.';\n\n    bool isTarget[31][31] = {};\n    for (auto [x, y] : targets) {\n        if (inBoard(x, y)) isTarget[x][y] = true;\n    }\n\n    if (isTarget[sx][sy]) return '.';\n\n    int dist[31][31];\n    char first[31][31];\n\n    for (int i = 1; i <= 30; i++) {\n        for (int j = 1; j <= 30; j++) {\n            dist[i][j] = -1;\n            first[i][j] = '.';\n        }\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();\n        q.pop();\n\n        if (isTarget[x][y]) {\n            return first[x][y];\n        }\n\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n\n            if (!inBoard(nx, ny)) continue;\n            if (!passable(nx, ny)) continue;\n            if (avoid[nx][ny]) continue;\n            if (restrictInside && !insideRegion(nx, ny)) continue;\n            if (dist[nx][ny] != -1) continue;\n\n            dist[nx][ny] = dist[x][y] + 1;\n            first[nx][ny] = (x == sx && y == sy) ? mvChar[d] : first[x][y];\n            q.push({nx, ny});\n        }\n    }\n\n    return '.';\n}\n\nvector<pair<int,int>> allInsideCells() {\n    vector<pair<int,int>> res;\n    for (int x = x1_; x <= x2_; x++) {\n        for (int y = y1_; y <= y2_; y++) {\n            if (passable(x, y)) res.push_back({x, y});\n        }\n    }\n    return res;\n}\n\npair<int,int> centerCell() {\n    return {(x1_ + x2_) / 2, (y1_ + y2_) / 2};\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++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    memset(wall_, false, sizeof(wall_));\n\n    selectRegion();\n    makeTasks();\n\n    bool startedBuild = false;\n\n    for (int turn = 0; turn < 300; turn++) {\n        bool occH[31][31] = {};\n        bool occP[31][31] = {};\n\n        for (auto &h : humans) occH[h.x][h.y] = true;\n        for (auto &p : pets) occP[p.x][p.y] = true;\n\n        string ans(M, '.');\n        bool avoid[31][31] = {};\n\n        bool humansIn = allHumansInside();\n\n        if (!humansIn) {\n            vector<pair<int,int>> targets = allInsideCells();\n            for (int i = 0; i < M; i++) {\n                ans[i] = bfsMove(humans[i].x, humans[i].y, targets, avoid, false);\n            }\n        } else {\n            if (!startedBuild) {\n                if (petsInside() == 0 || turn >= 100) {\n                    startedBuild = true;\n                }\n            }\n\n            if (!startedBuild) {\n                auto c = centerCell();\n                vector<pair<int,int>> targets = {c};\n                for (int i = 0; i < M; i++) {\n                    ans[i] = bfsMove(humans[i].x, humans[i].y, targets, avoid, true);\n                }\n            } else if (!allTasksDone()) {\n                bool scheduledWall[31][31] = {};\n\n                // First, humans already standing at task positions try to build.\n                for (int i = 0; i < M; i++) {\n                    int hx = humans[i].x;\n                    int hy = humans[i].y;\n\n                    for (auto &t : tasks) {\n                        if (wall_[t.wx][t.wy]) continue;\n                        if (t.sx != hx || t.sy != hy) continue;\n                        if (scheduledWall[t.wx][t.wy]) continue;\n                        if (!validBuildTarget(t.wx, t.wy, occH, occP)) continue;\n\n                        ans[i] = dirFromTo(hx, hy, t.wx, t.wy, true);\n                        scheduledWall[t.wx][t.wy] = true;\n                        avoid[t.wx][t.wy] = true;\n                        break;\n                    }\n                }\n\n                // Then move idle humans to useful task positions.\n                vector<pair<int,int>> goodTargets;\n                vector<pair<int,int>> fallbackTargets;\n\n                for (auto &t : tasks) {\n                    if (wall_[t.wx][t.wy]) continue;\n                    if (scheduledWall[t.wx][t.wy]) continue;\n\n                    fallbackTargets.push_back({t.sx, t.sy});\n\n                    if (validBuildTarget(t.wx, t.wy, occH, occP)) {\n                        goodTargets.push_back({t.sx, t.sy});\n                    }\n                }\n\n                if (goodTargets.empty()) goodTargets = fallbackTargets;\n\n                for (int i = 0; i < M; i++) {\n                    if (ans[i] != '.') continue;\n\n                    bool restrict = insideRegion(humans[i].x, humans[i].y);\n                    ans[i] = bfsMove(\n                        humans[i].x,\n                        humans[i].y,\n                        goodTargets,\n                        avoid,\n                        restrict\n                    );\n                }\n            } else {\n                auto c = centerCell();\n                vector<pair<int,int>> targets = {c};\n                for (int i = 0; i < M; i++) {\n                    ans[i] = bfsMove(humans[i].x, humans[i].y, targets, avoid, true);\n                }\n            }\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        // Apply human actions and created walls.\n        for (int i = 0; i < M; i++) {\n            char a = ans[i];\n\n            if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                for (int d = 0; d < 4; d++) {\n                    if (a == mvChar[d]) {\n                        humans[i].x += dx[d];\n                        humans[i].y += dy[d];\n                    }\n                }\n            } else if (a == 'u' || a == 'd' || a == 'l' || a == 'r') {\n                for (int d = 0; d < 4; d++) {\n                    if (a == buildChar[d]) {\n                        int wx = humans[i].x + dx[d];\n                        int wy = humans[i].y + dy[d];\n                        if (inBoard(wx, wy)) wall_[wx][wy] = true;\n                    }\n                }\n            }\n        }\n\n        // Read and apply pet movements.\n        for (int i = 0; i < N; i++) {\n            string s;\n            if (!(cin >> s)) return 0;\n\n            if (s == \".\") continue;\n\n            for (char c : s) {\n                if (c == 'U') pets[i].x--;\n                else if (c == 'D') pets[i].x++;\n                else if (c == 'L') pets[i].y--;\n                else if (c == 'R') pets[i].y++;\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int V = 400;\nstatic const int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble p_fail, p_succ;\nstring hwall[20], vwall[19];\n\nint start_id, target_id;\nint nxt_cell[4][V];\nint dist_to_t[V];\n\nfloat potential_value[MAXL + 1][V];\n\nconst string DIRS = \"UDLR\";\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos_of(int x) {\n    return {x / N, x % N};\n}\n\nint dir_id(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\nstruct Node {\n    array<float, V> prob;\n    double score;\n    double eval;\n    string path;\n};\n\nvoid build_graph() {\n    for (int x = 0; x < V; x++) {\n        auto [i, j] = pos_of(x);\n\n        if (i == 0 || vwall[i - 1][j] == '1') nxt_cell[0][x] = x;\n        else nxt_cell[0][x] = id(i - 1, j);\n\n        if (i == N - 1 || vwall[i][j] == '1') nxt_cell[1][x] = x;\n        else nxt_cell[1][x] = id(i + 1, j);\n\n        if (j == 0 || hwall[i][j - 1] == '1') nxt_cell[2][x] = x;\n        else nxt_cell[2][x] = id(i, j - 1);\n\n        if (j == N - 1 || hwall[i][j] == '1') nxt_cell[3][x] = x;\n        else nxt_cell[3][x] = id(i, j + 1);\n    }\n}\n\nvoid bfs_distance() {\n    const int INF = 1e9;\n    fill(dist_to_t, dist_to_t + V, INF);\n\n    queue<int> q;\n    dist_to_t[target_id] = 0;\n    q.push(target_id);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int to = nxt_cell[d][v];\n            if (to == v) continue;\n\n            if (dist_to_t[to] > dist_to_t[v] + 1) {\n                dist_to_t[to] = dist_to_t[v] + 1;\n                q.push(to);\n            }\n        }\n    }\n}\n\nvoid build_potential() {\n    static double hit_prob[MAXL + 1][MAXL + 1];\n    static double hit_ksum[MAXL + 1][MAXL + 1];\n\n    for (int rem = 0; rem <= MAXL; rem++) {\n        hit_prob[rem][0] = 1.0;\n        hit_ksum[rem][0] = 0.0;\n\n        for (int d = 1; d <= rem; d++) {\n            double pr = pow(p_succ, d);\n            double psum = 0.0;\n            double ksum = 0.0;\n\n            for (int k = d; k <= rem; k++) {\n                psum += pr;\n                ksum += pr * k;\n\n                if (k < rem) {\n                    pr *= (double)k / (double)(k - d + 1) * p_fail;\n                }\n            }\n\n            hit_prob[rem][d] = psum;\n            hit_ksum[rem][d] = ksum;\n        }\n    }\n\n    for (int t = 0; t <= MAXL; t++) {\n        int rem = MAXL - t;\n\n        for (int c = 0; c < V; c++) {\n            int d = dist_to_t[c];\n\n            if (d > rem || d > MAXL) {\n                potential_value[t][c] = 0.0f;\n                continue;\n            }\n\n            double nb = (401.0 - t) * hit_prob[rem][d] - hit_ksum[rem][d];\n\n            double mean = 401.0 - t - d / p_succ;\n            if (mean < 0.0) mean = 0.0;\n\n            // Mostly finite-horizon negative-binomial estimate,\n            // with a small optimistic mean-time component for beam diversity.\n            double val = 0.82 * nb + 0.18 * mean;\n\n            if (val < 0.0) val = 0.0;\n            potential_value[t][c] = (float)val;\n        }\n    }\n}\n\ndouble evaluate_string(const string& s) {\n    static double cur[V], nxt[V];\n\n    for (int i = 0; i < V; i++) cur[i] = 0.0;\n    cur[start_id] = 1.0;\n\n    double score = 0.0;\n\n    for (int t = 0; t < (int)s.size(); t++) {\n        int dir = dir_id(s[t]);\n\n        for (int i = 0; i < V; i++) nxt[i] = 0.0;\n\n        double arrive = 0.0;\n        double remain = 0.0;\n\n        for (int c = 0; c < V; c++) {\n            double pr = cur[c];\n            if (pr < 1e-18) continue;\n\n            int to = nxt_cell[dir][c];\n\n            if (to == target_id) {\n                arrive += pr * p_succ;\n                nxt[c] += pr * p_fail;\n            } else if (to == c) {\n                nxt[c] += pr;\n            } else {\n                nxt[c] += pr * p_fail;\n                nxt[to] += pr * p_succ;\n            }\n        }\n\n        score += arrive * (400 - t);\n\n        for (int i = 0; i < V; i++) {\n            cur[i] = nxt[i];\n            remain += cur[i];\n        }\n\n        if (remain < 1e-18) break;\n    }\n\n    return score;\n}\n\nstring beam_search() {\n    const int BEAM_WIDTH = 320;\n\n    vector<Node> beam;\n    beam.reserve(BEAM_WIDTH);\n\n    Node init;\n    init.prob.fill(0.0f);\n    init.prob[start_id] = 1.0f;\n    init.score = 0.0;\n    init.eval = potential_value[0][start_id];\n    init.path.clear();\n\n    beam.push_back(init);\n\n    for (int depth = 0; depth < MAXL; depth++) {\n        vector<Node> cand;\n        cand.reserve(beam.size() * 4);\n\n        for (const Node& par : beam) {\n            for (int dir = 0; dir < 4; dir++) {\n                Node ch;\n                ch.prob.fill(0.0f);\n\n                float arrive = 0.0f;\n\n                for (int c = 0; c < V; c++) {\n                    float pr = par.prob[c];\n                    if (pr < 1e-12f) continue;\n\n                    int to = nxt_cell[dir][c];\n\n                    if (to == target_id) {\n                        arrive += pr * (float)p_succ;\n                        ch.prob[c] += pr * (float)p_fail;\n                    } else if (to == c) {\n                        ch.prob[c] += pr;\n                    } else {\n                        ch.prob[c] += pr * (float)p_fail;\n                        ch.prob[to] += pr * (float)p_succ;\n                    }\n                }\n\n                int nt = depth + 1;\n                ch.score = par.score + arrive * (400 - depth);\n\n                double pot = 0.0;\n                for (int c = 0; c < V; c++) {\n                    float pr = ch.prob[c];\n                    if (pr < 1e-12f) continue;\n                    pot += pr * potential_value[nt][c];\n                }\n\n                ch.eval = ch.score + pot;\n                ch.path = par.path;\n                ch.path.push_back(DIRS[dir]);\n\n                cand.push_back(std::move(ch));\n            }\n        }\n\n        if ((int)cand.size() > BEAM_WIDTH) {\n            nth_element(\n                cand.begin(),\n                cand.begin() + BEAM_WIDTH,\n                cand.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            );\n            cand.resize(BEAM_WIDTH);\n        }\n\n        beam.swap(cand);\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)beam.size(); i++) {\n        if (beam[i].score > beam[best].score) best = i;\n    }\n\n    return beam[best].path;\n}\n\nstring shortest_path_by_order(const vector<int>& order) {\n    string res;\n    int cur = start_id;\n\n    while (cur != target_id && (int)res.size() < MAXL) {\n        bool moved = false;\n\n        for (int d : order) {\n            int to = nxt_cell[d][cur];\n            if (to != cur && dist_to_t[to] == dist_to_t[cur] - 1) {\n                res.push_back(DIRS[d]);\n                cur = to;\n                moved = true;\n                break;\n            }\n        }\n\n        if (!moved) break;\n    }\n\n    return res;\n}\n\nstring make_cycle_pattern(const string& base) {\n    string s;\n    if (base.empty()) return string(MAXL, 'D');\n\n    int k = 0;\n    while ((int)s.size() < MAXL) {\n        s.push_back(base[k]);\n        k++;\n        if (k == (int)base.size()) k = 0;\n    }\n\n    return s;\n}\n\nstring make_repeat_each_pattern(const string& base, int rep) {\n    string s;\n    if (base.empty()) return string(MAXL, 'D');\n\n    while ((int)s.size() < MAXL) {\n        for (char c : base) {\n            for (int r = 0; r < rep && (int)s.size() < MAXL; r++) {\n                s.push_back(c);\n            }\n            if ((int)s.size() >= MAXL) break;\n        }\n    }\n\n    return s;\n}\n\nvector<string> generate_path_candidates() {\n    vector<string> cand;\n\n    vector<int> perm = {0, 1, 2, 3};\n\n    sort(perm.begin(), perm.end());\n    do {\n        string p = shortest_path_by_order(perm);\n        if (p.empty()) continue;\n\n        cand.push_back(make_cycle_pattern(p));\n\n        for (int r = 2; r <= 6; r++) {\n            cand.push_back(make_repeat_each_pattern(p, r));\n        }\n    } while (next_permutation(perm.begin(), perm.end()));\n\n    return cand;\n}\n\nvoid local_improve(string& ans, chrono::steady_clock::time_point start_time) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    double best_score = evaluate_string(ans);\n\n    bool improved = true;\n\n    while (improved && elapsed() < 1.82) {\n        improved = false;\n\n        // Single-character replacement.\n        for (int p = 0; p < (int)ans.size(); p++) {\n            if (elapsed() > 1.86) break;\n\n            char orig = ans[p];\n            char best_char = orig;\n            double local_best = best_score;\n\n            for (char c : DIRS) {\n                if (c == orig) continue;\n\n                ans[p] = c;\n                double sc = evaluate_string(ans);\n\n                if (sc > local_best + 1e-11) {\n                    local_best = sc;\n                    best_char = c;\n                }\n            }\n\n            ans[p] = best_char;\n\n            if (best_char != orig) {\n                best_score = local_best;\n                improved = true;\n            }\n        }\n\n        // Adjacent swap.\n        for (int p = 0; p + 1 < (int)ans.size(); p++) {\n            if (elapsed() > 1.88) break;\n            if (ans[p] == ans[p + 1]) continue;\n\n            swap(ans[p], ans[p + 1]);\n            double sc = evaluate_string(ans);\n\n            if (sc > best_score + 1e-11) {\n                best_score = sc;\n                improved = true;\n            } else {\n                swap(ans[p], ans[p + 1]);\n            }\n        }\n    }\n\n    // Small stochastic 2-position improvement.\n    mt19937 rng(\n        1234567u\n        ^ (unsigned)(si_ * 100000 + sj_ * 10000 + ti_ * 1000 + tj_ * 100)\n        ^ (unsigned)(p_fail * 1000)\n    );\n\n    int iter = 0;\n    while (elapsed() < 1.92) {\n        iter++;\n\n        int a = rng() % ans.size();\n        int b = rng() % ans.size();\n        if (a == b) continue;\n\n        char oa = ans[a], ob = ans[b];\n\n        char na = DIRS[rng() % 4];\n        char nb = DIRS[rng() % 4];\n\n        if (na == oa && nb == ob) continue;\n\n        ans[a] = na;\n        ans[b] = nb;\n\n        double sc = evaluate_string(ans);\n\n        if (sc > best_score + 1e-11) {\n            best_score = sc;\n        } else {\n            ans[a] = oa;\n            ans[b] = ob;\n        }\n\n        if ((iter & 15) == 0 && elapsed() > 1.92) break;\n    }\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    cin >> si_ >> sj_ >> ti_ >> tj_ >> p_fail;\n    p_succ = 1.0 - p_fail;\n\n    for (int i = 0; i < 20; i++) cin >> hwall[i];\n    for (int i = 0; i < 19; i++) cin >> vwall[i];\n\n    start_id = id(si_, sj_);\n    target_id = id(ti_, tj_);\n\n    build_graph();\n    bfs_distance();\n    build_potential();\n\n    string ans = beam_search();\n    double best_score = evaluate_string(ans);\n\n    vector<string> candidates = generate_path_candidates();\n\n    for (const string& s : candidates) {\n        double sc = evaluate_string(s);\n        if (sc > best_score) {\n            best_score = sc;\n            ans = s;\n        }\n    }\n\n    local_improve(ans, start_time);\n\n    if ((int)ans.size() > MAXL) ans.resize(MAXL);\n\n    while ((int)ans.size() < MAXL) {\n        ans.push_back('D');\n    }\n\n    cout << ans << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int MAXP = 2000;\n\nstruct XorShift {\n    uint64_t x = chrono::steady_clock::now().time_since_epoch().count();\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n} rng;\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nconst int pieceCntOf[8] = {1,1,1,1,2,2,1,1};\n\nconst int A[8][2] = {\n    {0, -1},\n    {0, -1},\n    {2, -1},\n    {1, -1},\n    {0, 2},\n    {0, 1},\n    {0, -1},\n    {1, -1},\n};\n\nconst int B[8][2] = {\n    {1, -1},\n    {3, -1},\n    {3, -1},\n    {2, -1},\n    {1, 3},\n    {3, 2},\n    {2, -1},\n    {3, -1},\n};\n\nint parent_[MAXP], sz_[MAXP], open_[MAXP];\nint sidePid[V][4];\n\nint findp(int x) {\n    while (parent_[x] != x) {\n        parent_[x] = parent_[parent_[x]];\n        x = parent_[x];\n    }\n    return x;\n}\n\nvoid unite(int a, int b) {\n    int ra = findp(a), rb = findp(b);\n    if (ra == rb) return;\n    if (sz_[ra] < sz_[rb]) swap(ra, rb);\n    parent_[rb] = ra;\n    sz_[ra] += sz_[rb];\n}\n\nstruct Eval {\n    long long actual = 0;\n    int l1 = 0;\n    int l2 = 0;\n    double energy = 0;\n};\n\nEval evaluate(const uint8_t state[V]) {\n    for (int k = 0; k < V; k++) {\n        sidePid[k][0] = sidePid[k][1] = sidePid[k][2] = sidePid[k][3] = -1;\n    }\n\n    int pc = 0;\n\n    for (int k = 0; k < V; k++) {\n        int t = state[k];\n        int c = pieceCntOf[t];\n\n        for (int p = 0; p < c; p++) {\n            int id = pc++;\n            parent_[id] = id;\n            sz_[id] = 1;\n            open_[id] = 0;\n\n            int a = A[t][p];\n            int b = B[t][p];\n            sidePid[k][a] = id;\n            sidePid[k][b] = id;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            if (j + 1 < N) {\n                int a = sidePid[k][2];\n                int b = sidePid[k + 1][0];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n\n            if (i + 1 < N) {\n                int a = sidePid[k][3];\n                int b = sidePid[k + N][1];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            for (int d = 0; d < 4; d++) {\n                int id = sidePid[k][d];\n                if (id == -1) continue;\n\n                int ni = i + di[d];\n                int nj = j + dj[d];\n\n                bool bad = false;\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    bad = true;\n                } else {\n                    int nk = ni * N + nj;\n                    int od = (d + 2) & 3;\n                    if (sidePid[nk][od] == -1) bad = true;\n                }\n\n                if (bad) open_[findp(id)]++;\n            }\n        }\n    }\n\n    Eval res;\n    double potential = 0.0;\n\n    for (int id = 0; id < pc; id++) {\n        int r = findp(id);\n        if (r != id) continue;\n\n        int s = sz_[r];\n        int op = open_[r];\n\n        if (op == 0) {\n            if (s > res.l1) {\n                res.l2 = res.l1;\n                res.l1 = s;\n            } else if (s > res.l2) {\n                res.l2 = s;\n            }\n        } else {\n            potential += (double)s * s / (op + 1);\n        }\n    }\n\n    if (res.l2 > 0) res.actual = 1LL * res.l1 * res.l2;\n\n    res.energy =\n        50.0 * res.actual\n        + 2.0 * res.l1 * res.l1\n        + 4.0 * res.l2 * res.l2\n        + 0.80 * potential;\n\n    return res;\n}\n\nint rotateTile(int t, int r) {\n    if (t < 4) return (t + r) & 3;\n    if (t < 6) return 4 + ((t - 4 + r) & 1);\n    return 6 + ((t - 6 + r) & 1);\n}\n\nint outsideCountState(int k, int t) {\n    int i = k / N;\n    int j = k % N;\n\n    bool has[4] = {};\n    for (int p = 0; p < pieceCntOf[t]; p++) {\n        has[A[t][p]] = true;\n        has[B[t][p]] = true;\n    }\n\n    int cnt = 0;\n    for (int d = 0; d < 4; d++) {\n        if (!has[d]) continue;\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) cnt++;\n    }\n    return cnt;\n}\n\nint stateForPair(int base, int d1, int d2) {\n    if (d1 > d2) swap(d1, d2);\n\n    if (base >= 6) {\n        if (d1 == 0 && d2 == 2) return 6;\n        return 7;\n    }\n\n    bool dbl = (base >= 4);\n\n    int s = 0;\n    if (d1 == 0 && d2 == 1) s = 0;\n    else if (d1 == 0 && d2 == 3) s = 1;\n    else if (d1 == 2 && d2 == 3) s = 2;\n    else s = 3;\n\n    if (!dbl) return s;\n\n    if (s == 0 || s == 2) return 4;\n    return 5;\n}\n\nstruct Cycle {\n    vector<int> cells;\n    vector<uint8_t> states;\n    array<uint64_t, 15> mask{};\n    int len = 0;\n};\n\nbool disjointCycle(const Cycle& a, const Cycle& b) {\n    for (int i = 0; i < 15; i++) {\n        if (a.mask[i] & b.mask[i]) return false;\n    }\n    return true;\n}\n\nvoid buildMask(Cycle& c) {\n    c.mask.fill(0);\n    for (int k : c.cells) {\n        c.mask[k >> 6] |= 1ULL << (k & 63);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto timeStart = chrono::steady_clock::now();\n\n    string input[N];\n    for (int i = 0; i < N; i++) cin >> input[i];\n\n    uint8_t base[V];\n    int dom[V][4], domCnt[V];\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n            int t = input[i][j] - '0';\n            base[k] = t;\n\n            vector<int> states;\n            if (t < 4) states = {0, 1, 2, 3};\n            else if (t < 6) states = {4, 5};\n            else states = {6, 7};\n\n            bool border = (i == 0 || i == N - 1 || j == 0 || j == N - 1);\n\n            if (border) {\n                int bestOut = 100;\n                for (int s : states) bestOut = min(bestOut, outsideCountState(k, s));\n\n                vector<int> filtered;\n                for (int s : states) {\n                    if (outsideCountState(k, s) == bestOut) filtered.push_back(s);\n                }\n                states = filtered;\n            }\n\n            domCnt[k] = (int)states.size();\n            for (int x = 0; x < domCnt[k]; x++) dom[k][x] = states[x];\n        }\n    }\n\n    vector<Cycle> cycles;\n    cycles.reserve(1200);\n\n    static int posStamp[V * 4], posIdx[V * 4];\n    static int cellStamp[V];\n\n    int stamp = 1;\n\n    auto collectEnd = timeStart + chrono::milliseconds(330);\n\n    while (chrono::steady_clock::now() < collectEnd) {\n        stamp++;\n        if (stamp > 1000000000) {\n            memset(posStamp, 0, sizeof(posStamp));\n            memset(cellStamp, 0, sizeof(cellStamp));\n            stamp = 1;\n        }\n\n        int sk = rng.nextInt(V);\n        int sd = rng.nextInt(4);\n\n        vector<int> ks;\n        vector<int> ds;\n        vector<int> es;\n        ks.reserve(512);\n        ds.reserve(512);\n        es.reserve(512);\n\n        int k = sk;\n        int d = sd;\n\n        for (int step = 0; step < 1200; step++) {\n            int node = k * 4 + d;\n\n            if (posStamp[node] == stamp) break;\n\n            posStamp[node] = stamp;\n            posIdx[node] = (int)ks.size();\n            cellStamp[k] = stamp;\n\n            ks.push_back(k);\n            ds.push_back(d);\n\n            int t = base[k];\n\n            int cand[2];\n            int cc = 0;\n\n            if (t >= 6) {\n                cand[cc++] = (d + 2) & 3;\n            } else {\n                cand[cc++] = (d + 1) & 3;\n                cand[cc++] = (d + 3) & 3;\n                if (rng.nextInt(2)) swap(cand[0], cand[1]);\n            }\n\n            int chosen = -1;\n            int chosenNextK = -1;\n            int chosenNextD = -1;\n\n            for (int ci = 0; ci < cc; ci++) {\n                int e = cand[ci];\n                int ni = k / N + di[e];\n                int nj = k % N + dj[e];\n\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n\n                int nk = ni * N + nj;\n                int nd = (e + 2) & 3;\n                int nn = nk * 4 + nd;\n\n                if (posStamp[nn] == stamp) {\n                    int p = posIdx[nn];\n                    int len = (int)ks.size() - p;\n                    if (len >= 8) {\n                        chosen = e;\n                        chosenNextK = nk;\n                        chosenNextD = nd;\n                        break;\n                    }\n                }\n\n                if (cellStamp[nk] == stamp) continue;\n\n                if (chosen == -1 || rng.nextInt(2)) {\n                    chosen = e;\n                    chosenNextK = nk;\n                    chosenNextD = nd;\n                }\n            }\n\n            if (chosen == -1) break;\n\n            es.push_back(chosen);\n\n            int nextNode = chosenNextK * 4 + chosenNextD;\n\n            if (posStamp[nextNode] == stamp) {\n                int p = posIdx[nextNode];\n                int q = (int)ks.size();\n                int len = q - p;\n\n                if (len >= 8) {\n                    Cycle c;\n                    c.len = len;\n                    c.cells.reserve(len);\n                    c.states.reserve(len);\n\n                    bool ok = true;\n                    static int usedCell[V];\n                    static int usedStamp = 1;\n                    usedStamp++;\n\n                    for (int idx = p; idx < q; idx++) {\n                        int ck = ks[idx];\n                        if (usedCell[ck] == usedStamp) {\n                            ok = false;\n                            break;\n                        }\n                        usedCell[ck] = usedStamp;\n\n                        int cd = ds[idx];\n                        int ce = es[idx];\n                        int cb = base[ck];\n\n                        if (cb >= 6) {\n                            if (((cd + 2) & 3) != ce) {\n                                ok = false;\n                                break;\n                            }\n                        } else {\n                            if (((cd + 2) & 3) == ce || cd == ce) {\n                                ok = false;\n                                break;\n                            }\n                        }\n\n                        c.cells.push_back(ck);\n                        c.states.push_back((uint8_t)stateForPair(cb, cd, ce));\n                    }\n\n                    if (ok) {\n                        buildMask(c);\n\n                        if ((int)cycles.size() < 1000) {\n                            cycles.push_back(std::move(c));\n                        } else {\n                            int mn = 0;\n                            for (int x = 1; x < (int)cycles.size(); x++) {\n                                if (cycles[x].len < cycles[mn].len) mn = x;\n                            }\n                            if (c.len > cycles[mn].len) cycles[mn] = std::move(c);\n                        }\n                    }\n                }\n\n                break;\n            }\n\n            k = chosenNextK;\n            d = chosenNextD;\n        }\n    }\n\n    uint8_t cur[V], best[V], startState[V];\n\n    Eval bestEval;\n    bestEval.actual = -1;\n\n    Eval bestEnergyEval;\n    bestEnergyEval.energy = -1e100;\n\n    auto registerCandidate = [&](const uint8_t s[V]) {\n        Eval ev = evaluate(s);\n\n        if (ev.energy > bestEnergyEval.energy) {\n            bestEnergyEval = ev;\n            memcpy(startState, s, V);\n        }\n\n        if (\n            ev.actual > bestEval.actual ||\n            (ev.actual == bestEval.actual && ev.energy > bestEval.energy)\n        ) {\n            bestEval = ev;\n            memcpy(best, s, V);\n        }\n    };\n\n    for (int k = 0; k < V; k++) {\n        cur[k] = dom[k][rng.nextInt(domCnt[k])];\n    }\n\n    if (!cycles.empty()) {\n        int bi = -1, bj = -1;\n        long long bp = -1;\n\n        for (int i = 0; i < (int)cycles.size(); i++) {\n            for (int j = i + 1; j < (int)cycles.size(); j++) {\n                if (!disjointCycle(cycles[i], cycles[j])) continue;\n\n                long long p = 1LL * cycles[i].len * cycles[j].len;\n                if (p > bp) {\n                    bp = p;\n                    bi = i;\n                    bj = j;\n                }\n            }\n        }\n\n        if (bi != -1) {\n            for (int k = 0; k < V; k++) {\n                cur[k] = dom[k][rng.nextInt(domCnt[k])];\n            }\n\n            for (int x = 0; x < cycles[bi].len; x++) {\n                cur[cycles[bi].cells[x]] = cycles[bi].states[x];\n            }\n            for (int x = 0; x < cycles[bj].len; x++) {\n                cur[cycles[bj].cells[x]] = cycles[bj].states[x];\n            }\n\n            registerCandidate(cur);\n        }\n\n        sort(cycles.begin(), cycles.end(), [](const Cycle& a, const Cycle& b) {\n            return a.len > b.len;\n        });\n\n        int lim = min<int>(30, cycles.size());\n        for (int cidx = 0; cidx < lim; cidx++) {\n            for (int k = 0; k < V; k++) {\n                cur[k] = dom[k][rng.nextInt(domCnt[k])];\n            }\n\n            for (int x = 0; x < cycles[cidx].len; x++) {\n                cur[cycles[cidx].cells[x]] = cycles[cidx].states[x];\n            }\n\n            registerCandidate(cur);\n        }\n    }\n\n    constexpr int INIT_TRIALS = 700;\n\n    for (int tr = 0; tr < INIT_TRIALS; tr++) {\n        for (int k = 0; k < V; k++) {\n            cur[k] = dom[k][rng.nextInt(domCnt[k])];\n        }\n        registerCandidate(cur);\n    }\n\n    memcpy(cur, startState, V);\n    Eval curEval = evaluate(cur);\n\n    const double TL = 1.93;\n    const double T0 = 2500.0;\n    const double T1 = 1.0;\n\n    double temp = T0;\n    int iter = 0;\n\n    while (true) {\n        iter++;\n\n        if ((iter & 511) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - timeStart).count();\n            if (elapsed >= TL) break;\n\n            double progress = elapsed / TL;\n            temp = T0 * pow(T1 / T0, progress);\n        }\n\n        int m = 1;\n        int r = rng.nextInt(100);\n        if (r < 8) m = 2;\n        if (r == 0) m = 3;\n\n        int pos[3];\n        uint8_t oldVal[3];\n\n        bool okMove = true;\n\n        for (int x = 0; x < m; x++) {\n            int k = -1;\n\n            for (int tries = 0; tries < 50; tries++) {\n                int cand = rng.nextInt(V);\n                if (domCnt[cand] <= 1) continue;\n\n                bool used = false;\n                for (int y = 0; y < x; y++) {\n                    if (pos[y] == cand) used = true;\n                }\n\n                if (!used) {\n                    k = cand;\n                    break;\n                }\n            }\n\n            if (k == -1) {\n                okMove = false;\n                break;\n            }\n\n            pos[x] = k;\n            oldVal[x] = cur[k];\n\n            int nd;\n            do {\n                nd = dom[k][rng.nextInt(domCnt[k])];\n            } while (nd == cur[k]);\n\n            cur[k] = nd;\n        }\n\n        if (!okMove) {\n            for (int x = 0; x < m; x++) cur[pos[x]] = oldVal[x];\n            continue;\n        }\n\n        Eval ne = evaluate(cur);\n        double diff = ne.energy - curEval.energy;\n\n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double p = exp(diff / temp);\n            if (rng.nextDouble() < p) accept = true;\n        }\n\n        if (\n            ne.actual > bestEval.actual ||\n            (ne.actual == bestEval.actual && ne.energy > bestEval.energy)\n        ) {\n            bestEval = ne;\n            memcpy(best, cur, V);\n        }\n\n        if (accept) {\n            curEval = ne;\n        } else {\n            for (int x = 0; x < m; x++) cur[pos[x]] = oldVal[x];\n        }\n    }\n\n    string ans;\n    ans.reserve(V);\n\n    for (int k = 0; k < V; k++) {\n        int b = base[k];\n        int target = best[k];\n\n        int rr = 0;\n        for (int r = 0; r < 4; r++) {\n            if (rotateTile(b, r) == target) {\n                rr = r;\n                break;\n            }\n        }\n\n        ans.push_back(char('0' + rr));\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint N, T, M, FULLV;\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nint hexval(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nchar move_char_from_blank_to_tile(int blank, int tile) {\n    if (tile == blank - N) return 'U';\n    if (tile == blank + N) return 'D';\n    if (tile == blank - 1) return 'L';\n    return 'R';\n}\n\nint move_blank_pos(int blank, char c) {\n    if (c == 'U') return blank - N;\n    if (c == 'D') return blank + N;\n    if (c == 'L') return blank - 1;\n    return blank + 1;\n}\n\nbool legal_move(int blank, char c) {\n    int r = blank / N, col = blank % N;\n    if (c == 'U') return r > 0;\n    if (c == 'D') return r + 1 < N;\n    if (c == 'L') return col > 0;\n    return col + 1 < N;\n}\n\nvoid apply_move(array<unsigned char, 100>& b, int& blank, char c) {\n    int nb = move_blank_pos(blank, c);\n    swap(b[blank], b[nb]);\n    blank = nb;\n}\n\nstruct Eval {\n    int s;\n    int maxComp;\n    int cyc;\n};\n\nstruct DSU {\n    int p[100], sz[100], ed[100];\n\n    void init(const array<unsigned char, 100>& b, int M) {\n        for (int i = 0; i < M; i++) {\n            if (b[i]) {\n                p[i] = i;\n                sz[i] = 1;\n                ed[i] = 0;\n            } else {\n                p[i] = -1;\n                sz[i] = 0;\n                ed[i] = 0;\n            }\n        }\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    void add_edge(int a, int b) {\n        int ra = find(a), rb = find(b);\n        if (ra == rb) {\n            ed[ra]++;\n            return;\n        }\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        ed[ra] += ed[rb] + 1;\n    }\n};\n\nEval eval_board(const array<unsigned char, 100>& b) {\n    DSU d;\n    d.init(b, M);\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            if (b[p] == 0) continue;\n\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) d.add_edge(p, p + 1);\n            }\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) d.add_edge(p, p + N);\n            }\n        }\n    }\n\n    Eval ev{0, 0, 0};\n    for (int i = 0; i < M; i++) {\n        if (b[i] == 0) continue;\n        if (d.find(i) != i) continue;\n        ev.maxComp = max(ev.maxComp, d.sz[i]);\n        if (d.ed[i] == d.sz[i] - 1) ev.s = max(ev.s, d.sz[i]);\n        else if (d.ed[i] >= d.sz[i]) ev.cyc += d.ed[i] - d.sz[i] + 1;\n    }\n    return ev;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                            Target reconstruction                            */\n/* -------------------------------------------------------------------------- */\n\nstruct Edge {\n    int a, b;\n    int ba, bb;\n};\n\nint dir_bit(int from, int to) {\n    if (to == from - 1) return 1;\n    if (to == from - N) return 2;\n    if (to == from + 1) return 4;\n    return 8;\n}\n\nstruct ReconState {\n    vector<int> mask;\n    vector<int> cnt;\n    vector<char> tree;\n    vector<vector<pair<int,int>>> adj;\n    int diff;\n};\n\nvoid adj_add(vector<vector<pair<int,int>>>& adj, int u, int v, int eid) {\n    adj[u].push_back({v, eid});\n    adj[v].push_back({u, eid});\n}\n\nvoid adj_remove(vector<vector<pair<int,int>>>& adj, int u, int v, int eid) {\n    auto erase_one = [&](int x, int y) {\n        auto& vec = adj[x];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i].first == y && vec[i].second == eid) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n    erase_one(u, v);\n    erase_one(v, u);\n}\n\nstruct SmallDSU {\n    vector<int> p, sz;\n    SmallDSU(int n=0): p(n), sz(n,1) {\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nbool reconstruct_target(\n    const vector<int>& targetCnt,\n    array<unsigned char, 100>& target,\n    double time_limit\n) {\n    int emptyPos = M - 1;\n\n    vector<int> posToVid(M, -1), vidToPos;\n    for (int p = 0; p < M; p++) {\n        if (p == emptyPos) continue;\n        posToVid[p] = (int)vidToPos.size();\n        vidToPos.push_back(p);\n    }\n\n    int V = (int)vidToPos.size();\n    vector<Edge> edges;\n\n    for (int p = 0; p < M; p++) {\n        if (p == emptyPos) continue;\n        int r = p / N, c = p % N;\n        if (c + 1 < N && p + 1 != emptyPos) {\n            int q = p + 1;\n            edges.push_back({posToVid[p], posToVid[q], dir_bit(p, q), dir_bit(q, p)});\n        }\n        if (r + 1 < N && p + N != emptyPos) {\n            int q = p + N;\n            edges.push_back({posToVid[p], posToVid[q], dir_bit(p, q), dir_bit(q, p)});\n        }\n    }\n\n    int E = edges.size();\n    mt19937 rng(712367821);\n\n    auto calc_diff = [&](const vector<int>& cnt) {\n        int d = 0;\n        for (int i = 0; i < 16; i++) d += abs(cnt[i] - targetCnt[i]);\n        return d;\n    };\n\n    auto build_random_tree = [&]() {\n        ReconState st;\n        st.mask.assign(V, 0);\n        st.cnt.assign(16, 0);\n        st.tree.assign(E, 0);\n        st.adj.assign(V, {});\n\n        vector<int> ord(E);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n\n        SmallDSU dsu(V);\n        int used = 0;\n        for (int id : ord) {\n            auto &e = edges[id];\n            if (dsu.unite(e.a, e.b)) {\n                st.tree[id] = 1;\n                st.mask[e.a] |= e.ba;\n                st.mask[e.b] |= e.bb;\n                adj_add(st.adj, e.a, e.b, id);\n                used++;\n                if (used == V - 1) break;\n            }\n        }\n\n        for (int x : st.mask) st.cnt[x]++;\n        st.diff = calc_diff(st.cnt);\n        return st;\n    };\n\n    ReconState best;\n    best.diff = 1e9;\n\n    while (elapsed_sec() < time_limit) {\n        ReconState st = build_random_tree();\n        if (st.diff < best.diff) best = st;\n        if (st.diff == 0) {\n            best = st;\n            break;\n        }\n\n        double restart_start = elapsed_sec();\n\n        while (elapsed_sec() < time_limit) {\n            double t01 = (elapsed_sec() - restart_start) / max(0.001, time_limit - restart_start);\n            double temp = 4.0 * (1.0 - t01) + 0.05 * t01;\n\n            int addId = -1;\n            for (int tries = 0; tries < 20; tries++) {\n                int id = rng() % E;\n                if (!st.tree[id]) {\n                    addId = id;\n                    break;\n                }\n            }\n            if (addId == -1) continue;\n\n            int s = edges[addId].a, g = edges[addId].b;\n\n            vector<int> par(V, -1), parEdge(V, -1);\n            queue<int> q;\n            q.push(s);\n            par[s] = s;\n\n            while (!q.empty() && par[g] == -1) {\n                int v = q.front(); q.pop();\n                for (auto [to, eid] : st.adj[v]) {\n                    if (par[to] == -1) {\n                        par[to] = v;\n                        parEdge[to] = eid;\n                        q.push(to);\n                    }\n                }\n            }\n\n            vector<int> pathEdges;\n            int cur = g;\n            while (cur != s) {\n                pathEdges.push_back(parEdge[cur]);\n                cur = par[cur];\n            }\n\n            int remId = pathEdges[rng() % pathEdges.size()];\n\n            vector<int> nmask = st.mask;\n            auto &ae = edges[addId];\n            auto &re = edges[remId];\n\n            nmask[ae.a] |= ae.ba;\n            nmask[ae.b] |= ae.bb;\n            nmask[re.a] &= ~re.ba;\n            nmask[re.b] &= ~re.bb;\n\n            int ndiff = st.diff;\n            int affected[4] = {ae.a, ae.b, re.a, re.b};\n            sort(affected, affected + 4);\n            int len = unique(affected, affected + 4) - affected;\n\n            vector<int> ncnt = st.cnt;\n            for (int i = 0; i < len; i++) {\n                int v = affected[i];\n                int oldm = st.mask[v];\n                int newm = nmask[v];\n                if (oldm == newm) continue;\n\n                ndiff -= abs(ncnt[oldm] - targetCnt[oldm]);\n                ncnt[oldm]--;\n                ndiff += abs(ncnt[oldm] - targetCnt[oldm]);\n\n                ndiff -= abs(ncnt[newm] - targetCnt[newm]);\n                ncnt[newm]++;\n                ndiff += abs(ncnt[newm] - targetCnt[newm]);\n            }\n\n            bool accept = false;\n            if (ndiff <= st.diff) accept = true;\n            else {\n                double prob = exp((double)(st.diff - ndiff) / temp);\n                double rr = (double)rng() / (double)UINT_MAX;\n                if (rr < prob) accept = true;\n            }\n\n            if (accept) {\n                st.diff = ndiff;\n                st.mask.swap(nmask);\n                st.cnt.swap(ncnt);\n\n                st.tree[addId] = 1;\n                st.tree[remId] = 0;\n                adj_add(st.adj, ae.a, ae.b, addId);\n                adj_remove(st.adj, re.a, re.b, remId);\n\n                if (st.diff < best.diff) best = st;\n                if (st.diff == 0) {\n                    best = st;\n                    goto reconstruction_done;\n                }\n            }\n        }\n    }\n\nreconstruction_done:\n    if (best.diff != 0) return false;\n\n    target.fill(0);\n    target[emptyPos] = 0;\n    for (int v = 0; v < V; v++) {\n        target[vidToPos[v]] = (unsigned char)best.mask[v];\n    }\n    return true;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                              Sliding solver                                 */\n/* -------------------------------------------------------------------------- */\n\nvector<int> neighbors_of(int p) {\n    vector<int> ns;\n    int r = p / N, c = p % N;\n    if (r > 0) ns.push_back(p - N);\n    if (r + 1 < N) ns.push_back(p + N);\n    if (c > 0) ns.push_back(p - 1);\n    if (c + 1 < N) ns.push_back(p + 1);\n    return ns;\n}\n\nbool place_one_tile(\n    array<unsigned char, 100>& board,\n    int& blank,\n    const array<unsigned char, 100>& target,\n    vector<char>& fixed,\n    int pos,\n    string& ans\n) {\n    int val = target[pos];\n    if (board[pos] == val) {\n        fixed[pos] = 1;\n        return true;\n    }\n\n    int total = M * M;\n    vector<int> pre(total, -2);\n    vector<char> prem(total, 0);\n    queue<int> q;\n\n    for (int p = 0; p < M; p++) {\n        if (fixed[p]) continue;\n        if (board[p] == val && p != blank) {\n            int id = p * M + blank;\n            pre[id] = -1;\n            q.push(id);\n        }\n    }\n\n    int goal = -1;\n\n    while (!q.empty()) {\n        int id = q.front(); q.pop();\n        int tile = id / M;\n        int z = id % M;\n\n        if (tile == pos) {\n            goal = id;\n            break;\n        }\n\n        for (int nb : neighbors_of(z)) {\n            if (fixed[nb]) continue;\n\n            int ntile = tile;\n            if (nb == tile) ntile = z;\n            int nz = nb;\n\n            int nid = ntile * M + nz;\n            if (pre[nid] != -2) continue;\n\n            pre[nid] = id;\n            prem[nid] = move_char_from_blank_to_tile(z, nb);\n            q.push(nid);\n        }\n    }\n\n    if (goal == -1) return false;\n\n    string path;\n    int cur = goal;\n    while (pre[cur] != -1) {\n        path.push_back(prem[cur]);\n        cur = pre[cur];\n    }\n    reverse(path.begin(), path.end());\n\n    for (char c : path) {\n        if (!legal_move(blank, c)) return false;\n        apply_move(board, blank, c);\n        ans.push_back(c);\n        if ((int)ans.size() > T) return false;\n    }\n\n    if (board[pos] != val) return false;\n    fixed[pos] = 1;\n    return true;\n}\n\nuint64_t encode9(const array<unsigned char, 100>& b, const vector<int>& cells) {\n    uint64_t x = 0;\n    for (int i = 0; i < 9; i++) {\n        x |= (uint64_t)b[cells[i]] << (4 * i);\n    }\n    return x;\n}\n\nint zero_index9(uint64_t x) {\n    for (int i = 0; i < 9; i++) {\n        if (((x >> (4 * i)) & 15) == 0) return i;\n    }\n    return -1;\n}\n\nuint64_t swap_nibble(uint64_t x, int a, int b) {\n    uint64_t va = (x >> (4 * a)) & 15;\n    uint64_t vb = (x >> (4 * b)) & 15;\n    x &= ~(15ULL << (4 * a));\n    x &= ~(15ULL << (4 * b));\n    x |= va << (4 * b);\n    x |= vb << (4 * a);\n    return x;\n}\n\nbool solve_final_3x3(\n    array<unsigned char, 100>& board,\n    int& blank,\n    const array<unsigned char, 100>& target,\n    string& ans\n) {\n    vector<int> cells;\n    for (int r = N - 3; r < N; r++) {\n        for (int c = N - 3; c < N; c++) {\n            cells.push_back(r * N + c);\n        }\n    }\n\n    int blankIdx = -1;\n    for (int i = 0; i < 9; i++) {\n        if (cells[i] == blank) blankIdx = i;\n    }\n    if (blankIdx == -1) return false;\n\n    uint64_t start = encode9(board, cells);\n    uint64_t goal = encode9(target, cells);\n    if (start == goal) return true;\n\n    unordered_map<uint64_t, pair<uint64_t, char>> pre;\n    pre.reserve(400000);\n\n    queue<uint64_t> q;\n    q.push(start);\n    pre[start] = {UINT64_MAX, 0};\n\n    uint64_t found = 0;\n    bool ok = false;\n\n    while (!q.empty()) {\n        uint64_t x = q.front(); q.pop();\n        int zi = zero_index9(x);\n        int zr = zi / 3, zc = zi % 3;\n\n        const int dr[4] = {-1, 1, 0, 0};\n        const int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = zr + dr[k], nc = zc + dc[k];\n            if (nr < 0 || nr >= 3 || nc < 0 || nc >= 3) continue;\n\n            int ni = nr * 3 + nc;\n            uint64_t y = swap_nibble(x, zi, ni);\n            if (pre.count(y)) continue;\n\n            char mv = move_char_from_blank_to_tile(cells[zi], cells[ni]);\n            pre[y] = {x, mv};\n\n            if (y == goal) {\n                found = y;\n                ok = true;\n                while (!q.empty()) q.pop();\n                break;\n            }\n            q.push(y);\n        }\n    }\n\n    if (!ok) return false;\n\n    string path;\n    uint64_t cur = found;\n    while (pre[cur].first != UINT64_MAX) {\n        path.push_back(pre[cur].second);\n        cur = pre[cur].first;\n    }\n    reverse(path.begin(), path.end());\n\n    for (char c : path) {\n        if (!legal_move(blank, c)) return false;\n        apply_move(board, blank, c);\n        ans.push_back(c);\n        if ((int)ans.size() > T) return false;\n    }\n\n    return true;\n}\n\nbool solve_to_target(\n    const array<unsigned char, 100>& init,\n    const array<unsigned char, 100>& target,\n    int initBlank,\n    string& ans\n) {\n    array<unsigned char, 100> board = init;\n    int blank = initBlank;\n    vector<char> fixed(M, 0);\n    ans.clear();\n\n    vector<int> order;\n\n    for (int r = 0; r < N - 3; r++) {\n        for (int c = 0; c < N; c++) {\n            order.push_back(r * N + c);\n        }\n    }\n    for (int r = N - 3; r < N; r++) {\n        for (int c = 0; c < N - 3; c++) {\n            order.push_back(r * N + c);\n        }\n    }\n\n    for (int p : order) {\n        if (!place_one_tile(board, blank, target, fixed, p, ans)) return false;\n        if ((int)ans.size() > T) return false;\n    }\n\n    if (!solve_final_3x3(board, blank, target, ans)) return false;\n    if ((int)ans.size() > T) return false;\n\n    Eval ev = eval_board(board);\n    return ev.s == FULLV;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                                Beam fallback                                */\n/* -------------------------------------------------------------------------- */\n\null zob[100][16];\n\ninline bool edge_adj(const array<unsigned char, 100>& b, int x, int y) {\n    if (y == x - 1) return (b[x] & 1) && (b[y] & 4);\n    if (y == x + 1) return (b[x] & 4) && (b[y] & 1);\n    if (y == x - N) return (b[x] & 2) && (b[y] & 8);\n    if (y == x + N) return (b[x] & 8) && (b[y] & 2);\n    return false;\n}\n\nint local_edges(const array<unsigned char, 100>& b, int a, int c) {\n    int cells[2] = {a, c};\n    int keys[8];\n    int kc = 0;\n    int res = 0;\n\n    for (int ii = 0; ii < 2; ii++) {\n        int x = cells[ii];\n        for (int y : neighbors_of(x)) {\n            int u = min(x, y), v = max(x, y);\n            int key = u * 100 + v;\n\n            bool seen = false;\n            for (int t = 0; t < kc; t++) {\n                if (keys[t] == key) {\n                    seen = true;\n                    break;\n                }\n            }\n            if (seen) continue;\n\n            keys[kc++] = key;\n            if (edge_adj(b, x, y)) res++;\n        }\n    }\n    return res;\n}\n\nint total_edges(const array<unsigned char, 100>& b) {\n    int e = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            if (b[p] == 0) continue;\n            if (c + 1 < N && b[p + 1] != 0 && ((b[p] & 4) && (b[p + 1] & 1))) e++;\n            if (r + 1 < N && b[p + N] != 0 && ((b[p] & 8) && (b[p + N] & 2))) e++;\n        }\n    }\n    return e;\n}\n\nstruct Node {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    unsigned char prev;\n    ull hash;\n};\n\nstruct Cand {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    short maxComp;\n    short cyc;\n    unsigned char prev;\n    ull hash;\n    long long h;\n};\n\nchar inv_move(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return 0;\n}\n\nstring restore_path(const vector<Node>& pool, int idx) {\n    string res;\n    while (pool[idx].parent != -1) {\n        res.push_back((char)pool[idx].prev);\n        idx = pool[idx].parent;\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nstring beam_fallback(const array<unsigned char, 100>& init, int initBlank, ull initHash) {\n    int W;\n    if (N == 6) W = 2600;\n    else if (N == 7) W = 1850;\n    else if (N == 8) W = 1250;\n    else if (N == 9) W = 850;\n    else W = 600;\n\n    vector<Node> pool;\n    pool.reserve((size_t)W * min(T + 2, 700));\n\n    Node root;\n    root.b = init;\n    root.parent = -1;\n    root.blank = initBlank;\n    root.e = total_edges(init);\n    root.prev = 0;\n    root.hash = initHash;\n\n    Eval rootEv = eval_board(init);\n    root.s = rootEv.s;\n\n    pool.push_back(root);\n\n    if (rootEv.s == FULLV) return \"\";\n\n    vector<int> beam{0};\n    int bestIdx = 0;\n    int bestS = rootEv.s;\n\n    const char mvChar[4] = {'U', 'D', 'L', 'R'};\n\n    for (int step = 1; step <= T; step++) {\n        if (elapsed_sec() > 2.86) break;\n\n        vector<Cand> cand;\n        cand.reserve(beam.size() * 3 + 10);\n\n        for (int idx : beam) {\n            const Node& nd = pool[idx];\n            int z = nd.blank;\n\n            for (int dir = 0; dir < 4; dir++) {\n                char mc = mvChar[dir];\n                if (nd.prev && inv_move((char)nd.prev) == mc) continue;\n                if (!legal_move(z, mc)) continue;\n\n                int nz = move_blank_pos(z, mc);\n\n                Cand x;\n                x.b = nd.b;\n\n                int before = local_edges(x.b, z, nz);\n\n                unsigned char tile = x.b[nz];\n                x.b[z] = tile;\n                x.b[nz] = 0;\n\n                int after = local_edges(x.b, z, nz);\n\n                x.e = nd.e - before + after;\n                x.parent = idx;\n                x.blank = nz;\n                x.prev = (unsigned char)mc;\n                x.s = 0;\n                x.maxComp = 0;\n                x.cyc = 0;\n\n                ull h = nd.hash;\n                h ^= zob[z][0];\n                h ^= zob[nz][tile];\n                h ^= zob[z][tile];\n                h ^= zob[nz][0];\n                x.hash = h;\n\n                cand.push_back(std::move(x));\n            }\n        }\n\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.hash != b.hash) return a.hash < b.hash;\n            return a.e > b.e;\n        });\n\n        int write = 0;\n        for (int i = 0; i < (int)cand.size();) {\n            int j = i + 1;\n            int best = i;\n            while (j < (int)cand.size() && cand[j].hash == cand[i].hash) {\n                if (cand[j].e > cand[best].e) best = j;\n                j++;\n            }\n            cand[write++] = std::move(cand[best]);\n            i = j;\n        }\n        cand.resize(write);\n\n        int preLimit = min((int)cand.size(), max(W, 3 * W / 2));\n        if ((int)cand.size() > preLimit) {\n            nth_element(cand.begin(), cand.begin() + preLimit, cand.end(),\n                [](const Cand& a, const Cand& b) {\n                    return a.e > b.e;\n                });\n            cand.resize(preLimit);\n        }\n\n        for (Cand& x : cand) {\n            Eval ev = eval_board(x.b);\n            x.s = ev.s;\n            x.maxComp = ev.maxComp;\n            x.cyc = ev.cyc;\n\n            x.h = 0;\n            x.h += 120000LL * x.s;\n            x.h += 1200LL * x.s * x.s;\n            x.h += 8500LL * x.e;\n            x.h += 900LL * x.maxComp;\n            x.h -= 18000LL * x.cyc;\n            x.h += (long long)(x.hash & 2047ULL);\n\n            if (x.s > bestS) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n                pool.push_back(tmp);\n                bestIdx = (int)pool.size() - 1;\n                bestS = x.s;\n            }\n\n            if (x.s == FULLV) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n                pool.push_back(tmp);\n                return restore_path(pool, (int)pool.size() - 1);\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.h != b.h) return a.h > b.h;\n            return a.e > b.e;\n        });\n\n        int keep = min(W, (int)cand.size());\n        vector<int> nextBeam;\n        nextBeam.reserve(keep);\n\n        for (int i = 0; i < keep; i++) {\n            Node nd;\n            nd.b = cand[i].b;\n            nd.parent = cand[i].parent;\n            nd.blank = cand[i].blank;\n            nd.e = cand[i].e;\n            nd.s = cand[i].s;\n            nd.prev = cand[i].prev;\n            nd.hash = cand[i].hash;\n\n            pool.push_back(nd);\n            int ni = (int)pool.size() - 1;\n            nextBeam.push_back(ni);\n\n            if (nd.s > bestS) {\n                bestS = nd.s;\n                bestIdx = ni;\n            }\n        }\n\n        beam.swap(nextBeam);\n    }\n\n    return restore_path(pool, bestIdx);\n}\n\n/* -------------------------------------------------------------------------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    cin >> N >> T;\n    M = N * N;\n    FULLV = M - 1;\n\n    mt19937_64 rng(123456789);\n    for (int i = 0; i < 100; i++) {\n        for (int v = 0; v < 16; v++) {\n            zob[i][v] = rng();\n        }\n    }\n\n    array<unsigned char, 100> init{};\n    int initBlank = -1;\n    ull initHash = 0;\n\n    vector<int> targetCnt(16, 0);\n\n    for (int r = 0; r < N; r++) {\n        string s;\n        cin >> s;\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            int v = hexval(s[c]);\n            init[p] = (unsigned char)v;\n            if (v == 0) initBlank = p;\n            else targetCnt[v]++;\n            initHash ^= zob[p][v];\n        }\n    }\n\n    array<unsigned char, 100> target{};\n    double reconLimit = 0.78;\n    if (N >= 9) reconLimit = 0.92;\n\n    if (reconstruct_target(targetCnt, target, reconLimit)) {\n        string sol;\n        if (solve_to_target(init, target, initBlank, sol)) {\n            if ((int)sol.size() <= T) {\n                cout << sol << '\\n';\n                return 0;\n            }\n        }\n    }\n\n    string ans = beam_fallback(init, initBlank, initHash);\n    if ((int)ans.size() > T) ans.resize(T);\n    cout << ans << '\\n';\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Line {\n    double a, b, c; // a*x + b*y = c, (a,b) approximately unit normal\n};\n\nstruct EvalResult {\n    int matched;\n    int diff;\n    array<int, 11> hist;\n    long long value() const {\n        return 100000LL * matched - diff;\n    }\n};\n\nstruct GridCand {\n    double theta;\n    vector<double> cu, cv;\n    long long val;\n};\n\nstruct Key {\n    uint64_t lo, hi;\n    bool operator==(const Key& o) const { return lo == o.lo && hi == o.hi; }\n};\n\nstruct KeyHash {\n    size_t operator()(const Key& k) const {\n        uint64_t x = k.lo ^ (k.hi + 0x9e3779b97f4a7c15ULL + (k.lo << 6) + (k.lo >> 2));\n        x ^= x >> 30;\n        x *= 0xbf58476d1ce4e5b9ULL;\n        x ^= x >> 27;\n        x *= 0x94d049bb133111ebULL;\n        x ^= x >> 31;\n        return (size_t)x;\n    }\n};\n\nstatic const double PI = acos(-1.0);\nstatic const double R = 10000.0;\n\nint N, K;\narray<int, 11> targetA;\nvector<Point> pts;\nchrono::steady_clock::time_point st;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n}\n\nEvalResult make_eval_from_hist(const array<int, 11>& hist) {\n    EvalResult res;\n    res.hist = hist;\n    res.matched = 0;\n    res.diff = 0;\n    for (int d = 1; d <= 10; d++) {\n        res.matched += min(targetA[d], hist[d]);\n        res.diff += abs(targetA[d] - hist[d]);\n    }\n    return res;\n}\n\nEvalResult eval_grid(double theta, const vector<double>& cu, const vector<double>& cv) {\n    int gx = (int)cu.size() + 1;\n    int gy = (int)cv.size() + 1;\n    vector<int> cnt(gx * gy, 0);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double u = p.x * cs + p.y * sn;\n        double v = -p.x * sn + p.y * cs;\n        int ix = int(upper_bound(cu.begin(), cu.end(), u) - cu.begin());\n        int iy = int(upper_bound(cv.begin(), cv.end(), v) - cv.begin());\n        cnt[ix * gy + iy]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n    for (int c : cnt) {\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n    return make_eval_from_hist(hist);\n}\n\nEvalResult eval_lines(const vector<Line>& lines) {\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(pts.size() * 2);\n\n    int L = (int)lines.size();\n    for (const auto& p : pts) {\n        uint64_t lo = 0, hi = 0;\n        for (int i = 0; i < L; i++) {\n            double v = lines[i].a * p.x + lines[i].b * p.y - lines[i].c;\n            if (v > 0) {\n                if (i < 64) lo |= 1ULL << i;\n                else hi |= 1ULL << (i - 64);\n            }\n        }\n        mp[{lo, hi}]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n    for (auto& kv : mp) {\n        int c = kv.second;\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n    return make_eval_from_hist(hist);\n}\n\nvector<Line> build_grid_lines(double theta, const vector<double>& cu, const vector<double>& cv) {\n    vector<Line> lines;\n    lines.reserve(cu.size() + cv.size());\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (double c : cu) lines.push_back({cs, sn, c});\n    for (double c : cv) lines.push_back({-sn, cs, c});\n\n    return lines;\n}\n\nvector<double> uniform_cuts(int g) {\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n    for (int i = 1; i < g; i++) cuts.push_back(-R + 2.0 * R * i / g);\n    return cuts;\n}\n\nvector<double> projection_quantile_cuts(double theta, int g, bool second_axis) {\n    vector<double> vals;\n    vals.reserve(N);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double z;\n        if (!second_axis) z = p.x * cs + p.y * sn;\n        else z = -p.x * sn + p.y * cs;\n        vals.push_back(z);\n    }\n\n    sort(vals.begin(), vals.end());\n\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    for (int i = 1; i < g; i++) {\n        int r = (long long)N * i / g;\n        r = min(max(r, 1), N - 1);\n        double c = (vals[r - 1] + vals[r]) * 0.5;\n\n        if (fabs(vals[r] - vals[r - 1]) < 1e-9) {\n            c = vals[r] + 1e-7;\n        }\n\n        c = max(-R + 1e-6, min(R - 1e-6, c));\n        cuts.push_back(c);\n    }\n\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nvector<double> random_dirichlet_cuts(int g, double alpha, mt19937& rng) {\n    vector<double> w(g);\n\n    if (alpha > 500.0) {\n        for (int i = 0; i < g; i++) w[i] = 1.0;\n    } else {\n        gamma_distribution<double> gd(alpha, 1.0);\n        for (int i = 0; i < g; i++) w[i] = max(1e-12, gd(rng));\n    }\n\n    double sum = accumulate(w.begin(), w.end(), 0.0);\n\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    double cur = -R;\n    for (int i = 0; i + 1 < g; i++) {\n        cur += 2.0 * R * w[i] / sum;\n        cuts.push_back(cur);\n    }\n\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nlong long floor_div_ll(long long a, long long b) {\n    if (b < 0) a = -a, b = -b;\n    if (a >= 0) return a / b;\n    return - ((-a + b - 1) / b);\n}\n\nlong long ceil_div_ll(long long a, long long b) {\n    return -floor_div_ll(-a, b);\n}\n\nlong long extgcd(long long a, long long b, long long& x, long long& y) {\n    if (b == 0) {\n        x = (a >= 0 ? 1 : -1);\n        y = 0;\n        return llabs(a);\n    }\n    long long x1, y1;\n    long long g = extgcd(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\nbool collinear_any_coeff(long long A, long long B, long long C) {\n    for (const auto& p : pts) {\n        __int128 v = (__int128)A * p.x + (__int128)B * p.y;\n        if (v == C) return true;\n    }\n    return false;\n}\n\narray<long long, 4> line_to_integer_points(const Line& ln) {\n    // Represent a nearby line by A*x+B*y=C with large coprime integer A,B.\n    // Then output two integer points exactly on this integer-coefficient line.\n    const long long LIM = 1000000000LL;\n    const long long SCALE = 1000003LL;\n\n    double norm = hypot(ln.a, ln.b);\n    double aa = ln.a / norm;\n    double bb = ln.b / norm;\n    double cc = ln.c / norm;\n\n    long long A = llround(aa * SCALE);\n    long long B = llround(bb * SCALE);\n\n    if (A == 0 && B == 0) A = 1;\n\n    // Avoid pure vertical/horizontal reduced lattice spacing and ensure gcd=1.\n    if (A == 0) A = 1;\n    if (B == 0) B = 1;\n\n    for (int t = 0; std::gcd(llabs(A), llabs(B)) != 1 && t < 20; t++) {\n        if (llabs(A) < llabs(B)) A += (A >= 0 ? 1 : -1);\n        else B += (B >= 0 ? 1 : -1);\n    }\n\n    if (std::gcd(llabs(A), llabs(B)) != 1) {\n        A += 1;\n        while (std::gcd(llabs(A), llabs(B)) != 1) A++;\n    }\n\n    long double len = sqrt((long double)A * A + (long double)B * B);\n    long long C = llround((long double)cc * len);\n\n    for (int t = 0; t < 50 && collinear_any_coeff(A, B, C); t++) {\n        C += (t % 2 == 0 ? 1 : -2);\n    }\n\n    long long xg, yg;\n    long long g = extgcd(llabs(A), llabs(B), xg, yg);\n    (void)g;\n\n    if (A < 0) xg = -xg;\n    if (B < 0) yg = -yg;\n\n    __int128 x0_128 = (__int128)xg * C;\n    __int128 y0_128 = (__int128)yg * C;\n\n    long double px = aa * cc;\n    long double py = bb * cc;\n\n    long double dx = B;\n    long double dy = -A;\n    long double denom = dx * dx + dy * dy;\n\n    long double t_real =\n        ((px - (long double)x0_128) * dx + (py - (long double)y0_128) * dy) / denom;\n\n    long long t0 = llround(t_real);\n\n    __int128 x1_128 = x0_128 + (__int128)t0 * B;\n    __int128 y1_128 = y0_128 - (__int128)t0 * A;\n\n    long long x1 = (long long)x1_128;\n    long long y1 = (long long)y1_128;\n\n    long long stepMax = max(llabs(A), llabs(B));\n    long long T = max(1LL, min(900LL, (LIM - 1000000LL) / max(1LL, stepMax)));\n\n    long long x2 = x1 + B * T;\n    long long y2 = y1 - A * T;\n\n    if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) {\n        x2 = x1 - B * T;\n        y2 = y1 + A * T;\n    }\n\n    while ((x1 < -LIM || x1 > LIM || y1 < -LIM || y1 > LIM ||\n            x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) && T > 1) {\n        T /= 2;\n        x2 = x1 + B * T;\n        y2 = y1 - A * T;\n        if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) {\n            x2 = x1 - B * T;\n            y2 = y1 + A * T;\n        }\n    }\n\n    if (x1 < -LIM || x1 > LIM || y1 < -LIM || y1 > LIM ||\n        x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM ||\n        (x1 == x2 && y1 == y2)) {\n        // Extremely unlikely fallback.\n        x1 = -100000000;\n        y1 = llround(cc);\n        x2 = 100000000;\n        y2 = y1 + 1;\n    }\n\n    x1 = max(-LIM, min(LIM, x1));\n    y1 = max(-LIM, min(LIM, y1));\n    x2 = max(-LIM, min(LIM, x2));\n    y2 = max(-LIM, min(LIM, y2));\n\n    if (x1 == x2 && y1 == y2) {\n        if (x2 < LIM) x2++;\n        else x2--;\n    }\n\n    return {x1, y1, x2, y2};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st = chrono::steady_clock::now();\n\n    cin >> N >> K;\n    targetA.fill(0);\n\n    int M = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> targetA[d];\n        M += targetA[d];\n    }\n\n    pts.resize(N);\n    for (int i = 0; i < N; i++) cin >> pts[i].x >> pts[i].y;\n\n    mt19937 rng(1234567);\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n\n    vector<Line> bestLines;\n    long long bestValue = LLONG_MIN;\n\n    vector<GridCand> topGrids;\n\n    auto register_grid = [&](double theta, const vector<double>& cu, const vector<double>& cv) {\n        if ((int)cu.size() + (int)cv.size() > K) return;\n\n        EvalResult er = eval_grid(theta, cu, cv);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = build_grid_lines(theta, cu, cv);\n        }\n\n        GridCand gc{theta, cu, cv, val};\n        topGrids.push_back(gc);\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n        if ((int)topGrids.size() > 16) topGrids.pop_back();\n    };\n\n    auto register_lines = [&](const vector<Line>& lines) {\n        if ((int)lines.size() > K) return;\n        EvalResult er = eval_lines(lines);\n        long long val = er.value();\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = lines;\n        }\n    };\n\n    double baseUniformProduct = 4.0 * M / PI;\n    vector<double> factors = {0.45, 0.55, 0.65, 0.78, 0.90, 1.00, 1.12, 1.28, 1.50, 1.75, 2.05};\n    vector<double> aspects = {0.50, 0.62, 0.75, 0.88, 1.00, 1.15, 1.33, 1.60, 2.00};\n    vector<double> thetas;\n    for (int i = 0; i < 12; i++) thetas.push_back(PI * i / 24.0);\n\n    // Uniform coordinate grids.\n    for (double fac : factors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, baseUniformProduct * fac);\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            auto cu = uniform_cuts(gx);\n            auto cv = uniform_cuts(gy);\n\n            for (double th : thetas) register_grid(th, cu, cv);\n        }\n    }\n\n    // Quantile grids: often better adapted to the actual point distribution.\n    vector<double> qFactors = {0.50, 0.62, 0.75, 0.88, 1.00, 1.15, 1.32, 1.55, 1.85};\n    for (double fac : qFactors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, M * fac);\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            for (double th : thetas) {\n                auto cu = projection_quantile_cuts(th, gx, false);\n                auto cv = projection_quantile_cuts(th, gy, true);\n                register_grid(th, cu, cv);\n            }\n        }\n    }\n\n    // Some three-direction arrangements.\n    for (int rep = 0; rep < 40 && elapsed_sec() < 1.1; rep++) {\n        double hbase = sqrt(max(1.0, M / 3.0));\n        double scale = 0.55 + 0.035 * rep;\n        int g = max(2, (int)llround(hbase * scale));\n        g = min(g, 34);\n\n        double th0 = (rep % 15) * PI / 45.0;\n        vector<Line> lines;\n\n        for (int f = 0; f < 3; f++) {\n            double th = th0 + f * PI / 3.0;\n            double a = cos(th), b = sin(th);\n            auto cuts = uniform_cuts(g);\n            for (double c : cuts) lines.push_back({a, b, c});\n        }\n\n        register_lines(lines);\n    }\n\n    // Random non-uniform grids before local improvement.\n    vector<double> alphaList = {0.25, 0.35, 0.50, 0.75, 1.00, 1.50, 2.50, 5.00, 1000.0};\n\n    while (elapsed_sec() < 1.55) {\n        double logFac = log(0.45) + ur01(rng) * (log(2.15) - log(0.45));\n        double logAsp = log(0.45) + ur01(rng) * (log(2.20) - log(0.45));\n        double fac = exp(logFac);\n        double asp = exp(logAsp);\n\n        double prod = max(1.0, baseUniformProduct * fac);\n        int gx = max(1, (int)llround(sqrt(prod * asp)));\n        int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n        while (gx + gy - 2 > K) {\n            if (gx > gy) gx--;\n            else gy--;\n        }\n\n        double ax = alphaList[rng() % alphaList.size()];\n        double ay = alphaList[rng() % alphaList.size()];\n        auto cu = random_dirichlet_cuts(gx, ax, rng);\n        auto cv = random_dirichlet_cuts(gy, ay, rng);\n        double th = ur01(rng) * PI / 2.0;\n\n        register_grid(th, cu, cv);\n    }\n\n    // Local search / simulated annealing around promising grids.\n    auto improve_grid = [&](GridCand start, double timeLimit) {\n        GridCand cur = start;\n        GridCand best = start;\n\n        double begin = elapsed_sec();\n\n        while (elapsed_sec() < timeLimit) {\n            double now = elapsed_sec();\n            double progress = (now - begin) / max(1e-9, timeLimit - begin);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 30000.0 * (1.0 - progress) + 300.0;\n\n            GridCand nxt = cur;\n            int typ = rng() % 10;\n\n            if ((typ < 4 && !nxt.cu.empty()) || nxt.cv.empty()) {\n                int m = nxt.cu.size();\n                int id = rng() % m;\n                double lo = (id == 0 ? -R + 1e-6 : nxt.cu[id - 1] + 1e-6);\n                double hi = (id + 1 == m ? R - 1e-6 : nxt.cu[id + 1] - 1e-6);\n                double width = hi - lo;\n\n                double nv;\n                if (typ == 0) {\n                    normal_distribution<double> nd(0.0, width * 0.08);\n                    nv = nxt.cu[id] + nd(rng);\n                } else {\n                    nv = lo + ur01(rng) * width;\n                }\n                nxt.cu[id] = max(lo, min(hi, nv));\n            } else if (typ < 8 && !nxt.cv.empty()) {\n                int m = nxt.cv.size();\n                int id = rng() % m;\n                double lo = (id == 0 ? -R + 1e-6 : nxt.cv[id - 1] + 1e-6);\n                double hi = (id + 1 == m ? R - 1e-6 : nxt.cv[id + 1] - 1e-6);\n                double width = hi - lo;\n\n                double nv;\n                if (typ == 4) {\n                    normal_distribution<double> nd(0.0, width * 0.08);\n                    nv = nxt.cv[id] + nd(rng);\n                } else {\n                    nv = lo + ur01(rng) * width;\n                }\n                nxt.cv[id] = max(lo, min(hi, nv));\n            } else if (typ == 8) {\n                normal_distribution<double> nd(0.0, 0.015 * (1.0 - progress) + 0.002);\n                nxt.theta += nd(rng);\n                while (nxt.theta < 0) nxt.theta += PI;\n                while (nxt.theta >= PI) nxt.theta -= PI;\n            } else {\n                // Tiny global stretch of one axis.\n                bool axis = rng() & 1;\n                double scale = exp((ur01(rng) - 0.5) * 0.12 * (1.0 - progress));\n                vector<double>& arr = axis ? nxt.cu : nxt.cv;\n                for (double& x : arr) x = max(-R + 1e-6, min(R - 1e-6, x * scale));\n                sort(arr.begin(), arr.end());\n                for (int i = 1; i < (int)arr.size(); i++) {\n                    if (arr[i] <= arr[i - 1] + 1e-6) arr[i] = arr[i - 1] + 1e-6;\n                }\n                for (double& x : arr) x = max(-R + 1e-6, min(R - 1e-6, x));\n            }\n\n            EvalResult er = eval_grid(nxt.theta, nxt.cu, nxt.cv);\n            nxt.val = er.value();\n\n            long long delta = nxt.val - cur.val;\n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else {\n                double prob = exp((double)delta / temp);\n                if (ur01(rng) < prob) accept = true;\n            }\n\n            if (accept) cur = nxt;\n\n            if (nxt.val > best.val) {\n                best = nxt;\n                if (nxt.val > bestValue) {\n                    bestValue = nxt.val;\n                    bestLines = build_grid_lines(nxt.theta, nxt.cu, nxt.cv);\n                }\n            }\n        }\n    };\n\n    int idx = 0;\n    while (elapsed_sec() < 2.76 && idx < (int)topGrids.size()) {\n        double remaining = 2.76 - elapsed_sec();\n        int left = (int)topGrids.size() - idx;\n        double slice = min(0.22, max(0.04, remaining / max(1, left)));\n        improve_grid(topGrids[idx], min(2.76, elapsed_sec() + slice));\n        idx++;\n    }\n\n    // If time remains, keep improving the current best grid among top candidates.\n    while (elapsed_sec() < 2.82 && !topGrids.empty()) {\n        improve_grid(topGrids[0], min(2.82, elapsed_sec() + 0.08));\n    }\n\n    if (bestLines.empty()) {\n        auto cu = uniform_cuts(25);\n        auto cv = uniform_cuts(25);\n        bestLines = build_grid_lines(0.01, cu, cv);\n    }\n\n    if ((int)bestLines.size() > K) bestLines.resize(K);\n\n    cout << bestLines.size() << '\\n';\n    for (const auto& ln : bestLines) {\n        auto e = line_to_integer_points(ln);\n        cout << e[0] << ' ' << e[1] << ' ' << e[2] << ' ' << e[3] << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 61;\n\nint N, M;\nint Weight[MAXN][MAXN];\nvector<pair<int,int>> initialDots;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int mod) {\n        if (mod <= 0) return 0;\n        return (int)(next() % mod);\n    }\n};\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nstruct State {\n    bool dot[MAXN][MAXN];\n    bool seg[4][MAXN][MAXN];\n    vector<Move> ops;\n    long long totalWeight;\n\n    void init() {\n        memset(dot, 0, sizeof(dot));\n        memset(seg, 0, sizeof(seg));\n        ops.clear();\n        ops.reserve(N * N);\n        totalWeight = 0;\n\n        for (auto [x, y] : initialDots) {\n            dot[x][y] = true;\n            totalWeight += Weight[x][y];\n        }\n    }\n\n    int segType(int x1, int y1, int x2, int y2, int &sx, int &sy) const {\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n\n        if (dy == 0) {\n            sx = min(x1, x2);\n            sy = y1;\n            return 0;\n        }\n        if (dx == 0) {\n            sx = x1;\n            sy = min(y1, y2);\n            return 1;\n        }\n        if (dx == dy) {\n            sx = min(x1, x2);\n            sy = min(y1, y2);\n            return 2;\n        }\n\n        sx = min(x1, x2);\n        sy = min(y1, y2);\n        return 3;\n    }\n\n    bool unitUsed(int x1, int y1, int x2, int y2) const {\n        int sx, sy;\n        int t = segType(x1, y1, x2, y2, sx, sy);\n        return seg[t][sx][sy];\n    }\n\n    void markUnit(int x1, int y1, int x2, int y2) {\n        int sx, sy;\n        int t = segType(x1, y1, x2, y2, sx, sy);\n        seg[t][sx][sy] = true;\n    }\n\n    bool edgeFree(int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i < len; i++) {\n            int nx = x + dx;\n            int ny = y + dy;\n            if (unitUsed(x, y, nx, ny)) return false;\n            x = nx;\n            y = ny;\n        }\n        return true;\n    }\n\n    void markEdge(int ax, int ay, int bx, int by) {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i < len; i++) {\n            int nx = x + dx;\n            int ny = y + dy;\n            markUnit(x, y, nx, ny);\n            x = nx;\n            y = ny;\n        }\n    }\n\n    bool rectEdgesFree(const Move &m) const {\n        return edgeFree(m.x1, m.y1, m.x2, m.y2)\n            && edgeFree(m.x2, m.y2, m.x3, m.y3)\n            && edgeFree(m.x3, m.y3, m.x4, m.y4)\n            && edgeFree(m.x4, m.y4, m.x1, m.y1);\n    }\n\n    void apply(const Move &m) {\n        markEdge(m.x1, m.y1, m.x2, m.y2);\n        markEdge(m.x2, m.y2, m.x3, m.y3);\n        markEdge(m.x3, m.y3, m.x4, m.y4);\n        markEdge(m.x4, m.y4, m.x1, m.y1);\n\n        dot[m.x1][m.y1] = true;\n        totalWeight += Weight[m.x1][m.y1];\n        ops.push_back(m);\n    }\n};\n\nstruct Param {\n    int wcoef;\n    int pcoef;\n    int dcoef;\n    int acoef;\n    int noise;\n    int topR;\n    int phase;\n};\n\nstruct Result {\n    long long score;\n    vector<Move> ops;\n};\n\nstruct Candidate {\n    long long key;\n    Move mv;\n};\n\nint dx8[8] = {1, 0, -1, 0, 1, -1, -1, 1};\nint dy8[8] = {0, 1, 0, -1, 1, 1, -1, -1};\n\n// 0:E 1:N 2:W 3:S 4:NE 5:NW 6:SW 7:SE\npair<int,int> dirPairs[8] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0},\n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ninline int enc(int x, int y) {\n    return x * N + y;\n}\n\ninline int stepLen(int ax, int ay, int bx, int by) {\n    return max(abs(ax - bx), abs(ay - by));\n}\n\nResult simulate(const Param &param, uint64_t seed, const Timer &timer, double deadline) {\n    static short nearestDot[8][MAXN][MAXN];\n\n    State st;\n    st.init();\n\n    XorShift rng(seed);\n\n    while (true) {\n        if (timer.elapsed() > deadline) break;\n\n        for (int d = 0; d < 8; d++) {\n            int xs = dx8[d] > 0 ? N - 1 : 0;\n            int xe = dx8[d] > 0 ? -1 : N;\n            int xi = dx8[d] > 0 ? -1 : 1;\n\n            int ys = dy8[d] > 0 ? N - 1 : 0;\n            int ye = dy8[d] > 0 ? -1 : N;\n            int yi = dy8[d] > 0 ? -1 : 1;\n\n            for (int x = xs; x != xe; x += xi) {\n                for (int y = ys; y != ye; y += yi) {\n                    int nx = x + dx8[d];\n                    int ny = y + dy8[d];\n\n                    if (!inside(nx, ny)) {\n                        nearestDot[d][x][y] = -1;\n                    } else if (st.dot[nx][ny]) {\n                        nearestDot[d][x][y] = enc(nx, ny);\n                    } else {\n                        nearestDot[d][x][y] = nearestDot[d][nx][ny];\n                    }\n                }\n            }\n        }\n\n        bool found = false;\n        Move bestMove{};\n        long long bestKey = LLONG_MIN;\n        vector<Candidate> cands;\n\n        if (param.topR > 1) cands.reserve(4096);\n\n        int opCount = (int)st.ops.size();\n\n        long long pEff = param.pcoef;\n        if (param.phase == 1) {\n            // Stronger perimeter penalty in the early game.\n            pEff = 1LL * param.pcoef * 260 / (260 + opCount);\n        } else if (param.phase == 2) {\n            // Perimeter penalty gradually increases.\n            pEff = 1LL * param.pcoef * (120 + min(opCount, 400)) / 120;\n        }\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                if (st.dot[x][y]) continue;\n\n                int degree = 0;\n                for (int d = 0; d < 8; d++) {\n                    if (nearestDot[d][x][y] >= 0) degree++;\n                }\n\n                for (auto [d1, d2] : dirPairs) {\n                    int e2 = nearestDot[d1][x][y];\n                    int e4 = nearestDot[d2][x][y];\n\n                    if (e2 < 0 || e4 < 0) continue;\n\n                    int x2 = e2 / N, y2 = e2 % N;\n                    int x4 = e4 / N, y4 = e4 % N;\n\n                    int x3 = x2 + x4 - x;\n                    int y3 = y2 + y4 - y;\n\n                    if (!inside(x3, y3)) continue;\n                    if (!st.dot[x3][y3]) continue;\n\n                    int e3 = enc(x3, y3);\n                    if (nearestDot[d2][x2][y2] != e3) continue;\n                    if (nearestDot[d1][x4][y4] != e3) continue;\n\n                    Move mv{x, y, x2, y2, x3, y3, x4, y4};\n                    if (!st.rectEdgesFree(mv)) continue;\n\n                    int perim = stepLen(x, y, x2, y2)\n                              + stepLen(x2, y2, x3, y3)\n                              + stepLen(x3, y3, x4, y4)\n                              + stepLen(x4, y4, x, y);\n\n                    int area = abs((x2 - x) * (y4 - y) - (y2 - y) * (x4 - x));\n\n                    long long key = 0;\n                    key += 1LL * Weight[x][y] * param.wcoef;\n                    key -= 1LL * perim * pEff;\n                    key += 1LL * degree * param.dcoef;\n                    key += 1LL * area * param.acoef;\n                    if (param.noise > 0) key += rng.nextInt(param.noise);\n\n                    if (param.topR <= 1) {\n                        if (!found || key > bestKey || (key == bestKey && rng.nextInt(2))) {\n                            found = true;\n                            bestKey = key;\n                            bestMove = mv;\n                        }\n                    } else {\n                        cands.push_back({key, mv});\n                    }\n                }\n            }\n        }\n\n        if (param.topR > 1) {\n            if (cands.empty()) break;\n\n            sort(cands.begin(), cands.end(), [](const Candidate &a, const Candidate &b) {\n                return a.key > b.key;\n            });\n\n            int r = min<int>(param.topR, cands.size());\n\n            int idx;\n            if (r <= 1) {\n                idx = 0;\n            } else {\n                // Biased random choice: mostly near the best, sometimes lower.\n                int a = rng.nextInt(r);\n                int b = rng.nextInt(r);\n                idx = 1LL * a * b / r;\n                if (idx >= r) idx = r - 1;\n            }\n\n            bestMove = cands[idx].mv;\n            found = true;\n        }\n\n        if (!found) break;\n\n        st.apply(bestMove);\n    }\n\n    return Result{st.totalWeight, st.ops};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    initialDots.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initialDots[i].first >> initialDots[i].second;\n    }\n\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            Weight[x][y] = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n        }\n    }\n\n    Timer timer;\n    const double DEADLINE = 4.72;\n\n    vector<Param> params = {\n        // Old-style greedy/noisy variants.\n        {1000,    0,     0,    0,      0,  1, 0},\n        {1000,   20,     0,    0,  20000,  1, 0},\n        {1000,   80,     0,    0,  50000,  1, 0},\n        {1000,  200,     0,    0, 100000,  1, 0},\n        {1000,  -20,     0,    0,  50000,  1, 0},\n        {1000,  -80,     0,    0, 100000,  1, 0},\n        {1000,    0,     0,    0, 200000,  1, 0},\n\n        // Stronger perimeter control.\n        {1000, 1200,     0,    0,  50000,  4, 1},\n        {1000, 2500,     0,  -20,  80000,  6, 1},\n        {1000, 4500,     0,  -40, 100000,  8, 1},\n        { 900, 6500,     0,  -60, 120000, 10, 1},\n\n        // Visibility-degree bonus: points likely useful later.\n        {1000, 1200, 10000,    0,  70000,  6, 1},\n        {1000, 2500, 20000,  -20, 100000,  8, 1},\n        { 900, 4000, 35000,  -40, 130000, 12, 1},\n        { 700, 5500, 50000,  -50, 160000, 16, 1},\n\n        // Some aggressive large-rectangle variants.\n        {1000, -500,     0,   30,  80000,  5, 0},\n        {1000,-1200,     0,   60, 120000,  8, 0},\n\n        // Late-game tightening.\n        {1000, 1000, 10000,    0,  70000,  6, 2},\n        {1000, 2000, 25000,  -20, 100000, 10, 2},\n    };\n\n    Result best{-1, {}};\n\n    int run = 0;\n    while (timer.elapsed() < DEADLINE) {\n        const Param &p = params[run % params.size()];\n\n        uint64_t seed = 123456789ULL;\n        seed += 1000003ULL * run;\n        seed += 998244353ULL * N;\n        seed += 19260817ULL * M;\n\n        Result res = simulate(p, seed, timer, DEADLINE);\n\n        if (res.score > best.score) {\n            best = std::move(res);\n        }\n\n        run++;\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (const auto &m : best.ops) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed = 2463534242u) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n};\n\nusing Board = array<unsigned char, 100>;\n\nint F[101];\nint cntFlavor[4];\n\nint anchorR[4], anchorC[4];\nint distCell[4][100];\nint targetCell[100];\n\nconst int cornerR[4] = {0, 0, 9, 9};\nconst int cornerC[4] = {0, 9, 0, 9};\n\nchar dirChar[4] = {'F', 'B', 'L', 'R'};\n\nBoard tiltBoard(const Board& b, int dir) {\n    Board nb{};\n    nb.fill(0);\n\n    if (dir == 0) {\n        for (int c = 0; c < 10; c++) {\n            int w = 0;\n            for (int r = 0; r < 10; r++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w++ * 10 + c] = v;\n            }\n        }\n    } else if (dir == 1) {\n        for (int c = 0; c < 10; c++) {\n            int w = 9;\n            for (int r = 9; r >= 0; r--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w-- * 10 + c] = v;\n            }\n        }\n    } else if (dir == 2) {\n        for (int r = 0; r < 10; r++) {\n            int w = 0;\n            for (int c = 0; c < 10; c++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w++] = v;\n            }\n        }\n    } else {\n        for (int r = 0; r < 10; r++) {\n            int w = 9;\n            for (int c = 9; c >= 0; c--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w--] = v;\n            }\n        }\n    }\n\n    return nb;\n}\n\nvoid placeCandyByP(Board& b, int p, int flavor) {\n    int k = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            k++;\n            if (k == p) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n        }\n    }\n}\n\nvoid placeRandomCandy(Board& b, int emptyCnt, int flavor, XorShift& rng) {\n    int k = rng.randint(emptyCnt);\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            if (k == 0) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n            k--;\n        }\n    }\n}\n\nlong long componentRawScore(const Board& b) {\n    bool vis[100] = {};\n    long long res = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int q[100];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            int r = v / 10;\n            int c = v % 10;\n\n            if (r > 0) {\n                int ni = v - 10;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (r < 9) {\n                int ni = v + 10;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (c > 0) {\n                int ni = v - 1;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (c < 9) {\n                int ni = v + 1;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        res += 1LL * sz * sz;\n    }\n\n    return res;\n}\n\nlong long evalBoard(const Board& b) {\n    bool vis[100] = {};\n    long long comp = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int q[100];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            int r = v / 10;\n            int c = v % 10;\n\n            if (r > 0) {\n                int ni = v - 10;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (r < 9) {\n                int ni = v + 10;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (c > 0) {\n                int ni = v - 1;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (c < 9) {\n                int ni = v + 1;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        comp += 1LL * sz * sz;\n    }\n\n    int sameAdj = 0;\n    int diffAdj = 0;\n    int pref = 0;\n    int targetMatch = 0;\n\n    for (int r = 0; r < 10; r++) {\n        for (int c = 0; c < 10; c++) {\n            int id = r * 10 + c;\n            int fl = b[id];\n            if (fl == 0) continue;\n\n            pref += 18 - distCell[fl][id];\n            if (targetCell[id] == fl) targetMatch++;\n\n            if (r + 1 < 10) {\n                int fl2 = b[(r + 1) * 10 + c];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n            if (c + 1 < 10) {\n                int fl2 = b[r * 10 + c + 1];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n        }\n    }\n\n    return comp * 100 + sameAdj * 220 - diffAdj * 60 + pref * 28 + targetMatch * 300;\n}\n\nvoid buildTarget() {\n    for (int fl = 1; fl <= 3; fl++) {\n        for (int id = 0; id < 100; id++) {\n            int r = id / 10;\n            int c = id % 10;\n            distCell[fl][id] = abs(r - anchorR[fl]) + abs(c - anchorC[fl]);\n        }\n    }\n\n    fill(targetCell, targetCell + 100, 0);\n\n    struct Item {\n        int dist;\n        int fl;\n        int id;\n    };\n\n    vector<Item> items;\n    items.reserve(300);\n\n    for (int id = 0; id < 100; id++) {\n        for (int fl = 1; fl <= 3; fl++) {\n            items.push_back({distCell[fl][id], fl, id});\n        }\n    }\n\n    sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.fl != b.fl) return a.fl < b.fl;\n        return a.id < b.id;\n    });\n\n    int rem[4];\n    for (int fl = 1; fl <= 3; fl++) rem[fl] = cntFlavor[fl];\n\n    for (auto& it : items) {\n        if (targetCell[it.id] == 0 && rem[it.fl] > 0) {\n            targetCell[it.id] = it.fl;\n            rem[it.fl]--;\n        }\n    }\n}\n\nint choosePolicyDir(const Board& b) {\n    int bestDir = 0;\n    long long bestVal = LLONG_MIN;\n\n    for (int d = 0; d < 4; d++) {\n        Board nb = tiltBoard(b, d);\n        long long val = evalBoard(nb);\n        if (val > bestVal) {\n            bestVal = val;\n            bestDir = d;\n        }\n    }\n\n    return bestDir;\n}\n\nlong long simulatePolicyGame(uint32_t seed) {\n    XorShift rng(seed);\n    Board b{};\n    b.fill(0);\n\n    for (int t = 1; t <= 100; t++) {\n        placeRandomCandy(b, 101 - t, F[t], rng);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long simulateRollout(Board b, int nextT, uint32_t seed) {\n    XorShift rng(seed);\n\n    for (int t = nextT; t <= 100; t++) {\n        placeRandomCandy(b, 101 - t, F[t], rng);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long exactOneStepLookahead(const Board& b, int currentT) {\n    if (currentT >= 100) return evalBoard(b);\n\n    int nt = currentT + 1;\n    int fl = F[nt];\n\n    vector<int> emp;\n    emp.reserve(100);\n\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) emp.push_back(i);\n    }\n\n    long long sum = 0;\n\n    for (int id : emp) {\n        Board tmp = b;\n        tmp[id] = (unsigned char)fl;\n\n        if (nt == 100) {\n            sum += evalBoard(tmp);\n        } else {\n            long long best = LLONG_MIN;\n            for (int d = 0; d < 4; d++) {\n                Board nb = tiltBoard(tmp, d);\n                best = max(best, evalBoard(nb));\n            }\n            sum += best;\n        }\n    }\n\n    return sum / max(1, (int)emp.size());\n}\n\nvoid selectCornerAssignment() {\n    double bestScore = -1.0;\n    int bestCorner[4] = {0, 0, 1, 2};\n\n    vector<uint32_t> seeds;\n    for (int i = 0; i < 5; i++) {\n        seeds.push_back(1234567u + i * 1000003u);\n    }\n\n    for (int mask = 0; mask < (1 << 4); mask++) {\n        if (__builtin_popcount((unsigned)mask) != 3) continue;\n\n        vector<int> cs;\n        for (int i = 0; i < 4; i++) {\n            if (mask >> i & 1) cs.push_back(i);\n        }\n\n        sort(cs.begin(), cs.end());\n\n        do {\n            for (int fl = 1; fl <= 3; fl++) {\n                int cid = cs[fl - 1];\n                anchorR[fl] = cornerR[cid];\n                anchorC[fl] = cornerC[cid];\n            }\n\n            buildTarget();\n\n            long long sum = 0;\n            for (uint32_t seed : seeds) {\n                sum += simulatePolicyGame(seed);\n            }\n\n            double avg = (double)sum / seeds.size();\n\n            if (avg > bestScore) {\n                bestScore = avg;\n                for (int fl = 1; fl <= 3; fl++) {\n                    bestCorner[fl] = cs[fl - 1];\n                }\n            }\n\n        } while (next_permutation(cs.begin(), cs.end()));\n    }\n\n    for (int fl = 1; fl <= 3; fl++) {\n        int cid = bestCorner[fl];\n        anchorR[fl] = cornerR[cid];\n        anchorC[fl] = cornerC[cid];\n    }\n\n    buildTarget();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    for (int i = 1; i <= 100; i++) {\n        cin >> F[i];\n        cntFlavor[F[i]]++;\n    }\n\n    selectCornerAssignment();\n\n    Board board{};\n    board.fill(0);\n\n    XorShift rolloutRng(987654321u);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        placeCandyByP(board, p, F[t]);\n\n        Board cand[4];\n        long long baseEval[4];\n        long long lookEval[4];\n\n        for (int d = 0; d < 4; d++) {\n            cand[d] = tiltBoard(board, d);\n            baseEval[d] = evalBoard(cand[d]);\n        }\n\n        bool canLook = true;\n        {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > 1.72) canLook = false;\n        }\n\n        for (int d = 0; d < 4; d++) {\n            if (canLook && t < 100) lookEval[d] = exactOneStepLookahead(cand[d], t);\n            else lookEval[d] = baseEval[d];\n        }\n\n        long long rolloutTotal[4] = {};\n        int samples = 0;\n\n        if (t < 100) {\n            double ratio = (double)t / 100.0;\n            double targetTime = 0.03 + 1.77 * pow(ratio, 1.25);\n            const double HARD_LIMIT = 1.86;\n\n            while (true) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - startTime).count();\n\n                if (elapsed > HARD_LIMIT) break;\n                if (elapsed > targetTime && samples >= 1) break;\n\n                uint32_t seed = rolloutRng.next();\n\n                for (int d = 0; d < 4; d++) {\n                    rolloutTotal[d] += simulateRollout(cand[d], t + 1, seed);\n                }\n\n                samples++;\n\n                if (samples >= 250) break;\n            }\n        }\n\n        int bestDir = 0;\n        double bestScore = -1e100;\n\n        for (int d = 0; d < 4; d++) {\n            double score;\n\n            if (samples > 0) {\n                double rolloutAvg = (double)rolloutTotal[d] / samples;\n                double lookPseudoRaw = (double)lookEval[d] / 100.0;\n                double basePseudoRaw = (double)baseEval[d] / 100.0;\n\n                score = rolloutAvg + 0.12 * lookPseudoRaw + 0.03 * basePseudoRaw;\n            } else {\n                score = (double)lookEval[d] + 0.1 * (double)baseEval[d];\n            }\n\n            if (score > bestScore) {\n                bestScore = score;\n                bestDir = d;\n            }\n        }\n\n        board = cand[bestDir];\n\n        cout << dirChar[bestDir] << endl;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct FastRNG {\n    uint64_t x;\n    FastRNG(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstruct Candidate {\n    array<unsigned char, 100> deg{};\n    array<uint64_t, 2> mask{};\n    int edges = 0;\n};\n\nstruct Codebook {\n    int M = 0;\n    int N = 0;\n    double eps = 0.0;\n    vector<Candidate> code;\n    vector<string> out;\n};\n\nstatic inline bool getMaskBit(const Candidate& c, int j) {\n    return (c.mask[j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline bool getMaskBitRaw(const array<uint64_t, 2>& mask, int j) {\n    return (mask[j >> 6] >> (j & 63)) & 1ULL;\n}\n\nCandidate makeCandidate(int N, const array<uint64_t, 2>& mask) {\n    Candidate c;\n    c.mask = mask;\n\n    int suf[105];\n    suf[N] = 0;\n    for (int i = N - 1; i >= 0; i--) {\n        suf[i] = suf[i + 1] + (i == 0 ? 0 : (getMaskBitRaw(mask, i) ? 1 : 0));\n    }\n\n    vector<int> d(N);\n    int edges = 0;\n    for (int i = 0; i < N; i++) {\n        bool b = (i == 0 ? false : getMaskBitRaw(mask, i));\n        d[i] = suf[i + 1] + (b ? i : 0);\n        if (b) edges += i;\n    }\n\n    sort(d.begin(), d.end());\n    for (int i = 0; i < N; i++) c.deg[i] = (unsigned char)d[i];\n    c.edges = edges;\n    return c;\n}\n\nstring thresholdGraphString(const Candidate& c, int N) {\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(getMaskBit(c, j) ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nint ceilLog2Int(int x) {\n    int p = 1, r = 0;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\ndouble degreeDistanceMetric(const Candidate& a, const Candidate& b, int N) {\n    double ss = 0.0;\n    double sum = 0.0;\n    for (int i = 0; i < N; i++) {\n        double v = (double)a.deg[i] - (double)b.deg[i];\n        ss += v * v;\n        sum += v;\n    }\n\n    // Mahalanobis-like correction for the common edge-count fluctuation.\n    double score = ss - (sum * sum) / max(1.0, 2.0 * N - 2.0);\n    if (score < 0) score = 0;\n    return score;\n}\n\nvector<Candidate> generatePool(int N, int M, double eps, FastRNG& rng) {\n    int target = max(300, min(1600, 16 * M + 200));\n\n    vector<Candidate> pool;\n    pool.reserve(target + 10);\n\n    unordered_set<string> seen;\n    seen.reserve(target * 3);\n\n    auto addCandidate = [&](const array<uint64_t, 2>& mask) {\n        Candidate c = makeCandidate(N, mask);\n\n        string key;\n        key.resize(N);\n        for (int i = 0; i < N; i++) key[i] = (char)c.deg[i];\n\n        if (seen.insert(key).second) {\n            pool.push_back(c);\n        }\n    };\n\n    if (N - 1 <= 20) {\n        uint64_t total = 1ULL << (N - 1);\n        if ((int)total <= target) {\n            for (uint64_t m = 0; m < total; m++) {\n                array<uint64_t, 2> mask{0ULL, 0ULL};\n                mask[0] = m << 1;\n                addCandidate(mask);\n            }\n            return pool;\n        }\n    }\n\n    {\n        array<uint64_t, 2> emptyMask{0ULL, 0ULL};\n        addCandidate(emptyMask);\n\n        array<uint64_t, 2> fullMask{0ULL, 0ULL};\n        for (int j = 1; j < N; j++) {\n            fullMask[j >> 6] |= 1ULL << (j & 63);\n        }\n        addCandidate(fullMask);\n    }\n\n    int attempts = 0;\n    while ((int)pool.size() < target && attempts < target * 50) {\n        attempts++;\n\n        array<uint64_t, 2> mask{0ULL, 0ULL};\n        int mode = rng.nextInt(4);\n\n        if (mode == 0) {\n            double p = rng.nextDouble();\n            for (int j = 1; j < N; j++) {\n                if (rng.nextDouble() < p) mask[j >> 6] |= 1ULL << (j & 63);\n            }\n        } else if (mode == 1) {\n            int need = rng.nextInt(N);\n            int rem = N - 1;\n            for (int j = 1; j < N; j++) {\n                if (need > 0 && rng.nextInt(rem) < need) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                    need--;\n                }\n                rem--;\n            }\n        } else if (mode == 2) {\n            int cut = 1 + rng.nextInt(N - 1);\n            for (int j = cut; j < N; j++) {\n                mask[j >> 6] |= 1ULL << (j & 63);\n            }\n            for (int t = 0; t < N / 8 + 1; t++) {\n                int j = 1 + rng.nextInt(N - 1);\n                mask[j >> 6] ^= 1ULL << (j & 63);\n            }\n        } else {\n            double p;\n            int r = rng.nextInt(5);\n            if (r == 0) p = 0.08;\n            else if (r == 1) p = 0.20;\n            else if (r == 2) p = 0.50;\n            else if (r == 3) p = 0.80;\n            else p = 0.92;\n\n            for (int j = 1; j < N; j++) {\n                if (rng.nextDouble() < p) mask[j >> 6] |= 1ULL << (j & 63);\n            }\n        }\n\n        addCandidate(mask);\n    }\n\n    return pool;\n}\n\nCodebook buildCodebook(int M, int N, double eps, FastRNG& rng) {\n    vector<Candidate> pool = generatePool(N, M, eps, rng);\n    int K = (int)pool.size();\n\n    Codebook book;\n    book.M = M;\n    book.N = N;\n    book.eps = eps;\n\n    if (K < M) return book;\n\n    vector<char> used(K, 0);\n    vector<double> mind(K, 1e100);\n\n    int first = 0;\n\n    for (int it = 0; it < M; it++) {\n        int best = -1;\n\n        if (it == 0) {\n            best = first;\n        } else {\n            double bv = -1;\n            for (int i = 0; i < K; i++) {\n                if (!used[i] && mind[i] > bv) {\n                    bv = mind[i];\n                    best = i;\n                }\n            }\n        }\n\n        used[best] = 1;\n        Candidate chosen = pool[best];\n\n        for (int i = 0; i < K; i++) {\n            if (!used[i]) {\n                double d = degreeDistanceMetric(chosen, pool[i], N);\n                if (d < mind[i]) mind[i] = d;\n            }\n        }\n\n        book.code.push_back(chosen);\n    }\n\n    book.out.resize(M);\n    for (int k = 0; k < M; k++) {\n        book.out[k] = thresholdGraphString(book.code[k], N);\n    }\n\n    return book;\n}\n\nint decodeDegrees(const Codebook& book, const vector<int>& obsSorted) {\n    int N = book.N;\n    double eps = book.eps;\n    double base = eps * (N - 1);\n    double scale = 1.0 - 2.0 * eps;\n\n    int best = 0;\n    double bestScore = 1e100;\n\n    for (int k = 0; k < book.M; k++) {\n        double ss = 0.0;\n        double sum = 0.0;\n\n        const Candidate& c = book.code[k];\n        for (int i = 0; i < N; i++) {\n            double mu = base + scale * (double)c.deg[i];\n            double diff = obsSorted[i] - mu;\n            ss += diff * diff;\n            sum += diff;\n        }\n\n        double score;\n        if (eps <= 1e-12) {\n            score = ss;\n        } else {\n            score = ss - (sum * sum) / max(1.0, 2.0 * N - 2.0);\n        }\n\n        if (score < bestScore) {\n            bestScore = score;\n            best = k;\n        }\n    }\n\n    return best;\n}\n\nvector<int> parseObservedDegrees(const string& s, int N) {\n    vector<int> deg(N, 0);\n    int idx = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++, idx++) {\n            if (s[idx] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n        }\n    }\n\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nvector<int> simulateNoisyDegrees(const Candidate& c, int N, double eps, FastRNG& rng) {\n    vector<int> deg(N, 0);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = getMaskBit(c, j);\n            if (rng.nextDouble() < eps) e = !e;\n            if (e) {\n                deg[i]++;\n                deg[j]++;\n            }\n        }\n    }\n\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint simulateErrors(const Codebook& book, int T, FastRNG& rng) {\n    int err = 0;\n\n    for (int t = 0; t < T; t++) {\n        int s = rng.nextInt(book.M);\n        vector<int> obs = simulateNoisyDegrees(book.code[s], book.N, book.eps, rng);\n        int pred = decodeDegrees(book, obs);\n        if (pred != s) err++;\n    }\n\n    return err;\n}\n\nvector<int> candidateNs(int M, double eps) {\n    int minN = max(4, ceilLog2Int(M) + 1);\n\n    vector<int> ns;\n\n    if (eps <= 1e-12) {\n        ns.push_back(minN);\n        return ns;\n    }\n\n    int maxN;\n    if (eps <= 0.01) maxN = min(100, minN + 15);\n    else if (eps <= 0.05) maxN = min(100, minN + 40);\n    else if (eps <= 0.15) maxN = 80;\n    else maxN = 100;\n\n    for (int n = minN; n <= maxN; ) {\n        ns.push_back(n);\n\n        int step;\n        if (eps <= 0.05) {\n            if (n < 30) step = 1;\n            else if (n < 60) step = 3;\n            else step = 5;\n        } else {\n            if (n < 30) step = 2;\n            else if (n < 70) step = 5;\n            else step = 10;\n        }\n\n        n += step;\n    }\n\n    if (ns.empty() || ns.back() != maxN) ns.push_back(maxN);\n    if (eps >= 0.18 && ns.back() != 100) ns.push_back(100);\n\n    sort(ns.begin(), ns.end());\n    ns.erase(unique(ns.begin(), ns.end()), ns.end());\n    return ns;\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 epsInt = (int)llround(eps * 100);\n    FastRNG rng(123456789ULL + 10007ULL * M + 1000003ULL * epsInt);\n\n    Codebook bestBook;\n    double bestValue = -1.0;\n\n    vector<int> ns = candidateNs(M, eps);\n\n    for (int N : ns) {\n        Codebook book = buildCodebook(M, N, eps, rng);\n        if ((int)book.code.size() != M) continue;\n\n        double value;\n\n        if (eps <= 1e-12) {\n            value = 1.0 / N;\n        } else {\n            int T;\n            if (eps <= 0.03) T = 320;\n            else if (eps <= 0.15) T = 260;\n            else T = 220;\n\n            int err = simulateErrors(book, T, rng);\n\n            double p = (err + 0.25) / (T + 0.5);\n            value = exp(100.0 * log(max(1e-12, 1.0 - 0.1 * p))) / N;\n        }\n\n        if (value > bestValue) {\n            bestValue = value;\n            bestBook = std::move(book);\n        }\n    }\n\n    if ((int)bestBook.code.size() != M) {\n        int N = max(4, ceilLog2Int(M) + 1);\n        bestBook = buildCodebook(M, N, eps, rng);\n    }\n\n    cout << bestBook.N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << bestBook.out[k] << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        vector<int> obs = parseObservedDegrees(H, bestBook.N);\n        int ans = decodeDegrees(bestBook, obs);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF = (1LL << 60);\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int root(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = root(a);\n        b = root(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    int mx, my;\n    ll len2;\n};\n\nstruct Adj {\n    int to, w, id;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<vector<Adj>> g;\nvector<int> X, Y;\nvector<int> degv;\nmt19937 rng(1234567);\n\nuint64_t morton_key(int x, int y) {\n    uint64_t r = 0;\n    for (int i = 0; i < 12; i++) {\n        r |= uint64_t((x >> i) & 1) << (2 * i);\n        r |= uint64_t((y >> i) & 1) << (2 * i + 1);\n    }\n    return r;\n}\n\nvoid dijkstra_fill(int s, const vector<int>* assign, int ban_day, vector<ll>& dist) {\n    fill(dist.begin(), dist.end(), INF);\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 [du, u] = pq.top();\n        pq.pop();\n        if (du != dist[u]) continue;\n        for (const auto& e : g[u]) {\n            if (assign && (*assign)[e.id] == ban_day) continue;\n            ll nd = du + e.w;\n            if (nd < dist[e.to]) {\n                dist[e.to] = nd;\n                pq.push({nd, e.to});\n            }\n        }\n    }\n}\n\nbool connected_day(const vector<int>& assign, int day) {\n    if (M - count(assign.begin(), assign.end(), day) < N - 1) return false;\n    DSU uf(N);\n    for (int i = 0; i < M; i++) {\n        if (assign[i] != day) uf.unite(edges[i].u, edges[i].v);\n    }\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n    return true;\n}\n\nbool all_connected(const vector<int>& assign) {\n    for (int d = 0; d < D; d++) {\n        if (!connected_day(assign, d)) return false;\n    }\n    return true;\n}\n\nbool can_add_removal_keep_connected(const vector<int>& assign, int day, int eid) {\n    DSU uf(N);\n    int rem = 0;\n    for (int i = 0; i < M; i++) {\n        if (assign[i] == day || i == eid) {\n            rem++;\n        } else {\n            uf.unite(edges[i].u, edges[i].v);\n        }\n    }\n    if (M - rem < N - 1) return false;\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n    return true;\n}\n\nvoid repair_isolated(vector<int>& assign) {\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n    for (int i = 0; i < M; i++) {\n        int d = assign[i];\n        load[d]++;\n        vc[edges[i].u][d]++;\n        vc[edges[i].v][d]++;\n    }\n\n    bool changed = true;\n    int loop = 0;\n    while (changed && loop++ < 20) {\n        changed = false;\n        for (int v = 0; v < N; v++) {\n            for (int d = 0; d < D; d++) {\n                if (vc[v][d] < degv[v]) continue;\n\n                int eid = -1;\n                for (auto& a : g[v]) {\n                    if (assign[a.id] == d) {\n                        eid = a.id;\n                        break;\n                    }\n                }\n                if (eid == -1) continue;\n\n                int u = edges[eid].u;\n                int w = edges[eid].v;\n                int best = -1;\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == d) continue;\n                    if (load[nd] >= K) continue;\n                    if (vc[u][nd] + 1 >= degv[u]) continue;\n                    if (vc[w][nd] + 1 >= degv[w]) continue;\n                    best = nd;\n                    break;\n                }\n                if (best == -1) {\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd != d && load[nd] < K) {\n                            best = nd;\n                            break;\n                        }\n                    }\n                }\n                if (best != -1) {\n                    assign[eid] = best;\n                    load[d]--;\n                    load[best]++;\n                    vc[u][d]--;\n                    vc[w][d]--;\n                    vc[u][best]++;\n                    vc[w][best]++;\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\nvoid repair_connectivity(vector<int>& assign, const Timer& timer, double limit_time) {\n    vector<int> load(D, 0);\n    for (int x : assign) load[x]++;\n\n    for (int iter = 0; iter < 200 && timer.elapsed() < limit_time; iter++) {\n        bool changed = false;\n\n        for (int day = 0; day < D && timer.elapsed() < limit_time; day++) {\n            DSU uf(N);\n            int rem = 0;\n            for (int i = 0; i < M; i++) {\n                if (assign[i] == day) rem++;\n                else uf.unite(edges[i].u, edges[i].v);\n            }\n            int r0 = uf.root(0);\n            bool ok = true;\n            for (int i = 1; i < N; i++) {\n                if (uf.root(i) != r0) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (ok) continue;\n\n            vector<int> cand;\n            cand.reserve(rem);\n            for (int i = 0; i < M; i++) {\n                if (assign[i] == day && uf.root(edges[i].u) != uf.root(edges[i].v)) {\n                    cand.push_back(i);\n                }\n            }\n            shuffle(cand.begin(), cand.end(), rng);\n\n            bool moved = false;\n            for (int eid : cand) {\n                int best_day = -1;\n                int best_cost = INT_MAX;\n\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == day) continue;\n                    if (load[nd] >= K) continue;\n\n                    int cost = load[nd];\n                    if (!can_add_removal_keep_connected(assign, nd, eid)) {\n                        cost += 1000000;\n                    }\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_day = nd;\n                    }\n                }\n\n                if (best_day != -1) {\n                    assign[eid] = best_day;\n                    load[day]--;\n                    load[best_day]++;\n                    changed = true;\n                    moved = true;\n                    break;\n                }\n            }\n\n            if (moved) break;\n        }\n\n        if (!changed) break;\n        if (all_connected(assign)) break;\n    }\n}\n\nvector<int> make_order(int type) {\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    if (type == 0) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) < morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 1) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) > morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 2) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].mx != edges[b].mx) return edges[a].mx < edges[b].mx;\n            return edges[a].my < edges[b].my;\n        });\n    } else if (type == 3) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].my != edges[b].my) return edges[a].my < edges[b].my;\n            return edges[a].mx < edges[b].mx;\n        });\n    } else if (type == 4) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx + edges[a].my < edges[b].mx + edges[b].my;\n        });\n    } else if (type == 5) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx - edges[a].my < edges[b].mx - edges[b].my;\n        });\n    } else if (type == 6) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].len2 > edges[b].len2;\n        });\n    } else {\n        int A = uniform_int_distribution<int>(-1000, 1000)(rng);\n        int B = uniform_int_distribution<int>(-1000, 1000)(rng);\n        if (A == 0 && B == 0) A = 1;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ll va = 1LL * A * edges[a].mx + 1LL * B * edges[a].my;\n            ll vb = 1LL * A * edges[b].mx + 1LL * B * edges[b].my;\n            if (va != vb) return va < vb;\n            return a < b;\n        });\n    }\n    return ord;\n}\n\nvector<int> construct_cyclic(int type) {\n    vector<int> ord = make_order(type);\n    vector<int> perm(D);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n\n    int shift = uniform_int_distribution<int>(0, D - 1)(rng);\n    vector<int> assign(M);\n    for (int i = 0; i < M; i++) {\n        assign[ord[i]] = perm[(i + shift) % D];\n    }\n    repair_isolated(assign);\n    return assign;\n}\n\nvector<int> construct_greedy(int type) {\n    vector<int> ord;\n    if (type == 100) {\n        ord.resize(M);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n    } else {\n        ord = make_order(type);\n    }\n\n    vector<int> target(D, M / D);\n    for (int i = 0; i < M % D; i++) target[i]++;\n    shuffle(target.begin(), target.end(), rng);\n\n    vector<int> assign(M, -1);\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n\n    const int G = 18;\n    vector<vector<int>> cell(D, vector<int>(G * G, 0));\n\n    auto cid = [&](int eid) {\n        int cx = min(G - 1, max(0, edges[eid].mx * G / 2001));\n        int cy = min(G - 1, max(0, edges[eid].my * G / 2001));\n        return pair<int,int>(cx, cy);\n    };\n\n    for (int eid : ord) {\n        int u = edges[eid].u;\n        int v = edges[eid].v;\n        auto [cx, cy] = cid(eid);\n\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int pass = 0; pass < 2; pass++) {\n            best = -1;\n            best_cost = INT_MAX;\n\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= target[d]) continue;\n\n                if (pass == 0) {\n                    if (vc[u][d] + 1 >= degv[u]) continue;\n                    if (vc[v][d] + 1 >= degv[v]) continue;\n                }\n\n                int near = 0;\n                for (int dx = -1; dx <= 1; dx++) {\n                    for (int dy = -1; dy <= 1; dy++) {\n                        int nx = cx + dx;\n                        int ny = cy + dy;\n                        if (0 <= nx && nx < G && 0 <= ny && ny < G) {\n                            near += cell[d][nx * G + ny];\n                        }\n                    }\n                }\n\n                int cost = 0;\n                cost += (vc[u][d] + vc[v][d]) * 100000;\n                cost += near * 700;\n                cost += load[d] * 5;\n                cost += uniform_int_distribution<int>(0, 999)(rng);\n\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best = d;\n                }\n            }\n\n            if (best != -1) break;\n        }\n\n        if (best == -1) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] < target[d]) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n\n        assign[eid] = best;\n        load[best]++;\n        vc[u][best]++;\n        vc[v][best]++;\n        cell[best][cx * G + cy]++;\n    }\n\n    repair_isolated(assign);\n    return assign;\n}\n\nll evaluate_schedule(\n    const vector<int>& assign,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist\n) {\n    vector<int> load(D, 0);\n    for (int x : assign) {\n        if (x < 0 || x >= D) return (ll)4e18;\n        load[x]++;\n    }\n    for (int d = 0; d < D; d++) {\n        if (load[d] > K) return (ll)4e18;\n    }\n\n    // Connectivity is extremely important because unreachable pairs cost 1e9.\n    if (!all_connected(assign)) {\n        return (ll)3e18;\n    }\n\n    ll score = 0;\n    vector<ll> dist(N);\n\n    for (int day = 0; day < D; day++) {\n        for (int si = 0; si < S; si++) {\n            int s = sources[si];\n            dijkstra_fill(s, &assign, day, dist);\n            const auto& bd = base_dist[si];\n            for (int v = 0; v < N; v++) {\n                if (v == s) continue;\n                if (dist[v] >= INF / 2) {\n                    score += 1000000000LL - bd[v];\n                } else {\n                    score += dist[v] - bd[v];\n                }\n            }\n        }\n    }\n\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> D >> K;\n    edges.resize(M);\n    g.assign(N, {});\n    degv.assign(N, 0);\n\n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        g[u].push_back({v, w, i});\n        g[v].push_back({u, w, i});\n        degv[u]++;\n        degv[v]++;\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) {\n        cin >> X[i] >> Y[i];\n    }\n\n    for (int i = 0; i < M; i++) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n        edges[i].mx = X[u] + X[v];\n        edges[i].my = Y[u] + Y[v];\n        ll dx = X[u] - X[v];\n        ll dy = Y[u] - Y[v];\n        edges[i].len2 = dx * dx + dy * dy;\n    }\n\n    vector<int> vertices(N);\n    iota(vertices.begin(), vertices.end(), 0);\n    shuffle(vertices.begin(), vertices.end(), rng);\n\n    int Smax = min(N, 96);\n    int Ssmall = min(Smax, (D >= 20 ? 24 : 32));\n    int Sfinal = min(Smax, 80);\n\n    vector<int> sources(vertices.begin(), vertices.begin() + Smax);\n\n    vector<vector<ll>> base_dist(Smax, vector<ll>(N));\n    for (int i = 0; i < Smax; i++) {\n        dijkstra_fill(sources[i], nullptr, -1, base_dist[i]);\n    }\n\n    vector<pair<ll, vector<int>>> top;\n\n    auto add_candidate = [&](vector<int> assign) {\n        if (!all_connected(assign) && timer.elapsed() < 4.8) {\n            repair_connectivity(assign, timer, 4.9);\n        }\n\n        ll sc = evaluate_schedule(assign, Ssmall, sources, base_dist);\n\n        if ((int)top.size() < 8) {\n            top.push_back({sc, assign});\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        } else if (sc < top.back().first) {\n            top.back() = {sc, assign};\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        }\n    };\n\n    // Deterministic initial candidates.\n    for (int t = 0; t < 10 && timer.elapsed() < 4.5; t++) {\n        add_candidate(construct_cyclic(t % 8));\n    }\n    for (int t = 0; t < 10 && timer.elapsed() < 4.5; t++) {\n        add_candidate(construct_greedy(t % 8));\n    }\n\n    int iter = 0;\n    while (timer.elapsed() < 4.9) {\n        vector<int> cand;\n        if (iter % 3 == 0) {\n            cand = construct_greedy(100);\n        } else if (iter % 3 == 1) {\n            cand = construct_greedy(8 + iter);\n        } else {\n            cand = construct_cyclic(8 + iter);\n        }\n        add_candidate(std::move(cand));\n        iter++;\n    }\n\n    if (top.empty()) {\n        vector<int> fallback(M);\n        for (int i = 0; i < M; i++) fallback[i] = i % D;\n        repair_isolated(fallback);\n        top.push_back({0, fallback});\n    }\n\n    vector<int> best = top[0].second;\n    ll best_score = top[0].first;\n\n    // Re-evaluate promising candidates with more samples.\n    for (auto& p : top) {\n        if (timer.elapsed() > 5.55) break;\n        ll sc = evaluate_schedule(p.second, Sfinal, sources, base_dist);\n        if (sc < best_score || best_score >= (ll)3e18) {\n            best_score = sc;\n            best = p.second;\n        }\n    }\n\n    // Final emergency repair if possible.\n    if (!all_connected(best) && timer.elapsed() < 5.75) {\n        repair_connectivity(best, timer, 5.85);\n    }\n\n    // Ensure capacity, though constructions should already satisfy it.\n    vector<int> load(D, 0);\n    for (int x : best) load[x]++;\n    for (int i = 0; i < M; i++) {\n        if (load[best[i]] <= K) continue;\n        for (int d = 0; d < D; d++) {\n            if (load[d] < K) {\n                load[best[i]]--;\n                best[i] = d;\n                load[d]++;\n                break;\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << best[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nstring F[2][14], R_[2][14];\n\ninline int idx3(int x, int y, int z) {\n    return x * D * D + y * D + z;\n}\n\nstruct Rod {\n    vector<int> cells;\n};\n\nstruct Candidate {\n    vector<unsigned char> occ;\n    int volume = 0;\n};\n\nstruct LineDecomp {\n    vector<Rod> rods;\n    vector<int> lens;\n    int volume = 0;\n};\n\nstruct Cuboid {\n    vector<int> cells;\n    int a, b, c;\n    int key;\n    int vol;\n};\n\nstruct CuboidDecomp {\n    vector<Cuboid> cuboids;\n    int volume = 0;\n};\n\nstruct Params {\n    int extra;\n    int contW;\n    int futW;\n    int randAmp;\n    int reverse;\n    int favor;\n    uint32_t seed;\n};\n\nvector<pair<int,int>> solve_edge_cover(const vector<int>& X, const vector<int>& Y, int w[14][14]) {\n    int nx = (int)X.size();\n    int ny = (int)Y.size();\n    vector<pair<int,int>> res;\n\n    if (nx >= ny) {\n        int A = nx, B = ny;\n        int M = 1 << B;\n        const int NEG = -1000000000;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[i]][Y[j]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[i + 1][nm] = mask;\n                        ch[i + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int i = A; i >= 1; i--) {\n            int j = ch[i][mask];\n            int pm = pre[i][mask];\n            res.push_back({X[i - 1], Y[j]});\n            mask = pm;\n        }\n    } else {\n        int A = ny, B = nx;\n        int M = 1 << B;\n        const int NEG = -1000000000;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[j]][Y[i]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[i + 1][nm] = mask;\n                        ch[i + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int i = A; i >= 1; i--) {\n            int j = ch[i][mask];\n            int pm = pre[i][mask];\n            res.push_back({X[j], Y[i - 1]});\n            mask = pm;\n        }\n    }\n\n    return res;\n}\n\nCandidate build_candidate(int id, Params p) {\n    mt19937 rng(p.seed);\n\n    Candidate cand;\n    cand.occ.assign(D * D * D, 0);\n\n    bool prev[14][14] = {};\n\n    vector<int> zs;\n    if (!p.reverse) {\n        for (int z = 0; z < D; z++) zs.push_back(z);\n    } else {\n        for (int z = D - 1; z >= 0; z--) zs.push_back(z);\n    }\n\n    for (int ord = 0; ord < D; ord++) {\n        int z = zs[ord];\n        int zn = -1;\n        if (ord + 1 < D) zn = zs[ord + 1];\n\n        vector<int> X, Y;\n        for (int x = 0; x < D; x++) if (F[id][z][x] == '1') X.push_back(x);\n        for (int y = 0; y < D; y++) if (R_[id][z][y] == '1') Y.push_back(y);\n\n        int w[14][14] = {};\n        for (int x : X) {\n            for (int y : Y) {\n                int val = 0;\n                if (prev[x][y]) val += p.contW;\n                if (zn != -1 && F[id][zn][x] == '1' && R_[id][zn][y] == '1') {\n                    val += p.futW;\n                }\n                if (p.randAmp > 0) val += (int)(rng() % p.randAmp);\n                w[x][y] = val;\n            }\n        }\n\n        auto base = solve_edge_cover(X, Y, w);\n\n        bool sel[14][14] = {};\n        int cnt = 0;\n        for (auto [x, y] : base) {\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        int maxEdges = (int)X.size() * (int)Y.size();\n        int target = min(maxEdges, max((int)X.size(), (int)Y.size()) + p.extra);\n\n        vector<tuple<int,int,int>> add;\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) continue;\n\n                int sc = 0;\n                if (prev[x][y]) sc += 100000;\n                if (zn != -1 && F[id][zn][x] == '1' && R_[id][zn][y] == '1') sc += 20000;\n\n                if (p.favor == 1 || p.favor == 3) {\n                    if (x > 0 && sel[x - 1][y]) sc += 9000;\n                    if (x + 1 < D && sel[x + 1][y]) sc += 9000;\n                }\n                if (p.favor == 2 || p.favor == 3) {\n                    if (y > 0 && sel[x][y - 1]) sc += 9000;\n                    if (y + 1 < D && sel[x][y + 1]) sc += 9000;\n                }\n\n                sc += (int)(rng() % 1000);\n                add.push_back({sc, x, y});\n            }\n        }\n\n        sort(add.rbegin(), add.rend());\n\n        for (auto [sc, x, y] : add) {\n            if (cnt >= target) break;\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        memset(prev, 0, sizeof(prev));\n\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) {\n                    cand.occ[idx3(x, y, z)] = 1;\n                    prev[x][y] = true;\n                }\n            }\n        }\n    }\n\n    for (unsigned char v : cand.occ) cand.volume += v;\n    return cand;\n}\n\nLineDecomp decompose_lines(const Candidate& cand, int axis) {\n    LineDecomp dec;\n    dec.volume = cand.volume;\n\n    if (axis == 0) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                int x = 0;\n                while (x < D) {\n                    if (!cand.occ[idx3(x, y, z)]) {\n                        x++;\n                        continue;\n                    }\n                    Rod rod;\n                    while (x < D && cand.occ[idx3(x, y, z)]) {\n                        rod.cells.push_back(idx3(x, y, z));\n                        x++;\n                    }\n                    dec.lens.push_back((int)rod.cells.size());\n                    dec.rods.push_back(move(rod));\n                }\n            }\n        }\n    } else if (axis == 1) {\n        for (int x = 0; x < D; x++) {\n            for (int z = 0; z < D; z++) {\n                int y = 0;\n                while (y < D) {\n                    if (!cand.occ[idx3(x, y, z)]) {\n                        y++;\n                        continue;\n                    }\n                    Rod rod;\n                    while (y < D && cand.occ[idx3(x, y, z)]) {\n                        rod.cells.push_back(idx3(x, y, z));\n                        y++;\n                    }\n                    dec.lens.push_back((int)rod.cells.size());\n                    dec.rods.push_back(move(rod));\n                }\n            }\n        }\n    } else {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                int z = 0;\n                while (z < D) {\n                    if (!cand.occ[idx3(x, y, z)]) {\n                        z++;\n                        continue;\n                    }\n                    Rod rod;\n                    while (z < D && cand.occ[idx3(x, y, z)]) {\n                        rod.cells.push_back(idx3(x, y, z));\n                        z++;\n                    }\n                    dec.lens.push_back((int)rod.cells.size());\n                    dec.rods.push_back(move(rod));\n                }\n            }\n        }\n    }\n\n    return dec;\n}\n\nint cuboid_key(int dx, int dy, int dz) {\n    int a[3] = {dx, dy, dz};\n    sort(a, a + 3);\n    return a[0] * 256 + a[1] * 16 + a[2];\n}\n\nint cuboid_volume_from_key(int key) {\n    int a = key / 256;\n    int b = (key / 16) % 16;\n    int c = key % 16;\n    return a * b * c;\n}\n\nCuboidDecomp decompose_cuboids(const Candidate& cand) {\n    CuboidDecomp dec;\n    dec.volume = cand.volume;\n\n    vector<unsigned char> used(D * D * D, 0);\n\n    auto free_cell = [&](int x, int y, int z) {\n        int id = idx3(x, y, z);\n        return cand.occ[id] && !used[id];\n    };\n\n    for (int x0 = 0; x0 < D; x0++) {\n        for (int y0 = 0; y0 < D; y0++) {\n            for (int z0 = 0; z0 < D; z0++) {\n                if (!free_cell(x0, y0, z0)) continue;\n\n                int x1 = x0;\n                while (x1 < D && free_cell(x1, y0, z0)) x1++;\n\n                int y1 = y0 + 1;\n                while (y1 < D) {\n                    bool ok = true;\n                    for (int x = x0; x < x1; x++) {\n                        if (!free_cell(x, y1, z0)) {\n                            ok = false;\n                            break;\n                        }\n                    }\n                    if (!ok) break;\n                    y1++;\n                }\n\n                int z1 = z0 + 1;\n                while (z1 < D) {\n                    bool ok = true;\n                    for (int x = x0; x < x1 && ok; x++) {\n                        for (int y = y0; y < y1; y++) {\n                            if (!free_cell(x, y, z1)) {\n                                ok = false;\n                                break;\n                            }\n                        }\n                    }\n                    if (!ok) break;\n                    z1++;\n                }\n\n                Cuboid cb;\n                cb.a = x1 - x0;\n                cb.b = y1 - y0;\n                cb.c = z1 - z0;\n                cb.key = cuboid_key(cb.a, cb.b, cb.c);\n                cb.vol = cb.a * cb.b * cb.c;\n\n                for (int x = x0; x < x1; x++) {\n                    for (int y = y0; y < y1; y++) {\n                        for (int z = z0; z < z1; z++) {\n                            int id = idx3(x, y, z);\n                            used[id] = 1;\n                            cb.cells.push_back(id);\n                        }\n                    }\n                }\n\n                dec.cuboids.push_back(move(cb));\n            }\n        }\n    }\n\n    return dec;\n}\n\nlong double eval_lines(const LineDecomp& A, const LineDecomp& B) {\n    priority_queue<int> p, q;\n    for (int x : A.lens) p.push(x);\n    for (int x : B.lens) q.push(x);\n\n    long double score = 0;\n\n    for (int len = D; len >= 1; len--) {\n        while (!p.empty() && !q.empty() && p.top() >= len && q.top() >= len) {\n            int x = p.top(); p.pop();\n            int y = q.top(); q.pop();\n\n            score += 1.0L / len;\n\n            if (x - len > 0) p.push(x - len);\n            if (y - len > 0) q.push(y - len);\n        }\n    }\n\n    while (!p.empty()) {\n        score += p.top();\n        p.pop();\n    }\n    while (!q.empty()) {\n        score += q.top();\n        q.pop();\n    }\n\n    return score;\n}\n\nlong double eval_cuboids(const CuboidDecomp& A, const CuboidDecomp& B) {\n    unordered_map<int,int> ca, cb;\n    ca.reserve(512);\n    cb.reserve(512);\n\n    for (auto& c : A.cuboids) ca[c.key]++;\n    for (auto& c : B.cuboids) cb[c.key]++;\n\n    long double score = 0;\n\n    unordered_set<int> keys;\n    keys.reserve(ca.size() + cb.size() + 10);\n    for (auto [k, v] : ca) keys.insert(k);\n    for (auto [k, v] : cb) keys.insert(k);\n\n    for (int k : keys) {\n        int a = ca[k];\n        int b = cb[k];\n        int m = min(a, b);\n        int vol = cuboid_volume_from_key(k);\n\n        score += (long double)m / vol;\n        score += (long double)(a - m) * vol;\n        score += (long double)(b - m) * vol;\n    }\n\n    return score;\n}\n\nstruct Piece {\n    int len;\n    int rod;\n    int off;\n\n    bool operator<(const Piece& other) const {\n        if (len != other.len) return len < other.len;\n        if (rod != other.rod) return rod < other.rod;\n        return off < other.off;\n    }\n};\n\nvoid mark_line_piece(vector<int>& out, const LineDecomp& dec, const Piece& p, int useLen, int blockId) {\n    const Rod& rod = dec.rods[p.rod];\n    for (int i = 0; i < useLen; i++) {\n        out[rod.cells[p.off + i]] = blockId;\n    }\n}\n\nvoid output_line_solution(const LineDecomp& A, const LineDecomp& B) {\n    vector<int> out1(D * D * D, 0), out2(D * D * D, 0);\n\n    priority_queue<Piece> pq1, pq2;\n\n    for (int i = 0; i < (int)A.rods.size(); i++) {\n        pq1.push({(int)A.rods[i].cells.size(), i, 0});\n    }\n    for (int i = 0; i < (int)B.rods.size(); i++) {\n        pq2.push({(int)B.rods[i].cells.size(), i, 0});\n    }\n\n    int blockId = 0;\n\n    for (int len = D; len >= 1; len--) {\n        while (!pq1.empty() && !pq2.empty() && pq1.top().len >= len && pq2.top().len >= len) {\n            Piece a = pq1.top(); pq1.pop();\n            Piece b = pq2.top(); pq2.pop();\n\n            blockId++;\n            mark_line_piece(out1, A, a, len, blockId);\n            mark_line_piece(out2, B, b, len, blockId);\n\n            if (a.len - len > 0) {\n                pq1.push({a.len - len, a.rod, a.off + len});\n            }\n            if (b.len - len > 0) {\n                pq2.push({b.len - len, b.rod, b.off + len});\n            }\n        }\n    }\n\n    while (!pq1.empty()) {\n        Piece a = pq1.top(); pq1.pop();\n        blockId++;\n        mark_line_piece(out1, A, a, a.len, blockId);\n    }\n\n    while (!pq2.empty()) {\n        Piece b = pq2.top(); pq2.pop();\n        blockId++;\n        mark_line_piece(out2, B, b, b.len, blockId);\n    }\n\n    cout << blockId << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << out1[i];\n    }\n    cout << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << out2[i];\n    }\n    cout << '\\n';\n}\n\nvoid mark_cuboid(vector<int>& out, const Cuboid& c, int blockId) {\n    for (int id : c.cells) out[id] = blockId;\n}\n\nvoid output_cuboid_solution(const CuboidDecomp& A, const CuboidDecomp& B) {\n    vector<int> out1(D * D * D, 0), out2(D * D * D, 0);\n\n    unordered_map<int, vector<int>> ma, mb;\n    ma.reserve(512);\n    mb.reserve(512);\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) ma[A.cuboids[i].key].push_back(i);\n    for (int i = 0; i < (int)B.cuboids.size(); i++) mb[B.cuboids[i].key].push_back(i);\n\n    unordered_set<int> keys;\n    keys.reserve(ma.size() + mb.size() + 10);\n    for (auto& kv : ma) keys.insert(kv.first);\n    for (auto& kv : mb) keys.insert(kv.first);\n\n    int blockId = 0;\n\n    for (int k : keys) {\n        auto& va = ma[k];\n        auto& vb = mb[k];\n\n        int m = min((int)va.size(), (int)vb.size());\n\n        for (int i = 0; i < m; i++) {\n            blockId++;\n            mark_cuboid(out1, A.cuboids[va[i]], blockId);\n            mark_cuboid(out2, B.cuboids[vb[i]], blockId);\n        }\n\n        for (int i = m; i < (int)va.size(); i++) {\n            blockId++;\n            mark_cuboid(out1, A.cuboids[va[i]], blockId);\n        }\n\n        for (int i = m; i < (int)vb.size(); i++) {\n            blockId++;\n            mark_cuboid(out2, B.cuboids[vb[i]], blockId);\n        }\n    }\n\n    cout << blockId << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << out1[i];\n    }\n    cout << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << out2[i];\n    }\n    cout << '\\n';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D;\n\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) cin >> F[i][z];\n        for (int z = 0; z < D; z++) cin >> R_[i][z];\n    }\n\n    vector<Params> params;\n    vector<int> extras = {0, 1, 2, 4, 7, 12, 1000};\n\n    uint32_t baseSeed = 246813579u;\n\n    for (int e : extras) {\n        for (int rev = 0; rev < 2; rev++) {\n            for (int rep = 0; rep < 2; rep++) {\n                Params p;\n                p.extra = e;\n                p.contW = 1000 + rep * 400;\n                p.futW = 80 + rep * 80;\n                p.randAmp = 60;\n                p.reverse = rev;\n                p.favor = rep + 1;\n                p.seed = baseSeed + e * 10007u + rev * 1000003u + rep * 9176u;\n                params.push_back(p);\n            }\n        }\n    }\n\n    vector<Candidate> cand[2];\n\n    for (int id = 0; id < 2; id++) {\n        for (auto p : params) {\n            p.seed += id * 998244353u;\n            cand[id].push_back(build_candidate(id, p));\n        }\n    }\n\n    int n0 = cand[0].size();\n    int n1 = cand[1].size();\n\n    vector<array<LineDecomp, 3>> lines[2];\n    vector<CuboidDecomp> cubs[2];\n\n    lines[0].resize(n0);\n    lines[1].resize(n1);\n    cubs[0].resize(n0);\n    cubs[1].resize(n1);\n\n    for (int id = 0; id < 2; id++) {\n        int n = cand[id].size();\n        for (int i = 0; i < n; i++) {\n            for (int ax = 0; ax < 3; ax++) {\n                lines[id][i][ax] = decompose_lines(cand[id][i], ax);\n            }\n            cubs[id][i] = decompose_cuboids(cand[id][i]);\n        }\n    }\n\n    long double bestScore = 1e100L;\n    int bestType = 0;\n    int bestI = 0, bestJ = 0;\n    int bestAx0 = 0, bestAx1 = 0;\n\n    for (int i = 0; i < n0; i++) {\n        for (int j = 0; j < n1; j++) {\n            for (int ax0 = 0; ax0 < 3; ax0++) {\n                for (int ax1 = 0; ax1 < 3; ax1++) {\n                    long double sc = eval_lines(lines[0][i][ax0], lines[1][j][ax1]);\n                    if (sc < bestScore) {\n                        bestScore = sc;\n                        bestType = 0;\n                        bestI = i;\n                        bestJ = j;\n                        bestAx0 = ax0;\n                        bestAx1 = ax1;\n                    }\n                }\n            }\n\n            long double sc2 = eval_cuboids(cubs[0][i], cubs[1][j]);\n            if (sc2 < bestScore) {\n                bestScore = sc2;\n                bestType = 1;\n                bestI = i;\n                bestJ = j;\n                bestAx0 = bestAx1 = 0;\n            }\n        }\n    }\n\n    if (bestType == 0) {\n        output_line_solution(lines[0][bestI][bestAx0], lines[1][bestJ][bestAx1]);\n    } else {\n        output_cuboid_solution(cubs[0][bestI], cubs[1][bestJ]);\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) x = p[x] = p[p[x]];\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstatic const long long INF = (1LL << 60);\n\nint N, M, K;\nvector<int> X, Y;\nvector<Edge> edges;\nvector<int> A, RY;\n\nvector<vector<int>> cdist;\nvector<vector<pair<int,int>>> sortedRes;\n\nvector<vector<long long>> fw;\nvector<vector<int>> nxtv;\nvector<vector<int>> directEdge;\n\nchrono::steady_clock::time_point st_time;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st_time).count();\n}\n\nint ceil_sqrt_ll(long long x) {\n    long long r = sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r > 0 && (r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nvoid add_path_edges(int s, int t, vector<char>& sel) {\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n    }\n}\n\nvoid add_path_edges_mark(int s, int t, vector<char>& sel, vector<char>& inTree) {\n    inTree[s] = 1;\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n        inTree[s] = 1;\n    }\n}\n\npair<long long, vector<int>> build_best_tree(const vector<int>& P) {\n    long long bestCost = INF;\n    vector<int> bestB(M, 0);\n\n    auto consider = [&](vector<char> sel) {\n        vector<char> terminal(N, 0);\n        terminal[0] = 1;\n        for (int i = 0; i < N; i++) if (P[i] > 0) terminal[i] = 1;\n\n        vector<vector<pair<int,int>>> g(N);\n        vector<int> deg(N, 0);\n\n        for (int e = 0; e < M; e++) if (sel[e]) {\n            int u = edges[e].u, v = edges[e].v;\n            g[u].push_back({v, e});\n            g[v].push_back({u, e});\n            deg[u]++;\n            deg[v]++;\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (!terminal[i] && deg[i] <= 1) q.push(i);\n        }\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            if (terminal[v] || deg[v] != 1) continue;\n\n            for (auto [to, eid] : g[v]) {\n                if (!sel[eid]) continue;\n                sel[eid] = 0;\n                deg[v]--;\n                deg[to]--;\n                if (!terminal[to] && deg[to] == 1) q.push(to);\n                break;\n            }\n        }\n\n        long long cost = 0;\n        vector<int> B(M, 0);\n        for (int e = 0; e < M; e++) {\n            if (sel[e]) {\n                cost += edges[e].w;\n                B[e] = 1;\n            }\n        }\n\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestB = B;\n        }\n    };\n\n    vector<int> terms;\n    terms.push_back(0);\n    for (int i = 1; i < N; i++) if (P[i] > 0) terms.push_back(i);\n\n    int T = (int)terms.size();\n\n    // Metric-closure MST over terminals.\n    {\n        vector<char> sel(M, 0);\n\n        if (T >= 2) {\n            vector<long long> minD(T, INF);\n            vector<int> par(T, -1);\n            vector<char> used(T, 0);\n            minD[0] = 0;\n\n            for (int it = 0; it < T; it++) {\n                int v = -1;\n                for (int i = 0; i < T; i++) {\n                    if (!used[i] && (v == -1 || minD[i] < minD[v])) v = i;\n                }\n\n                if (v == -1) break;\n                used[v] = 1;\n\n                if (par[v] != -1) {\n                    add_path_edges(terms[v], terms[par[v]], sel);\n                }\n\n                for (int to = 0; to < T; to++) {\n                    if (!used[to] && fw[terms[v]][terms[to]] < minD[to]) {\n                        minD[to] = fw[terms[v]][terms[to]];\n                        par[to] = v;\n                    }\n                }\n            }\n        }\n\n        consider(sel);\n    }\n\n    // Union of shortest paths from root.\n    {\n        vector<char> sel(M, 0);\n        for (int i = 1; i < N; i++) {\n            if (P[i] > 0) add_path_edges(0, i, sel);\n        }\n        consider(sel);\n    }\n\n    // Ordinary graph MST, pruned.\n    {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].w < edges[b].w;\n        });\n\n        DSU dsu(N);\n        vector<char> sel(M, 0);\n\n        for (int eid : ord) {\n            if (dsu.unite(edges[eid].u, edges[eid].v)) {\n                sel[eid] = 1;\n            }\n        }\n\n        consider(sel);\n    }\n\n    // Incremental Steiner-style connections with several terminal orders.\n    {\n        vector<int> base;\n        for (int i = 1; i < N; i++) if (P[i] > 0) base.push_back(i);\n\n        vector<vector<int>> orders;\n\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return fw[0][a] < fw[0][b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return fw[0][a] > fw[0][b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return P[a] > P[b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return P[a] < P[b];\n            });\n            orders.push_back(v);\n        }\n\n        for (auto ord : orders) {\n            vector<char> sel(M, 0);\n            vector<char> inTree(N, 0);\n            inTree[0] = 1;\n\n            for (int t : ord) {\n                int best = -1;\n                long long bd = INF;\n\n                for (int v = 0; v < N; v++) {\n                    if (inTree[v] && fw[t][v] < bd) {\n                        bd = fw[t][v];\n                        best = v;\n                    }\n                }\n\n                if (best != -1) {\n                    add_path_edges_mark(t, best, sel, inTree);\n                }\n            }\n\n            consider(sel);\n        }\n    }\n\n    return {bestCost, bestB};\n}\n\nlong long total_cost(const vector<int>& P) {\n    long long radio = 0;\n    for (int p : P) radio += 1LL * p * p;\n\n    auto tr = build_best_tree(P);\n    return radio + tr.first;\n}\n\nbool compute_covered(const vector<int>& P, vector<char>& covered) {\n    covered.assign(K, 0);\n    int cnt = 0;\n\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                covered[k] = 1;\n                cnt++;\n                break;\n            }\n        }\n    }\n\n    return cnt == K;\n}\n\nvoid reduce_powers(vector<int>& P) {\n    vector<int> coverCnt(K, 0);\n\n    for (int i = 0; i < N; i++) if (P[i] > 0) {\n        for (int k = 0; k < K; k++) {\n            if (cdist[i][k] <= P[i]) coverCnt[k]++;\n        }\n    }\n\n    bool changed = true;\n    int loop = 0;\n\n    while (changed && loop < 12) {\n        loop++;\n        changed = false;\n\n        for (int i = 0; i < N; i++) {\n            int old = P[i];\n            if (old == 0) continue;\n\n            int req = 0;\n\n            for (int k = 0; k < K; k++) {\n                if (cdist[i][k] <= old && coverCnt[k] == 1) {\n                    req = max(req, cdist[i][k]);\n                }\n            }\n\n            if (req < old) {\n                for (int k = 0; k < K; k++) {\n                    if (cdist[i][k] <= old && cdist[i][k] > req) {\n                        coverCnt[k]--;\n                    }\n                }\n\n                P[i] = req;\n                changed = true;\n            }\n        }\n    }\n}\n\nbool greedy_complete(\n    vector<int>& P,\n    double alpha,\n    bool dynamicConn,\n    int capStation = -1,\n    int capRadius = 5000\n) {\n    vector<char> covered(K, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; k++) {\n        bool ok = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                ok = true;\n                break;\n            }\n        }\n\n        covered[k] = ok;\n        if (!ok) uncovered++;\n    }\n\n    vector<int> activeList;\n    activeList.push_back(0);\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0 && i != 0) activeList.push_back(i);\n    }\n\n    vector<double> rootPen(N, 0.0);\n    for (int i = 0; i < N; i++) rootPen[i] = alpha * (double)fw[0][i];\n\n    while (uncovered > 0) {\n        int bestI = -1;\n        int bestR = -1;\n        int bestGain = 0;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            int old = P[i];\n\n            if (i == capStation && old >= capRadius) continue;\n\n            double connPen = 0.0;\n\n            if (old == 0) {\n                if (dynamicConn) {\n                    long long md = INF;\n                    for (int a : activeList) md = min(md, fw[i][a]);\n                    connPen = alpha * (double)md;\n                } else {\n                    connPen = rootPen[i];\n                }\n            }\n\n            int gain = 0;\n            const auto& vec = sortedRes[i];\n\n            for (int idx = 0; idx < (int)vec.size();) {\n                int r = vec[idx].first;\n\n                if (r > 5000) break;\n                if (i == capStation && r > capRadius) break;\n\n                int add = 0;\n                while (idx < (int)vec.size() && vec[idx].first == r) {\n                    int k = vec[idx].second;\n                    if (r > old && !covered[k]) add++;\n                    idx++;\n                }\n\n                if (r <= old) continue;\n\n                gain += add;\n\n                if (gain > 0) {\n                    double delta = (double)r * r - (double)old * old;\n                    if (old == 0) delta += connPen;\n\n                    double score = delta / gain;\n\n                    if (score < bestScore ||\n                        (abs(score - bestScore) < 1e-9 && gain > bestGain)) {\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestGain = gain;\n                    }\n                }\n            }\n        }\n\n        if (bestI == -1) return false;\n\n        bool wasZero = (P[bestI] == 0);\n        P[bestI] = bestR;\n\n        if (wasZero) activeList.push_back(bestI);\n\n        for (auto [r, k] : sortedRes[bestI]) {\n            if (r > bestR) break;\n            if (!covered[k]) {\n                covered[k] = 1;\n                uncovered--;\n            }\n        }\n    }\n\n    return true;\n}\n\nvector<int> initial_nearest_solution() {\n    vector<int> P(N, 0);\n\n    for (int k = 0; k < K; k++) {\n        int bi = -1;\n        int bd = 1e9;\n\n        for (int i = 0; i < N; i++) {\n            if (cdist[i][k] <= 5000 && cdist[i][k] < bd) {\n                bd = cdist[i][k];\n                bi = i;\n            }\n        }\n\n        if (bi == -1) {\n            for (int i = 0; i < N; i++) {\n                if (cdist[i][k] < bd) {\n                    bd = cdist[i][k];\n                    bi = i;\n                }\n            }\n        }\n\n        P[bi] = max(P[bi], bd);\n    }\n\n    reduce_powers(P);\n    return P;\n}\n\nint lower_existing_radius(int station, int limit) {\n    int res = 0;\n    for (auto [d, k] : sortedRes[station]) {\n        if (d <= limit) res = d;\n        else break;\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st_time = chrono::steady_clock::now();\n\n    cin >> N >> M >> K;\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n        edges[i] = {u, v, w};\n    }\n\n    A.resize(K);\n    RY.resize(K);\n    for (int k = 0; k < K; k++) cin >> A[k] >> RY[k];\n\n    fw.assign(N, vector<long long>(N, INF));\n    nxtv.assign(N, vector<int>(N, -1));\n    directEdge.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; i++) {\n        fw[i][i] = 0;\n        nxtv[i][i] = i;\n    }\n\n    for (int e = 0; e < M; e++) {\n        int u = edges[e].u;\n        int v = edges[e].v;\n        long long w = edges[e].w;\n\n        if (w < fw[u][v]) {\n            fw[u][v] = fw[v][u] = w;\n            nxtv[u][v] = v;\n            nxtv[v][u] = u;\n            directEdge[u][v] = directEdge[v][u] = e;\n        }\n    }\n\n    for (int k = 0; k < N; k++) {\n        for (int i = 0; i < N; i++) if (fw[i][k] < INF) {\n            for (int j = 0; j < N; j++) if (fw[k][j] < INF) {\n                long long nd = fw[i][k] + fw[k][j];\n\n                if (nd < fw[i][j]) {\n                    fw[i][j] = nd;\n                    nxtv[i][j] = nxtv[i][k];\n                }\n            }\n        }\n    }\n\n    cdist.assign(N, vector<int>(K));\n    sortedRes.assign(N, {});\n\n    for (int i = 0; i < N; i++) {\n        sortedRes[i].reserve(K);\n\n        for (int k = 0; k < K; k++) {\n            long long dx = X[i] - A[k];\n            long long dy = Y[i] - RY[k];\n            int d = ceil_sqrt_ll(dx * dx + dy * dy);\n\n            cdist[i][k] = d;\n\n            if (d <= 5000) {\n                sortedRes[i].push_back({d, k});\n            }\n        }\n\n        sort(sortedRes[i].begin(), sortedRes[i].end());\n    }\n\n    vector<int> bestP = initial_nearest_solution();\n    long long bestS = total_cost(bestP);\n    double bestAlpha = 0.2;\n    bool bestDyn = true;\n\n    vector<double> alphas = {\n        0.0, 0.02, 0.05, 0.08, 0.12, 0.18,\n        0.27, 0.4, 0.6, 0.9, 1.3\n    };\n\n    // Static and dynamic greedy initial constructions.\n    for (double alpha : alphas) {\n        if (elapsed_sec() > 1.10) break;\n\n        for (int dyn = 0; dyn <= 1; dyn++) {\n            if (elapsed_sec() > 1.20) break;\n\n            vector<int> P(N, 0);\n            bool ok = greedy_complete(P, alpha, dyn == 1);\n\n            if (!ok) continue;\n\n            reduce_powers(P);\n            long long S = total_cost(P);\n\n            if (S < bestS) {\n                bestS = S;\n                bestP = P;\n                bestAlpha = alpha;\n                bestDyn = (dyn == 1);\n            }\n        }\n    }\n\n    vector<double> repairAlphas = {\n        0.0,\n        max(0.05, min(0.7, bestAlpha)),\n        0.25,\n        0.55\n    };\n\n    // Local search: remove or shrink active stations, then repair.\n    while (elapsed_sec() < 1.86) {\n        bool improved = false;\n        vector<int> nextBestP = bestP;\n        long long nextBestS = bestS;\n\n        vector<int> active;\n        for (int i = 0; i < N; i++) {\n            if (bestP[i] > 0) active.push_back(i);\n        }\n\n        sort(active.begin(), active.end(), [&](int a, int b) {\n            long long ca = 1LL * bestP[a] * bestP[a];\n            long long cb = 1LL * bestP[b] * bestP[b];\n            return ca > cb;\n        });\n\n        for (int s : active) {\n            if (elapsed_sec() > 1.90) break;\n\n            int old = bestP[s];\n            vector<int> limits;\n\n            limits.push_back(0);\n            limits.push_back(lower_existing_radius(s, old / 4));\n            limits.push_back(lower_existing_radius(s, old / 2));\n            limits.push_back(lower_existing_radius(s, old * 3 / 4));\n\n            sort(limits.begin(), limits.end());\n            limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n            for (int lim : limits) {\n                if (elapsed_sec() > 1.92) break;\n                if (lim >= old) continue;\n\n                for (double ra : repairAlphas) {\n                    if (elapsed_sec() > 1.94) break;\n\n                    vector<int> P = bestP;\n                    P[s] = lim;\n\n                    bool ok = greedy_complete(P, ra, true, s, lim);\n                    if (!ok) continue;\n\n                    reduce_powers(P);\n                    long long S = total_cost(P);\n\n                    if (S < nextBestS) {\n                        nextBestS = S;\n                        nextBestP = P;\n                        improved = true;\n                    }\n                }\n            }\n        }\n\n        if (improved) {\n            bestS = nextBestS;\n            bestP = nextBestP;\n        } else {\n            break;\n        }\n    }\n\n    vector<char> covered;\n    if (!compute_covered(bestP, covered)) {\n        greedy_complete(bestP, 0.0, true);\n        reduce_powers(bestP);\n    }\n\n    auto tree = build_best_tree(bestP);\n    vector<int> ansB = tree.second;\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n\n    for (int e = 0; e < M; e++) {\n        if (e) cout << ' ';\n        cout << ansB[e];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = N * (N + 1) / 2;\nconstexpr int MAX_OPS = 10000;\n\nstruct Op {\n    int u, v;\n};\n\nint ID[N][N];\nint X[M], Y[M];\n\narray<int, M> initialA;\n\nvector<pair<int,int>> adjEdges;\nvector<pair<int,int>> downEdges;\nvector<vector<int>> incidentDown;\nbool isAdj[M][M];\n\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsedSec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nint calcE(const array<int, M>& a) {\n    int e = 0;\n    for (auto [p, c] : downEdges) {\n        if (a[p] > a[c]) e++;\n    }\n    return e;\n}\n\nbool isValidFinal(const array<int, M>& a) {\n    for (auto [p, c] : downEdges) {\n        if (a[p] > a[c]) return false;\n    }\n    return true;\n}\n\nstruct State {\n    array<int, M> a;\n    vector<Op> ops;\n    int E = 0;\n};\n\nint deltaSwapLocal(const array<int, M>& a, int u, int v) {\n    int ids[16], cnt = 0;\n\n    auto add = [&](int e) {\n        for (int i = 0; i < cnt; i++) {\n            if (ids[i] == e) return;\n        }\n        ids[cnt++] = e;\n    };\n\n    for (int e : incidentDown[u]) add(e);\n    for (int e : incidentDown[v]) add(e);\n\n    int before = 0, after = 0;\n\n    for (int i = 0; i < cnt; i++) {\n        auto [p, c] = downEdges[ids[i]];\n\n        before += (a[p] > a[c]);\n\n        int vp = a[p];\n        int vc = a[c];\n\n        if (p == u) vp = a[v];\n        else if (p == v) vp = a[u];\n\n        if (c == u) vc = a[v];\n        else if (c == v) vc = a[u];\n\n        after += (vp > vc);\n    }\n\n    return before - after;\n}\n\nvoid applySwap(State& s, int u, int v) {\n    int d = deltaSwapLocal(s.a, u, v);\n    s.E -= d;\n    swap(s.a[u], s.a[v]);\n    s.ops.push_back({u, v});\n}\n\nvector<int> yOrder(int x, int type) {\n    vector<int> ys;\n    for (int y = 0; y <= x; y++) ys.push_back(y);\n\n    if (type == 1) {\n        reverse(ys.begin(), ys.end());\n    } else if (type == 2) {\n        if (x & 1) reverse(ys.begin(), ys.end());\n    } else if (type == 3) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da < db;\n            return a < b;\n        });\n    } else if (type == 4) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da > db;\n            return a < b;\n        });\n    }\n\n    return ys;\n}\n\nState runHeapify(State s, int yType) {\n    for (int x = N - 2; x >= 0; x--) {\n        auto ys = yOrder(x, yType);\n\n        for (int sy : ys) {\n            int cx = x;\n            int cy = sy;\n            int cur = ID[cx][cy];\n\n            while (cx + 1 < N) {\n                int c1 = ID[cx + 1][cy];\n                int c2 = ID[cx + 1][cy + 1];\n\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[cur] > s.a[ch]) {\n                    applySwap(s, cur, ch);\n                    cur = ch;\n                    cx = X[cur];\n                    cy = Y[cur];\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    return s;\n}\n\nState runScanBubble(State s, int rowType, int yType, int limitOps) {\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        bool changed = false;\n\n        vector<int> rows;\n        if (rowType == 0) {\n            for (int x = N - 2; x >= 0; x--) rows.push_back(x);\n        } else {\n            for (int x = 0; x <= N - 2; x++) rows.push_back(x);\n        }\n\n        for (int x : rows) {\n            auto ys = yOrder(x, yType);\n\n            for (int y : ys) {\n                if ((int)s.ops.size() >= limitOps) break;\n\n                int p = ID[x][y];\n                int c1 = ID[x + 1][y];\n                int c2 = ID[x + 1][y + 1];\n\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[p] > s.a[ch]) {\n                    applySwap(s, p, ch);\n                    changed = true;\n                }\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    return s;\n}\n\nState runViolationGreedy(State s, int mode, int limitOps) {\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        int bu = -1, bv = -1;\n        long long bk1 = LLONG_MIN;\n        long long bk2 = LLONG_MIN;\n        long long bk3 = LLONG_MIN;\n\n        for (auto [p, c] : downEdges) {\n            if (s.a[p] <= s.a[c]) continue;\n\n            int imp = deltaSwapLocal(s.a, p, c);\n            int diff = s.a[p] - s.a[c];\n\n            long long k1, k2, k3;\n\n            if (mode == 0) {\n                k1 = imp;\n                k2 = diff;\n                k3 = -X[p];\n            } else if (mode == 1) {\n                k1 = diff;\n                k2 = imp;\n                k3 = -X[p];\n            } else if (mode == 2) {\n                k1 = -s.a[c];\n                k2 = imp;\n                k3 = diff;\n            } else {\n                k1 = -X[p];\n                k2 = imp;\n                k3 = diff;\n            }\n\n            if (\n                k1 > bk1 ||\n                (k1 == bk1 && (k2 > bk2 || (k2 == bk2 && k3 > bk3)))\n            ) {\n                bk1 = k1;\n                bk2 = k2;\n                bk3 = k3;\n                bu = p;\n                bv = c;\n            }\n        }\n\n        if (bu == -1) break;\n\n        applySwap(s, bu, bv);\n    }\n\n    return s;\n}\n\nvector<Op> reduceOps(const vector<Op>& ops) {\n    vector<Op> st;\n    st.reserve(ops.size());\n\n    auto sameEdge = [](const Op& a, const Op& b) {\n        return (a.u == b.u && a.v == b.v) || (a.u == b.v && a.v == b.u);\n    };\n\n    for (auto op : ops) {\n        if (!st.empty() && sameEdge(st.back(), op)) {\n            st.pop_back();\n        } else {\n            st.push_back(op);\n        }\n    }\n\n    return st;\n}\n\nbool validateOps(const vector<Op>& ops) {\n    if ((int)ops.size() > MAX_OPS) return false;\n\n    array<int, M> a = initialA;\n\n    for (auto [u, v] : ops) {\n        if (!isAdj[u][v]) return false;\n        swap(a[u], a[v]);\n    }\n\n    return isValidFinal(a);\n}\n\nbool validWithoutRange(const vector<Op>& ops, int l, int r) {\n    array<int, M> a = initialA;\n\n    for (int i = 0; i < (int)ops.size(); i++) {\n        if (l <= i && i < r) continue;\n        auto [u, v] = ops[i];\n        swap(a[u], a[v]);\n    }\n\n    return isValidFinal(a);\n}\n\nvector<Op> pruneOps(vector<Op> ops) {\n    ops = reduceOps(ops);\n\n    if (!validateOps(ops)) return ops;\n\n    // Greedy deletion of individual operations and short consecutive blocks.\n    // This keeps legality because coordinates of swaps themselves do not depend on ball labels.\n    vector<int> blockSchedule = {\n        1, 1, 2, 1, 3, 2, 1, 4, 2, 1\n    };\n\n    for (int pass = 0; pass < (int)blockSchedule.size(); pass++) {\n        if (elapsedSec() > 1.80) break;\n\n        int len = blockSchedule[pass];\n        bool changed = false;\n\n        if (pass % 2 == 0) {\n            for (int i = 0; i + len <= (int)ops.size();) {\n                if (elapsedSec() > 1.85) break;\n\n                if (validWithoutRange(ops, i, i + len)) {\n                    ops.erase(ops.begin() + i, ops.begin() + i + len);\n                    ops = reduceOps(ops);\n                    changed = true;\n                    if (i > 2) i -= 2;\n                } else {\n                    i++;\n                }\n            }\n        } else {\n            for (int i = (int)ops.size() - len; i >= 0;) {\n                if (elapsedSec() > 1.85) break;\n\n                if (validWithoutRange(ops, i, i + len)) {\n                    ops.erase(ops.begin() + i, ops.begin() + i + len);\n                    ops = reduceOps(ops);\n                    changed = true;\n                    i = min(i, (int)ops.size() - len);\n                    if (i > 2) i -= 2;\n                } else {\n                    i--;\n                }\n            }\n        }\n\n        if (!changed && len >= 2) {\n            // Larger blocks are unlikely to help if no deletion happened.\n            continue;\n        }\n    }\n\n    ops = reduceOps(ops);\n\n    return ops;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    int id = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            ID[x][y] = id;\n            X[id] = x;\n            Y[id] = y;\n            id++;\n        }\n    }\n\n    incidentDown.assign(M, {});\n\n    memset(isAdj, 0, sizeof(isAdj));\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int u = ID[x][y];\n\n            if (y + 1 <= x) {\n                int v = ID[x][y + 1];\n                adjEdges.push_back({u, v});\n                isAdj[u][v] = isAdj[v][u] = true;\n            }\n\n            if (x + 1 < N) {\n                int v1 = ID[x + 1][y];\n                int v2 = ID[x + 1][y + 1];\n\n                adjEdges.push_back({u, v1});\n                adjEdges.push_back({u, v2});\n\n                isAdj[u][v1] = isAdj[v1][u] = true;\n                isAdj[u][v2] = isAdj[v2][u] = true;\n\n                int e1 = (int)downEdges.size();\n                downEdges.push_back({u, v1});\n                incidentDown[u].push_back(e1);\n                incidentDown[v1].push_back(e1);\n\n                int e2 = (int)downEdges.size();\n                downEdges.push_back({u, v2});\n                incidentDown[u].push_back(e2);\n                incidentDown[v2].push_back(e2);\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> initialA[ID[x][y]];\n        }\n    }\n\n    State base;\n    base.a = initialA;\n    base.E = calcE(initialA);\n\n    vector<Op> bestOps;\n    bool haveBest = false;\n\n    auto tryCandidate = [&](const State& s) {\n        if (s.E != 0) return;\n\n        vector<Op> ops = s.ops;\n        ops = reduceOps(ops);\n\n        if ((int)ops.size() > MAX_OPS) return;\n        if (!validateOps(ops)) return;\n\n        // New important improvement.\n        ops = pruneOps(ops);\n\n        if ((int)ops.size() > MAX_OPS) return;\n        if (!validateOps(ops)) return;\n\n        if (!haveBest || ops.size() < bestOps.size()) {\n            bestOps = move(ops);\n            haveBest = true;\n        }\n    };\n\n    // 1. Robust bottom-up heapify variants.\n    for (int t = 0; t < 5; t++) {\n        State s = runHeapify(base, t);\n        tryCandidate(s);\n    }\n\n    // Safety fallback.\n    if (!haveBest) {\n        State s = runHeapify(base, 0);\n        bestOps = reduceOps(s.ops);\n        haveBest = true;\n    }\n\n    int bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n\n    // 2. Repeated one-step bubble variants.\n    if (bestLimit > 0 && elapsedSec() < 1.55) {\n        for (int rowType = 0; rowType < 2; rowType++) {\n            for (int yType = 0; yType < 5; yType++) {\n                State s = runScanBubble(base, rowType, yType, bestLimit);\n                tryCandidate(s);\n\n                bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n\n                if (bestLimit <= 0 || elapsedSec() > 1.65) break;\n            }\n            if (bestLimit <= 0 || elapsedSec() > 1.65) break;\n        }\n    }\n\n    // 3. Greedy repair based on current violating edges.\n    bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n\n    if (bestLimit > 0 && elapsedSec() < 1.65) {\n        for (int mode = 0; mode < 4; mode++) {\n            State s = runViolationGreedy(base, mode, bestLimit);\n            tryCandidate(s);\n\n            bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n\n            if (bestLimit <= 0 || elapsedSec() > 1.75) break;\n        }\n    }\n\n    // 4. Prefix local improvements followed by heapify completion.\n    bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n\n    if (bestLimit > 0 && elapsedSec() < 1.70) {\n        State cur = base;\n        int maxSteps = min(700, bestLimit);\n\n        for (int step = 1; step <= maxSteps; step++) {\n            if (elapsedSec() > 1.78) break;\n\n            int bu = -1, bv = -1;\n            int bestImp = 0;\n            long long bestPot = LLONG_MIN;\n            int bestDiff = -1;\n\n            for (auto [u, v] : adjEdges) {\n                int imp = deltaSwapLocal(cur.a, u, v);\n                if (imp <= 0) continue;\n\n                long long pot = 1LL * (X[v] - X[u]) * (cur.a[u] - cur.a[v]);\n                int diff = abs(cur.a[u] - cur.a[v]);\n\n                if (\n                    imp > bestImp ||\n                    (imp == bestImp &&\n                     (pot > bestPot || (pot == bestPot && diff > bestDiff)))\n                ) {\n                    bestImp = imp;\n                    bestPot = pot;\n                    bestDiff = diff;\n                    bu = u;\n                    bv = v;\n                }\n            }\n\n            if (bu == -1) break;\n\n            applySwap(cur, bu, bv);\n\n            if (cur.E == 0) {\n                tryCandidate(cur);\n                break;\n            }\n\n            if (step <= 30 || step % 20 == 0 || step == maxSteps) {\n                for (int t = 0; t < 5; t++) {\n                    if (elapsedSec() > 1.82) break;\n\n                    State completed = runHeapify(cur, t);\n                    tryCandidate(completed);\n                }\n\n                bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n\n                if ((int)cur.ops.size() >= bestLimit) break;\n            }\n        }\n    }\n\n    // Final safety pruning pass for the selected answer.\n    if (elapsedSec() < 1.85) {\n        vector<Op> pruned = pruneOps(bestOps);\n        if ((int)pruned.size() <= MAX_OPS && validateOps(pruned)) {\n            if (pruned.size() < bestOps.size()) {\n                bestOps = move(pruned);\n            }\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n    for (auto [u, v] : bestOps) {\n        cout << X[u] << ' ' << Y[u] << ' ' << X[v] << ' ' << Y[v] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint D, N;\nint ENT;\nvector<int> freeIds;\nbool obstacleCell[100];\nint labelAt[100];\nint rankOfCell[100];\nbool usedLabel[100];\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nint id_of(int r, int c) {\n    return r * D + c;\n}\n\npair<int,int> rc_of(int id) {\n    return {id / D, id % D};\n}\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nvector<int> neighbors(int id) {\n    auto [r, c] = rc_of(id);\n    vector<int> res;\n    for (int k = 0; k < 4; k++) {\n        int nr = r + dr[k], nc = c + dc[k];\n        if (inside(nr, nc)) res.push_back(id_of(nr, nc));\n    }\n    return res;\n}\n\ninline void set_bit(ull &lo, ull &hi, int x) {\n    if (x < 64) lo |= 1ULL << x;\n    else hi |= 1ULL << (x - 64);\n}\n\ninline bool has_bit(ull lo, ull hi, int x) {\n    if (x < 64) return (lo >> x) & 1ULL;\n    return (hi >> (x - 64)) & 1ULL;\n}\n\ninline int popcnt2(ull lo, ull hi) {\n    return __builtin_popcountll(lo) + __builtin_popcountll(hi);\n}\n\n// Check whether filling cand keeps all remaining empty cells connected to entrance.\nbool legal_fill(int cand) {\n    int totalEmptyAfter = 0;\n    for (int id : freeIds) {\n        if (id != cand && labelAt[id] == -1) totalEmptyAfter++;\n    }\n\n    queue<int> q;\n    bool vis[100] = {};\n    vis[ENT] = true;\n    q.push(ENT);\n\n    int reached = 0;\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int to : neighbors(v)) {\n            if (vis[to]) continue;\n            if (obstacleCell[to]) continue;\n            if (to == cand) continue;\n            if (to != ENT && labelAt[to] != -1) continue;\n\n            vis[to] = true;\n            q.push(to);\n            if (to != ENT) reached++;\n        }\n    }\n\n    return reached == totalEmptyAfter;\n}\n\nbool is_accessible_container(int id, const bool emptyCell[]) {\n    for (int to : neighbors(id)) {\n        if (emptyCell[to]) return true;\n    }\n    return false;\n}\n\n// Estimate final inversions if current arriving label t is placed at cand.\n// Future unknown labels are assigned optimistically to remaining cells in rank order.\nint evaluate_candidate(\n    int cand,\n    int t,\n    const vector<int>& emptySorted,\n    const vector<int>& remLabels\n) {\n    int val[100];\n    fill(val, val + 100, -1);\n\n    for (int id : freeIds) {\n        if (labelAt[id] >= 0) val[id] = labelAt[id];\n    }\n    val[cand] = t;\n\n    int p = 0;\n    for (int id : emptySorted) {\n        if (id == cand) continue;\n        val[id] = remLabels[p++];\n    }\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    vector<int> seq;\n    seq.reserve(freeIds.size());\n\n    for (int step = 0; step < (int)freeIds.size(); step++) {\n        int best = -1;\n        int bestVal = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (val[id] < bestVal ||\n                (val[id] == bestVal && (best == -1 || rankOfCell[id] < rankOfCell[best]))) {\n                bestVal = val[id];\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    bestVal = val[id];\n                    break;\n                }\n            }\n        }\n\n        seq.push_back(bestVal);\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    int inv = 0;\n    int M = seq.size();\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (seq[i] > seq[j]) inv++;\n        }\n    }\n    return inv;\n}\n\nvector<int> greedy_removal_order() {\n    int M = freeIds.size();\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    vector<int> order;\n    order.reserve(M);\n\n    for (int step = 0; step < M; step++) {\n        int best = -1;\n        int bestLabel = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (labelAt[id] < bestLabel) {\n                bestLabel = labelAt[id];\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    break;\n                }\n            }\n        }\n\n        order.push_back(best);\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    return order;\n}\n\nint inversion_count_of_order(const vector<int>& order) {\n    int M = order.size();\n    int inv = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (labelAt[order[i]] > labelAt[order[j]]) inv++;\n        }\n    }\n    return inv;\n}\n\nstruct Key {\n    ull lo, hi;\n    bool operator==(const Key& other) const {\n        return lo == other.lo && hi == other.hi;\n    }\n};\n\nstruct KeyHash {\n    static uint64_t splitmix64(uint64_t x) {\n        x += 0x9e3779b97f4a7c15ULL;\n        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;\n        return x ^ (x >> 31);\n    }\n\n    size_t operator()(const Key& k) const {\n        return splitmix64(k.lo) ^ (splitmix64(k.hi) << 1);\n    }\n};\n\nstruct BeamState {\n    ull lo, hi;\n    ull flo, fhi;\n    int cost;\n    int prev;\n    int add;\n    int score;\n};\n\n// Beam search for better final removal order.\nvector<int> beam_removal_order() {\n    int M = freeIds.size();\n\n    vector<int> idToIdx(D * D, -1);\n    vector<int> idxToId(M);\n    for (int i = 0; i < M; i++) {\n        idToIdx[freeIds[i]] = i;\n        idxToId[i] = freeIds[i];\n    }\n\n    vector<int> lab(M);\n    for (int i = 0; i < M; i++) {\n        lab[i] = labelAt[idxToId[i]];\n    }\n\n    vector<ull> adjLo(M, 0), adjHi(M, 0);\n    ull initLo = 0, initHi = 0;\n\n    for (int i = 0; i < M; i++) {\n        int id = idxToId[i];\n        for (int to : neighbors(id)) {\n            if (to == ENT) {\n                set_bit(initLo, initHi, i);\n            } else if (0 <= to && to < D * D && idToIdx[to] != -1) {\n                int j = idToIdx[to];\n                set_bit(adjLo[i], adjHi[i], j);\n            }\n        }\n    }\n\n    vector<ull> lessLo(M, 0), lessHi(M, 0);\n    for (int x = 0; x < M; x++) {\n        ull lo = 0, hi = 0;\n        for (int i = 0; i < M; i++) {\n            if (lab[i] < x) set_bit(lo, hi, i);\n        }\n        lessLo[x] = lo;\n        lessHi[x] = hi;\n    }\n\n    auto calc_score = [&](int cost, ull flo, ull fhi) {\n        int mn1 = 100, mn2 = 100;\n\n        ull b = flo;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int x = lab[t];\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n            b &= b - 1;\n        }\n\n        b = fhi;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int idx = 64 + t;\n            int x = lab[idx];\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n            b &= b - 1;\n        }\n\n        return cost * 10000 + mn1 * 100 + mn2;\n    };\n\n    const int WIDTH = 5000;\n\n    vector<vector<BeamState>> layers;\n    layers.reserve(M + 1);\n\n    BeamState start;\n    start.lo = start.hi = 0;\n    start.flo = initLo;\n    start.fhi = initHi;\n    start.cost = 0;\n    start.prev = -1;\n    start.add = -1;\n    start.score = calc_score(0, initLo, initHi);\n\n    layers.push_back(vector<BeamState>{start});\n\n    for (int depth = 0; depth < M; depth++) {\n        vector<BeamState>& cur = layers.back();\n\n        vector<BeamState> nxt;\n        nxt.reserve(min((int)cur.size() * 20, WIDTH * 40));\n\n        unordered_map<Key, int, KeyHash> mp;\n        mp.reserve(WIDTH * 50);\n\n        for (int pi = 0; pi < (int)cur.size(); pi++) {\n            const BeamState& s = cur[pi];\n\n            auto expand_one = [&](int idx) {\n                ull bitLo = 0, bitHi = 0;\n                set_bit(bitLo, bitHi, idx);\n\n                ull nlo = s.lo | bitLo;\n                ull nhi = s.hi | bitHi;\n\n                int label = lab[idx];\n                int removedLess = popcnt2(s.lo & lessLo[label], s.hi & lessHi[label]);\n                int inc = label - removedLess;\n                int ncost = s.cost + inc;\n\n                ull nflo = ((s.flo & ~bitLo) | adjLo[idx]) & ~nlo;\n                ull nfhi = ((s.fhi & ~bitHi) | adjHi[idx]) & ~nhi;\n\n                BeamState ns;\n                ns.lo = nlo;\n                ns.hi = nhi;\n                ns.flo = nflo;\n                ns.fhi = nfhi;\n                ns.cost = ncost;\n                ns.prev = pi;\n                ns.add = idx;\n                ns.score = calc_score(ncost, nflo, nfhi);\n\n                Key key{nlo, nhi};\n                auto it = mp.find(key);\n                if (it == mp.end()) {\n                    int pos = nxt.size();\n                    mp.emplace(key, pos);\n                    nxt.push_back(ns);\n                } else {\n                    int pos = it->second;\n                    if (ns.cost < nxt[pos].cost ||\n                        (ns.cost == nxt[pos].cost && ns.score < nxt[pos].score)) {\n                        nxt[pos] = ns;\n                    }\n                }\n            };\n\n            ull b = s.flo;\n            while (b) {\n                int idx = __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n\n            b = s.fhi;\n            while (b) {\n                int idx = 64 + __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n        }\n\n        if ((int)nxt.size() > WIDTH) {\n            nth_element(\n                nxt.begin(),\n                nxt.begin() + WIDTH,\n                nxt.end(),\n                [](const BeamState& a, const BeamState& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.cost < b.cost;\n                }\n            );\n            nxt.resize(WIDTH);\n        }\n\n        layers.push_back(move(nxt));\n    }\n\n    if (layers.back().empty()) {\n        return greedy_removal_order();\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)layers[M].size(); i++) {\n        if (layers[M][i].cost < layers[M][best].cost) best = i;\n    }\n\n    vector<int> idxOrder;\n    idxOrder.reserve(M);\n\n    int curIdx = best;\n    for (int depth = M; depth >= 1; depth--) {\n        const BeamState& s = layers[depth][curIdx];\n        idxOrder.push_back(s.add);\n        curIdx = s.prev;\n    }\n\n    reverse(idxOrder.begin(), idxOrder.end());\n\n    vector<int> order;\n    order.reserve(M);\n    for (int idx : idxOrder) order.push_back(idxToId[idx]);\n\n    return order;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    ENT = id_of(0, (D - 1) / 2);\n\n    fill(obstacleCell, obstacleCell + 100, false);\n    fill(labelAt, labelAt + 100, -1);\n    fill(usedLabel, usedLabel + 100, false);\n\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        obstacleCell[id_of(r, c)] = true;\n    }\n\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            int id = id_of(r, c);\n            if (id == ENT) continue;\n            if (obstacleCell[id]) continue;\n            freeIds.push_back(id);\n        }\n    }\n\n    int M = freeIds.size();\n\n    const int INF = 1e9;\n    vector<int> dist(D * D, INF);\n    queue<int> q;\n    dist[ENT] = 0;\n    q.push(ENT);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int to : neighbors(v)) {\n            if (obstacleCell[to]) continue;\n            if (dist[to] != INF) continue;\n            dist[to] = dist[v] + 1;\n            q.push(to);\n        }\n    }\n\n    int center = (D - 1) / 2;\n\n    sort(freeIds.begin(), freeIds.end(), [&](int a, int b) {\n        auto [ra, ca] = rc_of(a);\n        auto [rb, cb] = rc_of(b);\n\n        tuple<int,int,int,int> ka = {\n            dist[a],\n            abs(ca - center),\n            ra,\n            ca\n        };\n        tuple<int,int,int,int> kb = {\n            dist[b],\n            abs(cb - center),\n            rb,\n            cb\n        };\n        return ka < kb;\n    });\n\n    for (int i = 0; i < M; i++) {\n        rankOfCell[freeIds[i]] = i;\n    }\n\n    // Arrival phase.\n    for (int step = 0; step < M; step++) {\n        int t;\n        cin >> t;\n\n        vector<int> emptySorted;\n        for (int id : freeIds) {\n            if (labelAt[id] == -1) emptySorted.push_back(id);\n        }\n        sort(emptySorted.begin(), emptySorted.end(), [&](int a, int b) {\n            return rankOfCell[a] < rankOfCell[b];\n        });\n\n        vector<int> remLabels;\n        for (int x = 0; x < M; x++) {\n            if (!usedLabel[x] && x != t) remLabels.push_back(x);\n        }\n\n        vector<int> legal;\n        for (int id : emptySorted) {\n            if (legal_fill(id)) legal.push_back(id);\n        }\n\n        if (legal.empty()) {\n            legal = emptySorted;\n        }\n\n        int bestCell = legal[0];\n        long long bestScore = (1LL << 60);\n\n        for (int cand : legal) {\n            int inv = evaluate_candidate(cand, t, emptySorted, remLabels);\n\n            long long mismatch = abs(rankOfCell[cand] - t);\n            long long score = inv * 1000LL + mismatch;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestCell = cand;\n            }\n        }\n\n        labelAt[bestCell] = t;\n        usedLabel[t] = true;\n\n        auto [r, c] = rc_of(bestCell);\n        cout << r << ' ' << c << endl;\n    }\n\n    // Final removal phase.\n    vector<int> greedyOrder = greedy_removal_order();\n    int greedyInv = inversion_count_of_order(greedyOrder);\n\n    vector<int> beamOrder = beam_removal_order();\n    int beamInv = inversion_count_of_order(beamOrder);\n\n    const vector<int>& finalOrder = (beamInv <= greedyInv ? beamOrder : greedyOrder);\n\n    for (int id : finalOrder) {\n        auto [r, c] = rc_of(id);\n        cout << r << ' ' << c << '\\n';\n    }\n\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXC = 101;\nstatic const int INF = 1e9;\n\nint n, m;\nbool allowedAdj[MAXC][MAXC];\n\nstruct State {\n    vector<vector<int>> g;\n    int cnt[MAXC]{};\n    int edgeCnt[MAXC][MAXC]{};\n\n    int stamp[MAXN][MAXN]{};\n    int curStamp = 1;\n\n    State() {\n        g.assign(n, vector<int>(n, 0));\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(stamp, 0, sizeof(stamp));\n    }\n\n    static void normPair(int &a, int &b) {\n        if (a > b) swap(a, b);\n    }\n\n    bool inside(int r, int c) const {\n        return 0 <= r && r < n && 0 <= c && c < n;\n    }\n\n    void addEdgeCount(int a, int b, int v) {\n        if (a == b) return;\n        normPair(a, b);\n        edgeCnt[a][b] += v;\n    }\n\n    void init(const vector<vector<int>> &src) {\n        g = src;\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                cnt[g[i][j]]++;\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = g[i][j];\n\n                if (i == 0) addEdgeCount(c, 0, 1);\n                if (i == n - 1) addEdgeCount(c, 0, 1);\n                if (j == 0) addEdgeCount(c, 0, 1);\n                if (j == n - 1) addEdgeCount(c, 0, 1);\n\n                if (i + 1 < n) addEdgeCount(c, g[i + 1][j], 1);\n                if (j + 1 < n) addEdgeCount(c, g[i][j + 1], 1);\n            }\n        }\n    }\n\n    bool adjacentZeroOrOutside(int r, int c) const {\n        if (r == 0 || r == n - 1 || c == 0 || c == n - 1) return true;\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == 0) return true;\n        }\n        return false;\n    }\n\n    bool oldColorConnectedAfterRemoval(int r, int c, int col) {\n        vector<pair<int, int>> starts;\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) {\n                starts.push_back({nr, nc});\n            }\n        }\n\n        if (starts.size() <= 1) return true;\n\n        curStamp++;\n        if (curStamp == INT_MAX) {\n            memset(stamp, 0, sizeof(stamp));\n            curStamp = 1;\n        }\n\n        queue<pair<int, int>> q;\n        q.push(starts[0]);\n        stamp[starts[0].first][starts[0].second] = curStamp;\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dr[k], ny = y + dc[k];\n                if (!inside(nx, ny)) continue;\n                if (nx == r && ny == c) continue;\n                if (stamp[nx][ny] == curStamp) continue;\n                if (g[nx][ny] != col) continue;\n\n                stamp[nx][ny] = curStamp;\n                q.push({nx, ny});\n            }\n        }\n\n        for (auto [x, y] : starts) {\n            if (stamp[x][y] != curStamp) return false;\n        }\n        return true;\n    }\n\n    bool zeroConnectedAfterRemoval(int r, int c) const {\n        if (cnt[0] <= 1) return true;\n\n        bool vis[MAXN][MAXN]{};\n        queue<pair<int, int>> q;\n\n        auto push = [&](int x, int y) {\n            if (!inside(x, y)) return;\n            if (x == r && y == c) return;\n            if (g[x][y] != 0) return;\n            if (vis[x][y]) return;\n            vis[x][y] = true;\n            q.push({x, y});\n        };\n\n        for (int i = 0; i < n; i++) {\n            push(i, 0);\n            push(i, n - 1);\n            push(0, i);\n            push(n - 1, i);\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dr[k], ny = y + dc[k];\n                push(nx, ny);\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (i == r && j == c) continue;\n                if (g[i][j] == 0 && !vis[i][j]) return false;\n            }\n        }\n        return true;\n    }\n\n    struct Delta {\n        int a, b, d;\n    };\n\n    void addDelta(vector<Delta> &ds, int a, int b, int d) const {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n\n        for (auto &x : ds) {\n            if (x.a == a && x.b == b) {\n                x.d += d;\n                return;\n            }\n        }\n        ds.push_back({a, b, d});\n    }\n\n    vector<Delta> makeDelta(int r, int c, int to) const {\n        vector<Delta> ds;\n        int from = g[r][c];\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n\n            int nb = 0;\n            if (inside(nr, nc)) nb = g[nr][nc];\n\n            addDelta(ds, from, nb, -1);\n            addDelta(ds, to, nb, +1);\n        }\n\n        return ds;\n    }\n\n    bool touchesColor(int r, int c, int col) const {\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) return true;\n        }\n        return false;\n    }\n\n    bool validChange(int r, int c, int to) {\n        int from = g[r][c];\n        if (from == to) return false;\n\n        if (from != 0 && cnt[from] <= 1) return false;\n\n        if (to == 0) {\n            if (from == 0) return false;\n            if (!adjacentZeroOrOutside(r, c)) return false;\n        } else {\n            if (!touchesColor(r, c, to)) return false;\n        }\n\n        if (from == 0) {\n            if (!zeroConnectedAfterRemoval(r, c)) return false;\n        } else {\n            if (!oldColorConnectedAfterRemoval(r, c, from)) return false;\n        }\n\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            int now = edgeCnt[x.a][x.b] + x.d;\n\n            if (allowedAdj[x.a][x.b]) {\n                if (now <= 0) return false;\n            } else {\n                if (now != 0) return false;\n            }\n        }\n\n        return true;\n    }\n\n    void applyChange(int r, int c, int to) {\n        int from = g[r][c];\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            edgeCnt[x.a][x.b] += x.d;\n        }\n\n        cnt[from]--;\n        cnt[to]++;\n        g[r][c] = to;\n    }\n\n    vector<int> computeDistanceToZero() const {\n        vector<int> dist(n * n, INF);\n        queue<int> q;\n\n        auto id = [&](int r, int c) {\n            return r * n + c;\n        };\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int v = id(i, j);\n\n                if (g[i][j] == 0) {\n                    dist[v] = 0;\n                    q.push(v);\n                } else if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    dist[v] = 1;\n                    q.push(v);\n                }\n            }\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            int r = v / n, c = v % n;\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!inside(nr, nc)) continue;\n\n                int nv = id(nr, nc);\n                if (dist[nv] > dist[v] + 1) {\n                    dist[nv] = dist[v] + 1;\n                    q.push(nv);\n                }\n            }\n        }\n\n        return dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    vector<vector<int>> original(n, vector<int>(n));\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> original[i][j];\n        }\n    }\n\n    memset(allowedAdj, 0, sizeof(allowedAdj));\n\n    auto addAllowed = [&](int a, int b) {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n        allowedAdj[a][b] = true;\n    };\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = original[i][j];\n\n            if (i == 0) addAllowed(c, 0);\n            if (i == n - 1) addAllowed(c, 0);\n            if (j == 0) addAllowed(c, 0);\n            if (j == n - 1) addAllowed(c, 0);\n\n            if (i + 1 < n) addAllowed(c, original[i + 1][j]);\n            if (j + 1 < n) addAllowed(c, original[i][j + 1]);\n        }\n    }\n\n    State st;\n    st.init(original);\n\n    vector<vector<int>> best = st.g;\n    int bestZero = st.cnt[0];\n\n    mt19937 rng(123456789);\n\n    auto startTime = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    vector<int> cells(n * n);\n    iota(cells.begin(), cells.end(), 0);\n\n    auto updateBest = [&]() {\n        if (st.cnt[0] > bestZero) {\n            bestZero = st.cnt[0];\n            best = st.g;\n        }\n    };\n\n    auto peelPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 255) == 0 && elapsed() > 1.88) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            if (st.g[r][c] == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n            }\n        }\n\n        updateBest();\n        return changed;\n    };\n\n    auto boundaryRecolorPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 700) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n                applied++;\n                continue;\n            }\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n                used[to] = true;\n\n                int sameAround = 0;\n                for (int t = 0; t < 4; t++) {\n                    int ar = r + dr[t], ac = c + dc[t];\n                    if (st.inside(ar, ac) && st.g[ar][ac] == to) sameAround++;\n                }\n\n                cand.push_back({-sameAround, to});\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto inwardRecolorPass = [&]() {\n        bool changed = false;\n\n        auto dist = st.computeDistanceToZero();\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        stable_sort(cells.begin(), cells.end(), [&](int a, int b) {\n            return dist[a] < dist[b];\n        });\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 700) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            int cd = dist[v];\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                int nd = dist[nr * n + nc];\n\n                if (nd <= cd) {\n                    used[to] = true;\n                    cand.push_back({nd, to});\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto randomRecolorPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 350) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<int> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                used[to] = true;\n                cand.push_back(to);\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            for (int to : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    int stagnant = 0;\n\n    while (elapsed() < 1.88) {\n        int beforeBest = bestZero;\n\n        bool any = false;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        any |= boundaryRecolorPass();\n        if (elapsed() > 1.88) break;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        any |= inwardRecolorPass();\n        if (elapsed() > 1.88) break;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        updateBest();\n\n        if (bestZero == beforeBest) stagnant++;\n        else stagnant = 0;\n\n        if (stagnant >= 2) {\n            randomRecolorPass();\n            peelPass();\n            stagnant = 0;\n        }\n\n        if (!any && elapsed() < 1.88) {\n            bool r = randomRecolorPass();\n            if (!r) break;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct QueryManager {\n    int N, D, Q;\n    int used = 0;\n\n    QueryManager(int N_, int D_, int Q_) : N(N_), D(D_), Q(Q_) {}\n\n    char query(const vector<int>& L, const vector<int>& R) {\n        if (used >= Q) return '?';\n\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        string s;\n        if (!(cin >> s)) exit(0);\n\n        used++;\n        return s[0];\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query(L, R);\n    }\n};\n\nint ceil_log2_int(int x) {\n    int r = 0;\n    int p = 1;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\nstruct Solver {\n    int N, D, Q;\n    QueryManager qm;\n\n    vector<double> estWeight;\n    vector<int> order;\n\n    vector<vector<int>> bins;\n    vector<double> estSum;\n    vector<int> answer;\n\n    mt19937 rng;\n\n    Solver(int N_, int D_, int Q_)\n        : N(N_), D(D_), Q(Q_), qm(N_, D_, Q_), rng(1234567 + N_ * 1009 + D_ * 917 + Q_) {}\n\n    bool heavier_single(int a, int b) {\n        char c = qm.query_single(a, b);\n        return c == '>';\n    }\n\n    vector<int> merge_sort_rec(const vector<int>& v) {\n        int n = (int)v.size();\n        if (n <= 1) return v;\n\n        int mid = n / 2;\n        vector<int> L(v.begin(), v.begin() + mid);\n        vector<int> R(v.begin() + mid, v.end());\n\n        L = merge_sort_rec(L);\n        R = merge_sort_rec(R);\n\n        vector<int> res;\n        res.reserve(n);\n\n        int i = 0, j = 0;\n        while (i < (int)L.size() && j < (int)R.size()) {\n            if (heavier_single(L[i], R[j])) {\n                res.push_back(L[i++]);\n            } else {\n                res.push_back(R[j++]);\n            }\n        }\n        while (i < (int)L.size()) res.push_back(L[i++]);\n        while (j < (int)R.size()) res.push_back(R[j++]);\n\n        return res;\n    }\n\n    void exact_sort_items() {\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        order = merge_sort_rec(order);\n    }\n\n    void approximate_sort_items(int targetQueries) {\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        vector<int> gaps;\n        for (int g = N / 2; g >= 1; g /= 2) gaps.push_back(g);\n\n        while (qm.used < targetQueries) {\n            bool anySwap = false;\n\n            for (int gap : gaps) {\n                for (int i = gap; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - gap];\n                    int b = order[i];\n\n                    char c = qm.query_single(a, b);\n                    if (c == '<') {\n                        swap(order[i - gap], order[i]);\n                        anySwap = true;\n                    }\n                }\n                if (qm.used >= targetQueries) break;\n            }\n\n            // If it already looks sorted, still spend useful adjacent comparisons.\n            if (!anySwap) {\n                for (int i = 1; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - 1];\n                    int b = order[i];\n                    char c = qm.query_single(a, b);\n                    if (c == '<') swap(order[i - 1], order[i]);\n                }\n            }\n        }\n    }\n\n    void make_estimated_weights() {\n        vector<double> H(N + 1, 0.0);\n        for (int i = 1; i <= N; i++) H[i] = H[i - 1] + 1.0 / i;\n\n        estWeight.assign(N, 0.0);\n\n        // Expected k-th largest value of Exp(1) samples is H_N - H_k.\n        for (int k = 0; k < N; k++) {\n            int item = order[k];\n            estWeight[item] = H[N] - H[k];\n        }\n    }\n\n    int compare_bins_by_est(int a, int b) {\n        const double eps = 1e-12;\n        if (estSum[a] + eps < estSum[b]) return -1;\n        if (estSum[a] > estSum[b] + eps) return 1;\n        return 0;\n    }\n\n    int compare_bins(int a, int b, bool allowQuery = true) {\n        if (a == b) return 0;\n\n        if (allowQuery && qm.used < Q) {\n            char c = qm.query(bins[a], bins[b]);\n            if (c == '<') return -1;\n            if (c == '>') return 1;\n            return 0;\n        } else {\n            return compare_bins_by_est(a, b);\n        }\n    }\n\n    void build_partition() {\n        bins.assign(D, {});\n        estSum.assign(D, 0.0);\n        answer.assign(N, 0);\n\n        for (int i = 0; i < D; i++) {\n            int item = order[i];\n            bins[i].push_back(item);\n            estSum[i] += estWeight[item];\n            answer[item] = i;\n        }\n\n        vector<int> binOrder(D);\n        iota(binOrder.begin(), binOrder.end(), 0);\n\n        sort(binOrder.begin(), binOrder.end(), [&](int a, int b) {\n            return estSum[a] < estSum[b];\n        });\n\n        for (int idx = D; idx < N; idx++) {\n            int item = order[idx];\n\n            int b = binOrder.front();\n            binOrder.erase(binOrder.begin());\n\n            bins[b].push_back(item);\n            estSum[b] += estWeight[item];\n            answer[item] = b;\n\n            int lo = 0, hi = (int)binOrder.size();\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int cmp = compare_bins(b, binOrder[mid], true);\n                if (cmp <= 0) hi = mid;\n                else lo = mid + 1;\n            }\n            binOrder.insert(binOrder.begin() + lo, b);\n        }\n    }\n\n    bool find_min_max_bins(int& mn, int& mx) {\n        if (qm.used + 2 * (D - 1) > Q) return false;\n\n        mn = 0;\n        mx = 0;\n\n        for (int b = 1; b < D; b++) {\n            int c1 = compare_bins(b, mn, true);\n            if (c1 < 0) mn = b;\n\n            int c2 = compare_bins(b, mx, true);\n            if (c2 > 0) mx = b;\n        }\n\n        return true;\n    }\n\n    void local_improve() {\n        int iteration = 0;\n\n        while (qm.used < Q && iteration < 10000) {\n            iteration++;\n\n            int lo, hi;\n            if (!find_min_max_bins(lo, hi)) break;\n            if (lo == hi) break;\n            if ((int)bins[hi].size() <= 1) break;\n\n            vector<int> cand = bins[hi];\n            sort(cand.begin(), cand.end(), [&](int a, int b) {\n                return estWeight[a] > estWeight[b];\n            });\n\n            bool moved = false;\n\n            for (int x : cand) {\n                if (qm.used >= Q) break;\n                if ((int)bins[hi].size() <= 1) break;\n\n                vector<int> leftSet;\n                leftSet.reserve(bins[hi].size() - 1);\n                for (int y : bins[hi]) {\n                    if (y != x) leftSet.push_back(y);\n                }\n\n                if (leftSet.empty()) continue;\n\n                vector<int> rightSet = bins[lo];\n                rightSet.push_back(x);\n\n                char c = qm.query(leftSet, rightSet);\n\n                // If after moving x, the old heavy bin is still not lighter,\n                // this is a safe balancing move.\n                if (c == '>' || c == '=') {\n                    auto it = find(bins[hi].begin(), bins[hi].end(), x);\n                    if (it != bins[hi].end()) bins[hi].erase(it);\n\n                    bins[lo].push_back(x);\n                    estSum[hi] -= estWeight[x];\n                    estSum[lo] += estWeight[x];\n                    answer[x] = lo;\n\n                    moved = true;\n                    break;\n                }\n            }\n\n            if (!moved) break;\n        }\n    }\n\n    void spend_remaining_queries() {\n        while (qm.used < Q) {\n            qm.query_single(0, 1);\n        }\n    }\n\n    void output_answer() {\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << answer[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n\n    void solve() {\n        int lgN = ceil_log2_int(N);\n        int mergeWorst = N * lgN - (1 << lgN) + 1;\n        if (mergeWorst < 0) mergeWorst = N * lgN;\n\n        int lgD = ceil_log2_int(D);\n        int constructionCostApprox = max(0, N - D) * max(1, lgD);\n\n        bool useExactSort = false;\n        if (Q >= mergeWorst + D) useExactSort = true;\n\n        if (useExactSort) {\n            exact_sort_items();\n        } else {\n            int reserve = min(constructionCostApprox, Q / 3);\n            int target = max(0, Q - reserve);\n            approximate_sort_items(target);\n        }\n\n        make_estimated_weights();\n\n        build_partition();\n\n        if (qm.used < Q) {\n            local_improve();\n        }\n\n        spend_remaining_queries();\n\n        output_answer();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    cin >> N >> D >> Q;\n\n    Solver solver(N, D, Q);\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int v, to;\n};\n\nstruct Result {\n    vector<Op> ops;\n    int energy = INT_MAX;\n    bool valid = false;\n};\n\nstatic const int N = 200;\nstatic const int M = 10;\nstatic const int INF_LABEL = 1000;\n\nint seg_max(const vector<int>& a) {\n    int mx = 0;\n    for (int x : a) mx = max(mx, x);\n    return mx;\n}\n\nint stack_min_value(const vector<int>& st) {\n    if (st.empty()) return INF_LABEL;\n    int mn = INF_LABEL;\n    for (int x : st) mn = min(mn, x);\n    return mn;\n}\n\nint stack_badness(const vector<int>& st) {\n    int bad = 0;\n    for (int i = 1; i < (int)st.size(); i++) {\n        if (st[i - 1] < st[i]) {\n            bad += st[i] - st[i - 1];\n        }\n    }\n    return bad;\n}\n\nbool has_good_destination_top(const vector<vector<int>>& stacks, int src, const vector<int>& vals) {\n    int mx = seg_max(vals);\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n        if (stacks[d].empty()) return true;\n        if (stacks[d].back() > mx) return true;\n    }\n    return false;\n}\n\nint choose_destination(\n    const vector<vector<int>>& stacks,\n    int src,\n    const vector<int>& vals,\n    int policy,\n    mt19937& rng,\n    double noise_amp\n) {\n    int mx = seg_max(vals);\n    int len = (int)vals.size();\n\n    uniform_real_distribution<double> dist(0.0, noise_amp);\n\n    int best = -1;\n    double best_score = 1e100;\n\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n\n        int h = (int)stacks[d].size();\n        bool empty = stacks[d].empty();\n\n        int top = empty ? INF_LABEL : stacks[d].back();\n        int mn = stack_min_value(stacks[d]);\n\n        bool good_top = empty || top > mx;\n        bool good_all = empty || mn > mx;\n\n        double score = 0.0;\n\n        switch (policy % 14) {\n            case 0:\n                // Patience-sorting style: smallest top that can accept the block.\n                if (good_top) score = top * 100.0 + h;\n                else score = 1e6 - top * 100.0 + h;\n                break;\n\n            case 1:\n                // Prefer low height, but still prioritize good destinations.\n                score = (good_top ? 0.0 : 100000.0) + h * 100.0 + top;\n                break;\n\n            case 2:\n                // Stronger: prefer stacks whose all boxes are larger.\n                if (good_all) score = mn * 100.0 + h;\n                else if (good_top) score = 200000.0 + top * 100.0 + h;\n                else score = 1e6 - mn * 50.0 - top * 10.0 + h;\n                break;\n\n            case 3:\n                // Prefer smallest positive gap.\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0;\n                else score = 1e6 + (mx - top) * 100.0 + h;\n                break;\n\n            case 4:\n                // Height balancing.\n                score = h * 100.0 + (good_top ? 0.0 : 50000.0) + top;\n                break;\n\n            case 5:\n                // Prefer taller good stacks.\n                if (good_top) score = top * 100.0 - h * 20.0;\n                else score = 1e6 - top * 100.0 - h * 10.0;\n                break;\n\n            case 6:\n                // Prefer large top labels.\n                score = (good_top ? 0.0 : 500000.0) - top * 100.0 + h * 10.0;\n                break;\n\n            case 7:\n                // Prefer destination with large minimum.\n                score = (good_top ? 0.0 : 300000.0) - mn * 100.0 - top * 10.0 + h;\n                break;\n\n            case 8:\n                // Explicit gap minimization.\n                if (good_top) score = (top - mx) * 200.0 + h;\n                else score = 1e6 + (mx - top) * 200.0 + h;\n                break;\n\n            case 9:\n                // Consider current disorder of destination stack.\n                if (good_top) score = top * 100.0 + h * 20.0 + stack_badness(stacks[d]) * 2.0;\n                else score = 1e6 - top * 100.0 + h * 20.0 + stack_badness(stacks[d]) * 2.0;\n                break;\n\n            case 10:\n                // Boundary-violation penalty.\n                if (empty) {\n                    score = 50000.0 + h;\n                } else {\n                    int violation = max(0, mx - top);\n                    score = violation * 10000.0 + (good_top ? top : -top) * 10.0 + h;\n                }\n                break;\n\n            case 11:\n                // Avoid empty stacks unless useful.\n                if (empty) {\n                    score = good_top ? 150000.0 : 1000000.0;\n                } else if (good_top) {\n                    score = (top - mx) * 100.0 + h * 3.0;\n                } else {\n                    score = 1e6 - top * 200.0 + h;\n                }\n                break;\n\n            case 12:\n                // Slightly prefer putting larger blocks on safer stacks.\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0 - len * 20.0;\n                else score = 1e6 + (mx - top) * 100.0 + h - len * 20.0;\n                break;\n\n            case 13:\n                // Conservative: minimize added adjacent violation.\n                if (empty) score = 10000.0 + h;\n                else {\n                    int add = max(0, mx - top);\n                    score = add * 20000.0 + abs(top - mx) * 20.0 + h;\n                }\n                break;\n        }\n\n        if (noise_amp > 0.0) score += dist(rng);\n\n        if (score < best_score) {\n            best_score = score;\n            best = d;\n        }\n    }\n\n    return best;\n}\n\nint choose_left_index(\n    const vector<vector<int>>& stacks,\n    int s,\n    int pos,\n    int split_mode\n) {\n    const auto& st = stacks[s];\n    int h = (int)st.size();\n\n    if (split_mode == 0) {\n        return pos + 1; // whole suffix above target\n    }\n\n    if (split_mode == 2) {\n        return h - 1; // single box\n    }\n\n    int run_start = h - 1;\n    while (run_start - 1 > pos && st[run_start - 1] > st[run_start]) {\n        run_start--;\n    }\n\n    if (split_mode == 1) {\n        return run_start; // maximal decreasing top-run\n    }\n\n    auto suffix_vals = [&](int l) {\n        return vector<int>(st.begin() + l, st.end());\n    };\n\n    if (split_mode == 3) {\n        // Longest suffix of the decreasing run that can be safely placed.\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            if (has_good_destination_top(stacks, s, vals)) return l;\n        }\n        return run_start;\n    }\n\n    if (split_mode == 4) {\n        // Same as mode 3, but if impossible, move the whole suffix.\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            if (has_good_destination_top(stacks, s, vals)) return l;\n        }\n        return pos + 1;\n    }\n\n    if (split_mode == 5) {\n        // Prefer safe long suffix, but be more willing to split.\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            bool good = has_good_destination_top(stacks, s, vals);\n            int len = h - l;\n            int mx = seg_max(vals);\n\n            double score = (good ? 0.0 : 100000.0 + mx * 10.0) - len * 120.0;\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 6) {\n        // If maximal run is unsafe, try a single top box.\n        vector<int> vals = suffix_vals(run_start);\n        if (has_good_destination_top(stacks, s, vals)) return run_start;\n\n        vector<int> one = suffix_vals(h - 1);\n        if (has_good_destination_top(stacks, s, one)) return h - 1;\n\n        return run_start;\n    }\n\n    return run_start;\n}\n\nResult simulate(\n    const vector<vector<int>>& initial,\n    int split_mode,\n    int policy,\n    uint32_t seed,\n    double noise_amp\n) {\n    mt19937 rng(seed);\n\n    vector<vector<int>> stacks = initial;\n    vector<Op> ops;\n    int energy = 0;\n\n    for (int cur = 1; cur <= N; cur++) {\n        int s = -1, pos = -1;\n\n        for (int i = 0; i < M; i++) {\n            for (int j = 0; j < (int)stacks[i].size(); j++) {\n                if (stacks[i][j] == cur) {\n                    s = i;\n                    pos = j;\n                }\n            }\n        }\n\n        if (s == -1) return Result{};\n\n        while (pos != (int)stacks[s].size() - 1) {\n            if ((int)ops.size() >= 5000) return Result{};\n\n            int h = (int)stacks[s].size();\n\n            int l;\n            if ((int)ops.size() > 4600) {\n                l = pos + 1;\n            } else {\n                l = choose_left_index(stacks, s, pos, split_mode);\n            }\n\n            if (l <= pos || l >= h) return Result{};\n\n            vector<int> vals(stacks[s].begin() + l, stacks[s].end());\n\n            int d = choose_destination(stacks, s, vals, policy, rng, noise_amp);\n            if (d < 0 || d == s) return Result{};\n\n            ops.push_back({vals.front(), d + 1});\n            energy += (int)vals.size() + 1;\n\n            stacks[s].erase(stacks[s].begin() + l, stacks[s].end());\n            stacks[d].insert(stacks[d].end(), vals.begin(), vals.end());\n\n            if ((int)ops.size() > 5000) return Result{};\n        }\n\n        if (stacks[s].empty() || stacks[s].back() != cur) {\n            return Result{};\n        }\n\n        ops.push_back({cur, 0});\n        stacks[s].pop_back();\n\n        if ((int)ops.size() > 5000) return Result{};\n    }\n\n    Result res;\n    res.ops = move(ops);\n    res.energy = energy;\n    res.valid = true;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> initial(M);\n\n    for (int i = 0; i < M; i++) {\n        initial[i].resize(N / M);\n        for (int j = 0; j < N / M; j++) {\n            cin >> initial[i][j];\n        }\n    }\n\n    uint32_t base_seed = 123456789u;\n    for (int i = 0; i < M; i++) {\n        for (int x : initial[i]) {\n            base_seed = base_seed * 1000003u + (uint32_t)x;\n        }\n    }\n\n    Result best;\n\n    auto try_result = [&](const Result& r) {\n        if (!r.valid) return;\n        if ((int)r.ops.size() > 5000) return;\n\n        if (!best.valid ||\n            r.energy < best.energy ||\n            (r.energy == best.energy && r.ops.size() < best.ops.size())) {\n            best = r;\n        }\n    };\n\n    auto start_time = chrono::steady_clock::now();\n\n    // Deterministic variants.\n    for (int split = 0; split <= 6; split++) {\n        for (int policy = 0; policy < 14; policy++) {\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + split * 1009u + policy * 9176u,\n                0.0\n            );\n            try_result(r);\n        }\n    }\n\n    // Additional randomized search under time budget.\n    mt19937 rng(base_seed ^ 0x9e3779b9u);\n\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.80) break;\n\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 10) split = 0;\n        else if (sr < 35) split = 1;\n        else if (sr < 45) split = 2;\n        else if (sr < 70) split = 3;\n        else if (sr < 82) split = 4;\n        else if (sr < 94) split = 5;\n        else split = 6;\n\n        int policy = rng() % 14;\n\n        double noise;\n        int nr = rng() % 7;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 3.0;\n        else if (nr == 2) noise = 10.0;\n        else if (nr == 3) noise = 30.0;\n        else if (nr == 4) noise = 100.0;\n        else if (nr == 5) noise = 400.0;\n        else noise = 1500.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 1000003u + (uint32_t)iter * 17777u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    // Fallback.\n    if (!best.valid) {\n        best = simulate(initial, 0, 0, base_seed, 0.0);\n    }\n\n    for (const auto& op : best.ops) {\n        cout << op.v << ' ' << op.to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    char c;\n};\n\nstatic const uint16_t INF16 = 65535;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    int N;\n    cin >> N;\n\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    int V = N * N;\n    vector<int> dirt(V);\n    long long sumD = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> dirt[i * N + j];\n            sumD += dirt[i * N + j];\n        }\n    }\n    double avgD = (double)sumD / V;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    vector<vector<Edge>> g(V);\n\n    auto add_edge = [&](int a, int b, char c1, char c2) {\n        g[a].push_back({b, c1});\n        g[b].push_back({a, c2});\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (i + 1 < N && h[i][j] == '0') {\n                add_edge(id(i, j), id(i + 1, j), 'D', 'U');\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                add_edge(id(i, j), id(i, j + 1), 'R', 'L');\n            }\n        }\n    }\n\n    // all-pairs shortest paths\n    vector<uint16_t> dist((size_t)V * V, INF16);\n    vector<int> q(V);\n\n    for (int s = 0; s < V; s++) {\n        uint16_t* ds = &dist[(size_t)s * V];\n        int head = 0, tail = 0;\n        ds[s] = 0;\n        q[tail++] = s;\n\n        while (head < tail) {\n            int cur = q[head++];\n            uint16_t nd = ds[cur] + 1;\n            for (auto &e : g[cur]) {\n                if (ds[e.to] == INF16) {\n                    ds[e.to] = nd;\n                    q[tail++] = e.to;\n                }\n            }\n        }\n    }\n\n    int maxDist = 0;\n    for (int i = 0; i < V; i++) {\n        for (int j = 0; j < V; j++) {\n            maxDist = max(maxDist, (int)dist[(size_t)i * V + j]);\n        }\n    }\n\n    vector<double> alphas = {1.0, 1.5, 2.0, 3.0};\n    vector<vector<double>> denom(alphas.size(), vector<double>(maxDist + 2));\n    for (int a = 0; a < (int)alphas.size(); a++) {\n        for (int d = 0; d <= maxDist + 1; d++) {\n            denom[a][d] = pow((double)d, alphas[a]);\n        }\n    }\n\n    auto score_route = [&](const string &route) -> long double {\n        int L = (int)route.size();\n        if (L == 0 || L > 100000) return 1e100L;\n\n        vector<vector<int>> times(V);\n        int cur = 0;\n        times[0].push_back(0);\n\n        for (int t = 1; t <= L; t++) {\n            char c = route[t - 1];\n            bool moved = false;\n            for (auto &e : g[cur]) {\n                if (e.c == c) {\n                    cur = e.to;\n                    moved = true;\n                    break;\n                }\n            }\n            if (!moved) return 1e100L;\n\n            if (t < L) {\n                times[cur].push_back(t);\n            }\n        }\n\n        if (cur != 0) return 1e100L;\n\n        long double total = 0.0L;\n\n        for (int x = 0; x < V; x++) {\n            if (times[x].empty()) return 1e100L;\n\n            auto &ts = times[x];\n            long long ss = 0;\n\n            for (int k = 0; k + 1 < (int)ts.size(); k++) {\n                long long gap = ts[k + 1] - ts[k];\n                ss += gap * (gap - 1);\n            }\n\n            long long gap = L - ts.back() + ts.front();\n            ss += gap * (gap - 1);\n\n            total += (long double)dirt[x] * ss / (2.0L * L);\n        }\n\n        return total;\n    };\n\n    string bestRoute;\n    long double bestScore = 1e100L;\n\n    auto consider = [&](const string &route) {\n        if (route.empty() || route.size() > 100000) return;\n        long double sc = score_route(route);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n        }\n    };\n\n    // DFS baseline routes\n    for (int mode = 0; mode < 4; mode++) {\n        vector<int> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n\n            vector<Edge> es = g[cur];\n\n            if (mode == 1) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] > dirt[b.to];\n                });\n            } else if (mode == 2) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] < dirt[b.to];\n                });\n            } else if (mode == 3) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return a.c < b.c;\n                });\n            }\n\n            for (auto &e : es) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n\n                    for (auto &r : g[e.to]) {\n                        if (r.to == cur) {\n                            route.push_back(r.c);\n                            break;\n                        }\n                    }\n                }\n            }\n        };\n\n        dfs(0);\n        consider(route);\n    }\n\n    uint32_t rng = 123456789;\n    auto rnd01 = [&]() {\n        rng ^= rng << 13;\n        rng ^= rng >> 17;\n        rng ^= rng << 5;\n        return (rng & 0xffff) / 65536.0;\n    };\n\n    auto generate_route = [&](int cap, int covAlphaIdx, int patAlphaIdx, double coverBiasMul, bool noise) {\n        string route;\n        route.reserve(min(100000, max(cap, V * 2)));\n\n        vector<int> last(V, 0);\n        vector<char> visited(V, 0);\n        int visitedCnt = 1;\n        visited[0] = 1;\n\n        int cur = 0;\n        int t = 0;\n\n        auto append_path = [&](int target) {\n            while (cur != target) {\n                uint16_t dc = dist[(size_t)cur * V + target];\n\n                int bestNext = -1;\n                char bestChar = '?';\n                long long bestVal = LLONG_MIN;\n\n                for (auto &e : g[cur]) {\n                    if (dist[(size_t)e.to * V + target] + 1 == dc) {\n                        long long val = 0;\n                        if (!visited[e.to]) val += (long long)4e18 / 4;\n                        val += (long long)dirt[e.to] * (t - last[e.to] + 1);\n\n                        if (val > bestVal) {\n                            bestVal = val;\n                            bestNext = e.to;\n                            bestChar = e.c;\n                        }\n                    }\n                }\n\n                if (bestNext == -1) return;\n\n                route.push_back(bestChar);\n                cur = bestNext;\n                t++;\n\n                last[cur] = t;\n                if (!visited[cur]) {\n                    visited[cur] = 1;\n                    visitedCnt++;\n                }\n            }\n        };\n\n        double coverBias = avgD * coverBiasMul;\n\n        // Phase 1: visit all cells\n        while (visitedCnt < V) {\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                if (visited[x]) continue;\n\n                int ds = dist[(size_t)cur * V + x];\n                double val = (coverBias + dirt[x]) / denom[covAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.9 + 0.2 * rnd01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n            append_path(target);\n\n            if ((int)route.size() > 100000) break;\n        }\n\n        // Phase 2: patrol high-dirt / long-unvisited cells\n        int limit = cap;\n        if (limit <= 0) limit = (int)route.size();\n\n        int iter = 0;\n        while ((int)route.size() + dist[(size_t)cur * V + 0] < limit &&\n               (int)route.size() < 100000) {\n            if ((++iter & 255) == 0 && elapsed() > 1.82) break;\n\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                int ds = dist[(size_t)cur * V + x];\n                if (ds == 0) continue;\n\n                int ret = dist[(size_t)x * V + 0];\n                if ((int)route.size() + ds + ret > limit) continue;\n                if ((int)route.size() + ds + ret > 100000) continue;\n\n                int age = t - last[x];\n                double val = (double)dirt[x] * (age + 1) / denom[patAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.9 + 0.2 * rnd01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n            append_path(target);\n        }\n\n        append_path(0);\n        return route;\n    };\n\n    struct Param {\n        int cap;\n        int covA;\n        int patA;\n        double bias;\n        bool noise;\n    };\n\n    vector<Param> params;\n\n    // Coverage-only variants\n    params.push_back({0, 3, 1, 20.0, false});\n    params.push_back({0, 2, 1, 20.0, false});\n    params.push_back({0, 2, 1, 0.0, false});\n    params.push_back({0, 1, 1, 0.0, false});\n\n    vector<int> caps = {\n        V * 2,\n        V * 3,\n        V * 5,\n        V * 8,\n        V * 13,\n        30000,\n        60000,\n        100000\n    };\n\n    for (int &x : caps) {\n        x = min(100000, max(1, x));\n    }\n    sort(caps.begin(), caps.end());\n    caps.erase(unique(caps.begin(), caps.end()), caps.end());\n\n    for (int cap : caps) {\n        params.push_back({cap, 2, 1, 10.0, false});\n    }\n\n    params.push_back({30000, 2, 0, 10.0, false});\n    params.push_back({30000, 2, 2, 10.0, false});\n    params.push_back({60000, 2, 0, 10.0, false});\n    params.push_back({100000, 2, 0, 10.0, false});\n\n    params.push_back({60000, 2, 1, 10.0, true});\n    params.push_back({100000, 2, 1, 10.0, true});\n\n    for (auto &p : params) {\n        if (elapsed() > 1.84) break;\n        string r = generate_route(p.cap, p.covA, p.patA, p.bias, p.noise);\n        consider(r);\n    }\n\n    // Absolute safety fallback, should practically never be needed.\n    if (bestRoute.empty()) {\n        vector<int> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n            for (auto &e : g[cur]) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n                    for (auto &r : g[e.to]) {\n                        if (r.to == cur) {\n                            route.push_back(r.c);\n                            break;\n                        }\n                    }\n                }\n            }\n        };\n\n        dfs(0);\n        bestRoute = route;\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\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 nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nint N, M;\nint si, sj;\nvector<string> Agrid;\nvector<string> t;\nvector<pair<int,int>> occ[26];\nint mindist_ch[26][26];\n\nint manhattan(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nint overlap_word(const string& a, const string& b) {\n    for (int k = 4; k >= 1; --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) return k;\n    }\n    return 0;\n}\n\nint overlap_suffix_string(const string& s, const string& w) {\n    int lim = min<int>(4, s.size());\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (s[(int)s.size() - k + i] != w[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nlong long pathCost(const vector<int>& p, const vector<vector<int>>& W, const vector<int>& startCost) {\n    long long c = startCost[p[0]];\n    for (int i = 0; i + 1 < (int)p.size(); ++i) c += W[p[i]][p[i + 1]];\n    return c;\n}\n\nlong long contrib(const vector<int>& p, int idx, const vector<vector<int>>& W, const vector<int>& startCost) {\n    int n = (int)p.size();\n    if (idx == -1) return startCost[p[0]];\n    if (0 <= idx && idx + 1 < n) return W[p[idx]][p[idx + 1]];\n    return 0;\n}\n\nlong long deltaSwap(const vector<int>& p, int a, int b, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (a == b) return 0;\n    if (a > b) swap(a, b);\n\n    vector<int> ids = {-1, a - 1, a, b - 1, b};\n    sort(ids.begin(), ids.end());\n    ids.erase(unique(ids.begin(), ids.end()), ids.end());\n\n    long long oldv = 0, newv = 0;\n    for (int id : ids) oldv += contrib(p, id, W, startCost);\n\n    vector<int> q = p;\n    swap(q[a], q[b]);\n\n    for (int id : ids) newv += contrib(q, id, W, startCost);\n    return newv - oldv;\n}\n\nvector<int> greedyOrder(const vector<vector<int>>& W, const vector<int>& startCost, const vector<vector<int>>& ov) {\n    vector<int> best;\n    long long bestCost = (1LL << 60);\n\n    for (int st = 0; st < M; ++st) {\n        vector<int> p;\n        vector<char> used(M, 0);\n        p.reserve(M);\n        p.push_back(st);\n        used[st] = 1;\n\n        for (int step = 1; step < M; ++step) {\n            int last = p.back();\n            int bj = -1;\n            pair<int,int> bestKey = {INT_MAX, INT_MAX};\n\n            for (int j = 0; j < M; ++j) if (!used[j]) {\n                // primary: estimated cost, secondary: larger overlap\n                pair<int,int> key = {W[last][j], -ov[last][j]};\n                if (key < bestKey) {\n                    bestKey = key;\n                    bj = j;\n                }\n            }\n\n            used[bj] = 1;\n            p.push_back(bj);\n        }\n\n        long long c = pathCost(p, W, startCost);\n        if (c < bestCost) {\n            bestCost = c;\n            best = p;\n        }\n    }\n\n    return best;\n}\n\nstring buildStringFromOrder(const vector<int>& ord) {\n    string s;\n\n    for (int id : ord) {\n        if (s.find(t[id]) != string::npos) continue;\n\n        if (s.empty()) {\n            s = t[id];\n        } else {\n            int k = overlap_suffix_string(s, t[id]);\n            s += t[id].substr(k);\n        }\n    }\n\n    // Safety fallback.\n    for (int i = 0; i < M; ++i) {\n        if (s.find(t[i]) == string::npos) {\n            int k = overlap_suffix_string(s, t[i]);\n            s += t[i].substr(k);\n        }\n    }\n\n    return s;\n}\n\npair<int, vector<pair<int,int>>> solveTypingDP(const string& s) {\n    const int INF = 1e9;\n    int L = (int)s.size();\n\n    vector<vector<int>> par(L);\n    vector<int> dp_prev, dp_cur;\n\n    for (int pos = 0; pos < L; ++pos) {\n        int c = s[pos] - 'A';\n        int C = (int)occ[c].size();\n\n        dp_cur.assign(C, INF);\n        par[pos].assign(C, -1);\n\n        if (pos == 0) {\n            pair<int,int> start = {si, sj};\n            for (int i = 0; i < C; ++i) {\n                dp_cur[i] = manhattan(start, occ[c][i]) + 1;\n            }\n        } else {\n            int pc = s[pos - 1] - 'A';\n            int P = (int)occ[pc].size();\n\n            for (int i = 0; i < C; ++i) {\n                for (int j = 0; j < P; ++j) {\n                    int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                    if (val < dp_cur[i]) {\n                        dp_cur[i] = val;\n                        par[pos][i] = j;\n                    }\n                }\n            }\n        }\n\n        dp_prev.swap(dp_cur);\n    }\n\n    int bestIdx = 0;\n    int bestCost = INF;\n    for (int i = 0; i < (int)dp_prev.size(); ++i) {\n        if (dp_prev[i] < bestCost) {\n            bestCost = dp_prev[i];\n            bestIdx = i;\n        }\n    }\n\n    vector<pair<int,int>> path(L);\n    int idx = bestIdx;\n    for (int pos = L - 1; pos >= 0; --pos) {\n        int c = s[pos] - 'A';\n        path[pos] = occ[c][idx];\n        idx = par[pos][idx];\n    }\n\n    return {bestCost, path};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto timeStart = chrono::steady_clock::now();\n\n    cin >> N >> M;\n    cin >> si >> sj;\n\n    Agrid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> Agrid[i];\n\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            occ[Agrid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) {\n            int best = 1e9;\n            for (auto pa : occ[a]) {\n                for (auto pb : occ[b]) {\n                    best = min(best, manhattan(pa, pb));\n                }\n            }\n            mindist_ch[a][b] = best;\n        }\n    }\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i != j) ov[i][j] = overlap_word(t[i], t[j]);\n        }\n    }\n\n    vector<vector<int>> W(M, vector<int>(M, 1e8));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            int o = ov[i][j];\n            int prev = t[i][4] - 'A';\n            int cost = 0;\n            for (int k = o; k < 5; ++k) {\n                int c = t[j][k] - 'A';\n                cost += mindist_ch[prev][c] + 1;\n                prev = c;\n            }\n            W[i][j] = cost;\n        }\n    }\n\n    vector<int> startCost(M, 0);\n    pair<int,int> startPos = {si, sj};\n    for (int i = 0; i < M; ++i) {\n        int cost = 1e9;\n        int c0 = t[i][0] - 'A';\n        for (auto p : occ[c0]) {\n            cost = min(cost, manhattan(startPos, p) + 1);\n        }\n        for (int k = 1; k < 5; ++k) {\n            int a = t[i][k - 1] - 'A';\n            int b = t[i][k] - 'A';\n            cost += mindist_ch[a][b] + 1;\n        }\n        startCost[i] = cost;\n    }\n\n    vector<int> perm = greedyOrder(W, startCost, ov);\n    long long curCost = pathCost(perm, W, startCost);\n    vector<int> bestPerm = perm;\n    long long bestCost = curCost;\n\n    // Additional pure-overlap candidate.\n    vector<vector<int>> Wover(M, vector<int>(M, 1000000));\n    vector<int> zeroStart(M, 0);\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            Wover[i][j] = 5 - ov[i][j];\n        }\n    }\n    vector<int> overlapPerm = greedyOrder(Wover, zeroStart, ov);\n\n    // Simulated annealing / local search on estimated typing cost.\n    XorShift rng;\n    vector<int> np;\n    np.reserve(M);\n\n    const double TL = 1.78;\n    int iter = 0;\n    while (true) {\n        if ((iter & 1023) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - timeStart).count();\n            if (elapsed > TL) break;\n        }\n        ++iter;\n\n        double progress = min(1.0, chrono::duration<double>(chrono::steady_clock::now() - timeStart).count() / TL);\n        double temp = 18.0 * pow(0.03 / 18.0, progress);\n\n        if (rng.nextInt(100) < 55) {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            long long d = deltaSwap(perm, a, b, W, startCost);\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                swap(perm[a], perm[b]);\n                curCost += d;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        } else {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            np = perm;\n            int val = np[a];\n            np.erase(np.begin() + a);\n            np.insert(np.begin() + b, val);\n\n            long long ncost = pathCost(np, W, startCost);\n            long long d = ncost - curCost;\n\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                perm.swap(np);\n                curCost = ncost;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        }\n    }\n\n    vector<string> candidates;\n    candidates.push_back(buildStringFromOrder(bestPerm));\n    candidates.push_back(buildStringFromOrder(overlapPerm));\n\n    // A simple lexicographic-order fallback, surprisingly useful in rare cases.\n    vector<int> lexPerm(M);\n    iota(lexPerm.begin(), lexPerm.end(), 0);\n    candidates.push_back(buildStringFromOrder(lexPerm));\n\n    int answerCost = INT_MAX;\n    vector<pair<int,int>> answerPath;\n\n    sort(candidates.begin(), candidates.end());\n    candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n    for (const string& s : candidates) {\n        auto res = solveTypingDP(s);\n        if (res.first < answerCost) {\n            answerCost = res.first;\n            answerPath = move(res.second);\n        }\n    }\n\n    if ((int)answerPath.size() > 5000) {\n        answerPath.resize(5000);\n    }\n\n    for (auto [i, j] : answerPath) {\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXC = 400;\n\nint N, M, C;\ndouble EPSV;\nint MAX_OPS;\nint op_cnt = 0;\n\nstruct Placement {\n    vector<int> cells;\n    bitset<MAXC> mask;\n};\n\nstruct Obs {\n    bitset<MAXC> mask;\n    int k;\n    double target;\n    double weight;\n    bool drill;\n    int cell;\n    int value;\n};\n\nstruct State {\n    vector<int> pos;\n    double score;\n    bitset<MAXC> uni;\n};\n\nvector<vector<pair<int,int>>> shapes;\nvector<vector<Placement>> placements;\nvector<Obs> observations;\n\nvector<int> drilled; // -1 unknown, otherwise exact v(i,j)\n\nmt19937 rng(1234567);\nauto time_start = chrono::steady_clock::now();\n\ndouble elapsed_ms() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double, milli>(now - time_start).count();\n}\n\nint id_of(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> coord_of(int id) {\n    return {id / N, id % N};\n}\n\nint ask_query(const vector<int>& cells) {\n    cout << \"q \" << cells.size();\n    for (int id : cells) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n    return res;\n}\n\nbool ask_answer(bitset<MAXC> mask) {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] > 0) mask.set(id);\n    }\n\n    vector<int> ans;\n    for (int id = 0; id < C; id++) {\n        if (mask.test(id)) ans.push_back(id);\n    }\n\n    cout << \"a \" << ans.size();\n    for (int id : ans) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n    if (res == 1) exit(0);\n    return false;\n}\n\nvoid add_divination_observation(const vector<int>& cells, int y) {\n    Obs obs;\n    obs.mask.reset();\n    for (int id : cells) obs.mask.set(id);\n    obs.k = (int)cells.size();\n    obs.drill = false;\n    obs.cell = -1;\n    obs.value = -1;\n\n    double a = 1.0 - 2.0 * EPSV;\n    double target = (y - obs.k * EPSV) / max(1e-9, a);\n    target = max(0.0, min(target, (double)M * obs.k));\n\n    double var = obs.k * EPSV * (1.0 - EPSV) + 0.35;\n    double weight = a * a / max(1e-9, var);\n\n    obs.target = target;\n    obs.weight = weight;\n    observations.push_back(obs);\n}\n\nvoid add_drill_observation(int cell, int val) {\n    Obs obs;\n    obs.mask.reset();\n    obs.mask.set(cell);\n    obs.k = 1;\n    obs.target = val;\n    obs.weight = 10000.0;\n    obs.drill = true;\n    obs.cell = cell;\n    obs.value = val;\n    observations.push_back(obs);\n}\n\nvoid do_divination(const vector<int>& cells) {\n    if ((int)cells.size() < 2) return;\n    int y = ask_query(cells);\n    add_divination_observation(cells, y);\n}\n\nint do_drill(int cell) {\n    vector<int> q = {cell};\n    int v = ask_query(q);\n    drilled[cell] = v;\n    add_drill_observation(cell, v);\n    return v;\n}\n\nvoid build_placements() {\n    placements.assign(M, {});\n\n    for (int m = 0; m < M; m++) {\n        int imax = 0, jmax = 0;\n        for (auto [i, j] : shapes[m]) {\n            imax = max(imax, i);\n            jmax = max(jmax, j);\n        }\n\n        for (int di = 0; di + imax < N; di++) {\n            for (int dj = 0; dj + jmax < N; dj++) {\n                Placement p;\n                p.mask.reset();\n                for (auto [i, j] : shapes[m]) {\n                    int id = id_of(di + i, dj + j);\n                    p.cells.push_back(id);\n                    p.mask.set(id);\n                }\n                placements[m].push_back(p);\n            }\n        }\n    }\n}\n\nvoid initial_queries() {\n    // Whole grid: almost free and gives total amount.\n    vector<int> all;\n    for (int id = 0; id < C; id++) all.push_back(id);\n    do_divination(all);\n\n    // Rows.\n    for (int i = 0; i < N; i++) {\n        vector<int> cells;\n        for (int j = 0; j < N; j++) cells.push_back(id_of(i, j));\n        do_divination(cells);\n    }\n\n    // Columns.\n    for (int j = 0; j < N; j++) {\n        vector<int> cells;\n        for (int i = 0; i < N; i++) cells.push_back(id_of(i, j));\n        do_divination(cells);\n    }\n\n    // Coarse blocks.\n    int B = 4;\n    for (int si = 0; si < N; si += B) {\n        for (int sj = 0; sj < N; sj += B) {\n            vector<int> cells;\n            for (int i = si; i < min(N, si + B); i++) {\n                for (int j = sj; j < min(N, sj + B); j++) {\n                    cells.push_back(id_of(i, j));\n                }\n            }\n            if ((int)cells.size() >= 2) do_divination(cells);\n        }\n    }\n\n    // Random half-grid masks. Cheap global linear measurements.\n    int R = (N <= 10 ? 18 : 30);\n    vector<int> ids(C);\n    iota(ids.begin(), ids.end(), 0);\n    for (int r = 0; r < R; r++) {\n        shuffle(ids.begin(), ids.end(), rng);\n        vector<int> cells;\n        int sz = max(2, C / 2);\n        for (int t = 0; t < sz; t++) cells.push_back(ids[t]);\n        do_divination(cells);\n    }\n}\n\nbitset<MAXC> union_of_state(const vector<int>& pos) {\n    bitset<MAXC> res;\n    res.reset();\n    for (int m = 0; m < M; m++) {\n        res |= placements[m][pos[m]].mask;\n    }\n    return res;\n}\n\nbool union_consistent_with_drills(const bitset<MAXC>& mask) {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) continue;\n        if (drilled[id] == 0 && mask.test(id)) return false;\n        if (drilled[id] > 0 && !mask.test(id)) return false;\n    }\n    return true;\n}\n\nstring mask_key(const bitset<MAXC>& mask) {\n    string s;\n    s.reserve(C);\n    for (int id = 0; id < C; id++) s.push_back(mask.test(id) ? '1' : '0');\n    return s;\n}\n\nvector<State> find_candidates(int want, int time_ms) {\n    int O = observations.size();\n\n    vector<vector<vector<unsigned char>>> contrib(M);\n    for (int m = 0; m < M; m++) {\n        int P = placements[m].size();\n        contrib[m].assign(P, vector<unsigned char>(O, 0));\n        for (int p = 0; p < P; p++) {\n            for (int o = 0; o < O; o++) {\n                bitset<MAXC> b = placements[m][p].mask & observations[o].mask;\n                contrib[m][p][o] = (unsigned char)b.count();\n            }\n        }\n    }\n\n    auto score_of_sums = [&](const vector<int>& sums) {\n        double sc = 0.0;\n        for (int o = 0; o < O; o++) {\n            double e = sums[o] - observations[o].target;\n            sc += observations[o].weight * e * e;\n        }\n        return sc;\n    };\n\n    vector<State> result;\n    auto deadline = chrono::steady_clock::now() + chrono::milliseconds(max(5, time_ms));\n\n    int restarts = 0;\n    while (restarts < 3 || chrono::steady_clock::now() < deadline) {\n        restarts++;\n\n        vector<int> pos(M);\n        for (int m = 0; m < M; m++) {\n            uniform_int_distribution<int> dist(0, (int)placements[m].size() - 1);\n            pos[m] = dist(rng);\n        }\n\n        vector<int> sums(O, 0);\n        for (int m = 0; m < M; m++) {\n            for (int o = 0; o < O; o++) {\n                sums[o] += contrib[m][pos[m]][o];\n            }\n        }\n\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n\n        for (int sweep = 0; sweep < 7; sweep++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool changed = false;\n\n            for (int mm = 0; mm < M; mm++) {\n                int m = order[mm];\n                int oldp = pos[m];\n\n                for (int o = 0; o < O; o++) {\n                    sums[o] -= contrib[m][oldp][o];\n                }\n\n                int bestp = oldp;\n                double bestsc = numeric_limits<double>::infinity();\n\n                int P = placements[m].size();\n                for (int p = 0; p < P; p++) {\n                    double sc = 0.0;\n                    for (int o = 0; o < O; o++) {\n                        double v = sums[o] + contrib[m][p][o];\n                        double e = v - observations[o].target;\n                        sc += observations[o].weight * e * e;\n                        if (sc >= bestsc) break;\n                    }\n                    if (sc < bestsc) {\n                        bestsc = sc;\n                        bestp = p;\n                    }\n                }\n\n                pos[m] = bestp;\n                for (int o = 0; o < O; o++) {\n                    sums[o] += contrib[m][bestp][o];\n                }\n\n                if (bestp != oldp) changed = true;\n            }\n\n            if (!changed) break;\n        }\n\n        State st;\n        st.pos = pos;\n        st.score = score_of_sums(sums);\n        st.uni = union_of_state(pos);\n        result.push_back(st);\n\n        if (elapsed_ms() > 2700.0) break;\n    }\n\n    sort(result.begin(), result.end(), [](const State& a, const State& b) {\n        return a.score < b.score;\n    });\n\n    vector<State> uniq;\n    unordered_set<string> seen;\n    for (auto &st : result) {\n        string key = mask_key(st.uni);\n        if (seen.insert(key).second) {\n            uniq.push_back(st);\n            if ((int)uniq.size() >= want) break;\n        }\n    }\n\n    return uniq;\n}\n\nint choose_drill_cell(const vector<State>& cand, int wrong_same_count) {\n    int K = cand.size();\n    vector<int> freq(C, 0);\n\n    for (auto &st : cand) {\n        for (int id = 0; id < C; id++) {\n            if (st.uni.test(id)) freq[id]++;\n        }\n    }\n\n    int best = -1;\n    int bestScore = -1;\n\n    // Prefer uncertain cells among candidate unions.\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] != -1) continue;\n        int f = freq[id];\n        if (f == 0 || f == K) continue;\n        int score = min(f, K - f);\n        if (score > bestScore) {\n            bestScore = score;\n            best = id;\n        }\n    }\n\n    if (best != -1) return best;\n\n    // If all candidates agree, verify predicted positives and nearby negatives.\n    if (!cand.empty()) {\n        const bitset<MAXC>& mask = cand[0].uni;\n\n        if (wrong_same_count % 2 == 0) {\n            for (int id = 0; id < C; id++) {\n                if (drilled[id] == -1 && mask.test(id)) return id;\n            }\n        }\n\n        // Boundary negatives.\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] != -1 || mask.test(id)) continue;\n            int i = id / N, j = id % N;\n            bool near = false;\n            const int di[4] = {-1, 1, 0, 0};\n            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 (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    if (mask.test(id_of(ni, nj))) near = true;\n                }\n            }\n            if (near) return id;\n        }\n\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] == -1 && !mask.test(id)) return id;\n        }\n    }\n\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) return id;\n    }\n\n    return -1;\n}\n\nvoid fallback_drill_all_and_answer() {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) {\n            do_drill(id);\n        }\n    }\n\n    bitset<MAXC> ans;\n    ans.reset();\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] > 0) ans.set(id);\n    }\n\n    ask_answer(ans);\n    exit(0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> EPSV;\n    C = N * N;\n    MAX_OPS = 2 * C;\n\n    shapes.resize(M);\n    for (int m = 0; m < M; m++) {\n        int d;\n        cin >> d;\n        shapes[m].resize(d);\n        for (int k = 0; k < d; k++) {\n            cin >> shapes[m][k].first >> shapes[m][k].second;\n        }\n    }\n\n    drilled.assign(C, -1);\n    build_placements();\n\n    initial_queries();\n\n    unordered_set<string> guessed;\n    int heuristic_drills = 0;\n    int guesses = 0;\n    int wrong_same_count = 0;\n\n    while (true) {\n        int unknown = 0;\n        for (int id = 0; id < C; id++) if (drilled[id] == -1) unknown++;\n\n        // Keep enough operations to drill everything and submit.\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        if (elapsed_ms() > 2700.0 || heuristic_drills >= 55) {\n            fallback_drill_all_and_answer();\n        }\n\n        int tlim = 90;\n        if (heuristic_drills == 0) tlim = 350;\n        if (elapsed_ms() > 2200.0) tlim = 20;\n\n        vector<State> cand = find_candidates(10, tlim);\n        if (cand.empty()) {\n            fallback_drill_all_and_answer();\n        }\n\n        bitset<MAXC> bestMask = cand[0].uni;\n        string key = mask_key(bestMask);\n\n        bool can_try_answer =\n            guesses < 25 &&\n            op_cnt + unknown + 2 <= MAX_OPS &&\n            guessed.find(key) == guessed.end() &&\n            union_consistent_with_drills(bestMask);\n\n        if (can_try_answer) {\n            guessed.insert(key);\n            guesses++;\n            bool ok = ask_answer(bestMask);\n            if (ok) return 0;\n            wrong_same_count++;\n        }\n\n        unknown = 0;\n        for (int id = 0; id < C; id++) if (drilled[id] == -1) unknown++;\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        int cell = choose_drill_cell(cand, wrong_same_count);\n        if (cell == -1) {\n            fallback_drill_all_and_answer();\n        }\n\n        do_drill(cell);\n        heuristic_drills++;\n    }\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int W = 1000;\nusing ll = long long;\nusing ull = unsigned long long;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nstruct Option {\n    int l, r;\n    int h;\n    ll cost;\n    bool stat;\n};\n\nint D, N;\nvector<vector<int>> A;\nvector<int> maxA;\n\ninline int ceil_div(int x, int y) {\n    return (x + y - 1) / y;\n}\n\nstruct Scorer {\n    int HN = 999 * 1000;\n    int VN = 1000 * 999;\n    int HW, VW;\n\n    Scorer() {\n        HW = (HN + 63) >> 6;\n        VW = (VN + 63) >> 6;\n    }\n\n    inline void setbit(vector<ull>& b, int idx) const {\n        b[idx >> 6] |= 1ULL << (idx & 63);\n    }\n\n    ll score(const vector<vector<Rect>>& sol) const {\n        vector<ull> prevH(HW, 0), prevV(VW, 0), curH(HW), curV(VW);\n        ll total = 0;\n\n        for (int d = 0; d < D; d++) {\n            fill(curH.begin(), curH.end(), 0);\n            fill(curV.begin(), curV.end(), 0);\n\n            for (int k = 0; k < N; k++) {\n                const Rect& r = sol[d][k];\n\n                ll area = 1LL * (r.i1 - r.i0) * (r.j1 - r.j0);\n                if (area < A[d][k]) total += 100LL * (A[d][k] - area);\n\n                if (r.i0 > 0) {\n                    int row = r.i0 - 1;\n                    for (int x = r.j0; x < r.j1; x++) {\n                        setbit(curH, row * 1000 + x);\n                    }\n                }\n                if (r.i1 < W) {\n                    int row = r.i1 - 1;\n                    for (int x = r.j0; x < r.j1; x++) {\n                        setbit(curH, row * 1000 + x);\n                    }\n                }\n                if (r.j0 > 0) {\n                    int col = r.j0 - 1;\n                    for (int y = r.i0; y < r.i1; y++) {\n                        setbit(curV, y * 999 + col);\n                    }\n                }\n                if (r.j1 < W) {\n                    int col = r.j1 - 1;\n                    for (int y = r.i0; y < r.i1; y++) {\n                        setbit(curV, y * 999 + col);\n                    }\n                }\n            }\n\n            if (d > 0) {\n                for (int i = 0; i < HW; i++) total += __builtin_popcountll(prevH[i] ^ curH[i]);\n                for (int i = 0; i < VW; i++) total += __builtin_popcountll(prevV[i] ^ curV[i]);\n            }\n\n            prevH.swap(curH);\n            prevV.swap(curV);\n        }\n\n        return total;\n    }\n};\n\nvector<vector<Rect>> make_empty_solution() {\n    return vector<vector<Rect>>(D, vector<Rect>(N));\n}\n\nbool valid_solution(const vector<vector<Rect>>& sol) {\n    if ((int)sol.size() != D) return false;\n    for (int d = 0; d < D; d++) {\n        if ((int)sol[d].size() != N) return false;\n        for (int k = 0; k < N; k++) {\n            auto r = sol[d][k];\n            if (!(0 <= r.i0 && r.i0 < r.i1 && r.i1 <= W)) return false;\n            if (!(0 <= r.j0 && r.j0 < r.j1 && r.j1 <= W)) return false;\n        }\n    }\n    return true;\n}\n\n// Best-Fit Decreasing packing into rows of capacity 1000.\n// widths[k] is required width of reservation k.\n// h is row height, so at most floor(1000/h) rows are usable.\nbool pack_bfd(const vector<int>& widths, int h, vector<vector<int>>& rows) {\n    rows.clear();\n    if (h <= 0 || h > 1000) return false;\n\n    int maxRows = 1000 / h;\n    if (maxRows <= 0) return false;\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 (widths[x] != widths[y]) return widths[x] > widths[y];\n        return x < y;\n    });\n\n    vector<int> rem;\n\n    for (int id : ids) {\n        int w = widths[id];\n        if (w <= 0 || w > 1000) return false;\n\n        int best = -1;\n        int bestRem = 1000000;\n\n        for (int r = 0; r < (int)rows.size(); r++) {\n            if (rem[r] >= w && rem[r] - w < bestRem) {\n                bestRem = rem[r] - w;\n                best = r;\n            }\n        }\n\n        if (best == -1) {\n            if ((int)rows.size() >= maxRows) return false;\n            rows.push_back(vector<int>{id});\n            rem.push_back(1000 - w);\n        } else {\n            rows[best].push_back(id);\n            rem[best] -= w;\n        }\n    }\n\n    for (auto& row : rows) {\n        sort(row.begin(), row.end());\n    }\n\n    sort(rows.begin(), rows.end(), [](const vector<int>& a, const vector<int>& b) {\n        return a.front() < b.front();\n    });\n\n    return true;\n}\n\nvector<vector<Rect>> build_from_rows_dynamic_height(\n    const vector<vector<vector<int>>>& allRows,\n    const vector<int>& hs\n) {\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        int h = hs[d];\n        int y = 0;\n\n        for (const auto& row : allRows[d]) {\n            int x = 0;\n            for (int t = 0; t < (int)row.size(); t++) {\n                int k = row[t];\n                int w;\n                if (t + 1 == (int)row.size()) {\n                    w = W - x;\n                } else {\n                    w = ceil_div(A[d][k], h);\n                }\n                if (w <= 0) w = 1;\n                sol[d][k] = {y, x, y + h, x + w};\n                x += w;\n            }\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> stable_shelf_dp() {\n    int K = N + 1;\n    int HD = 1001;\n\n    vector<int> pref(HD * D * K, 0);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) {\n                P(h, d, k + 1) = P(h, d, k) + ceil_div(A[d][k], h);\n            }\n        }\n    }\n\n    vector<int> prefMax(HD * K, 0);\n    auto PM = [&](int h, int k) -> int& {\n        return prefMax[h * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        PM(h, 0) = 0;\n        for (int k = 0; k < N; k++) {\n            PM(h, k + 1) = PM(h, k) + ceil_div(maxA[k], h);\n        }\n    }\n\n    auto dyn_feasible = [&](int l, int r, int h) {\n        for (int d = 0; d < D; d++) {\n            int s = P(h, d, r + 1) - P(h, d, l);\n            if (s > W) return false;\n        }\n        return true;\n    };\n\n    auto stat_feasible = [&](int l, int r, int h) {\n        int s = PM(h, r + 1) - PM(h, l);\n        return s <= W;\n    };\n\n    auto dyn_cost = [&](int l, int r, int h) -> ll {\n        int m = r - l + 1;\n        if (m <= 1) return 0;\n\n        ll res = 0;\n        vector<int> a, b;\n        a.reserve(m - 1);\n        b.reserve(m - 1);\n\n        for (int d = 1; d < D; d++) {\n            a.clear();\n            b.clear();\n\n            for (int t = l; t < r; t++) {\n                a.push_back(P(h, d - 1, t + 1) - P(h, d - 1, l));\n                b.push_back(P(h, d, t + 1) - P(h, d, l));\n            }\n\n            int i = 0, j = 0, common = 0;\n            while (i < (int)a.size() && j < (int)b.size()) {\n                if (a[i] == b[j]) {\n                    common++;\n                    i++;\n                    j++;\n                } else if (a[i] < b[j]) {\n                    i++;\n                } else {\n                    j++;\n                }\n            }\n\n            int sym = 2 * (m - 1) - 2 * common;\n            res += 1LL * sym * h;\n        }\n\n        return res;\n    };\n\n    vector<Option> opts;\n    vector<vector<int>> byStart(N);\n\n    for (int l = 0; l < N; l++) {\n        for (int r = l; r < N; r++) {\n            int hmin = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (dyn_feasible(l, r, h)) {\n                    hmin = h;\n                    break;\n                }\n            }\n            if (hmin == -1) continue;\n\n            vector<Option> tmp;\n\n            auto add_dyn = [&](int h) {\n                if (h < hmin || h > 1000) return;\n                if (!dyn_feasible(l, r, h)) return;\n                tmp.push_back({l, r, h, dyn_cost(l, r, h), false});\n            };\n\n            add_dyn(hmin);\n            for (int x = 1; x <= 8; x++) add_dyn(hmin + x);\n\n            vector<pair<int,int>> fs = {\n                {11,10}, {6,5}, {5,4}, {4,3}, {3,2},\n                {2,1}, {5,2}, {3,1}, {4,1}, {5,1},\n                {6,1}, {8,1}, {10,1}\n            };\n            for (auto [num, den] : fs) {\n                int h = (hmin * num + den - 1) / den;\n                add_dyn(h);\n            }\n\n            int hs = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (stat_feasible(l, r, h)) {\n                    hs = h;\n                    break;\n                }\n            }\n            if (hs != -1) tmp.push_back({l, r, hs, 0, true});\n\n            sort(tmp.begin(), tmp.end(), [](const Option& a, const Option& b) {\n                if (a.h != b.h) return a.h < b.h;\n                if (a.cost != b.cost) return a.cost < b.cost;\n                return a.stat > b.stat;\n            });\n\n            vector<Option> uniq;\n            for (auto &op : tmp) {\n                if (uniq.empty() || uniq.back().h != op.h) {\n                    uniq.push_back(op);\n                } else if (op.cost < uniq.back().cost) {\n                    uniq.back() = op;\n                }\n            }\n\n            ll best = (1LL << 60);\n            for (auto &op : uniq) {\n                if (op.cost < best) {\n                    best = op.cost;\n                    int id = (int)opts.size();\n                    opts.push_back(op);\n                    byStart[l].push_back(id);\n                }\n            }\n        }\n    }\n\n    const ll INF = (1LL << 60);\n    vector<vector<ll>> dp(N + 1, vector<ll>(1001, INF));\n    vector<vector<int>> parH(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parK(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parO(N + 1, vector<int>(1001, -1));\n\n    dp[0][0] = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int used = 0; used <= 1000; used++) {\n            if (dp[i][used] == INF) continue;\n\n            for (int id : byStart[i]) {\n                const Option& op = opts[id];\n                int nu = used + op.h;\n                if (nu > 1000) continue;\n\n                int ni = op.r + 1;\n                ll nv = dp[i][used] + op.cost;\n                if (nv < dp[ni][nu]) {\n                    dp[ni][nu] = nv;\n                    parH[ni][nu] = used;\n                    parK[ni][nu] = i;\n                    parO[ni][nu] = id;\n                }\n            }\n        }\n    }\n\n    int bestH = -1;\n    ll bestV = INF;\n    for (int h = 0; h <= 1000; h++) {\n        if (dp[N][h] < bestV) {\n            bestV = dp[N][h];\n            bestH = h;\n        }\n    }\n\n    if (bestH == -1 || bestV == INF) return {};\n\n    vector<Option> rows;\n    int curK = N, curH = bestH;\n    while (curK > 0) {\n        int id = parO[curK][curH];\n        if (id < 0) return {};\n        rows.push_back(opts[id]);\n\n        int pk = parK[curK][curH];\n        int ph = parH[curK][curH];\n        curK = pk;\n        curH = ph;\n    }\n\n    reverse(rows.begin(), rows.end());\n\n    auto sol = make_empty_solution();\n\n    int y = 0;\n    for (auto &op : rows) {\n        int l = op.l, r = op.r, h = op.h;\n\n        if (op.stat) {\n            vector<int> widths(r - l + 1);\n            int sum = 0;\n            for (int k = l; k < r; k++) {\n                widths[k - l] = ceil_div(maxA[k], h);\n                sum += widths[k - l];\n            }\n            widths[r - l] = W - sum;\n\n            for (int d = 0; d < D; d++) {\n                int x = 0;\n                for (int k = l; k <= r; k++) {\n                    int w = widths[k - l];\n                    sol[d][k] = {y, x, y + h, x + w};\n                    x += w;\n                }\n            }\n        } else {\n            for (int d = 0; d < D; d++) {\n                vector<int> widths(r - l + 1);\n                int sum = 0;\n                for (int k = l; k < r; k++) {\n                    widths[k - l] = ceil_div(A[d][k], h);\n                    sum += widths[k - l];\n                }\n                widths[r - l] = W - sum;\n\n                int x = 0;\n                for (int k = l; k <= r; k++) {\n                    int w = widths[k - l];\n                    sol[d][k] = {y, x, y + h, x + w};\n                    x += w;\n                }\n            }\n        }\n\n        y += h;\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> day_shelf_solution() {\n    int K = N + 1;\n    int HD = 1001;\n\n    vector<int> pref(HD * D * K, 0);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) {\n                P(h, d, k + 1) = P(h, d, k) + ceil_div(A[d][k], h);\n            }\n        }\n    }\n\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        vector<vector<int>> hmin(N, vector<int>(N, -1));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l; r < N; r++) {\n                for (int h = 1; h <= 1000; h++) {\n                    int s = P(h, d, r + 1) - P(h, d, l);\n                    if (s <= W) {\n                        hmin[l][r] = h;\n                        break;\n                    }\n                }\n            }\n        }\n\n        const int INF = 1e9;\n        vector<int> dp(N + 1, INF), par(N + 1, -1);\n        dp[0] = 0;\n\n        for (int i = 0; i < N; i++) {\n            if (dp[i] == INF) continue;\n            for (int r = i; r < N; r++) {\n                int h = hmin[i][r];\n                if (h < 0) continue;\n                if (dp[i] + h < dp[r + 1]) {\n                    dp[r + 1] = dp[i] + h;\n                    par[r + 1] = i;\n                }\n            }\n        }\n\n        if (dp[N] > 1000) return {};\n\n        vector<pair<int,int>> rows;\n        int cur = N;\n        while (cur > 0) {\n            int p = par[cur];\n            if (p < 0) return {};\n            rows.push_back({p, cur - 1});\n            cur = p;\n        }\n        reverse(rows.begin(), rows.end());\n\n        int y = 0;\n        for (auto [l, r] : rows) {\n            int h = hmin[l][r];\n\n            int x = 0;\n            for (int k = l; k < r; k++) {\n                int w = ceil_div(A[d][k], h);\n                sol[d][k] = {y, x, y + h, x + w};\n                x += w;\n            }\n            sol[d][r] = {y, x, y + h, W};\n\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\nvector<int> allocate_single_day_heights(int d) {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) -> int {\n        int rem = A[d][k] - h[k] * W;\n        if (rem <= 0) return 0;\n        return min(W, rem);\n    };\n\n    priority_queue<pair<int,int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n        if (b <= 0) break;\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<int> allocate_static_heights() {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) -> int {\n        int res = 0;\n        for (int d = 0; d < D; d++) {\n            int rem = A[d][k] - h[k] * W;\n            if (rem > 0) res += min(W, rem);\n        }\n        return res;\n    };\n\n    priority_queue<pair<int,int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n        if (b <= 0) break;\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<vector<Rect>> singleton_dynamic_solution() {\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        vector<int> h = allocate_single_day_heights(d);\n        int y = 0;\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> singleton_static_solution() {\n    auto sol = make_empty_solution();\n    vector<int> h = allocate_static_heights();\n\n    for (int d = 0; d < D; d++) {\n        int y = 0;\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\n// Fully static non-contiguous row packing using max demand.\n// If feasible, this often gives total cost 0.\nvector<vector<Rect>> static_bfd_solution() {\n    ll bestEst = (1LL << 60);\n    int bestH = -1;\n    vector<vector<int>> bestRows;\n\n    for (int h = 1; h <= 1000; h++) {\n        vector<int> widths(N);\n        bool ok = true;\n        for (int k = 0; k < N; k++) {\n            widths[k] = ceil_div(maxA[k], h);\n            if (widths[k] > 1000) ok = false;\n        }\n        if (!ok) continue;\n\n        vector<vector<int>> rows;\n        if (!pack_bfd(widths, h, rows)) continue;\n\n        ll est = 1LL * rows.size() * h;\n        if (est < bestEst) {\n            bestEst = est;\n            bestH = h;\n            bestRows = rows;\n        }\n    }\n\n    if (bestH == -1) return {};\n\n    auto sol = make_empty_solution();\n    int y = 0;\n\n    for (const auto& row : bestRows) {\n        int x = 0;\n        for (int t = 0; t < (int)row.size(); t++) {\n            int k = row[t];\n            int w;\n            if (t + 1 == (int)row.size()) {\n                w = W - x;\n            } else {\n                w = ceil_div(maxA[k], bestH);\n            }\n            for (int d = 0; d < D; d++) {\n                sol[d][k] = {y, x, y + bestH, x + w};\n            }\n            x += w;\n        }\n        y += bestH;\n    }\n\n    return sol;\n}\n\n// Each day chooses its own best BFD shelf height.\n// This is mainly a robust no-shortage fallback.\nvector<vector<Rect>> per_day_bfd_solution() {\n    vector<vector<vector<int>>> allRows(D);\n    vector<int> hs(D, -1);\n\n    for (int d = 0; d < D; d++) {\n        ll bestEst = (1LL << 60);\n        int bestH = -1;\n        vector<vector<int>> bestRows;\n\n        for (int h = 1; h <= 1000; h++) {\n            vector<int> widths(N);\n            bool ok = true;\n            for (int k = 0; k < N; k++) {\n                widths[k] = ceil_div(A[d][k], h);\n                if (widths[k] > 1000) ok = false;\n            }\n            if (!ok) continue;\n\n            vector<vector<int>> rows;\n            if (!pack_bfd(widths, h, rows)) continue;\n\n            int R = (int)rows.size();\n\n            // Rough estimate of partition amount for the day.\n            // Not exact, but good enough to choose a reasonable h.\n            ll est = 0;\n            est += 1000LL * max(0, R - 1);\n            est += 1LL * h * max(0, N - R);\n\n            // Prefer stable-ish medium heights slightly.\n            est += abs(h - 50);\n\n            if (est < bestEst) {\n                bestEst = est;\n                bestH = h;\n                bestRows = rows;\n            }\n        }\n\n        if (bestH == -1) return {};\n\n        hs[d] = bestH;\n        allRows[d] = bestRows;\n    }\n\n    return build_from_rows_dynamic_height(allRows, hs);\n}\n\n// Same height h for every day, but row assignments may differ by day.\n// Several promising h values are generated outside this function.\nvector<vector<Rect>> fixed_h_bfd_solution(int h) {\n    vector<vector<vector<int>>> allRows(D);\n    vector<int> hs(D, h);\n\n    for (int d = 0; d < D; d++) {\n        vector<int> widths(N);\n        bool ok = true;\n        for (int k = 0; k < N; k++) {\n            widths[k] = ceil_div(A[d][k], h);\n            if (widths[k] > 1000) ok = false;\n        }\n        if (!ok) return {};\n\n        vector<vector<int>> rows;\n        if (!pack_bfd(widths, h, rows)) return {};\n\n        allRows[d] = rows;\n    }\n\n    return build_from_rows_dynamic_height(allRows, hs);\n}\n\nvector<int> promising_fixed_heights() {\n    vector<pair<ll,int>> cand;\n\n    for (int h = 1; h <= 1000; h++) {\n        bool allok = true;\n        ll est = 0;\n\n        for (int d = 0; d < D; d++) {\n            vector<int> widths(N);\n            bool ok = true;\n            for (int k = 0; k < N; k++) {\n                widths[k] = ceil_div(A[d][k], h);\n                if (widths[k] > 1000) ok = false;\n            }\n            if (!ok) {\n                allok = false;\n                break;\n            }\n\n            vector<vector<int>> rows;\n            if (!pack_bfd(widths, h, rows)) {\n                allok = false;\n                break;\n            }\n\n            int R = (int)rows.size();\n            est += 1000LL * max(0, R - 1);\n            est += 1LL * h * max(0, N - R);\n        }\n\n        if (allok) {\n            // Prefer heights that divide 1000-ish less badly.\n            est += (1000 % h);\n            cand.push_back({est, h});\n        }\n    }\n\n    sort(cand.begin(), cand.end());\n\n    vector<int> res;\n    for (auto [e, h] : cand) {\n        bool close = false;\n        for (int x : res) {\n            if (abs(x - h) <= 2) close = true;\n        }\n        if (!close) res.push_back(h);\n        if ((int)res.size() >= 8) break;\n    }\n\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inputW;\n    cin >> inputW >> D >> N;\n\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    maxA.assign(N, 0);\n    for (int k = 0; k < N; k++) {\n        for (int d = 0; d < D; d++) {\n            maxA[k] = max(maxA[k], A[d][k]);\n        }\n    }\n\n    vector<vector<vector<Rect>>> candidates;\n\n    auto add_candidate = [&](vector<vector<Rect>> s) {\n        if (valid_solution(s)) candidates.push_back(move(s));\n    };\n\n    add_candidate(stable_shelf_dp());\n    add_candidate(static_bfd_solution());\n    add_candidate(per_day_bfd_solution());\n\n    for (int h : promising_fixed_heights()) {\n        add_candidate(fixed_h_bfd_solution(h));\n    }\n\n    add_candidate(day_shelf_solution());\n    add_candidate(singleton_dynamic_solution());\n    add_candidate(singleton_static_solution());\n\n    Scorer scorer;\n    ll bestScore = (1LL << 62);\n    int bestId = 0;\n\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        ll sc = scorer.score(candidates[i]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestId = i;\n        }\n    }\n\n    const auto& ans = candidates[bestId];\n\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            const Rect& r = ans[d][k];\n            cout << r.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 P = 7;\nstatic constexpr int K = 81;\nstatic constexpr int MOD = 998244353;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int nextInt(int n) {\n        return int(next() % n);\n    }\n};\n\nstruct Action {\n    int m, p, q;\n    int cell[9];\n    int val[9];\n};\n\nstruct State {\n    array<int, 81> board;\n    array<int, 81> seq;\n    long long score;\n};\n\nclass Solver {\nprivate:\n    int inN, M, inK;\n    int stamp[20][3][3];\n\n    vector<Action> actions;\n    int DUMMY;\n\n    array<int, 81> initBoard;\n    long long initScore = 0;\n\n    chrono::steady_clock::time_point startTime;\n    static constexpr double TIME_LIMIT = 1.86;\n\n    XorShift rng;\n\n    inline double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    }\n\n    inline bool timeOver() const {\n        return elapsed() >= TIME_LIMIT;\n    }\n\n    inline long long gainAdd(const array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long g = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv + a.val[k];\n            if (nv >= MOD) nv -= MOD;\n            g += (long long)nv - oldv;\n        }\n\n        return g;\n    }\n\n    inline long long applyAdd(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv + a.val[k];\n            if (nv >= MOD) nv -= MOD;\n\n            board[c] = nv;\n            diff += (long long)nv - oldv;\n        }\n\n        return diff;\n    }\n\n    inline long long applyRemove(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv - a.val[k];\n            if (nv < 0) nv += MOD;\n\n            board[c] = nv;\n            diff += (long long)nv - oldv;\n        }\n\n        return diff;\n    }\n\n    State emptyState() const {\n        State st;\n        st.board = initBoard;\n        st.seq.fill(DUMMY);\n        st.score = initScore;\n        return st;\n    }\n\n    void insertTop(array<int, 32>& ids, array<long long, 32>& gs, int id, long long g, int C) {\n        if (g <= gs[C - 1]) return;\n\n        int pos = C - 1;\n        while (pos > 0 && g > gs[pos - 1]) {\n            ids[pos] = ids[pos - 1];\n            gs[pos] = gs[pos - 1];\n            pos--;\n        }\n        ids[pos] = id;\n        gs[pos] = g;\n    }\n\n    int bestAction(const array<int, 81>& board) const {\n        long long bestG = 0;\n        int bestId = DUMMY;\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(board, id);\n            if (g > bestG) {\n                bestG = g;\n                bestId = id;\n            }\n        }\n\n        return bestId;\n    }\n\n    State greedyState() {\n        State st = emptyState();\n\n        for (int t = 0; t < K; t++) {\n            int id = bestAction(st.board);\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    State randomizedGreedyState(int topC) {\n        State st = emptyState();\n\n        topC = min(topC, 32);\n\n        for (int t = 0; t < K; t++) {\n            array<int, 32> ids;\n            array<long long, 32> gs;\n\n            ids.fill(DUMMY);\n            gs.fill(LLONG_MIN / 4);\n\n            insertTop(ids, gs, DUMMY, 0, topC);\n\n            for (int id = 0; id < DUMMY; id++) {\n                long long g = gainAdd(st.board, id);\n                insertTop(ids, gs, id, g, topC);\n            }\n\n            int r;\n            uint64_t x = rng.next() % 100;\n\n            if (x < 55) r = 0;\n            else if (x < 75) r = min(1, topC - 1);\n            else if (x < 88) r = min(2, topC - 1);\n            else r = rng.nextInt(topC);\n\n            int id = ids[r];\n            if (gs[r] < 0) id = DUMMY;\n\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    void shuffleOrder(array<int, 81>& ord) {\n        for (int i = K - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    void coordinateDescent(State& st, int maxPass) {\n        array<int, 81> ord;\n        for (int i = 0; i < K; i++) ord[i] = i;\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            if (timeOver()) return;\n\n            shuffleOrder(ord);\n            bool changed = false;\n\n            for (int oi = 0; oi < K; oi++) {\n                if ((oi & 7) == 0 && timeOver()) return;\n\n                int idx = ord[oi];\n                int oldId = st.seq[idx];\n\n                st.score += applyRemove(st.board, oldId);\n\n                long long bestG = 0;\n                int bestId = DUMMY;\n\n                for (int id = 0; id < DUMMY; id++) {\n                    long long g = gainAdd(st.board, id);\n                    if (g > bestG) {\n                        bestG = g;\n                        bestId = id;\n                    }\n                }\n\n                st.seq[idx] = bestId;\n                st.score += applyAdd(st.board, bestId);\n\n                if (bestId != oldId) changed = true;\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void randomPerturb(State& st, int strength) {\n        for (int r = 0; r < strength; r++) {\n            int idx = rng.nextInt(K);\n            int oldId = st.seq[idx];\n\n            st.score += applyRemove(st.board, oldId);\n\n            int newId = rng.nextInt(DUMMY);\n            st.seq[idx] = newId;\n            st.score += applyAdd(st.board, newId);\n        }\n    }\n\n    void ruinRecreate(State& st, int strength) {\n        bool used[81] = {};\n        vector<int> slots;\n        slots.reserve(strength);\n\n        while ((int)slots.size() < strength) {\n            int idx = rng.nextInt(K);\n            if (!used[idx]) {\n                used[idx] = true;\n                slots.push_back(idx);\n            }\n        }\n\n        for (int idx : slots) {\n            st.score += applyRemove(st.board, st.seq[idx]);\n            st.seq[idx] = DUMMY;\n        }\n\n        for (int i = (int)slots.size() - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(slots[i], slots[j]);\n        }\n\n        for (int idx : slots) {\n            int id = bestAction(st.board);\n            st.seq[idx] = id;\n            st.score += applyAdd(st.board, id);\n        }\n    }\n\n    bool pairAttempt(State& st) {\n        int x = rng.nextInt(K);\n        int y = rng.nextInt(K - 1);\n        if (y >= x) y++;\n\n        int oldX = st.seq[x];\n        int oldY = st.seq[y];\n\n        long long originalScore = st.score;\n\n        st.score += applyRemove(st.board, oldX);\n        st.score += applyRemove(st.board, oldY);\n\n        long long baseScore = st.score;\n\n        static constexpr int C = 26;\n\n        array<int, 32> firstIds;\n        array<long long, 32> firstGs;\n\n        firstIds.fill(DUMMY);\n        firstGs.fill(LLONG_MIN / 4);\n\n        insertTop(firstIds, firstGs, DUMMY, 0, C);\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(st.board, id);\n            insertTop(firstIds, firstGs, id, g, C);\n        }\n\n        long long bestTotal = 0;\n        int bestA = DUMMY;\n        int bestB = DUMMY;\n\n        auto evalFirst = [&](int a) {\n            long long g1 = gainAdd(st.board, a);\n            applyAdd(st.board, a);\n\n            long long bestG2 = 0;\n            int b = DUMMY;\n\n            for (int id = 0; id < DUMMY; id++) {\n                long long g2 = gainAdd(st.board, id);\n                if (g2 > bestG2) {\n                    bestG2 = g2;\n                    b = id;\n                }\n            }\n\n            long long total = g1 + bestG2;\n\n            if (total > bestTotal) {\n                bestTotal = total;\n                bestA = a;\n                bestB = b;\n            }\n\n            applyRemove(st.board, a);\n        };\n\n        for (int i = 0; i < C; i++) {\n            evalFirst(firstIds[i]);\n        }\n\n        evalFirst(oldX);\n        evalFirst(oldY);\n\n        for (int i = 0; i < 4; i++) {\n            evalFirst(rng.nextInt(DUMMY));\n        }\n\n        if (baseScore + bestTotal > originalScore) {\n            st.seq[x] = bestA;\n            st.seq[y] = bestB;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, bestA);\n            st.score += applyAdd(st.board, bestB);\n\n            return true;\n        } else {\n            st.seq[x] = oldX;\n            st.seq[y] = oldY;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, oldX);\n            st.score += applyAdd(st.board, oldY);\n\n            return false;\n        }\n    }\n\n    void pairLocalSearch(State& st, int attempts) {\n        int improved = 0;\n\n        for (int t = 0; t < attempts; t++) {\n            if ((t & 3) == 0 && timeOver()) return;\n\n            if (pairAttempt(st)) {\n                improved++;\n\n                if ((improved & 7) == 0) {\n                    coordinateDescent(st, 2);\n                }\n            }\n        }\n\n        if (improved > 0) {\n            coordinateDescent(st, 5);\n        }\n    }\n\npublic:\n    void readInput() {\n        cin >> inN >> M >> inK;\n\n        uint64_t seed = 123456789123ULL;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int x;\n                cin >> x;\n\n                initBoard[i * N + j] = x;\n                initScore += x;\n\n                seed ^= uint64_t(x + 1) * 1000003ULL;\n                seed = seed * 11995408973635179863ULL + 101;\n            }\n        }\n\n        for (int m = 0; m < M; m++) {\n            for (int i = 0; i < 3; i++) {\n                for (int j = 0; j < 3; j++) {\n                    cin >> stamp[m][i][j];\n\n                    seed ^= uint64_t(stamp[m][i][j] + 7) * 1000000007ULL;\n                    seed = seed * 1000003ULL + 97;\n                }\n            }\n        }\n\n        rng = XorShift(seed);\n    }\n\n    void buildActions() {\n        actions.clear();\n\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                for (int m = 0; m < M; m++) {\n                    Action a;\n                    a.m = m;\n                    a.p = p;\n                    a.q = q;\n\n                    int idx = 0;\n                    for (int di = 0; di < 3; di++) {\n                        for (int dj = 0; dj < 3; dj++) {\n                            a.cell[idx] = (p + di) * N + (q + dj);\n                            a.val[idx] = stamp[m][di][dj];\n                            idx++;\n                        }\n                    }\n\n                    actions.push_back(a);\n                }\n            }\n        }\n\n        DUMMY = (int)actions.size();\n    }\n\n    void solve() {\n        startTime = chrono::steady_clock::now();\n\n        buildActions();\n\n        State best = greedyState();\n        coordinateDescent(best, 1000);\n\n        pairLocalSearch(best, 80);\n\n        int iter = 0;\n\n        while (!timeOver()) {\n            State cand;\n\n            int mode = iter % 8;\n\n            if (mode <= 3) {\n                cand = best;\n                int strength = 3 + rng.nextInt(10);\n                ruinRecreate(cand, strength);\n                coordinateDescent(cand, 25);\n                pairLocalSearch(cand, 20);\n            } else if (mode == 4 || mode == 5) {\n                cand = best;\n                int strength = 3 + rng.nextInt(12);\n                randomPerturb(cand, strength);\n                coordinateDescent(cand, 30);\n                pairLocalSearch(cand, 15);\n            } else {\n                int topC = 6 + rng.nextInt(12);\n                cand = randomizedGreedyState(topC);\n                coordinateDescent(cand, 40);\n                pairLocalSearch(cand, 15);\n            }\n\n            if (cand.score > best.score) {\n                best = cand;\n                coordinateDescent(best, 8);\n            }\n\n            iter++;\n        }\n\n        vector<tuple<int, int, int>> ans;\n\n        for (int i = 0; i < K; i++) {\n            int id = best.seq[i];\n            if (id == DUMMY) continue;\n\n            const Action& a = actions[id];\n            ans.emplace_back(a.m, a.p, a.q);\n        }\n\n        cout << ans.size() << '\\n';\n        for (auto [m, p, q] : ans) {\n            cout << m << ' ' << p << ' ' << q << '\\n';\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\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static constexpr int N = 5;\n\n    vector<vector<int>> A;\n    int grid[N][N];\n    int idx[N];\n\n    int cr = 0, cc = 0;\n    int hold = -1;\n\n    vector<string> S;\n    bool first_step = true;\n\n    vector<int> nextNeed;\n    vector<int> delivered;\n    int deliveredCnt = 0;\n\n    Solver(const vector<vector<int>>& A_) : A(A_) {\n        memset(grid, -1, sizeof(grid));\n        memset(idx, 0, sizeof(idx));\n        S.assign(N, \"\");\n        nextNeed.resize(N);\n        delivered.assign(N * N, 0);\n        for (int g = 0; g < N; g++) nextNeed[g] = g * N;\n    }\n\n    int dist(pair<int,int> a, pair<int,int> b) {\n        return abs(a.first - b.first) + abs(a.second - b.second);\n    }\n\n    void step(char act) {\n        // 1. arrivals\n        for (int r = 0; r < N; r++) {\n            bool blocked_by_holding_crane = (hold != -1 && cr == r && cc == 0);\n            if (idx[r] < N && grid[r][0] == -1 && !blocked_by_holding_crane) {\n                grid[r][0] = A[r][idx[r]];\n                idx[r]++;\n            }\n        }\n\n        // output operation\n        S[0].push_back(act);\n        for (int i = 1; i < N; i++) {\n            if (first_step) S[i].push_back('B');\n            else S[i].push_back('.');\n        }\n        first_step = false;\n\n        // 2. action of the large crane\n        if (act == 'P') {\n            hold = grid[cr][cc];\n            grid[cr][cc] = -1;\n        } else if (act == 'Q') {\n            grid[cr][cc] = hold;\n            hold = -1;\n        } else if (act == 'U') {\n            cr--;\n        } else if (act == 'D') {\n            cr++;\n        } else if (act == 'L') {\n            cc--;\n        } else if (act == 'R') {\n            cc++;\n        }\n\n        // 3. dispatch\n        for (int r = 0; r < N; r++) {\n            if (grid[r][N - 1] != -1) {\n                grid[r][N - 1] = -1;\n            }\n        }\n    }\n\n    void moveTo(int r, int c) {\n        while (cr < r) step('D');\n        while (cr > r) step('U');\n        while (cc < c) step('R');\n        while (cc > c) step('L');\n    }\n\n    void pickAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('P');\n    }\n\n    void releaseAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('Q');\n    }\n\n    void markDelivered(int id) {\n        if (!delivered[id]) {\n            delivered[id] = 1;\n            deliveredCnt++;\n        }\n        int g = id / N;\n        while (nextNeed[g] < (g + 1) * N && delivered[nextNeed[g]]) {\n            nextNeed[g]++;\n        }\n    }\n\n    optional<pair<int,int>> findAccessible(int id) {\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (grid[r][c] == id) return pair<int,int>{r, c};\n            }\n        }\n\n        // A hidden next container at an empty receiving gate is accessible:\n        // it will appear at the beginning of the next turn.\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == id) {\n                return pair<int,int>{r, 0};\n            }\n        }\n\n        return nullopt;\n    }\n\n    int frontId(int r) {\n        if (grid[r][0] != -1) return grid[r][0];\n        if (idx[r] < N) return A[r][idx[r]];\n        return -1;\n    }\n\n    vector<pair<int,int>> freeStorageCells() {\n        vector<pair<int,int>> res;\n\n        // Main storage: inner 15 cells.\n        for (int r = 0; r < N; r++) {\n            for (int c = 1; c <= 3; c++) {\n                if (grid[r][c] == -1) res.push_back({r, c});\n            }\n        }\n\n        // Receiving gates whose input has already been exhausted are also safe storage.\n        for (int r = 0; r < N; r++) {\n            if (idx[r] >= N && grid[r][0] == -1) {\n                res.push_back({r, 0});\n            }\n        }\n\n        return res;\n    }\n\n    pair<int,int> chooseStorageCell(pair<int,int> from) {\n        auto cells = freeStorageCells();\n        pair<int,int> best = cells[0];\n        int bestCost = 1e9;\n\n        for (auto p : cells) {\n            int cost = dist(from, p);\n            if (cost < bestCost) {\n                bestCost = cost;\n                best = p;\n            }\n        }\n\n        return best;\n    }\n\n    void dispatchContainer(int id) {\n        auto srcOpt = findAccessible(id);\n        if (!srcOpt) return;\n\n        auto src = *srcOpt;\n        pickAt(src);\n\n        int g = id / N;\n        releaseAt({g, N - 1});\n\n        markDelivered(id);\n    }\n\n    void storeFrontContainer(int r) {\n        int id = frontId(r);\n        if (id == -1) return;\n\n        pair<int,int> src = {r, 0};\n        auto dst = chooseStorageCell(src);\n\n        pickAt(src);\n        releaseAt(dst);\n    }\n\n    int depthToNeeded(int r) {\n        set<int> need;\n        for (int g = 0; g < N; g++) {\n            if (nextNeed[g] < (g + 1) * N) need.insert(nextNeed[g]);\n        }\n\n        int d = 0;\n\n        if (grid[r][0] != -1) {\n            if (need.count(grid[r][0])) return 0;\n            d = 1;\n        }\n\n        for (int k = idx[r]; k < N; k++, d++) {\n            if (need.count(A[r][k])) return d;\n        }\n\n        return 100;\n    }\n\n    int chooseRowToDig() {\n        int bestRow = -1;\n        int bestDepth = 1e9;\n        int bestDist = 1e9;\n\n        for (int r = 0; r < N; r++) {\n            int f = frontId(r);\n            if (f == -1) continue;\n\n            // If this row has no hidden future containers, digging it does not unlock much.\n            if (idx[r] >= N && grid[r][0] != -1) continue;\n\n            int dep = depthToNeeded(r);\n            int dcur = abs(cr - r) + cc;\n\n            if (dep < bestDepth || (dep == bestDepth && dcur < bestDist)) {\n                bestDepth = dep;\n                bestDist = dcur;\n                bestRow = r;\n            }\n        }\n\n        if (bestRow != -1) return bestRow;\n\n        // Fallback: any row with a front container.\n        for (int r = 0; r < N; r++) {\n            if (frontId(r) != -1) return r;\n        }\n\n        return -1;\n    }\n\n    vector<pair<int,pair<int,int>>> accessibleCandidates() {\n        vector<pair<int,pair<int,int>>> res;\n        bool seen[N * N] = {};\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                int id = grid[r][c];\n                if (id != -1 && !delivered[id] && !seen[id]) {\n                    seen[id] = true;\n                    res.push_back({id, {r, c}});\n                }\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N) {\n                int id = A[r][idx[r]];\n                if (!delivered[id] && !seen[id]) {\n                    seen[id] = true;\n                    res.push_back({id, {r, 0}});\n                }\n            }\n        }\n\n        return res;\n    }\n\n    int missingSmallerInGroup(int id) {\n        int g = id / N;\n        int cnt = 0;\n        for (int x = g * N; x < id; x++) {\n            if (!delivered[x]) cnt++;\n        }\n        return cnt;\n    }\n\n    int chooseFallbackDispatch() {\n        auto cand = accessibleCandidates();\n\n        int bestId = -1;\n        tuple<int,int,int> best = {1e9, 1e9, 1e9};\n\n        for (auto [id, pos] : cand) {\n            int g = id / N;\n            int invRisk = missingSmallerInGroup(id);\n            int cost = dist({cr, cc}, pos) + dist(pos, {g, N - 1});\n\n            tuple<int,int,int> key = {invRisk, cost, id};\n            if (key < best) {\n                best = key;\n                bestId = id;\n            }\n        }\n\n        return bestId;\n    }\n\n    void solve() {\n        while (deliveredCnt < N * N && (int)S[0].size() < 9500) {\n            int bestId = -1;\n            pair<int,int> bestSrc;\n            int bestCost = 1e9;\n\n            // Prefer dispatching the exact next needed container for some gate.\n            for (int g = 0; g < N; g++) {\n                if (nextNeed[g] >= (g + 1) * N) continue;\n\n                int id = nextNeed[g];\n                auto srcOpt = findAccessible(id);\n                if (!srcOpt) continue;\n\n                auto src = *srcOpt;\n                int cost = dist({cr, cc}, src) + dist(src, {g, N - 1});\n\n                if (cost < bestCost) {\n                    bestCost = cost;\n                    bestId = id;\n                    bestSrc = src;\n                }\n            }\n\n            if (bestId != -1) {\n                dispatchContainer(bestId);\n                continue;\n            }\n\n            // Otherwise, store a blocking front container if possible.\n            auto freeCells = freeStorageCells();\n            if (!freeCells.empty()) {\n                int r = chooseRowToDig();\n                if (r != -1) {\n                    storeFrontContainer(r);\n                    continue;\n                }\n            }\n\n            // Storage full: dispatch something out of order but to its correct gate.\n            int id = chooseFallbackDispatch();\n            if (id != -1) {\n                dispatchContainer(id);\n                continue;\n            }\n\n            // Should not happen, but keep output valid.\n            step('.');\n        }\n\n        // If all containers are not delivered due to some unexpected situation,\n        // keep the output valid. Usually this is unnecessary.\n        if (S[0].empty()) step('.');\n    }\n\n    void output() {\n        int T = 0;\n        for (auto &s : S) T = max(T, (int)s.size());\n\n        for (auto &s : S) {\n            while ((int)s.size() < T) s.push_back('.');\n        }\n\n        for (int i = 0; i < N; i++) {\n            cout << S[i] << '\\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\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> A[i][j];\n    }\n\n    Solver solver(A);\n    solver.solve();\n    solver.output();\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int B = 10;\nstatic const int V = N * N;\nstatic const long long INF = (1LL << 60);\n\nint hval[V];\nlong long base_cost = 0;\n\nint dr[4] = {-1, 0, 1, 0};\nint dc[4] = {0, 1, 0, -1};\nchar mvchar[4] = {'U', 'R', 'D', 'L'};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a);\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 a, b;\n};\n\nstruct EvalResult {\n    long long cost = INF;\n    vector<int> order;\n};\n\nint id20(int r, int c) {\n    return r * N + c;\n}\n\nint dir_between(int a, int b) {\n    int ar = a / N, ac = a % N;\n    int br = b / N, bc = b % N;\n    for (int d = 0; d < 4; d++) {\n        if (ar + dr[d] == br && ac + dc[d] == bc) return d;\n    }\n    return -1;\n}\n\nvoid add_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n    if (d < 0 || e < 0) return;\n    mask[a] |= (1u << d);\n    mask[b] |= (1u << e);\n}\n\nvoid remove_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n    if (d < 0 || e < 0) return;\n    mask[a] &= ~(1u << d);\n    mask[b] &= ~(1u << e);\n}\n\nbool build_cycle_from_tree_edges(const vector<Edge>& tree_edges, vector<int>& cyc) {\n    array<unsigned char, V> mask;\n    mask.fill(0);\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int a = id20(2 * r, 2 * c);\n            int b = id20(2 * r, 2 * c + 1);\n            int e = id20(2 * r + 1, 2 * c + 1);\n            int d = id20(2 * r + 1, 2 * c);\n\n            add_edge_cell(mask, a, b);\n            add_edge_cell(mask, b, e);\n            add_edge_cell(mask, e, d);\n            add_edge_cell(mask, d, a);\n        }\n    }\n\n    for (auto ed : tree_edges) {\n        int ar = ed.a / B, ac = ed.a % B;\n        int br = ed.b / B, bc = ed.b % B;\n\n        if (ar == br) {\n            int r = ar;\n            int c = min(ac, bc);\n\n            int a1 = id20(2 * r, 2 * c + 1);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r, 2 * c + 2);\n            int b2 = id20(2 * r + 1, 2 * c + 2);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        } else {\n            int r = min(ar, br);\n            int c = ac;\n\n            int a1 = id20(2 * r + 1, 2 * c);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r + 2, 2 * c);\n            int b2 = id20(2 * r + 2, 2 * c + 1);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        }\n    }\n\n    for (int i = 0; i < V; i++) {\n        if (__builtin_popcount((int)mask[i]) != 2) return false;\n    }\n\n    cyc.clear();\n    int start = 0;\n    int cur = start;\n    int prev = -1;\n\n    while (true) {\n        cyc.push_back(cur);\n\n        int nxt = -1;\n        for (int d = 0; d < 4; d++) {\n            if (!(mask[cur] & (1u << d))) continue;\n            int r = cur / N + dr[d];\n            int c = cur % N + dc[d];\n            int nb = id20(r, c);\n            if (nb != prev) {\n                nxt = nb;\n                break;\n            }\n        }\n\n        if (nxt < 0) return false;\n\n        prev = cur;\n        cur = nxt;\n\n        if (cur == start) break;\n        if ((int)cyc.size() > V) return false;\n    }\n\n    return (int)cyc.size() == V;\n}\n\nvoid evaluate_cycle_order(const vector<int>& cyc, EvalResult& res, bool store_order) {\n    const int L = V;\n    vector<int> pref(L + 1, 0);\n\n    for (int i = 0; i < L; i++) {\n        pref[i + 1] = pref[i] + hval[cyc[i]];\n    }\n\n    int mn = pref[0];\n    for (int i = 0; i < L; i++) mn = min(mn, pref[i]);\n\n    for (int k = 0; k < L; k++) {\n        if (pref[k] != mn) continue;\n\n        long long load = 0;\n        long long load_move_cost = 0;\n        bool ok = true;\n\n        for (int t = 0; t < L; t++) {\n            int id = cyc[(k + t) % L];\n            load += hval[id];\n\n            if (load < 0) {\n                ok = false;\n                break;\n            }\n\n            if (t != L - 1) {\n                load_move_cost += load;\n            }\n        }\n\n        if (!ok || load != 0) continue;\n\n        int st = cyc[k];\n        int sr = st / N;\n        int sc = st % N;\n        int empty_dist = sr + sc;\n\n        long long cost = base_cost + 100LL * (empty_dist + L - 1) + load_move_cost;\n\n        if (cost < res.cost) {\n            res.cost = cost;\n\n            if (store_order) {\n                res.order.clear();\n                res.order.reserve(L);\n                for (int t = 0; t < L; t++) {\n                    res.order.push_back(cyc[(k + t) % L]);\n                }\n            }\n        }\n    }\n}\n\nEvalResult evaluate_cycle(const vector<int>& cyc, bool store_order) {\n    EvalResult res;\n\n    evaluate_cycle_order(cyc, res, store_order);\n\n    vector<int> rev = cyc;\n    reverse(rev.begin(), rev.end());\n    evaluate_cycle_order(rev, res, store_order);\n\n    return res;\n}\n\nvector<Edge> all_edges;\nint edge_id[100][100];\n\nvector<char> tree_to_mask(const vector<Edge>& tr) {\n    vector<char> in(all_edges.size(), 0);\n\n    for (auto e : tr) {\n        int id = edge_id[e.a][e.b];\n        if (id >= 0) in[id] = 1;\n    }\n\n    return in;\n}\n\nvector<Edge> mask_to_tree_edges(const vector<char>& in) {\n    vector<Edge> tr;\n    tr.reserve(B * B - 1);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        if (in[i]) tr.push_back(all_edges[i]);\n    }\n\n    return tr;\n}\n\nEvalResult evaluate_tree_mask(const vector<char>& in, bool store_order) {\n    vector<Edge> tr = mask_to_tree_edges(in);\n    vector<int> cyc;\n\n    if ((int)tr.size() != B * B - 1) return EvalResult();\n\n    if (!build_cycle_from_tree_edges(tr, cyc)) return EvalResult();\n\n    return evaluate_cycle(cyc, store_order);\n}\n\nvector<Edge> make_row_tree(int col) {\n    vector<Edge> res;\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c + 1 < B; c++) {\n            res.push_back({r * B + c, r * B + c + 1});\n        }\n    }\n\n    for (int r = 0; r + 1 < B; r++) {\n        res.push_back({r * B + col, (r + 1) * B + col});\n    }\n\n    return res;\n}\n\nvector<Edge> make_col_tree(int row) {\n    vector<Edge> res;\n\n    for (int c = 0; c < B; c++) {\n        for (int r = 0; r + 1 < B; r++) {\n            res.push_back({r * B + c, (r + 1) * B + c});\n        }\n    }\n\n    for (int c = 0; c + 1 < B; c++) {\n        res.push_back({row * B + c, row * B + c + 1});\n    }\n\n    return res;\n}\n\nvector<char> random_kruskal_tree(mt19937& rng) {\n    vector<int> perm(all_edges.size());\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n\n    DSU dsu(B * B);\n    vector<char> in(all_edges.size(), 0);\n    int cnt = 0;\n\n    for (int id : perm) {\n        auto e = all_edges[id];\n        if (dsu.unite(e.a, e.b)) {\n            in[id] = 1;\n            cnt++;\n            if (cnt == B * B - 1) break;\n        }\n    }\n\n    return in;\n}\n\nvector<char> random_prim_tree(mt19937& rng) {\n    vector<vector<pair<int, int>>> g(B * B);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        auto e = all_edges[i];\n        g[e.a].push_back({e.b, i});\n        g[e.b].push_back({e.a, i});\n    }\n\n    vector<char> used(B * B, 0);\n    vector<char> in(all_edges.size(), 0);\n\n    int st = uniform_int_distribution<int>(0, B * B - 1)(rng);\n    used[st] = 1;\n\n    vector<pair<int, int>> frontier;\n    for (auto p : g[st]) frontier.push_back({p.first, p.second});\n\n    int cnt = 0;\n\n    while (cnt < B * B - 1 && !frontier.empty()) {\n        int k = uniform_int_distribution<int>(0, (int)frontier.size() - 1)(rng);\n        auto [to, eid] = frontier[k];\n        frontier[k] = frontier.back();\n        frontier.pop_back();\n\n        auto e = all_edges[eid];\n        int a = e.a, b = e.b;\n        int nxt = -1;\n\n        if (used[a] && !used[b]) nxt = b;\n        else if (used[b] && !used[a]) nxt = a;\n        else continue;\n\n        used[nxt] = 1;\n        in[eid] = 1;\n        cnt++;\n\n        for (auto p : g[nxt]) {\n            if (!used[p.first]) frontier.push_back({p.first, p.second});\n        }\n    }\n\n    return in;\n}\n\nvector<int> get_path_edges_in_tree(const vector<char>& in, int s, int t) {\n    vector<vector<pair<int, int>>> g(B * B);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        if (!in[i]) continue;\n        auto e = all_edges[i];\n        g[e.a].push_back({e.b, i});\n        g[e.b].push_back({e.a, i});\n    }\n\n    vector<int> par(B * B, -1);\n    vector<int> pedge(B * B, -1);\n    queue<int> q;\n\n    par[s] = s;\n    q.push(s);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        if (v == t) break;\n\n        for (auto [to, eid] : g[v]) {\n            if (par[to] != -1) continue;\n            par[to] = v;\n            pedge[to] = eid;\n            q.push(to);\n        }\n    }\n\n    vector<int> path;\n    if (par[t] == -1) return path;\n\n    int cur = t;\n    while (cur != s) {\n        path.push_back(pedge[cur]);\n        cur = par[cur];\n    }\n\n    return path;\n}\n\nvoid local_search(vector<char>& cur_tree, EvalResult& global_best, const Timer& timer) {\n    EvalResult cur_eval = evaluate_tree_mask(cur_tree, false);\n    long long cur_cost = cur_eval.cost;\n\n    if (cur_cost >= INF) return;\n\n    bool improved = true;\n\n    while (timer.elapsed() < 1.85 && improved) {\n        improved = false;\n\n        long long best_cost = cur_cost;\n        int best_add = -1;\n        int best_rem = -1;\n\n        vector<int> non_edges;\n        for (int i = 0; i < (int)all_edges.size(); i++) {\n            if (!cur_tree[i]) non_edges.push_back(i);\n        }\n\n        for (int eid : non_edges) {\n            if (timer.elapsed() > 1.85) break;\n\n            auto e = all_edges[eid];\n            vector<int> path = get_path_edges_in_tree(cur_tree, e.a, e.b);\n\n            for (int rem : path) {\n                cur_tree[eid] = 1;\n                cur_tree[rem] = 0;\n\n                EvalResult ev = evaluate_tree_mask(cur_tree, false);\n\n                cur_tree[eid] = 0;\n                cur_tree[rem] = 1;\n\n                if (ev.cost < best_cost) {\n                    best_cost = ev.cost;\n                    best_add = eid;\n                    best_rem = rem;\n                }\n            }\n        }\n\n        if (best_add != -1) {\n            cur_tree[best_add] = 1;\n            cur_tree[best_rem] = 0;\n            cur_cost = best_cost;\n            improved = true;\n\n            EvalResult stored = evaluate_tree_mask(cur_tree, true);\n            if (stored.cost < global_best.cost) {\n                global_best = stored;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int n;\n    cin >> n;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            hval[id20(i, j)] = x;\n            base_cost += abs(x);\n        }\n    }\n\n    if (base_cost == 0) {\n        return 0;\n    }\n\n    memset(edge_id, -1, sizeof(edge_id));\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int v = r * B + c;\n            if (r + 1 < B) {\n                int u = (r + 1) * B + c;\n                int id = all_edges.size();\n                all_edges.push_back({v, u});\n                edge_id[v][u] = edge_id[u][v] = id;\n            }\n            if (c + 1 < B) {\n                int u = r * B + c + 1;\n                int id = all_edges.size();\n                all_edges.push_back({v, u});\n                edge_id[v][u] = edge_id[u][v] = id;\n            }\n        }\n    }\n\n    mt19937 rng(123456789);\n\n    EvalResult best;\n    vector<char> best_tree;\n\n    auto try_tree = [&](const vector<char>& in) {\n        EvalResult ev = evaluate_tree_mask(in, true);\n        if (ev.cost < best.cost) {\n            best = ev;\n            best_tree = in;\n        }\n    };\n\n    for (int c = 0; c < B; c++) {\n        try_tree(tree_to_mask(make_row_tree(c)));\n    }\n\n    for (int r = 0; r < B; r++) {\n        try_tree(tree_to_mask(make_col_tree(r)));\n    }\n\n    int iter = 0;\n\n    while (timer.elapsed() < 0.95) {\n        vector<char> tr;\n\n        if (iter & 1) tr = random_kruskal_tree(rng);\n        else tr = random_prim_tree(rng);\n\n        try_tree(tr);\n        iter++;\n    }\n\n    if (!best_tree.empty()) {\n        vector<char> cur = best_tree;\n        local_search(cur, best, timer);\n        best_tree = cur;\n    }\n\n    while (timer.elapsed() < 1.83) {\n        vector<char> tr;\n\n        if (iter & 1) tr = random_kruskal_tree(rng);\n        else tr = random_prim_tree(rng);\n\n        EvalResult ev = evaluate_tree_mask(tr, true);\n\n        if (ev.cost < best.cost) {\n            best = ev;\n            best_tree = tr;\n\n            vector<char> cur = best_tree;\n            local_search(cur, best, timer);\n            best_tree = cur;\n        }\n\n        iter++;\n    }\n\n    if (best.order.empty()) {\n        return 0;\n    }\n\n    vector<string> ans;\n\n    int first = best.order[0];\n    int tr = first / N;\n    int tc = first % N;\n\n    for (int i = 0; i < tr; i++) ans.push_back(\"D\");\n    for (int j = 0; j < tc; j++) ans.push_back(\"R\");\n\n    long long load = 0;\n\n    for (int idx = 0; idx < (int)best.order.size(); idx++) {\n        int id = best.order[idx];\n        int v = hval[id];\n\n        if (v > 0) {\n            ans.push_back(\"+\" + to_string(v));\n            load += v;\n        } else if (v < 0) {\n            ans.push_back(\"-\" + to_string(-v));\n            load += v;\n        }\n\n        if (idx + 1 < (int)best.order.size()) {\n            int a = best.order[idx];\n            int b = best.order[idx + 1];\n            int d = dir_between(a, b);\n            ans.push_back(string(1, mvchar[d]));\n        }\n    }\n\n    for (const string& s : ans) {\n        cout << s << '\\n';\n    }\n\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    int randint(int n) {\n        return (int)(next_u32() % n);\n    }\n\n    double uniform01() {\n        return (next_u32() >> 8) * (1.0 / 16777216.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int G = N * N;\n    const int K = 2 * N * (N - 1);\n    const int MAXS = 1500;\n    const int TOTAL = 1 << 15;\n\n    vector<vector<int>> X(K, vector<int>(M));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    vector<int> initialMax(M, 0);\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) {\n            initialMax[j] = max(initialMax[j], X[i][j]);\n        }\n    }\n\n    vector<pair<int, int>> edges;\n    vector<vector<int>> incident(G);\n\n    auto gid = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j + 1 < N; j++) {\n            int a = gid(i, j);\n            int b = gid(i, j + 1);\n            int e = edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n        }\n    }\n\n    for (int i = 0; i + 1 < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = gid(i, j);\n            int b = gid(i + 1, j);\n            int e = edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n        }\n    }\n\n    vector<int> posOrder(G);\n    iota(posOrder.begin(), posOrder.end(), 0);\n\n    sort(posOrder.begin(), posOrder.end(), [&](int a, int b) {\n        int da = incident[a].size();\n        int db = incident[b].size();\n        if (da != db) return da > db;\n\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n        double ca = abs(ai - (N - 1) / 2.0) + abs(aj - (N - 1) / 2.0);\n        double cb = abs(bi - (N - 1) / 2.0) + abs(bj - (N - 1) / 2.0);\n        return ca < cb;\n    });\n\n    XorShift rng;\n\n    vector<double> logVal(TOTAL + 1, -1e100);\n    for (int i = 1; i <= TOTAL; i++) {\n        logVal[i] = log((double)i / TOTAL);\n    }\n\n    auto calc_delta_pair_score = [&](const vector<int>& slots,\n                                     const vector<vector<double>>& W,\n                                     int a,\n                                     int b) -> double {\n        if (a == b) return 0.0;\n        if (a >= G && b >= G) return 0.0;\n\n        double delta = 0.0;\n\n        for (auto [u, v] : edges) {\n            if (u != a && u != b && v != a && v != b) continue;\n\n            int su = slots[u];\n            int sv = slots[v];\n\n            int nsu = su;\n            int nsv = sv;\n\n            if (u == a) nsu = slots[b];\n            else if (u == b) nsu = slots[a];\n\n            if (v == a) nsv = slots[b];\n            else if (v == b) nsv = slots[a];\n\n            delta += W[nsu][nsv] - W[su][sv];\n        }\n\n        return delta;\n    };\n\n    auto total_pair_score = [&](const vector<int>& slots,\n                                const vector<vector<double>>& W) -> double {\n        double s = 0.0;\n        for (auto [u, v] : edges) {\n            s += W[slots[u]][slots[v]];\n        }\n        return s;\n    };\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> sumValue(K, 0);\n        for (int i = 0; i < K; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) s += X[i][j];\n            sumValue[i] = s;\n        }\n\n        double progress = (T == 1 ? 1.0 : (double)turn / (T - 1));\n\n        bool useExactQuantile = (turn >= 5);\n        bool finalTurn = (turn == T - 1);\n\n        vector<vector<int>> q985(K, vector<int>(K, 0));\n        vector<vector<int>> q995(K, vector<int>(K, 0));\n\n        vector<unsigned short> cdf;\n        if (finalTurn) {\n            cdf.assign(K * K * (MAXS + 1), 0);\n        }\n\n        if (useExactQuantile || finalTurn) {\n            vector<int> cnt(MAXS + 1, 0), nxt(MAXS + 1, 0);\n            vector<int> active, nactive;\n\n            int target985 = (985 * TOTAL + 999) / 1000;\n            int target995 = (995 * TOTAL + 999) / 1000;\n\n            for (int i = 0; i < K; i++) {\n                for (int j = i + 1; j < K; j++) {\n                    fill(cnt.begin(), cnt.end(), 0);\n                    fill(nxt.begin(), nxt.end(), 0);\n                    active.clear();\n                    active.push_back(0);\n                    cnt[0] = 1;\n\n                    for (int l = 0; l < M; l++) {\n                        nactive.clear();\n\n                        int a = X[i][l];\n                        int b = X[j][l];\n\n                        for (int s : active) {\n                            int c = cnt[s];\n\n                            int s1 = s + a;\n                            if (nxt[s1] == 0) nactive.push_back(s1);\n                            nxt[s1] += c;\n\n                            int s2 = s + b;\n                            if (nxt[s2] == 0) nactive.push_back(s2);\n                            nxt[s2] += c;\n                        }\n\n                        for (int s : active) cnt[s] = 0;\n\n                        for (int s : nactive) {\n                            cnt[s] = nxt[s];\n                            nxt[s] = 0;\n                        }\n\n                        active.swap(nactive);\n                    }\n\n                    int cum = 0;\n                    int qq985 = MAXS;\n                    int qq995 = MAXS;\n                    bool f985 = false, f995 = false;\n\n                    int base1 = (i * K + j) * (MAXS + 1);\n                    int base2 = (j * K + i) * (MAXS + 1);\n\n                    for (int s = 0; s <= MAXS; s++) {\n                        cum += cnt[s];\n\n                        if (!f985 && cum >= target985) {\n                            qq985 = s;\n                            f985 = true;\n                        }\n\n                        if (!f995 && cum >= target995) {\n                            qq995 = s;\n                            f995 = true;\n                        }\n\n                        if (finalTurn) {\n                            cdf[base1 + s] = (unsigned short)cum;\n                            cdf[base2 + s] = (unsigned short)cum;\n                        }\n                    }\n\n                    q985[i][j] = q985[j][i] = qq985;\n                    q995[i][j] = q995[j][i] = qq995;\n                }\n            }\n        }\n\n        double alpha = 0.45 * (1.0 - progress) + 0.08 * progress;\n        double tailCoef = 0.55 * (1.0 - progress) + 1.30 * progress;\n        double geneCoef = 0.08 * (1.0 - progress) + 0.02 * progress;\n\n        vector<vector<double>> W(K, vector<double>(K, 0.0));\n\n        for (int i = 0; i < K; i++) {\n            for (int j = i + 1; j < K; j++) {\n                double mu = 0.5 * (sumValue[i] + sumValue[j]);\n\n                double cmax = 0.0;\n                double diff2 = 0.0;\n                double gene = 0.0;\n\n                for (int l = 0; l < M; l++) {\n                    int a = X[i][l];\n                    int b = X[j][l];\n                    int mx = max(a, b);\n                    int d = a - b;\n\n                    cmax += mx;\n                    diff2 += (double)d * d;\n\n                    int den = max(1, initialMax[l]);\n                    gene += (double)mx * mx / den;\n                }\n\n                double sigma = 0.5 * sqrt(diff2);\n\n                double baseScore = mu;\n                baseScore += alpha * (cmax - mu);\n                baseScore += tailCoef * sigma;\n                baseScore += geneCoef * gene;\n\n                double score = baseScore;\n\n                if (useExactQuantile) {\n                    double exactScore =\n                        0.70 * q985[i][j] +\n                        0.20 * q995[i][j] +\n                        0.10 * cmax;\n\n                    double blend = progress * progress;\n                    score = (1.0 - blend) * baseScore + blend * exactScore;\n                }\n\n                W[i][j] = W[j][i] = score;\n            }\n        }\n\n        vector<pair<double, int>> potential;\n        potential.reserve(K);\n\n        for (int i = 0; i < K; i++) {\n            vector<double> v;\n            v.reserve(K - 1);\n\n            for (int j = 0; j < K; j++) {\n                if (i != j) v.push_back(W[i][j]);\n            }\n\n            nth_element(v.begin(), v.begin() + 8, v.end(), greater<double>());\n\n            double p = 0.0;\n            for (int k = 0; k < 8; k++) p += v[k];\n\n            p += 0.20 * sumValue[i];\n\n            potential.push_back({p, i});\n        }\n\n        sort(potential.begin(), potential.end(), greater<pair<double, int>>());\n\n        vector<int> slots(K, -1);\n        vector<int> used(K, 0);\n\n        for (int k = 0; k < G; k++) {\n            int seed = potential[k].second;\n            int pos = posOrder[k];\n            slots[pos] = seed;\n            used[seed] = 1;\n        }\n\n        int ptr = G;\n        for (int i = 0; i < K; i++) {\n            if (!used[i]) {\n                slots[ptr++] = i;\n            }\n        }\n\n        double curScore = total_pair_score(slots, W);\n\n        int ITER = finalTurn ? 70000 : 90000;\n        double T0 = finalTurn ? 60.0 : 80.0;\n        double T1 = 0.05;\n\n        for (int it = 0; it < ITER; it++) {\n            int a, b;\n\n            if (rng.randint(100) < 65) {\n                a = rng.randint(G);\n                b = rng.randint(K);\n            } else {\n                a = rng.randint(K);\n                b = rng.randint(K);\n            }\n\n            if (a == b) continue;\n            if (a >= G && b >= G) continue;\n\n            double delta = calc_delta_pair_score(slots, W, a, b);\n\n            double ratio = (double)it / ITER;\n            double temp = T0 * (1.0 - ratio) + T1 * ratio;\n\n            bool accept = false;\n            if (delta >= 0.0) {\n                accept = true;\n            } else {\n                double prob = exp(delta / temp);\n                if (rng.uniform01() < prob) accept = true;\n            }\n\n            if (accept) {\n                swap(slots[a], slots[b]);\n                curScore += delta;\n            }\n        }\n\n        for (int pass = 0; pass < 3; pass++) {\n            bool improved = false;\n\n            for (int a = 0; a < K; a++) {\n                for (int b = a + 1; b < K; b++) {\n                    if (a >= G && b >= G) continue;\n\n                    double delta = calc_delta_pair_score(slots, W, a, b);\n                    if (delta > 1e-9) {\n                        swap(slots[a], slots[b]);\n                        curScore += delta;\n                        improved = true;\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n\n        if (finalTurn) {\n            vector<double> sumLog(MAXS + 1, 0.0), tmpLog(MAXS + 1);\n            vector<int> zeroCnt(MAXS + 1, 0), tmpZero(MAXS + 1);\n\n            auto pairIndex = [&](int a, int b, int s) {\n                return (a * K + b) * (MAXS + 1) + s;\n            };\n\n            auto addPair = [&](vector<double>& sl,\n                               vector<int>& zc,\n                               int a,\n                               int b,\n                               int coef) {\n                int base = (a * K + b) * (MAXS + 1);\n                for (int s = 0; s <= MAXS; s++) {\n                    int c = cdf[base + s];\n                    if (c == 0) {\n                        zc[s] += coef;\n                    } else {\n                        sl[s] += coef * logVal[c];\n                    }\n                }\n            };\n\n            auto exactScoreFromState = [&](const vector<double>& sl,\n                                           const vector<int>& zc) {\n                double res = 0.0;\n                for (int s = 0; s < MAXS; s++) {\n                    double prod = (zc[s] > 0 ? 0.0 : exp(sl[s]));\n                    res += 1.0 - prod;\n                }\n                return res;\n            };\n\n            for (auto [u, v] : edges) {\n                addPair(sumLog, zeroCnt, slots[u], slots[v], +1);\n            }\n\n            double exactCur = exactScoreFromState(sumLog, zeroCnt);\n\n            auto evalExactSwap = [&](int a, int b) -> double {\n                tmpLog = sumLog;\n                tmpZero = zeroCnt;\n\n                vector<int> aff;\n                if (a < G) {\n                    for (int e : incident[a]) aff.push_back(e);\n                }\n                if (b < G) {\n                    for (int e : incident[b]) aff.push_back(e);\n                }\n\n                sort(aff.begin(), aff.end());\n                aff.erase(unique(aff.begin(), aff.end()), aff.end());\n\n                for (int e : aff) {\n                    auto [u, v] = edges[e];\n\n                    int oldU = slots[u];\n                    int oldV = slots[v];\n\n                    int newU = oldU;\n                    int newV = oldV;\n\n                    if (u == a) newU = slots[b];\n                    else if (u == b) newU = slots[a];\n\n                    if (v == a) newV = slots[b];\n                    else if (v == b) newV = slots[a];\n\n                    addPair(tmpLog, tmpZero, oldU, oldV, -1);\n                    addPair(tmpLog, tmpZero, newU, newV, +1);\n                }\n\n                return exactScoreFromState(tmpLog, tmpZero);\n            };\n\n            const int EXACT_ITER = 12000;\n\n            for (int it = 0; it < EXACT_ITER; it++) {\n                int a, b;\n\n                if (rng.randint(100) < 70) {\n                    a = rng.randint(G);\n                    b = rng.randint(K);\n                } else {\n                    a = rng.randint(K);\n                    b = rng.randint(K);\n                }\n\n                if (a == b) continue;\n                if (a >= G && b >= G) continue;\n\n                double nxtScore = evalExactSwap(a, b);\n                double delta = nxtScore - exactCur;\n\n                double ratio = (double)it / EXACT_ITER;\n                double temp = 3.0 * (1.0 - ratio) + 0.01 * ratio;\n\n                bool accept = false;\n                if (delta >= 0.0) {\n                    accept = true;\n                } else {\n                    if (rng.uniform01() < exp(delta / temp)) accept = true;\n                }\n\n                if (accept) {\n                    swap(slots[a], slots[b]);\n                    sumLog.swap(tmpLog);\n                    zeroCnt.swap(tmpZero);\n                    exactCur = nxtScore;\n                }\n            }\n\n            for (int pass = 0; pass < 2; pass++) {\n                bool improved = false;\n\n                for (int a = 0; a < K; a++) {\n                    for (int b = a + 1; b < K; b++) {\n                        if (a >= G && b >= G) continue;\n\n                        double nxtScore = evalExactSwap(a, b);\n                        if (nxtScore > exactCur + 1e-9) {\n                            swap(slots[a], slots[b]);\n                            sumLog.swap(tmpLog);\n                            zeroCnt.swap(tmpZero);\n                            exactCur = nxtScore;\n                            improved = true;\n                        }\n                    }\n                }\n\n                if (!improved) break;\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << slots[gid(i, j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < M; j++) {\n                if (!(cin >> X[i][j])) return 0;\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nint manhattan(const Pos& a, const Pos& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    const int INF = 1e9;\n\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            int delta = INF;\n            int j1 = 0;\n\n            for (int j = 1; j <= n; j++) {\n                if (used[j]) continue;\n\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    vector<int> assignment(n, -1);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] != 0) {\n            assignment[p[j] - 1] = j - 1;\n        }\n    }\n\n    return assignment;\n}\n\nlong long eval_plan(\n    const vector<pair<int, int>>& plan,\n    const vector<Pos>& src,\n    const vector<Pos>& dst\n) {\n    long long cost = 0;\n\n    for (int i = 0; i < (int)plan.size(); i++) {\n        int s = plan[i].first;\n        int t = plan[i].second;\n\n        if (i > 0) {\n            int pt = plan[i - 1].second;\n            cost += manhattan(dst[pt], src[s]);\n        }\n\n        cost += manhattan(src[s], dst[t]);\n    }\n\n    return cost;\n}\n\nvector<pair<int, int>> plan_greedy_pair(\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    int alpha_num\n) {\n    int n = (int)src.size();\n\n    vector<int> remS(n), remT(n);\n    iota(remS.begin(), remS.end(), 0);\n    iota(remT.begin(), remT.end(), 0);\n\n    vector<pair<int, int>> plan;\n    bool has_cur = false;\n    Pos cur{0, 0};\n\n    while (!remS.empty()) {\n        long long best_score = (1LL << 60);\n        int best_si = -1;\n        int best_ti = -1;\n        int best_dcur = 0;\n        int best_dtr = 0;\n\n        for (int ai = 0; ai < (int)remS.size(); ai++) {\n            int s = remS[ai];\n            int dcur = has_cur ? manhattan(cur, src[s]) : 0;\n\n            for (int bi = 0; bi < (int)remT.size(); bi++) {\n                int t = remT[bi];\n                int dtr = manhattan(src[s], dst[t]);\n\n                long long score = 1LL * alpha_num * dcur + 2LL * dtr;\n\n                if (\n                    score < best_score ||\n                    (score == best_score && make_pair(dcur, dtr) < make_pair(best_dcur, best_dtr))\n                ) {\n                    best_score = score;\n                    best_si = ai;\n                    best_ti = bi;\n                    best_dcur = dcur;\n                    best_dtr = dtr;\n                }\n            }\n        }\n\n        int s = remS[best_si];\n        int t = remT[best_ti];\n\n        plan.push_back({s, t});\n        cur = dst[t];\n        has_cur = true;\n\n        remS[best_si] = remS.back();\n        remS.pop_back();\n\n        remT[best_ti] = remT.back();\n        remT.pop_back();\n    }\n\n    return plan;\n}\n\nvector<pair<int, int>> plan_greedy_nearest(\n    const vector<Pos>& src,\n    const vector<Pos>& dst\n) {\n    int n = (int)src.size();\n\n    vector<int> remS(n), remT(n);\n    iota(remS.begin(), remS.end(), 0);\n    iota(remT.begin(), remT.end(), 0);\n\n    vector<pair<int, int>> plan;\n    bool has_cur = false;\n    Pos cur{0, 0};\n\n    while (!remS.empty()) {\n        int best_si = -1;\n        int best_ti = -1;\n\n        if (!has_cur) {\n            int best = 1e9;\n\n            for (int ai = 0; ai < (int)remS.size(); ai++) {\n                int s = remS[ai];\n\n                for (int bi = 0; bi < (int)remT.size(); bi++) {\n                    int t = remT[bi];\n                    int d = manhattan(src[s], dst[t]);\n\n                    if (d < best) {\n                        best = d;\n                        best_si = ai;\n                        best_ti = bi;\n                    }\n                }\n            }\n        } else {\n            int best_source_dist = 1e9;\n            int best_source_nearest_target = 1e9;\n\n            for (int ai = 0; ai < (int)remS.size(); ai++) {\n                int s = remS[ai];\n                int dcur = manhattan(cur, src[s]);\n\n                int nearest_target = 1e9;\n                for (int t : remT) {\n                    nearest_target = min(nearest_target, manhattan(src[s], dst[t]));\n                }\n\n                if (\n                    dcur < best_source_dist ||\n                    (dcur == best_source_dist && nearest_target < best_source_nearest_target)\n                ) {\n                    best_source_dist = dcur;\n                    best_source_nearest_target = nearest_target;\n                    best_si = ai;\n                }\n            }\n\n            int s = remS[best_si];\n            int best = 1e9;\n\n            for (int bi = 0; bi < (int)remT.size(); bi++) {\n                int t = remT[bi];\n                int d = manhattan(src[s], dst[t]);\n\n                if (d < best) {\n                    best = d;\n                    best_ti = bi;\n                }\n            }\n        }\n\n        int s = remS[best_si];\n        int t = remT[best_ti];\n\n        plan.push_back({s, t});\n        cur = dst[t];\n        has_cur = true;\n\n        remS[best_si] = remS.back();\n        remS.pop_back();\n\n        remT[best_ti] = remT.back();\n        remT.pop_back();\n    }\n\n    return plan;\n}\n\nvector<pair<int, int>> plan_hungarian_ordered(\n    const vector<Pos>& src,\n    const vector<Pos>& dst\n) {\n    int n = (int)src.size();\n\n    vector<vector<int>> cost(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cost[i][j] = manhattan(src[i], dst[j]);\n        }\n    }\n\n    vector<int> assign = hungarian(cost);\n\n    vector<pair<int, int>> best_plan;\n    long long best_cost = (1LL << 60);\n\n    for (int st = 0; st < n; st++) {\n        vector<unsigned char> used(n, 0);\n        vector<pair<int, int>> plan;\n        plan.reserve(n);\n\n        int curS = st;\n        used[curS] = 1;\n        plan.push_back({curS, assign[curS]});\n\n        Pos cur = dst[assign[curS]];\n\n        for (int step = 1; step < n; step++) {\n            int best = -1;\n            int best_d = 1e9;\n            int best_tr = 1e9;\n\n            for (int i = 0; i < n; i++) {\n                if (used[i]) continue;\n\n                int d = manhattan(cur, src[i]);\n                int tr = manhattan(src[i], dst[assign[i]]);\n\n                if (d < best_d || (d == best_d && tr < best_tr)) {\n                    best_d = d;\n                    best_tr = tr;\n                    best = i;\n                }\n            }\n\n            used[best] = 1;\n            plan.push_back({best, assign[best]});\n            cur = dst[assign[best]];\n        }\n\n        long long c = eval_plan(plan, src, dst);\n\n        if (c < best_cost) {\n            best_cost = c;\n            best_plan = move(plan);\n        }\n    }\n\n    return best_plan;\n}\n\nvoid append_move(\n    vector<string>& ops,\n    Pos& cur,\n    const Pos& to,\n    bool action_on_arrival\n) {\n    vector<char> moves;\n\n    while (cur.x < to.x) {\n        moves.push_back('D');\n        cur.x++;\n    }\n    while (cur.x > to.x) {\n        moves.push_back('U');\n        cur.x--;\n    }\n    while (cur.y < to.y) {\n        moves.push_back('R');\n        cur.y++;\n    }\n    while (cur.y > to.y) {\n        moves.push_back('L');\n        cur.y--;\n    }\n\n    if (moves.empty()) {\n        if (action_on_arrival) {\n            ops.push_back(\".P\");\n        }\n        return;\n    }\n\n    for (int i = 0; i < (int)moves.size(); i++) {\n        string op = \"..\";\n        op[0] = moves[i];\n\n        if (i == (int)moves.size() - 1 && action_on_arrival) {\n            op[1] = 'P';\n        }\n\n        ops.push_back(op);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<Pos> src, dst;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                src.push_back({i, j});\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    int D = (int)src.size();\n\n    vector<pair<int, int>> best_plan;\n    long long best_cost = (1LL << 60);\n\n    auto consider = [&](vector<pair<int, int>> plan) {\n        long long c = eval_plan(plan, src, dst);\n        if (c < best_cost) {\n            best_cost = c;\n            best_plan = move(plan);\n        }\n    };\n\n    if (D > 0) {\n        consider(plan_greedy_nearest(src, dst));\n        consider(plan_greedy_pair(src, dst, 0));\n        consider(plan_greedy_pair(src, dst, 1));\n        consider(plan_greedy_pair(src, dst, 2));\n        consider(plan_greedy_pair(src, dst, 4));\n        consider(plan_hungarian_ordered(src, dst));\n    }\n\n    Pos initial_root{0, 0};\n    Pos cur{0, 0};\n    vector<string> ops;\n\n    if (D > 0) {\n        initial_root = src[best_plan[0].first];\n        cur = initial_root;\n\n        // First pickup at the initial root position.\n        ops.push_back(\".P\");\n\n        for (int i = 0; i < D; i++) {\n            int si = best_plan[i].first;\n            int ti = best_plan[i].second;\n\n            if (i > 0) {\n                append_move(ops, cur, src[si], true); // pickup\n            }\n\n            append_move(ops, cur, dst[ti], true); // release\n        }\n    }\n\n    // Use a one-vertex arm.\n    // The root itself is also the only leaf/fingertip.\n    cout << 1 << '\\n';\n    cout << initial_root.x << ' ' << initial_root.y << '\\n';\n\n    for (const string& op : ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Fish {\n    int x, y, w;\n};\n\nstruct PolyCand {\n    int diff = -1000000000;\n    vector<pair<int,int>> poly;\n};\n\nstruct EvalResult {\n    bool ok = false;\n    int diff = -1000000000;\n    vector<char> mask;\n    vector<pair<int,int>> poly;\n};\n\nstatic const int LIM = 100000;\nstatic const int MAX_PERIM = 400000;\nstatic const int MAX_VERT = 1000;\n\nint N;\nvector<Fish> fishes;\nPolyCand bestAns;\n\nstatic inline int id(int x, int y, int G) {\n    return y * G + x;\n}\n\nint exactDiffRect(int x1, int y1, int x2, int y2) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) s += p.w;\n    }\n    return s;\n}\n\nvoid updateBest(const vector<pair<int,int>>& poly, int diff) {\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return;\n    if (diff > bestAns.diff) {\n        bestAns.diff = diff;\n        bestAns.poly = poly;\n    }\n}\n\nbool pointInsideMask(const vector<char>& mask, int G, int L, int px, int py) {\n    int xs[2], ys[2];\n    int nx = 0, ny = 0;\n\n    if (px == LIM) xs[nx++] = G - 1;\n    else xs[nx++] = px / L;\n    if (px > 0 && px % L == 0) xs[nx++] = px / L - 1;\n\n    if (py == LIM) ys[ny++] = G - 1;\n    else ys[ny++] = py / L;\n    if (py > 0 && py % L == 0) ys[ny++] = py / L - 1;\n\n    for (int i = 0; i < nx; i++) {\n        for (int j = 0; j < ny; j++) {\n            int x = xs[i], y = ys[j];\n            if (0 <= x && x < G && 0 <= y && y < G && mask[id(x,y,G)]) return true;\n        }\n    }\n    return false;\n}\n\nint exactDiffMask(const vector<char>& mask, int G, int L) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (pointInsideMask(mask, G, L, p.x, p.y)) s += p.w;\n    }\n    return s;\n}\n\nbool isConnected(const vector<char>& mask, int G) {\n    int st = -1, cnt = 0;\n    for (int i = 0; i < G * G; i++) {\n        if (mask[i]) {\n            cnt++;\n            if (st == -1) st = i;\n        }\n    }\n    if (cnt == 0) return false;\n\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    q.push(st);\n    vis[st] = 1;\n    int got = 0;\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        got++;\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n            int ni = id(nx,ny,G);\n            if (!mask[ni] || vis[ni]) continue;\n            vis[ni] = 1;\n            q.push(ni);\n        }\n    }\n    return got == cnt;\n}\n\nvoid fillHoles(vector<char>& mask, int G) {\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n\n    auto push_empty = [&](int x, int y) {\n        if (x < 0 || x >= G || y < 0 || y >= G) return;\n        int v = id(x,y,G);\n        if (!mask[v] && !vis[v]) {\n            vis[v] = 1;\n            q.push(v);\n        }\n    };\n\n    for (int i = 0; i < G; i++) {\n        push_empty(i, 0);\n        push_empty(i, G - 1);\n        push_empty(0, i);\n        push_empty(G - 1, i);\n    }\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            push_empty(x + dx[d], y + dy[d]);\n        }\n    }\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] && !vis[i]) mask[i] = 1;\n    }\n}\n\nvoid normalizeMask(vector<char>& mask, int G, const vector<int>& cellW) {\n    fillHoles(mask, G);\n\n    for (int iter = 0; iter < G * G; iter++) {\n        bool changed = false;\n        for (int y = 0; y + 1 < G; y++) {\n            for (int x = 0; x + 1 < G; x++) {\n                int a = id(x,y,G);\n                int b = id(x+1,y,G);\n                int c = id(x,y+1,G);\n                int d = id(x+1,y+1,G);\n\n                if (mask[a] && mask[d] && !mask[b] && !mask[c]) {\n                    if (cellW[b] >= cellW[c]) mask[b] = 1;\n                    else mask[c] = 1;\n                    changed = true;\n                }\n                if (mask[b] && mask[c] && !mask[a] && !mask[d]) {\n                    if (cellW[a] >= cellW[d]) mask[a] = 1;\n                    else mask[d] = 1;\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n        fillHoles(mask, G);\n    }\n}\n\nint calcPerimCells(const vector<char>& mask, int G) {\n    int per = 0;\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n            if (x == 0 || !mask[id(x-1,y,G)]) per++;\n            if (x == G-1 || !mask[id(x+1,y,G)]) per++;\n            if (y == 0 || !mask[id(x,y-1,G)]) per++;\n            if (y == G-1 || !mask[id(x,y+1,G)]) per++;\n        }\n    }\n    return per;\n}\n\nvector<pair<int,int>> extractPolygon(const vector<char>& mask, int G, int L) {\n    int V = (G + 1) * (G + 1);\n    vector<int> nxt(V, -1), indeg(V, 0);\n    bool bad = false;\n    int edgeCnt = 0;\n\n    auto vid = [&](int x, int y) {\n        return y * (G + 1) + x;\n    };\n\n    auto addEdge = [&](int x1, int y1, int x2, int y2) {\n        int u = vid(x1,y1), v = vid(x2,y2);\n        if (nxt[u] != -1) bad = true;\n        nxt[u] = v;\n        indeg[v]++;\n        if (indeg[v] > 1) bad = true;\n        edgeCnt++;\n    };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n\n            if (y == 0 || !mask[id(x,y-1,G)]) {\n                addEdge(x, y, x+1, y);\n            }\n            if (x == G-1 || !mask[id(x+1,y,G)]) {\n                addEdge(x+1, y, x+1, y+1);\n            }\n            if (y == G-1 || !mask[id(x,y+1,G)]) {\n                addEdge(x+1, y+1, x, y+1);\n            }\n            if (x == 0 || !mask[id(x-1,y,G)]) {\n                addEdge(x, y+1, x, y);\n            }\n        }\n    }\n\n    if (bad || edgeCnt == 0) return {};\n\n    int st = -1;\n    for (int i = 0; i < V; i++) {\n        if (nxt[i] != -1) {\n            st = i;\n            break;\n        }\n    }\n\n    vector<char> used(V, 0);\n    vector<pair<int,int>> poly;\n    int cur = st;\n\n    for (int step = 0; step <= edgeCnt; step++) {\n        if (cur == -1) return {};\n        if (cur == st && step > 0) break;\n        if (used[cur]) return {};\n        used[cur] = 1;\n\n        int gx = cur % (G + 1);\n        int gy = cur / (G + 1);\n        poly.push_back({gx * L, gy * L});\n\n        cur = nxt[cur];\n    }\n\n    if (cur != st) return {};\n\n    int usedEdges = 0;\n    for (int i = 0; i < V; i++) if (used[i]) usedEdges++;\n    if ((int)poly.size() != edgeCnt) {\n        // This usually means multiple cycles or invalid touching.\n        // Collinear vertices are counted here, so size should equal boundary edges.\n        return {};\n    }\n\n    auto collinear = [](pair<int,int> a, pair<int,int> b, pair<int,int> c) {\n        return (a.first == b.first && b.first == c.first) ||\n               (a.second == b.second && b.second == c.second);\n    };\n\n    bool changed = true;\n    while (changed && poly.size() >= 4) {\n        changed = false;\n        vector<pair<int,int>> np;\n        int m = (int)poly.size();\n        for (int i = 0; i < m; i++) {\n            auto a = poly[(i - 1 + m) % m];\n            auto b = poly[i];\n            auto c = poly[(i + 1) % m];\n            if (collinear(a,b,c)) {\n                changed = true;\n            } else {\n                np.push_back(b);\n            }\n        }\n        poly.swap(np);\n    }\n\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return {};\n\n    set<pair<int,int>> ss(poly.begin(), poly.end());\n    if (ss.size() != poly.size()) return {};\n\n    return poly;\n}\n\nEvalResult evalMask(vector<char> mask, int G, int L, const vector<int>& cellW) {\n    EvalResult res;\n    normalizeMask(mask, G, cellW);\n\n    if (!isConnected(mask, G)) return res;\n\n    int perCells = calcPerimCells(mask, G);\n    if (perCells * L > MAX_PERIM) return res;\n\n    auto poly = extractPolygon(mask, G, L);\n    if (poly.empty()) return res;\n\n    int diff = exactDiffMask(mask, G, L);\n\n    res.ok = true;\n    res.diff = diff;\n    res.mask = std::move(mask);\n    res.poly = std::move(poly);\n    return res;\n}\n\nvector<int> buildGridWeight(int G, int L) {\n    vector<int> w(G * G, 0);\n    for (auto &p : fishes) {\n        int x = min(G - 1, p.x / L);\n        int y = min(G - 1, p.y / L);\n        w[id(x,y,G)] += p.w;\n    }\n    return w;\n}\n\nvoid tryTinyBaseline() {\n    for (int i = 0; i < N; i++) {\n        int x = fishes[i].x;\n        int y = fishes[i].y;\n        int x1, x2, y1, y2;\n\n        if (x < LIM) x1 = x, x2 = x + 1;\n        else x1 = x - 1, x2 = x;\n\n        if (y < LIM) y1 = y, y2 = y + 1;\n        else y1 = y - 1, y2 = y;\n\n        int diff = exactDiffRect(x1,y1,x2,y2);\n        vector<pair<int,int>> poly = {\n            {x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}\n        };\n        updateBest(poly, diff);\n    }\n}\n\nvoid tryBestRectangle(int G, int L, const vector<int>& cellW) {\n    int maxSideSum = MAX_PERIM / (2 * L);\n\n    int bestVal = -1000000000;\n    int bx1 = 0, by1 = 0, bx2 = 1, by2 = 1;\n\n    vector<int> arr(G), pref(G + 1);\n\n    for (int xl = 0; xl < G; xl++) {\n        fill(arr.begin(), arr.end(), 0);\n\n        for (int xr = xl; xr < G; xr++) {\n            for (int y = 0; y < G; y++) {\n                arr[y] += cellW[id(xr,y,G)];\n            }\n\n            int width = xr - xl + 1;\n            int maxH = maxSideSum - width;\n            if (maxH <= 0) continue;\n            maxH = min(maxH, G);\n\n            pref[0] = 0;\n            for (int y = 0; y < G; y++) pref[y+1] = pref[y] + arr[y];\n\n            deque<int> dq;\n            for (int e = 1; e <= G; e++) {\n                int sNew = e - 1;\n                while (!dq.empty() && pref[dq.back()] >= pref[sNew]) dq.pop_back();\n                dq.push_back(sNew);\n\n                while (!dq.empty() && dq.front() < e - maxH) dq.pop_front();\n\n                int s = dq.front();\n                int val = pref[e] - pref[s];\n                if (val > bestVal) {\n                    bestVal = val;\n                    bx1 = xl;\n                    bx2 = xr + 1;\n                    by1 = s;\n                    by2 = e;\n                }\n            }\n        }\n    }\n\n    int x1 = bx1 * L;\n    int x2 = bx2 * L;\n    int y1 = by1 * L;\n    int y2 = by2 * L;\n\n    int diff = exactDiffRect(x1,y1,x2,y2);\n    vector<pair<int,int>> poly = {\n        {x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}\n    };\n    updateBest(poly, diff);\n}\n\nstruct Comp {\n    int score = 0;\n    int size = 0;\n    long long sx = 0, sy = 0;\n    vector<int> cells;\n};\n\nvector<Comp> getComponents(const vector<char>& mask, int G, const vector<int>& cellW) {\n    vector<Comp> comps;\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] || vis[i]) continue;\n\n        Comp c;\n        vis[i] = 1;\n        q.push(i);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            int x = v % G, y = v / G;\n\n            c.cells.push_back(v);\n            c.score += cellW[v];\n            c.size++;\n            c.sx += x;\n            c.sy += y;\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n                int ni = id(nx,ny,G);\n                if (!mask[ni] || vis[ni]) continue;\n                vis[ni] = 1;\n                q.push(ni);\n            }\n        }\n\n        if (c.size > 0) comps.push_back(std::move(c));\n    }\n\n    sort(comps.begin(), comps.end(), [](const Comp& a, const Comp& b) {\n        return a.score > b.score;\n    });\n\n    return comps;\n}\n\nvector<char> makeCompMask(const Comp& c, int G) {\n    vector<char> m(G * G, 0);\n    for (int v : c.cells) m[v] = 1;\n    return m;\n}\n\nvoid addPath(vector<char>& m, int G, int x1, int y1, int x2, int y2, bool hv) {\n    if (hv) {\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y1,G)] = 1;\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x2,y,G)] = 1;\n    } else {\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x1,y,G)] = 1;\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y2,G)] = 1;\n    }\n}\n\nvoid tryGreedyUnion(vector<Comp>& comps, int G, int L, const vector<int>& cellW) {\n    vector<Comp> pos;\n    for (auto &c : comps) {\n        if (c.score > 0) pos.push_back(c);\n        if ((int)pos.size() >= 20) break;\n    }\n    if (pos.empty()) return;\n\n    vector<char> cur = makeCompMask(pos[0], G);\n    auto er0 = evalMask(cur, G, L, cellW);\n    if (!er0.ok) return;\n\n    updateBest(er0.poly, er0.diff);\n    cur = er0.mask;\n    int curDiff = er0.diff;\n\n    for (int ci = 1; ci < (int)pos.size(); ci++) {\n        const Comp& c = pos[ci];\n\n        int cx = (int)(c.sx / max(1, c.size));\n        int cy = (int)(c.sy / max(1, c.size));\n\n        int ax = -1, ay = -1, bestD = INT_MAX;\n        for (int y = 0; y < G; y++) {\n            for (int x = 0; x < G; x++) {\n                if (!cur[id(x,y,G)]) continue;\n                int d = abs(x - cx) + abs(y - cy);\n                if (d < bestD) {\n                    bestD = d;\n                    ax = x;\n                    ay = y;\n                }\n            }\n        }\n\n        int bx = -1, by = -1;\n        bestD = INT_MAX;\n        for (int v : c.cells) {\n            int x = v % G, y = v / G;\n            int d = abs(x - ax) + abs(y - ay);\n            if (d < bestD) {\n                bestD = d;\n                bx = x;\n                by = y;\n            }\n        }\n\n        vector<char> base = cur;\n        for (int v : c.cells) base[v] = 1;\n\n        vector<char> m1 = base, m2 = base;\n        addPath(m1, G, ax, ay, bx, by, true);\n        addPath(m2, G, ax, ay, bx, by, false);\n\n        auto e1 = evalMask(m1, G, L, cellW);\n        auto e2 = evalMask(m2, G, L, cellW);\n\n        EvalResult bestE;\n        if (e1.ok) bestE = e1;\n        if (e2.ok && (!bestE.ok || e2.diff > bestE.diff)) bestE = e2;\n\n        if (bestE.ok) {\n            updateBest(bestE.poly, bestE.diff);\n            if (bestE.diff > curDiff) {\n                curDiff = bestE.diff;\n                cur = bestE.mask;\n            }\n        }\n    }\n}\n\nvector<int> boxSmooth(const vector<int>& w, int G, int r) {\n    vector<int> pref((G+1)*(G+1), 0);\n    auto pid = [&](int x, int y) { return y * (G + 1) + x; };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            pref[pid(x+1,y+1)] =\n                pref[pid(x+1,y)] + pref[pid(x,y+1)] - pref[pid(x,y)] + w[id(x,y,G)];\n        }\n    }\n\n    vector<int> sm(G * G, 0);\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            int x1 = max(0, x - r);\n            int y1 = max(0, y - r);\n            int x2 = min(G, x + r + 1);\n            int y2 = min(G, y + r + 1);\n            int val =\n                pref[pid(x2,y2)] - pref[pid(x1,y2)] -\n                pref[pid(x2,y1)] + pref[pid(x1,y1)];\n            sm[id(x,y,G)] = val;\n        }\n    }\n    return sm;\n}\n\nvoid processGrid(int L) {\n    int G = LIM / L;\n    vector<int> cellW = buildGridWeight(G, L);\n\n    tryBestRectangle(G, L, cellW);\n\n    vector<int> radii;\n    if (L == 500) radii = {0,1,2,3,5,8,12};\n    else if (L == 1000) radii = {0,1,2,3,5,8};\n    else if (L == 2000) radii = {0,1,2,3,4};\n    else radii = {0,1,2,3};\n\n    for (int r : radii) {\n        vector<int> sm = boxSmooth(cellW, G, r);\n\n        vector<int> thresholds;\n        if (r == 0) thresholds = {0};\n        else thresholds = {-1, 0, 1, 2, 4};\n\n        for (int th : thresholds) {\n            vector<char> mask(G * G, 0);\n            for (int i = 0; i < G * G; i++) {\n                if (sm[i] > th) mask[i] = 1;\n            }\n\n            auto comps = getComponents(mask, G, cellW);\n\n            int cnt = 0;\n            for (auto &c : comps) {\n                if (c.score <= 0) continue;\n                auto cm = makeCompMask(c, G);\n                auto er = evalMask(cm, G, L, cellW);\n                if (er.ok) updateBest(er.poly, er.diff);\n\n                cnt++;\n                if (cnt >= 30) break;\n            }\n\n            tryGreedyUnion(comps, G, L, cellW);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    fishes.reserve(2 * N);\n\n    for (int i = 0; i < 2 * N; i++) {\n        int x, y;\n        cin >> x >> y;\n        int w = (i < N ? 1 : -1);\n        fishes.push_back({x,y,w});\n    }\n\n    tryTinyBaseline();\n\n    vector<int> Ls = {500, 1000, 2000, 2500, 4000, 5000};\n    for (int L : Ls) {\n        processGrid(L);\n    }\n\n    if (bestAns.poly.empty()) {\n        // Absolute fallback.\n        cout << 4 << '\\n';\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << bestAns.poly.size() << '\\n';\n    for (auto [x,y] : bestAns.poly) {\n        x = max(0, min(LIM, x));\n        y = max(0, min(LIM, y));\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Op {\n    int p, r;\n    char d;\n    int b;\n};\n\nstruct RectPlaced {\n    ll x, y, w, h;\n};\n\nstruct Solution {\n    vector<Op> ops;\n    ll estScore;\n};\n\nstatic inline bool overlap(ll l1, ll r1, ll l2, ll r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstruct Solver {\n    int N, T;\n    ll sigma;\n    vector<ll> w, h;\n    vector<Solution> sols;\n    unordered_set<string> seen;\n    chrono::steady_clock::time_point st;\n    mt19937 rng;\n\n    Solver() : rng(1234567) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    pair<ll, ll> simulate(const vector<Op>& ops) const {\n        vector<ll> X(N), Y(N), W(N), H(N);\n        vector<char> used(N, 0);\n        ll BW = 0, BH = 0;\n\n        for (auto &op : ops) {\n            int p = op.p;\n            ll rw = op.r ? h[p] : w[p];\n            ll rh = op.r ? w[p] : h[p];\n            ll x = 0, y = 0;\n\n            if (op.d == 'U') {\n                x = (op.b == -1 ? 0 : X[op.b] + W[op.b]);\n                y = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap(x, x + rw, X[j], X[j] + W[j])) {\n                        y = max(y, Y[j] + H[j]);\n                    }\n                }\n            } else {\n                y = (op.b == -1 ? 0 : Y[op.b] + H[op.b]);\n                x = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap(y, y + rh, Y[j], Y[j] + H[j])) {\n                        x = max(x, X[j] + W[j]);\n                    }\n                }\n            }\n\n            X[p] = x;\n            Y[p] = y;\n            W[p] = rw;\n            H[p] = rh;\n            used[p] = 1;\n            BW = max(BW, x + rw);\n            BH = max(BH, y + rh);\n        }\n        return {BW, BH};\n    }\n\n    string makeKey(const vector<Op>& ops) const {\n        string s;\n        s.reserve(ops.size() * 3);\n        for (auto &op : ops) {\n            s.push_back(char(op.r));\n            s.push_back(op.d);\n            s.push_back(char(op.b + 1));\n        }\n        return s;\n    }\n\n    void addSolution(const vector<Op>& ops) {\n        if ((int)ops.size() != N) return;\n        string key = makeKey(ops);\n        if (seen.find(key) != seen.end()) return;\n        seen.insert(key);\n        auto [W0, H0] = simulate(ops);\n        sols.push_back({ops, W0 + H0});\n    }\n\n    struct SegInfo {\n        bool ok = false;\n        ll rowH = 0;\n        ll rowW = 0;\n        vector<int> rot;\n    };\n\n    SegInfo calcSegment(int l, int r, ll limitW, bool needRot) const {\n        vector<ll> cand;\n        cand.reserve((r - l) * 2);\n        for (int i = l; i < r; i++) {\n            cand.push_back(h[i]); // non-rotated height\n            cand.push_back(w[i]); // rotated height\n        }\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        SegInfo best;\n\n        for (ll HH : cand) {\n            ll sumW = 0;\n            bool ok = true;\n            vector<int> rots;\n            if (needRot) rots.reserve(r - l);\n\n            for (int i = l; i < r; i++) {\n                const ll INF = (1LL << 60);\n                ll bw = INF;\n                int br = -1;\n\n                if (h[i] <= HH) {\n                    bw = w[i];\n                    br = 0;\n                }\n                if (w[i] <= HH) {\n                    if (h[i] < bw) {\n                        bw = h[i];\n                        br = 1;\n                    }\n                }\n\n                if (br == -1) {\n                    ok = false;\n                    break;\n                }\n\n                sumW += bw;\n                if (sumW > limitW) {\n                    ok = false;\n                    break;\n                }\n                if (needRot) rots.push_back(br);\n            }\n\n            if (ok) {\n                best.ok = true;\n                best.rowH = HH;\n                best.rowW = sumW;\n                if (needRot) best.rot = move(rots);\n                return best;\n            }\n        }\n        return best;\n    }\n\n    void generateShelf(ll limitW) {\n        const ll INF = (1LL << 60);\n\n        vector<vector<ll>> segH(N, vector<ll>(N + 1, INF));\n        vector<vector<ll>> segW(N, vector<ll>(N + 1, INF));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l + 1; r <= N; r++) {\n                SegInfo si = calcSegment(l, r, limitW, false);\n                if (si.ok) {\n                    segH[l][r] = si.rowH;\n                    segW[l][r] = si.rowW;\n                }\n            }\n        }\n\n        vector<ll> dpH(N + 1, INF), dpMaxW(N + 1, INF);\n        vector<int> prv(N + 1, -1);\n        dpH[0] = 0;\n        dpMaxW[0] = 0;\n\n        for (int i = 1; i <= N; i++) {\n            for (int l = 0; l < i; l++) {\n                if (dpH[l] == INF || segH[l][i] == INF) continue;\n                ll nh = dpH[l] + segH[l][i];\n                ll nw = max(dpMaxW[l], segW[l][i]);\n                if (nh < dpH[i] || (nh == dpH[i] && nw < dpMaxW[i])) {\n                    dpH[i] = nh;\n                    dpMaxW[i] = nw;\n                    prv[i] = l;\n                }\n            }\n        }\n\n        if (prv[N] == -1) return;\n\n        vector<pair<int,int>> rows;\n        int cur = N;\n        while (cur > 0) {\n            int l = prv[cur];\n            rows.push_back({l, cur});\n            cur = l;\n        }\n        reverse(rows.begin(), rows.end());\n\n        vector<int> rot(N, 0);\n        for (auto [l, r] : rows) {\n            SegInfo si = calcSegment(l, r, limitW, true);\n            if (!si.ok) return;\n            for (int k = l; k < r; k++) {\n                rot[k] = si.rot[k - l];\n            }\n        }\n\n        vector<Op> ops;\n        ops.reserve(N);\n\n        int prevAnchor = -1;\n\n        for (int row = 0; row < (int)rows.size(); row++) {\n            auto [l, r] = rows[row];\n            int b = (row == 0 ? -1 : prevAnchor);\n\n            for (int i = l; i < r; i++) {\n                ops.push_back({i, rot[i], 'L', b});\n            }\n\n            ll bestH = -1;\n            int anchor = l;\n            for (int i = l; i < r; i++) {\n                ll hh = rot[i] ? w[i] : h[i];\n                if (hh > bestH) {\n                    bestH = hh;\n                    anchor = i;\n                }\n            }\n            prevAnchor = anchor;\n        }\n\n        addSolution(ops);\n    }\n\n    void generateSimpleRows() {\n        // One horizontal row, several rotation policies.\n        for (int policy = 0; policy < 4; policy++) {\n            vector<Op> ops;\n            ops.reserve(N);\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (policy == 1) r = 1;\n                else if (policy == 2) r = (h[i] < w[i]); // smaller width\n                else if (policy == 3) r = (w[i] < h[i]); // smaller height\n                ops.push_back({i, r, 'L', -1});\n            }\n            addSolution(ops);\n        }\n\n        // One vertical column.\n        for (int policy = 0; policy < 4; policy++) {\n            vector<Op> ops;\n            ops.reserve(N);\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (policy == 1) r = 1;\n                else if (policy == 2) r = (h[i] < w[i]);\n                else if (policy == 3) r = (w[i] < h[i]);\n                ops.push_back({i, r, 'U', -1});\n            }\n            addSolution(ops);\n        }\n    }\n\n    void generateGreedy(double wp, double wa, double wb, double noiseCoef) {\n        vector<Op> ops;\n        ops.reserve(N);\n\n        vector<ll> X(N), Y(N), RW(N), RH(N);\n        vector<char> used(N, 0);\n        ll curW = 0, curH = 0;\n\n        long double area = 0;\n        for (int i = 0; i < N; i++) area += (long double)w[i] * h[i];\n        double scale = max(1.0, sqrt((double)area));\n\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        for (int i = 0; i < N; i++) {\n            double bestCost = 1e100;\n            Op bestOp{i, 0, 'L', -1};\n            ll bestX = 0, bestY = 0, bestRW = w[i], bestRH = h[i];\n            ll bestBW = 0, bestBH = 0;\n\n            for (int r = 0; r < 2; r++) {\n                ll rw = r ? h[i] : w[i];\n                ll rh = r ? w[i] : h[i];\n\n                for (int d0 = 0; d0 < 2; d0++) {\n                    char d = d0 ? 'L' : 'U';\n\n                    for (int b = -1; b < i; b++) {\n                        ll x = 0, y = 0;\n\n                        if (d == 'U') {\n                            x = (b == -1 ? 0 : X[b] + RW[b]);\n                            y = 0;\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (overlap(x, x + rw, X[j], X[j] + RW[j])) {\n                                    y = max(y, Y[j] + RH[j]);\n                                }\n                            }\n                        } else {\n                            y = (b == -1 ? 0 : Y[b] + RH[b]);\n                            x = 0;\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (overlap(y, y + rh, Y[j], Y[j] + RH[j])) {\n                                    x = max(x, X[j] + RW[j]);\n                                }\n                            }\n                        }\n\n                        ll BW = max(curW, x + rw);\n                        ll BH = max(curH, y + rh);\n\n                        double cost = 0.0;\n                        cost += wp * (double)(BW + BH);\n                        cost += wa * ((double)BW * (double)BH / scale);\n                        cost += wb * (double)llabs(BW - BH);\n                        cost += noiseCoef * scale * ud(rng);\n\n                        // Slight preference for compact coordinates.\n                        cost += 0.0001 * (double)(x + y);\n\n                        if (cost < bestCost) {\n                            bestCost = cost;\n                            bestOp = {i, r, d, b};\n                            bestX = x;\n                            bestY = y;\n                            bestRW = rw;\n                            bestRH = rh;\n                            bestBW = BW;\n                            bestBH = BH;\n                        }\n                    }\n                }\n            }\n\n            ops.push_back(bestOp);\n            X[i] = bestX;\n            Y[i] = bestY;\n            RW[i] = bestRW;\n            RH[i] = bestRH;\n            used[i] = 1;\n            curW = bestBW;\n            curH = bestBH;\n        }\n\n        addSolution(ops);\n    }\n\n    void generateAll() {\n        st = chrono::steady_clock::now();\n\n        generateSimpleRows();\n\n        long double area = 0;\n        ll minSingleW = 1;\n        for (int i = 0; i < N; i++) {\n            area += (long double)w[i] * h[i];\n            minSingleW = max(minSingleW, min(w[i], h[i]));\n        }\n        double sqrtA = sqrt((double)area);\n\n        vector<ll> limits;\n        for (int k = 0; k < 48; k++) {\n            double f = 0.55 + (2.45 - 0.55) * k / 47.0;\n            ll L = max<ll>(minSingleW, (ll)llround(sqrtA * f));\n            limits.push_back(L);\n        }\n        sort(limits.begin(), limits.end());\n        limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n        for (ll L : limits) {\n            if (elapsed() > 1.65) break;\n            generateShelf(L);\n        }\n\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        int greedyTrials = 0;\n        while (elapsed() < 2.45 && greedyTrials < 500) {\n            greedyTrials++;\n\n            double wp = 1.0;\n            double wa = pow(10.0, -0.4 + 1.2 * ud(rng)); // about 0.4 to 6.3\n            double wb = 0.05 + 1.2 * ud(rng);\n            double nz = 0.0;\n\n            if (greedyTrials % 3 == 0) nz = 0.01 * ud(rng);\n            if (greedyTrials % 7 == 0) nz = 0.05 * ud(rng);\n\n            generateGreedy(wp, wa, wb, nz);\n        }\n\n        if (sols.empty()) {\n            vector<Op> ops;\n            for (int i = 0; i < N; i++) ops.push_back({i, 0, 'L', -1});\n            addSolution(ops);\n        }\n\n        sort(sols.begin(), sols.end(), [](const Solution& a, const Solution& b) {\n            return a.estScore < b.estScore;\n        });\n    }\n\n    void run() {\n        cin >> N >> T >> sigma;\n        w.resize(N);\n        h.resize(N);\n        for (int i = 0; i < N; i++) cin >> w[i] >> h[i];\n\n        generateAll();\n\n        for (int t = 0; t < T; t++) {\n            const vector<Op>& ops = sols[t % sols.size()].ops;\n\n            cout << ops.size() << '\\n';\n            for (auto &op : ops) {\n                cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n            }\n            cout.flush();\n\n            ll Wobs, Hobs;\n            if (!(cin >> Wobs >> Hobs)) return;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.run();\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 10;\nstatic constexpr long long NEG = -(1LL << 60);\n\nstruct Edge {\n    int u, v;\n    long long len2;\n};\n\nstruct Solver {\n    int N, M, HH;\n    vector<int> A;\n    vector<Edge> edges;\n    vector<vector<int>> adj;\n    vector<int> xs, ys;\n\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n\n    vector<array<long long, 11>> dp_no, dp_need;\n    vector<vector<int>> children;\n\n    vector<int> orderHigh, orderLow;\n\n    Solver() : rng(1234567) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    long long scoreLabels(const vector<int>& d) const {\n        long long s = 0;\n        for (int i = 0; i < N; i++) s += 1LL * (d[i] + 1) * A[i];\n        return s;\n    }\n\n    long long keyPrim(int mode, int from, int to) {\n        long long noise = (long long)(rng() % 100000);\n        long long dx = xs[from] - xs[to];\n        long long dy = ys[from] - ys[to];\n        long long len2 = dx * dx + dy * dy;\n\n        if (mode == 0) return 1LL * A[to] * 100000 + noise;\n        if (mode == 1) return 1LL * (101 - A[to]) * 100000 + noise;\n        if (mode == 2) return (long long)(rng() & 0x7fffffff);\n        if (mode == 3) return len2 * 1000 + noise;\n        if (mode == 4) return (2000000LL - min(len2, 2000000LL)) * 1000 + noise;\n        return 1LL * A[to] * 50000 + len2 + noise;\n    }\n\n    vector<int> makePrimTree(int mode) {\n        vector<int> par(N, -2), used(N, 0);\n\n        int start = 0;\n        if (mode == 0 || mode == 5) {\n            start = min_element(A.begin(), A.end()) - A.begin();\n        } else if (mode == 1) {\n            start = max_element(A.begin(), A.end()) - A.begin();\n        } else {\n            start = rng() % N;\n        }\n\n        using T = tuple<long long, int, int>;\n        priority_queue<T, vector<T>, greater<T>> pq;\n\n        used[start] = 1;\n        par[start] = -1;\n        int cnt = 1;\n\n        for (int to : adj[start]) {\n            pq.emplace(keyPrim(mode, start, to), start, to);\n        }\n\n        while (cnt < N && !pq.empty()) {\n            auto [key, from, v] = pq.top();\n            pq.pop();\n            if (used[v]) continue;\n            used[v] = 1;\n            par[v] = from;\n            cnt++;\n            for (int to : adj[v]) {\n                if (!used[to]) pq.emplace(keyPrim(mode, v, to), v, to);\n            }\n        }\n\n        return par;\n    }\n\n    vector<int> makeDFSTree(int mode) {\n        vector<vector<pair<long long, int>>> ord(N);\n        for (int v = 0; v < N; v++) {\n            for (int to : adj[v]) {\n                long long noise = (long long)(rng() % 100000);\n                long long key;\n                if (mode == 0) key = 1LL * A[to] * 100000 + noise;\n                else if (mode == 1) key = 1LL * (101 - A[to]) * 100000 + noise;\n                else key = (long long)(rng() & 0x7fffffff);\n                ord[v].push_back({key, to});\n            }\n            sort(ord[v].begin(), ord[v].end());\n        }\n\n        int start;\n        if (mode == 0) start = min_element(A.begin(), A.end()) - A.begin();\n        else if (mode == 1) start = max_element(A.begin(), A.end()) - A.begin();\n        else start = rng() % N;\n\n        vector<int> par(N, -2), used(N, 0), idx(N, 0);\n        vector<int> stk;\n        stk.push_back(start);\n        used[start] = 1;\n        par[start] = -1;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n            while (idx[v] < (int)ord[v].size() && used[ord[v][idx[v]].second]) idx[v]++;\n            if (idx[v] == (int)ord[v].size()) {\n                stk.pop_back();\n                continue;\n            }\n            int to = ord[v][idx[v]++].second;\n            used[to] = 1;\n            par[to] = v;\n            stk.push_back(to);\n        }\n\n        return par;\n    }\n\n    long long childVal(int c, int childLabel, int parentLabel) const {\n        if (childLabel == 0 || parentLabel == childLabel - 1) {\n            return dp_no[c][childLabel];\n        } else {\n            return dp_need[c][childLabel];\n        }\n    }\n\n    vector<int> solveOnTree(const vector<int>& treePar) {\n        vector<vector<int>> tadj(N);\n        for (int v = 0; v < N; v++) {\n            if (treePar[v] >= 0) {\n                tadj[v].push_back(treePar[v]);\n                tadj[treePar[v]].push_back(v);\n            }\n        }\n\n        children.assign(N, {});\n        vector<int> parent(N, -1), order;\n        order.reserve(N);\n\n        vector<int> stk = {0};\n        parent[0] = -2;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n            stk.pop_back();\n            order.push_back(v);\n            for (int to : tadj[v]) {\n                if (to == parent[v]) continue;\n                parent[to] = v;\n                children[v].push_back(to);\n                stk.push_back(to);\n            }\n        }\n\n        dp_no.assign(N, {});\n        dp_need.assign(N, {});\n\n        for (int ii = N - 1; ii >= 0; ii--) {\n            int v = order[ii];\n\n            for (int l = 0; l <= H; l++) {\n                long long base = 1LL * (l + 1) * A[v];\n                vector<long long> bestChild;\n                bestChild.reserve(children[v].size());\n\n                bool ok = true;\n                long long sum = base;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n                    for (int lc = 0; lc <= H; lc++) {\n                        best = max(best, childVal(c, lc, l));\n                    }\n                    if (best <= NEG / 2) ok = false;\n                    sum += best;\n                    bestChild.push_back(best);\n                }\n\n                dp_no[v][l] = ok ? sum : NEG;\n\n                if (l == 0 || !ok) {\n                    dp_need[v][l] = NEG;\n                } else {\n                    int forcedLabel = l - 1;\n                    long long bestDelta = NEG;\n\n                    for (int idx = 0; idx < (int)children[v].size(); idx++) {\n                        int c = children[v][idx];\n                        long long fv = childVal(c, forcedLabel, l);\n                        if (fv <= NEG / 2) continue;\n                        bestDelta = max(bestDelta, fv - bestChild[idx]);\n                    }\n\n                    if (bestDelta <= NEG / 2) dp_need[v][l] = NEG;\n                    else dp_need[v][l] = sum + bestDelta;\n                }\n            }\n        }\n\n        int rootLabel = 0;\n        bool rootNeed = false;\n        long long bestRoot = dp_no[0][0];\n\n        for (int l = 1; l <= H; l++) {\n            if (dp_need[0][l] > bestRoot) {\n                bestRoot = dp_need[0][l];\n                rootLabel = l;\n                rootNeed = true;\n            }\n        }\n\n        vector<int> label(N, 0);\n\n        function<void(int, int, bool)> rec = [&](int v, int l, bool needSupportChild) {\n            label[v] = l;\n\n            int forcedChild = -1;\n            if (needSupportChild) {\n                int forcedLabel = l - 1;\n                long long bestDelta = NEG;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n                    for (int lc = 0; lc <= H; lc++) best = max(best, childVal(c, lc, l));\n\n                    long long fv = childVal(c, forcedLabel, l);\n                    if (fv <= NEG / 2) continue;\n\n                    long long delta = fv - best;\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        forcedChild = c;\n                    }\n                }\n            }\n\n            for (int c : children[v]) {\n                int lcBest = 0;\n                long long valBest = NEG;\n\n                if (c == forcedChild) {\n                    lcBest = l - 1;\n                } else {\n                    for (int lc = 0; lc <= H; lc++) {\n                        long long val = childVal(c, lc, l);\n                        if (val > valBest) {\n                            valBest = val;\n                            lcBest = lc;\n                        }\n                    }\n                }\n\n                bool childNeed = !(lcBest == 0 || l == lcBest - 1);\n                rec(c, lcBest, childNeed);\n            }\n        };\n\n        rec(0, rootLabel, rootNeed);\n        return label;\n    }\n\n    vector<int> calcCnt(const vector<int>& d) const {\n        vector<int> cnt(N, 0);\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) continue;\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) cnt[v]++;\n            }\n        }\n        return cnt;\n    }\n\n    bool canMove(const vector<int>& d, const vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n        if (old == nl) return false;\n\n        if (nl > 0) {\n            bool has = false;\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) {\n                    has = true;\n                    break;\n                }\n            }\n            if (!has) return false;\n        }\n\n        for (int to : adj[v]) {\n            if (d[to] > 0 && d[to] - 1 == old && cnt[to] == 1) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    void applyMove(vector<int>& d, vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n\n        for (int to : adj[v]) {\n            if (d[to] > 0) {\n                if (old == d[to] - 1) cnt[to]--;\n                if (nl == d[to] - 1) cnt[to]++;\n            }\n        }\n\n        d[v] = nl;\n\n        if (nl == 0) {\n            cnt[v] = 0;\n        } else {\n            int c = 0;\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) c++;\n            }\n            cnt[v] = c;\n        }\n    }\n\n    void greedyImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 20; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int old = d[v];\n                for (int nl = H; nl > old; nl--) {\n                    if (canMove(d, cnt, v, nl)) {\n                        applyMove(d, cnt, v, nl);\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void supportPairImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 5; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int dv = d[v];\n                if (dv == H) continue;\n\n                for (int t = H; t > dv; t--) {\n                    if (canMove(d, cnt, v, t)) {\n                        applyMove(d, cnt, v, t);\n                        changed = true;\n                        dv = t;\n                        break;\n                    }\n\n                    int need = t - 1;\n                    int bestU = -1;\n                    long long bestNet = 0;\n\n                    for (int u : adj[v]) {\n                        if (d[u] == need) continue;\n                        if (!canMove(d, cnt, u, need)) continue;\n\n                        long long net = 1LL * (t - dv) * A[v] + 1LL * (need - d[u]) * A[u];\n                        if (net > bestNet) {\n                            bestNet = net;\n                            bestU = u;\n                        }\n                    }\n\n                    if (bestU != -1) {\n                        int oldU = d[bestU];\n\n                        applyMove(d, cnt, bestU, need);\n\n                        if (canMove(d, cnt, v, t)) {\n                            applyMove(d, cnt, v, t);\n                            changed = true;\n                            dv = t;\n                            break;\n                        } else {\n                            applyMove(d, cnt, bestU, oldU);\n                        }\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void lowPerturbAndImprove(vector<int>& d) const {\n        vector<int> best = d;\n        long long bestScore = scoreLabels(d);\n\n        vector<int> cur = d;\n        vector<int> cnt = calcCnt(cur);\n\n        int tried = 0;\n        for (int v : orderLow) {\n            if (++tried > 350) break;\n\n            int old = cur[v];\n            if (old == 0) continue;\n\n            int chosen = -1;\n            for (int nl = 0; nl < old; nl++) {\n                if (!canMove(cur, cnt, v, nl)) continue;\n\n                long long loss = 1LL * A[v] * (old - nl);\n                long long pot = 0;\n                for (int to : adj[v]) {\n                    if (cur[to] == nl + 1) pot += A[to];\n                    if (cur[to] <= H - 1 && cur[to] + 1 > cur[to]) pot += A[to] / 8;\n                }\n\n                if (loss <= 120 + pot) {\n                    chosen = nl;\n                    break;\n                }\n            }\n\n            if (chosen != -1) applyMove(cur, cnt, v, chosen);\n        }\n\n        greedyImprove(cur);\n        supportPairImprove(cur);\n\n        long long sc = scoreLabels(cur);\n        if (sc > bestScore) d = cur;\n    }\n\n    bool checkFeasible(const vector<int>& d) const {\n        for (int v = 0; v < N; v++) {\n            if (d[v] < 0 || d[v] > H) return false;\n            if (d[v] == 0) continue;\n\n            bool ok = false;\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n            if (!ok) return false;\n        }\n        return true;\n    }\n\n    void annealImprove(vector<int>& bestLabel, double timeLimit) {\n        vector<int> cur = bestLabel;\n        vector<int> cnt = calcCnt(cur);\n\n        long long curScore = scoreLabels(cur);\n        long long bestScore = curScore;\n\n        double startTime = elapsed();\n        int iter = 0;\n\n        uniform_real_distribution<double> real01(0.0, 1.0);\n\n        while (elapsed() < timeLimit) {\n            iter++;\n\n            double now = elapsed();\n            double progress = (now - startTime) / max(1e-9, timeLimit - startTime);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 70.0 * (1.0 - progress) + 1.5 * progress;\n\n            int v;\n            if ((rng() % 100) < 65) {\n                v = orderHigh[rng() % min(N, 500)];\n            } else {\n                v = rng() % N;\n            }\n\n            int old = cur[v];\n            int nl;\n\n            if ((rng() % 100) < 70) {\n                nl = old + 1 + (rng() % max(1, H - old));\n                if (nl > H) nl = H;\n            } else {\n                nl = rng() % (H + 1);\n            }\n\n            if (nl == old) continue;\n            if (!canMove(cur, cnt, v, nl)) continue;\n\n            long long delta = 1LL * (nl - old) * A[v];\n\n            bool accept = false;\n            if (delta >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / temp);\n                if (real01(rng) < prob) accept = true;\n            }\n\n            if (accept) {\n                applyMove(cur, cnt, v, nl);\n                curScore += delta;\n\n                if (curScore > bestScore && checkFeasible(cur)) {\n                    bestScore = curScore;\n                    bestLabel = cur;\n                }\n            }\n\n            if (iter % 2500 == 0) {\n                greedyImprove(cur);\n                supportPairImprove(cur);\n\n                cnt = calcCnt(cur);\n                curScore = scoreLabels(cur);\n\n                if (curScore > bestScore && checkFeasible(cur)) {\n                    bestScore = curScore;\n                    bestLabel = cur;\n                }\n\n                if (curScore + 3000 < bestScore || (rng() % 100) < 15) {\n                    cur = bestLabel;\n                    cnt = calcCnt(cur);\n                    curScore = bestScore;\n                }\n            }\n        }\n\n        greedyImprove(bestLabel);\n        supportPairImprove(bestLabel);\n    }\n\n    vector<int> buildParents(const vector<int>& d) const {\n        vector<int> p(N, -1);\n\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) {\n                p[v] = -1;\n            } else {\n                int best = -1;\n                int bestA = 1e9;\n\n                for (int to : adj[v]) {\n                    if (d[to] == d[v] - 1) {\n                        if (A[to] < bestA) {\n                            bestA = A[to];\n                            best = to;\n                        }\n                    }\n                }\n\n                p[v] = best;\n            }\n        }\n\n        return p;\n    }\n\n    void run() {\n        cin >> N >> M >> HH;\n\n        A.resize(N);\n        for (int i = 0; i < N; i++) cin >> A[i];\n\n        edges.resize(M);\n        adj.assign(N, {});\n\n        for (int i = 0; i < M; i++) {\n            int u, v;\n            cin >> u >> v;\n\n            edges[i] = {u, v, 0};\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n\n        xs.resize(N);\n        ys.resize(N);\n\n        for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n        for (auto& e : edges) {\n            long long dx = xs[e.u] - xs[e.v];\n            long long dy = ys[e.u] - ys[e.v];\n            e.len2 = dx * dx + dy * dy;\n        }\n\n        orderHigh.resize(N);\n        orderLow.resize(N);\n        iota(orderHigh.begin(), orderHigh.end(), 0);\n        iota(orderLow.begin(), orderLow.end(), 0);\n\n        sort(orderHigh.begin(), orderHigh.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] > A[b];\n            return adj[a].size() > adj[b].size();\n        });\n\n        sort(orderLow.begin(), orderLow.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] < A[b];\n            return adj[a].size() < adj[b].size();\n        });\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestLabel(N, 0);\n        long long bestScore = scoreLabels(bestLabel);\n\n        int iter = 0;\n\n        while (elapsed() < 1.35) {\n            vector<int> treePar;\n\n            if (iter % 5 == 0) {\n                treePar = makeDFSTree((iter / 5) % 3);\n            } else {\n                treePar = makePrimTree(iter % 6);\n            }\n\n            vector<int> label = solveOnTree(treePar);\n\n            greedyImprove(label);\n            supportPairImprove(label);\n\n            if (iter % 2 == 0) {\n                lowPerturbAndImprove(label);\n            }\n\n            long long sc = scoreLabels(label);\n\n            if (sc > bestScore && checkFeasible(label)) {\n                bestScore = sc;\n                bestLabel = label;\n            }\n\n            iter++;\n        }\n\n        annealImprove(bestLabel, 1.88);\n\n        if (!checkFeasible(bestLabel)) {\n            fill(bestLabel.begin(), bestLabel.end(), 0);\n        }\n\n        vector<int> parent = buildParents(bestLabel);\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << parent[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.run();\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nchar opposite_dir(char d) {\n    if (d == 'L') return 'R';\n    if (d == 'R') return 'L';\n    if (d == 'U') return 'D';\n    return 'U';\n}\n\nbool apply_shift(vector<string>& b, char d, int p) {\n    if (d == 'L') {\n        if (b[p][0] == 'o') return false;\n        for (int j = 0; j + 1 < N; j++) b[p][j] = b[p][j + 1];\n        b[p][N - 1] = '.';\n    } else if (d == 'R') {\n        if (b[p][N - 1] == 'o') return false;\n        for (int j = N - 1; j >= 1; j--) b[p][j] = b[p][j - 1];\n        b[p][0] = '.';\n    } else if (d == 'U') {\n        if (b[0][p] == 'o') return false;\n        for (int i = 0; i + 1 < N; i++) b[i][p] = b[i + 1][p];\n        b[N - 1][p] = '.';\n    } else {\n        if (b[N - 1][p] == 'o') return false;\n        for (int i = N - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n    return true;\n}\n\nint count_oni(const vector<string>& b) {\n    int c = 0;\n    for (auto& s : b) {\n        for (char ch : s) if (ch == 'x') c++;\n    }\n    return c;\n}\n\nbool validate_solution(const vector<string>& init, const vector<Op>& ops) {\n    if ((int)ops.size() > 4 * N * N) return false;\n    vector<string> b = init;\n    for (auto [d, p] : ops) {\n        if (p < 0 || p >= N) return false;\n        if (!apply_shift(b, d, p)) return false;\n    }\n    return count_oni(b) == 0;\n}\n\n/* -------------------- Restoring set-cover solver -------------------- */\n\nstruct Cand {\n    char d;\n    int p;\n    int s;\n    uint64_t mask;\n};\n\nint eval_cover(const vector<int>& sel, const vector<Cand>& cand, uint64_t allmask) {\n    uint64_t u = 0;\n    int sum = 0, mx = 0;\n    for (int id : sel) {\n        u |= cand[id].mask;\n        sum += cand[id].s;\n        mx = max(mx, cand[id].s);\n    }\n    if (u != allmask) return 1e9;\n    return 2 * sum - mx;\n}\n\nvoid prune_cover(vector<int>& sel, const vector<Cand>& cand, uint64_t allmask, mt19937& rng) {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        shuffle(sel.begin(), sel.end(), rng);\n        for (int k = 0; k < (int)sel.size(); k++) {\n            uint64_t u = 0;\n            for (int t = 0; t < (int)sel.size(); t++) {\n                if (t != k) u |= cand[sel[t]].mask;\n            }\n            if (u == allmask) {\n                sel.erase(sel.begin() + k);\n                changed = true;\n                break;\n            }\n        }\n    }\n}\n\nvector<Op> build_ops_from_cover(const vector<int>& sel, const vector<Cand>& cand) {\n    vector<Op> ops;\n    if (sel.empty()) return ops;\n\n    int last_pos = 0;\n    for (int i = 1; i < (int)sel.size(); i++) {\n        if (cand[sel[i]].s > cand[sel[last_pos]].s) last_pos = i;\n    }\n\n    for (int k = 0; k < (int)sel.size(); k++) {\n        const Cand& c = cand[sel[k]];\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        if (k != last_pos) {\n            char od = opposite_dir(c.d);\n            for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n        }\n    }\n    return ops;\n}\n\nvector<Op> solve_set_cover(const vector<string>& init, mt19937& rng) {\n    int id[N][N];\n    memset(id, -1, sizeof(id));\n    vector<pair<int,int>> oni;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (init[i][j] == 'x') {\n                id[i][j] = (int)oni.size();\n                oni.push_back({i, j});\n            }\n        }\n    }\n\n    int Mx = oni.size();\n    uint64_t allmask = (Mx == 64 ? ~0ULL : ((1ULL << Mx) - 1));\n    vector<Cand> cand;\n\n    auto add_cand = [&](char d, int p, int s, uint64_t mask) {\n        if (mask) cand.push_back({d, p, s, mask});\n    };\n\n    for (int i = 0; i < N; i++) {\n        int first_o = N;\n        for (int j = 0; j < N; j++) if (init[i][j] == 'o') { first_o = j; break; }\n\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int j = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('L', i, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int j = N - 1; j >= 0; j--) if (init[i][j] == 'o') { last_o = j; break; }\n\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int j = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('R', i, s, mask);\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int first_o = N;\n        for (int i = 0; i < N; i++) if (init[i][j] == 'o') { first_o = i; break; }\n\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int i = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('U', j, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int i = N - 1; i >= 0; i--) if (init[i][j] == 'o') { last_o = i; break; }\n\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int i = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('D', j, s, mask);\n            }\n        }\n    }\n\n    int C = cand.size();\n    vector<int> alive(C, 1);\n    for (int i = 0; i < C; i++) {\n        for (int j = 0; j < C; j++) if (i != j) {\n            bool subset = (cand[i].mask & ~cand[j].mask) == 0;\n            if (subset && (cand[j].s < cand[i].s || (cand[j].s == cand[i].s && j < i))) {\n                alive[i] = 0;\n                break;\n            }\n        }\n    }\n\n    vector<Cand> nc;\n    for (int i = 0; i < C; i++) if (alive[i]) nc.push_back(cand[i]);\n    cand.swap(nc);\n\n    vector<int> best_sel;\n\n    {\n        vector<int> sel;\n        for (int k = 0; k < Mx; k++) {\n            int best = -1;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                if ((cand[i].mask >> k) & 1ULL) {\n                    if (best == -1 || cand[i].s < cand[best].s) best = i;\n                }\n            }\n            if (best != -1) sel.push_back(best);\n        }\n\n        sort(sel.begin(), sel.end());\n        sel.erase(unique(sel.begin(), sel.end()), sel.end());\n        prune_cover(sel, cand, allmask, rng);\n        best_sel = sel;\n    }\n\n    int best_score = eval_cover(best_sel, cand, allmask);\n\n    for (int iter = 0; iter < 5000; iter++) {\n        uint64_t covered = 0;\n        vector<int> sel;\n        double alpha = 1.0 + (rng() % 1200) / 1000.0;\n\n        while (covered != allmask) {\n            vector<pair<double,int>> v;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                uint64_t nw = cand[i].mask & ~covered;\n                if (!nw) continue;\n                int cnt = __builtin_popcountll(nw);\n                double noise = 0.85 + (rng() % 3000) / 10000.0;\n                double sc = cand[i].s / pow((double)cnt, alpha) * noise;\n                v.push_back({sc, i});\n            }\n\n            if (v.empty()) break;\n            sort(v.begin(), v.end());\n\n            int K = min<int>((int)v.size(), 3 + (rng() % 8));\n            int chosen = v[rng() % K].second;\n            sel.push_back(chosen);\n            covered |= cand[chosen].mask;\n        }\n\n        if (covered != allmask) continue;\n\n        prune_cover(sel, cand, allmask, rng);\n        int sc = eval_cover(sel, cand, allmask);\n\n        if (sc < best_score) {\n            best_score = sc;\n            best_sel = sel;\n        }\n    }\n\n    return build_ops_from_cover(best_sel, cand);\n}\n\n/* -------------------- Dynamic macro solvers -------------------- */\n\nstruct DynCand {\n    char d;\n    int p;\n    int s;\n    int rem;\n    bool bounce;\n};\n\nvoid add_dyn_cands_for_line(vector<DynCand>& res, const vector<string>& b, bool bounce_allowed) {\n    for (int i = 0; i < N; i++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[i][s - 1] != 'o'; s++) {\n            if (b[i][s - 1] == 'x') {\n                rem++;\n                res.push_back({'L', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'L', i, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[i][N - s] != 'o'; s++) {\n            if (b[i][N - s] == 'x') {\n                rem++;\n                res.push_back({'R', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'R', i, s, rem, true});\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[s - 1][j] != 'o'; s++) {\n            if (b[s - 1][j] == 'x') {\n                rem++;\n                res.push_back({'U', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'U', j, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[N - s][j] != 'o'; s++) {\n            if (b[N - s][j] == 'x') {\n                rem++;\n                res.push_back({'D', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'D', j, s, rem, true});\n            }\n        }\n    }\n}\n\nbool apply_dyn(vector<string>& b, vector<Op>& ops, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n        ops.push_back({c.d, c.p});\n    }\n\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n            ops.push_back({od, c.p});\n        }\n    }\n\n    return true;\n}\n\nbool apply_dyn_board_only(vector<string>& b, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n    }\n\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n        }\n    }\n\n    return true;\n}\n\nint dyn_cost(const DynCand& c) {\n    return c.s * (c.bounce ? 2 : 1);\n}\n\nvector<Op> dynamic_trial(const vector<string>& init, mt19937& rng, int mode) {\n    vector<string> b = init;\n    vector<Op> ops;\n\n    double alpha = 1.0 + (rng() % 1400) / 1000.0;\n    bool bounce_allowed = (mode != 0);\n\n    for (int step = 0; step < 45; step++) {\n        int oni = count_oni(b);\n        if (oni == 0) return ops;\n        if ((int)ops.size() > 4 * N * N) return {};\n\n        vector<DynCand> cs;\n        add_dyn_cands_for_line(cs, b, bounce_allowed);\n        if (cs.empty()) return {};\n\n        vector<pair<double,int>> rank;\n        for (int i = 0; i < (int)cs.size(); i++) {\n            int cost = dyn_cost(cs[i]);\n            double sc = cost / pow((double)cs[i].rem, alpha);\n\n            if (mode == 0 && cs[i].bounce) continue;\n            if (mode == 1 && cs[i].bounce) sc *= 1.15;\n            if (mode == 2 && !cs[i].bounce) sc *= 0.85;\n            if (mode == 3 && cs[i].bounce) sc *= 0.85;\n\n            double noise = 0.80 + (rng() % 4000) / 10000.0;\n            sc *= noise;\n\n            rank.push_back({sc, i});\n        }\n\n        if (rank.empty()) return {};\n        sort(rank.begin(), rank.end());\n\n        int K;\n        if (mode == 4) K = 1;\n        else K = min<int>((int)rank.size(), 3 + (rng() % 8));\n\n        DynCand chosen = cs[rank[(K == 1 ? 0 : (int)(rng() % K))].second];\n\n        if (!apply_dyn(b, ops, chosen)) return {};\n    }\n\n    if (count_oni(b) == 0) return ops;\n    return {};\n}\n\n/* -------------------- Beam macro solver -------------------- */\n\nuint64_t hash_board(const vector<string>& b) {\n    uint64_t h = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        for (char c : b[i]) {\n            h ^= (unsigned char)c;\n            h *= 1099511628211ULL;\n        }\n    }\n    return h;\n}\n\nint sum_visible_min_dist(const vector<string>& b) {\n    int sum = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) if (b[i][j] == 'x') {\n            int best = 25;\n\n            bool ok = true;\n            for (int k = 0; k < j; k++) if (b[i][k] == 'o') ok = false;\n            if (ok) best = min(best, j + 1);\n\n            ok = true;\n            for (int k = j + 1; k < N; k++) if (b[i][k] == 'o') ok = false;\n            if (ok) best = min(best, N - j);\n\n            ok = true;\n            for (int k = 0; k < i; k++) if (b[k][j] == 'o') ok = false;\n            if (ok) best = min(best, i + 1);\n\n            ok = true;\n            for (int k = i + 1; k < N; k++) if (b[k][j] == 'o') ok = false;\n            if (ok) best = min(best, N - i);\n\n            if (best == 25) best = 12;\n            sum += best;\n        }\n    }\n\n    return sum;\n}\n\nstruct BeamNode {\n    vector<string> b;\n    vector<DynCand> path;\n    int cost;\n    int rem;\n    double eval;\n};\n\nvector<Op> build_ops_from_dyn_path(const vector<DynCand>& path) {\n    vector<Op> ops;\n    for (auto& c : path) {\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        if (c.bounce) {\n            char od = opposite_dir(c.d);\n            for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n        }\n    }\n    return ops;\n}\n\nvector<Op> beam_search_solver(\n    const vector<string>& init,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline,\n    int incumbent_cost\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    vector<Op> best_ops;\n\n    BeamNode root;\n    root.b = init;\n    root.cost = 0;\n    root.rem = count_oni(init);\n    root.eval = root.rem;\n    vector<BeamNode> beam;\n    beam.push_back(root);\n\n    const int BEAM_WIDTH = 120;\n    const int MAX_CAND = 45;\n\n    for (int depth = 0; depth < 45 && elapsed() < deadline; depth++) {\n        vector<BeamNode> nxt;\n        unordered_map<uint64_t, int> seen;\n        seen.reserve(BEAM_WIDTH * MAX_CAND * 2);\n\n        for (auto& node : beam) {\n            if (elapsed() >= deadline) break;\n\n            vector<DynCand> cs;\n            add_dyn_cands_for_line(cs, node.b, true);\n            if (cs.empty()) continue;\n\n            vector<pair<double,int>> ord;\n            ord.reserve(cs.size());\n\n            for (int i = 0; i < (int)cs.size(); i++) {\n                double sc = dyn_cost(cs[i]) / pow((double)cs[i].rem, 1.35);\n                if (cs[i].bounce) sc *= 1.08;\n                sc *= 0.98 + (rng() % 400) / 10000.0;\n                ord.push_back({sc, i});\n            }\n\n            sort(ord.begin(), ord.end());\n            int lim = min<int>(MAX_CAND, ord.size());\n\n            for (int z = 0; z < lim; z++) {\n                const DynCand& c = cs[ord[z].second];\n                int ncst = node.cost + dyn_cost(c);\n                if (ncst >= incumbent_cost) continue;\n\n                BeamNode nb;\n                nb.b = node.b;\n                if (!apply_dyn_board_only(nb.b, c)) continue;\n\n                nb.rem = count_oni(nb.b);\n                if (nb.rem >= node.rem) continue;\n\n                nb.cost = ncst;\n                nb.path = node.path;\n                nb.path.push_back(c);\n\n                if (nb.rem == 0) {\n                    vector<Op> ops = build_ops_from_dyn_path(nb.path);\n                    if ((int)ops.size() < incumbent_cost) {\n                        incumbent_cost = ops.size();\n                        best_ops = ops;\n                    }\n                    continue;\n                }\n\n                uint64_t h = hash_board(nb.b);\n                auto it = seen.find(h);\n                if (it != seen.end() && it->second <= nb.cost) continue;\n                seen[h] = nb.cost;\n\n                nb.eval = nb.cost + 1.6 * nb.rem + 0.10 * sum_visible_min_dist(nb.b);\n                nxt.push_back(std::move(nb));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        sort(nxt.begin(), nxt.end(), [](const BeamNode& a, const BeamNode& b) {\n            if (a.eval != b.eval) return a.eval < b.eval;\n            return a.cost < b.cost;\n        });\n\n        if ((int)nxt.size() > BEAM_WIDTH) nxt.resize(BEAM_WIDTH);\n        beam.swap(nxt);\n    }\n\n    return best_ops;\n}\n\n/* -------------------- Sequence simplification -------------------- */\n\nvoid postprocess_remove_blocks(\n    const vector<string>& init,\n    vector<Op>& ops,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    if (!validate_solution(init, ops)) return;\n\n    bool improved = true;\n\n    while (improved && elapsed() < deadline) {\n        improved = false;\n\n        for (int len = 8; len >= 1 && elapsed() < deadline; len--) {\n            if ((int)ops.size() < len) continue;\n\n            vector<int> idx;\n            for (int i = 0; i + len <= (int)ops.size(); i++) idx.push_back(i);\n\n            // Mostly deterministic, partly randomized.\n            if (len <= 3) shuffle(idx.begin(), idx.end(), rng);\n\n            for (int st : idx) {\n                if (elapsed() >= deadline) break;\n                if (st + len > (int)ops.size()) continue;\n\n                vector<Op> cand;\n                cand.reserve(ops.size() - len);\n                for (int i = 0; i < (int)ops.size(); i++) {\n                    if (i < st || i >= st + len) cand.push_back(ops[i]);\n                }\n\n                if (validate_solution(init, cand)) {\n                    ops.swap(cand);\n                    improved = true;\n                    break;\n                }\n            }\n\n            if (improved) break;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n\n    vector<string> init(N);\n    for (int i = 0; i < N; i++) cin >> init[i];\n\n    mt19937 rng(1234567);\n    auto start = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    vector<Op> best = solve_set_cover(init, rng);\n    if (!validate_solution(init, best)) best.clear();\n\n    {\n        vector<Op> beam_ops = beam_search_solver(\n            init,\n            rng,\n            start,\n            0.55,\n            best.empty() ? 4 * N * N + 1 : (int)best.size()\n        );\n\n        if (!beam_ops.empty() && (best.empty() || beam_ops.size() < best.size())) {\n            if (validate_solution(init, beam_ops)) best = beam_ops;\n        }\n    }\n\n    int trial = 0;\n    while (elapsed() < 1.75) {\n        int mode;\n        if (trial == 0) mode = 4;\n        else if (trial == 1) mode = 0;\n        else mode = rng() % 5;\n\n        vector<Op> ops = dynamic_trial(init, rng, mode);\n\n        if (!ops.empty() && (best.empty() || ops.size() < best.size())) {\n            if (validate_solution(init, ops)) best = ops;\n        }\n\n        trial++;\n    }\n\n    if (!best.empty()) {\n        postprocess_remove_blocks(init, best, rng, start, 1.94);\n    }\n\n    if (best.empty() || !validate_solution(init, best) || (int)best.size() > 4 * N * N) {\n        rng.seed(42);\n        best = solve_set_cover(init, rng);\n        if (!validate_solution(init, best)) best.clear();\n    }\n\n    for (auto [d, p] : best) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T;\nmt19937 rng(123456789);\n\ndouble elapsed_sec() {\n    static auto st = chrono::steady_clock::now();\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - st).count();\n}\n\nstruct Graph {\n    array<int, MAXN> a{}, b{}, cnt{};\n    int err = INT_MAX;\n};\n\nGraph evaluate(const array<int, MAXN>& a, const array<int, MAXN>& b) {\n    Graph g;\n    g.a = a;\n    g.b = b;\n    g.cnt.fill(0);\n\n    int cur = 0;\n    g.cnt[cur] = 1;\n\n    for (int step = 1; step < L; step++) {\n        int c = g.cnt[cur];\n        cur = (c & 1) ? a[cur] : b[cur];\n        g.cnt[cur]++;\n    }\n\n    long long e = 0;\n    for (int i = 0; i < N; i++) {\n        e += llabs((long long)g.cnt[i] - T[i]);\n    }\n    g.err = (int)e;\n    return g;\n}\n\nint weighted_pick(const vector<int>& v, const vector<int>& w) {\n    long long sum = 0;\n    for (int x : w) sum += x;\n    if (sum <= 0) return v[rng() % v.size()];\n\n    long long r = rng() % sum;\n    for (int i = 0; i < (int)v.size(); i++) {\n        if (r < w[i]) return v[i];\n        r -= w[i];\n    }\n    return v.back();\n}\n\nGraph make_cycle_candidate(int id) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    sort(active.begin(), active.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    if (id == 1) {\n        reverse(active.begin(), active.end());\n    } else if (id >= 2) {\n        int m = (int)active.size();\n        int swaps = (id % 9 + 1) * m / 16;\n        for (int k = 0; k < swaps; k++) {\n            int p = rng() % m;\n            int q = rng() % m;\n            swap(active[p], active[q]);\n        }\n    }\n\n    int m = (int)active.size();\n\n    vector<int> succ(N, root);\n    array<long long, MAXN> in{};\n    in.fill(0);\n\n    for (int k = 0; k < m; k++) {\n        int v = active[k];\n        int to = active[(k + 1) % m];\n        succ[v] = to;\n        in[to] += T[v];\n    }\n\n    vector<int> sources = active;\n    sort(sources.begin(), sources.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    vector<int> assigned(N, root);\n\n    for (int s : sources) {\n        long long w = T[s];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(m);\n\n        for (int d : active) {\n            long long before = llabs(in[d] - 2LL * T[d]);\n            long long after = llabs(in[d] + w - 2LL * T[d]);\n            cand.push_back({after - before, d});\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int choose = 0;\n        if (id >= 2) {\n            int lim = min(5, (int)cand.size());\n            choose = rng() % lim;\n        }\n\n        int d = cand[choose].second;\n        assigned[s] = d;\n        in[d] += w;\n    }\n\n    for (int it = 0; it < 45; it++) {\n        long long best_delta = 0;\n        int best_s = -1, best_d = -1;\n\n        for (int s : sources) {\n            int old = assigned[s];\n            long long w = T[s];\n\n            for (int d : active) {\n                if (d == old) continue;\n\n                long long cur =\n                    llabs(in[old] - 2LL * T[old]) +\n                    llabs(in[d] - 2LL * T[d]);\n\n                long long nxt =\n                    llabs(in[old] - w - 2LL * T[old]) +\n                    llabs(in[d] + w - 2LL * T[d]);\n\n                long long delta = nxt - cur;\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_s = s;\n                    best_d = d;\n                }\n            }\n        }\n\n        if (best_s == -1) break;\n\n        int old = assigned[best_s];\n        long long w = T[best_s];\n        in[old] -= w;\n        in[best_d] += w;\n        assigned[best_s] = best_d;\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            a[i] = succ[i];\n            b[i] = assigned[i];\n            if (id >= 2 && (rng() & 1)) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nstruct Token {\n    int src;\n    int slot;\n    int w;\n};\n\nGraph make_balanced_candidate(int id) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    vector<Token> tok;\n    tok.reserve(active.size() * 2);\n    for (int s : active) {\n        tok.push_back({s, 0, T[s]});\n        tok.push_back({s, 1, T[s]});\n    }\n\n    int M = (int)tok.size();\n\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    vector<int> noise(M);\n    for (int i = 0; i < M; i++) noise[i] = (int)(rng() & 1023);\n\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        long long kx = 1000000LL * tok[x].w + noise[x] * (id % 7);\n        long long ky = 1000000LL * tok[y].w + noise[y] * (id % 7);\n        if (kx != ky) return kx > ky;\n        return x < y;\n    });\n\n    if (id % 11 == 0) {\n        shuffle(ord.begin(), ord.end(), rng);\n    } else if (id % 5 == 0) {\n        int block = 8 + (id % 7);\n        for (int l = 0; l < M; l += block) {\n            int r = min(M, l + block);\n            shuffle(ord.begin() + l, ord.begin() + r, rng);\n        }\n    }\n\n    array<long long, MAXN> rem{};\n    for (int i = 0; i < N; i++) rem[i] = 2LL * T[i];\n\n    array<array<int, 2>, MAXN> dest;\n    for (int i = 0; i < N; i++) dest[i][0] = dest[i][1] = -1;\n\n    vector<int> token_dest(M, -1);\n\n    bool hard_no_self = (id % 6 == 0 || id % 6 == 3);\n    bool avoid_same = (id % 6 != 1);\n\n    for (int idx : ord) {\n        int s = tok[idx].src;\n        int sl = tok[idx].slot;\n        int w = tok[idx].w;\n        int other = dest[s][1 - sl];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(active.size());\n\n        for (int d : active) {\n            if (hard_no_self && d == s && active.size() > 1) continue;\n\n            long long delta = llabs(rem[d] - w) - llabs(rem[d]);\n            long long penalty = 0;\n\n            if (d == s) penalty += 2LL * w + 500;\n            if (avoid_same && other == d) penalty += w / 2 + 300;\n\n            long long score = delta * 100000LL + penalty * 100LL + (int)(rng() & 2047);\n            cand.push_back({score, d});\n        }\n\n        if (cand.empty()) {\n            for (int d : active) {\n                long long delta = llabs(rem[d] - w) - llabs(rem[d]);\n                cand.push_back({delta * 100000LL + (int)(rng() & 2047), d});\n            }\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int lim = min((int)cand.size(), 1 + (id % 5));\n        if (id % 13 == 0) lim = min((int)cand.size(), 8);\n\n        int d = cand[rng() % lim].second;\n        dest[s][sl] = d;\n        token_dest[idx] = d;\n        rem[d] -= w;\n    }\n\n    auto violates = [&](int idx, int d) -> bool {\n        int s = tok[idx].src;\n        int sl = tok[idx].slot;\n        if (hard_no_self && d == s && active.size() > 1) return true;\n        if (avoid_same && dest[s][1 - sl] == d && active.size() > 2) return true;\n        return false;\n    };\n\n    int improve_trials = 3500;\n    for (int it = 0; it < improve_trials; it++) {\n        if (rng() & 1) {\n            int idx = rng() % M;\n            int old = token_dest[idx];\n            int d = active[rng() % active.size()];\n            if (d == old) continue;\n            if (violates(idx, d)) continue;\n\n            long long w = tok[idx].w;\n            long long delta =\n                llabs(rem[old] + w) - llabs(rem[old]) +\n                llabs(rem[d] - w) - llabs(rem[d]);\n\n            if (delta < 0 || (delta == 0 && (rng() & 7) == 0)) {\n                rem[old] += w;\n                rem[d] -= w;\n                token_dest[idx] = d;\n                dest[tok[idx].src][tok[idx].slot] = d;\n            }\n        } else {\n            int x = rng() % M;\n            int y = rng() % M;\n            if (x == y) continue;\n\n            int dx = token_dest[x];\n            int dy = token_dest[y];\n            if (dx == dy) continue;\n            if (violates(x, dy) || violates(y, dx)) continue;\n\n            long long wx = tok[x].w;\n            long long wy = tok[y].w;\n\n            long long before = llabs(rem[dx]) + llabs(rem[dy]);\n\n            long long ndx = rem[dx] + wx - wy;\n            long long ndy = rem[dy] + wy - wx;\n\n            long long after = llabs(ndx) + llabs(ndy);\n            long long delta = after - before;\n\n            if (delta < 0 || (delta == 0 && (rng() & 15) == 0)) {\n                rem[dx] = ndx;\n                rem[dy] = ndy;\n\n                token_dest[x] = dy;\n                token_dest[y] = dx;\n\n                dest[tok[x].src][tok[x].slot] = dy;\n                dest[tok[y].src][tok[y].slot] = dx;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            int x = dest[i][0];\n            int y = dest[i][1];\n            if (x < 0) x = root;\n            if (y < 0) y = root;\n            a[i] = x;\n            b[i] = y;\n\n            if (rng() & 1) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n\n    uint64_t seed = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n        seed ^= (uint64_t)(T[i] + 1000003) * (i + 1009);\n        seed *= 1099511628211ULL;\n    }\n    rng.seed((uint32_t)(seed ^ (seed >> 32)));\n\n    Graph best;\n    best.err = INT_MAX;\n\n    for (int id = 0; id < 35; id++) {\n        if (elapsed_sec() > 0.45) break;\n        Graph g = make_cycle_candidate(id);\n        if (g.err < best.err) best = g;\n    }\n\n    for (int id = 0; id < 220; id++) {\n        if (elapsed_sec() > 1.05) break;\n        Graph g = make_balanced_candidate(id);\n        if (g.err < best.err) best = g;\n    }\n\n    Graph cur = best;\n\n    for (int pass = 0; pass < 4; pass++) {\n        bool improved = false;\n\n        for (int i = 0; i < N; i++) {\n            if (elapsed_sec() > 1.25) break;\n            if (cur.a[i] == cur.b[i]) continue;\n\n            swap(cur.a[i], cur.b[i]);\n            Graph ng = evaluate(cur.a, cur.b);\n\n            if (ng.err <= cur.err) {\n                cur = ng;\n                improved = true;\n                if (cur.err < best.err) best = cur;\n            } else {\n                swap(cur.a[i], cur.b[i]);\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    cur = best;\n\n    while (elapsed_sec() < 1.88) {\n        vector<int> over, under, wover, wunder;\n\n        for (int i = 0; i < N; i++) {\n            int d = cur.cnt[i] - T[i];\n            if (d > 0) {\n                over.push_back(i);\n                wover.push_back(d);\n            } else if (d < 0) {\n                under.push_back(i);\n                wunder.push_back(-d);\n            }\n        }\n\n        if (over.empty() || under.empty()) break;\n\n        array<int, MAXN> na = cur.a;\n        array<int, MAXN> nb = cur.b;\n\n        int typ = rng() % 100;\n\n        if (typ < 18) {\n            int i = rng() % N;\n            if (na[i] == nb[i]) continue;\n            swap(na[i], nb[i]);\n        } else if (typ < 72) {\n            int v = weighted_pick(over, wover);\n            int u = weighted_pick(under, wunder);\n\n            vector<pair<int, int>> edges;\n            for (int i = 0; i < N; i++) {\n                if (na[i] == v) edges.push_back({i, 0});\n                if (nb[i] == v) edges.push_back({i, 1});\n            }\n\n            if (edges.empty()) continue;\n\n            auto [s, slot] = edges[rng() % edges.size()];\n            if (slot == 0) na[s] = u;\n            else nb[s] = u;\n        } else if (typ < 88) {\n            int s = weighted_pick(over, wover);\n            int u = weighted_pick(under, wunder);\n\n            if (rng() & 1) na[s] = u;\n            else nb[s] = u;\n        } else {\n            int s = rng() % N;\n            int u = weighted_pick(under, wunder);\n\n            if (rng() & 1) na[s] = u;\n            else nb[s] = u;\n        }\n\n        Graph ng = evaluate(na, nb);\n\n        bool accept = false;\n\n        if (ng.err <= cur.err) {\n            accept = true;\n        } else {\n            double e = elapsed_sec();\n            double remain = max(0.0, 1.88 - e);\n            int temp = max(1, (int)(900.0 * remain / 1.88));\n            int diff = ng.err - cur.err;\n\n            if (diff < temp && (int)(rng() % temp) < temp - diff) {\n                accept = true;\n            }\n        }\n\n        if (accept) {\n            cur = ng;\n            if (cur.err < best.err) best = cur;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), 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\nint N, M, Q, L, W;\nvector<int> G;\nvector<double> cx, cy;\n\ninline double dist2p(double x1, double y1, double x2, double y2) {\n    double dx = x1 - x2;\n    double dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\ninline double edist(int a, int b) {\n    return sqrt(dist2p(cx[a], cy[a], cx[b], cy[b]));\n}\n\ninline unsigned long long ekey(int a, int b) {\n    if (a > b) swap(a, b);\n    return (unsigned long long)a << 32 | (unsigned int)b;\n}\n\ninline pair<int,int> decode_key(unsigned long long k) {\n    int a = (int)(k >> 32);\n    int b = (int)(k & 0xffffffffu);\n    return {a, b};\n}\n\nlong long hilbert_index(int x, int y, int bits = 14) {\n    long long d = 0;\n    int n = 1 << bits;\n    for (int s = n >> 1; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += 1LL * s * s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = n - 1 - x;\n                y = n - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\ndouble mst_cost(const vector<int>& verts) {\n    int n = (int)verts.size();\n    if (n <= 1) return 0.0;\n    if (n == 2) return edist(verts[0], verts[1]);\n\n    vector<double> minv(n, 1e100);\n    vector<char> used(n, 0);\n    minv[0] = 0.0;\n    double res = 0.0;\n\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n        used[v] = 1;\n        res += best;\n\n        int cv = verts[v];\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(cv, verts[u]);\n                if (d < minv[u]) minv[u] = d;\n            }\n        }\n    }\n\n    return res;\n}\n\nvector<pair<int,int>> prim_edges(const vector<int>& verts) {\n    int n = (int)verts.size();\n    vector<pair<int,int>> ret;\n    if (n <= 1) return ret;\n    if (n == 2) {\n        ret.push_back({verts[0], verts[1]});\n        return ret;\n    }\n\n    vector<double> minv(n, 1e100);\n    vector<int> par(n, -1);\n    vector<char> used(n, 0);\n    minv[0] = 0.0;\n\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n\n        used[v] = 1;\n        if (par[v] != -1) ret.push_back({verts[v], verts[par[v]]});\n\n        int cv = verts[v];\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(cv, verts[u]);\n                if (d < minv[u]) {\n                    minv[u] = d;\n                    par[u] = v;\n                }\n            }\n        }\n    }\n\n    return ret;\n}\n\ndouble total_mst_cost(const vector<vector<int>>& groups) {\n    double s = 0.0;\n    for (auto& g : groups) s += mst_cost(g);\n    return s;\n}\n\nvector<vector<int>> build_from_order(const vector<int>& ord, const vector<int>& perm) {\n    vector<vector<int>> groups(M);\n    int pos = 0;\n    for (int id : perm) {\n        groups[id].assign(ord.begin() + pos, ord.begin() + pos + G[id]);\n        pos += G[id];\n    }\n    return groups;\n}\n\nvector<vector<int>> make_size_perms() {\n    vector<vector<int>> vars;\n\n    vector<int> p(M);\n    iota(p.begin(), p.end(), 0);\n    vars.push_back(p);\n\n    vector<int> r = p;\n    reverse(r.begin(), r.end());\n    vars.push_back(r);\n\n    vector<int> asc = p;\n    sort(asc.begin(), asc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n    vars.push_back(asc);\n\n    vector<int> desc = p;\n    sort(desc.begin(), desc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n    vars.push_back(desc);\n\n    return vars;\n}\n\npair<vector<int>, int> split_group_ids_subset_sum(const vector<int>& gids, int total) {\n    int target = total / 2;\n    vector<char> dp(total + 1, 0);\n    vector<int> preSum(total + 1, -1), preId(total + 1, -1);\n    dp[0] = 1;\n\n    for (int id : gids) {\n        int w = G[id];\n        for (int s = total - w; s >= 0; s--) {\n            if (dp[s] && !dp[s + w]) {\n                dp[s + w] = 1;\n                preSum[s + w] = s;\n                preId[s + w] = id;\n            }\n        }\n    }\n\n    int best = -1;\n    for (int d = 0; d <= total; d++) {\n        int s1 = target - d;\n        int s2 = target + d;\n        if (s1 > 0 && s1 < total && dp[s1]) {\n            best = s1;\n            break;\n        }\n        if (s2 > 0 && s2 < total && dp[s2]) {\n            best = s2;\n            break;\n        }\n    }\n\n    if (best == -1) {\n        vector<int> left = {gids[0]};\n        return {left, G[gids[0]]};\n    }\n\n    vector<int> left;\n    int cur = best;\n    while (cur > 0) {\n        int id = preId[cur];\n        left.push_back(id);\n        cur = preSum[cur];\n    }\n\n    return {left, best};\n}\n\nvoid recursive_partition(\n    const vector<int>& cities,\n    const vector<int>& gids,\n    int depth,\n    int variant,\n    vector<vector<int>>& groups\n) {\n    if (gids.size() == 1) {\n        groups[gids[0]] = cities;\n        return;\n    }\n\n    int total = cities.size();\n    auto [leftIds, leftCount] = split_group_ids_subset_sum(gids, total);\n\n    vector<char> inLeft(M, 0);\n    for (int id : leftIds) inLeft[id] = 1;\n\n    vector<int> rightIds;\n    for (int id : gids) {\n        if (!inLeft[id]) rightIds.push_back(id);\n    }\n\n    vector<int> sorted = cities;\n\n    if (variant == 0) {\n        double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n        for (int v : cities) {\n            minx = min(minx, cx[v]);\n            maxx = max(maxx, cx[v]);\n            miny = min(miny, cy[v]);\n            maxy = max(maxy, cy[v]);\n        }\n        bool useX = (maxx - minx >= maxy - miny);\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            if (useX) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            } else {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            }\n        });\n    } else if (variant == 1) {\n        bool useX = (depth % 2 == 0);\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            if (useX) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            } else {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            }\n        });\n    } else if (variant == 2) {\n        double mx = 0.0, my = 0.0;\n        for (int v : cities) {\n            mx += cx[v];\n            my += cy[v];\n        }\n        mx /= cities.size();\n        my /= cities.size();\n\n        double sxx = 0.0, syy = 0.0, sxy = 0.0;\n        for (int v : cities) {\n            double x = cx[v] - mx;\n            double y = cy[v] - my;\n            sxx += x * x;\n            syy += y * y;\n            sxy += x * y;\n        }\n\n        double theta = 0.5 * atan2(2.0 * sxy, sxx - syy);\n        double vx = cos(theta), vy = sin(theta);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            double pa = cx[a] * vx + cy[a] * vy;\n            double pb = cx[b] * vx + cy[b] * vy;\n            if (pa != pb) return pa < pb;\n            return a < b;\n        });\n    } else {\n        bool diag = (depth % 2 == 0);\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            double pa = diag ? (cx[a] + cy[a]) : (cx[a] - cy[a]);\n            double pb = diag ? (cx[b] + cy[b]) : (cx[b] - cy[b]);\n            if (pa != pb) return pa < pb;\n            return a < b;\n        });\n    }\n\n    vector<int> leftCities(sorted.begin(), sorted.begin() + leftCount);\n    vector<int> rightCities(sorted.begin() + leftCount, sorted.end());\n\n    recursive_partition(leftCities, leftIds, depth + 1, variant, groups);\n    recursive_partition(rightCities, rightIds, depth + 1, variant, groups);\n}\n\nvector<vector<int>> make_recursive_candidate(int variant) {\n    vector<int> cities(N), gids(M);\n    iota(cities.begin(), cities.end(), 0);\n    iota(gids.begin(), gids.end(), 0);\n\n    vector<vector<int>> groups(M);\n    recursive_partition(cities, gids, 0, variant, groups);\n    return groups;\n}\n\nstring subset_key(vector<int> v) {\n    sort(v.begin(), v.end());\n    string s;\n    s.reserve(v.size() * 5);\n    for (int x : v) {\n        s += to_string(x);\n        s += ',';\n    }\n    return s;\n}\n\nvector<pair<int,int>> do_query(const vector<int>& c) {\n    cout << \"? \" << c.size();\n    for (int v : c) cout << ' ' << v;\n    cout << endl;\n    cout.flush();\n\n    vector<pair<int,int>> ret;\n    for (int i = 0; i < (int)c.size() - 1; i++) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        ret.push_back({a, b});\n    }\n    return ret;\n}\n\nvector<int> nearest_subset_to_seed(const vector<int>& group, int seed) {\n    vector<pair<double,int>> v;\n    v.reserve(group.size());\n    for (int x : group) {\n        v.push_back({edist(seed, x), x});\n    }\n    sort(v.begin(), v.end());\n\n    vector<int> sub;\n    int lim = min(L, (int)v.size());\n    for (int i = 0; i < lim; i++) sub.push_back(v[i].second);\n    return sub;\n}\n\nvector<int> nearest_subset_to_edge(const vector<int>& group, int a, int b) {\n    double mx = (cx[a] + cx[b]) * 0.5;\n    double my = (cy[a] + cy[b]) * 0.5;\n\n    vector<pair<double,int>> v;\n    v.reserve(group.size());\n    for (int x : group) {\n        double d = dist2p(cx[x], cy[x], mx, my);\n        if (x == a || x == b) d -= 1e18;\n        v.push_back({d, x});\n    }\n    sort(v.begin(), v.end());\n\n    vector<int> sub;\n    int lim = min(L, (int)v.size());\n    for (int i = 0; i < lim; i++) sub.push_back(v[i].second);\n\n    bool hasA = false, hasB = false;\n    for (int x : sub) {\n        if (x == a) hasA = true;\n        if (x == b) hasB = true;\n    }\n    if (!hasA && !sub.empty()) sub.back() = a;\n    hasB = false;\n    for (int x : sub) if (x == b) hasB = true;\n    if (!hasB && sub.size() >= 2) sub[sub.size() - 2] = b;\n\n    sort(sub.begin(), sub.end());\n    sub.erase(unique(sub.begin(), sub.end()), sub.end());\n\n    for (int x : group) {\n        if ((int)sub.size() >= min(L, (int)group.size())) break;\n        if (find(sub.begin(), sub.end(), x) == sub.end()) sub.push_back(x);\n    }\n\n    return sub;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    cx.resize(N);\n    cy.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cx[i] = (lx + rx) * 0.5;\n        cy[i] = (ly + ry) * 0.5;\n    }\n\n    vector<vector<vector<int>>> candidates;\n    auto perms = make_size_perms();\n\n    // Hilbert variants.\n    for (int t = 0; t < 8; t++) {\n        vector<pair<long long,int>> v;\n        for (int i = 0; i < N; i++) {\n            double x = cx[i], y = cy[i];\n            double X = x, Y = y;\n\n            if (t == 0) { X = x; Y = y; }\n            if (t == 1) { X = y; Y = x; }\n            if (t == 2) { X = 10000 - x; Y = y; }\n            if (t == 3) { X = x; Y = 10000 - y; }\n            if (t == 4) { X = 10000 - x; Y = 10000 - y; }\n            if (t == 5) { X = y; Y = 10000 - x; }\n            if (t == 6) { X = 10000 - y; Y = x; }\n            if (t == 7) { X = 10000 - y; Y = 10000 - x; }\n\n            int xi = min(16383, max(0, (int)llround(X * 16383.0 / 10000.0)));\n            int yi = min(16383, max(0, (int)llround(Y * 16383.0 / 10000.0)));\n            v.push_back({hilbert_index(xi, yi), i});\n        }\n\n        sort(v.begin(), v.end());\n        vector<int> ord;\n        for (auto [d, i] : v) ord.push_back(i);\n\n        for (auto& p : perms) {\n            candidates.push_back(build_from_order(ord, p));\n        }\n    }\n\n    // Simple linear orders.\n    for (int t = 0; t < 6; t++) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            double ka, kb;\n            if (t == 0) ka = cx[a], kb = cx[b];\n            else if (t == 1) ka = cy[a], kb = cy[b];\n            else if (t == 2) ka = cx[a] + cy[a], kb = cx[b] + cy[b];\n            else if (t == 3) ka = cx[a] - cy[a], kb = cx[b] - cy[b];\n            else if (t == 4) ka = -cx[a] + cy[a], kb = -cx[b] + cy[b];\n            else ka = -cx[a] - cy[a], kb = -cx[b] - cy[b];\n\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n\n        for (auto& p : perms) {\n            candidates.push_back(build_from_order(ord, p));\n        }\n    }\n\n    // Recursive geometric bisection candidates.\n    for (int v = 0; v < 4; v++) {\n        candidates.push_back(make_recursive_candidate(v));\n    }\n\n    double bestScore = 1e100;\n    vector<vector<int>> groups;\n\n    for (auto& cand : candidates) {\n        double sc = total_mst_cost(cand);\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = cand;\n        }\n    }\n\n    // Local city-swap improvement.\n    vector<int> cityGroup(N), cityPos(N);\n    vector<double> groupCost(M);\n    for (int gid = 0; gid < M; gid++) {\n        for (int p = 0; p < (int)groups[gid].size(); p++) {\n            cityGroup[groups[gid][p]] = gid;\n            cityPos[groups[gid][p]] = p;\n        }\n        groupCost[gid] = mst_cost(groups[gid]);\n    }\n\n    const int KNN = 16;\n    vector<vector<int>> knn(N);\n    for (int i = 0; i < N; i++) {\n        vector<pair<double,int>> v;\n        v.reserve(N - 1);\n        for (int j = 0; j < N; j++) {\n            if (i == j) continue;\n            v.push_back({edist(i, j), j});\n        }\n        sort(v.begin(), v.end());\n        int lim = min(KNN, (int)v.size());\n        for (int k = 0; k < lim; k++) knn[i].push_back(v[k].second);\n    }\n\n    auto mst_cost_with_swap = [&](int gid, int outCity, int inCity) {\n        vector<int> tmp = groups[gid];\n        int p = cityPos[outCity];\n        tmp[p] = inCity;\n        return mst_cost(tmp);\n    };\n\n    for (int pass = 0; pass < 4; pass++) {\n        if (timer.sec() > 1.25) break;\n\n        vector<double> gx(M, 0.0), gy(M, 0.0);\n        for (int gid = 0; gid < M; gid++) {\n            for (int v : groups[gid]) {\n                gx[gid] += cx[v];\n                gy[gid] += cy[v];\n            }\n            if (!groups[gid].empty()) {\n                gx[gid] /= groups[gid].size();\n                gy[gid] /= groups[gid].size();\n            }\n        }\n\n        struct Cand {\n            double approx;\n            int a, b;\n        };\n\n        vector<Cand> sw;\n        unordered_set<unsigned long long> seen;\n        seen.reserve(N * KNN * 2);\n\n        for (int a = 0; a < N; a++) {\n            int ga = cityGroup[a];\n            for (int b : knn[a]) {\n                int gb = cityGroup[b];\n                if (ga == gb) continue;\n\n                int u = min(a, b), v = max(a, b);\n                unsigned long long key = ekey(u, v);\n                if (seen.count(key)) continue;\n                seen.insert(key);\n\n                double da1 = sqrt(dist2p(cx[a], cy[a], gx[ga], gy[ga]));\n                double db1 = sqrt(dist2p(cx[b], cy[b], gx[gb], gy[gb]));\n                double da2 = sqrt(dist2p(cx[a], cy[a], gx[gb], gy[gb]));\n                double db2 = sqrt(dist2p(cx[b], cy[b], gx[ga], gy[ga]));\n                double approx = da2 + db2 - da1 - db1;\n\n                if (approx < 300.0) {\n                    sw.push_back({approx, a, b});\n                }\n            }\n        }\n\n        sort(sw.begin(), sw.end(), [](const Cand& x, const Cand& y) {\n            return x.approx < y.approx;\n        });\n\n        if ((int)sw.size() > 6000) sw.resize(6000);\n\n        bool changed = false;\n\n        for (auto c : sw) {\n            if (timer.sec() > 1.45) break;\n\n            int a = c.a, b = c.b;\n            int ga = cityGroup[a], gb = cityGroup[b];\n            if (ga == gb) continue;\n\n            double oldCost = groupCost[ga] + groupCost[gb];\n            double na = mst_cost_with_swap(ga, a, b);\n            double nb = mst_cost_with_swap(gb, b, a);\n            double newCost = na + nb;\n\n            if (newCost + 1e-7 < oldCost) {\n                int pa = cityPos[a], pb = cityPos[b];\n\n                groups[ga][pa] = b;\n                groups[gb][pb] = a;\n\n                cityGroup[a] = gb;\n                cityGroup[b] = ga;\n                cityPos[a] = pb;\n                cityPos[b] = pa;\n\n                groupCost[ga] = na;\n                groupCost[gb] = nb;\n\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    // Backup estimated MST edges after refinement.\n    vector<vector<pair<int,int>>> backupEdges(M);\n    for (int gid = 0; gid < M; gid++) {\n        backupEdges[gid] = prim_edges(groups[gid]);\n    }\n\n    vector<vector<pair<int,int>>> finalEdges(M);\n    vector<unordered_map<unsigned long long,int>> oracleEdges(M);\n\n    struct PlannedQuery {\n        int gid;\n        vector<int> cities;\n        bool exactSmall;\n    };\n\n    vector<PlannedQuery> queries;\n    unordered_set<string> usedSubset;\n    usedSubset.reserve(2000);\n\n    auto add_query = [&](int gid, const vector<int>& c, bool exactSmall) -> bool {\n        if ((int)queries.size() >= Q) return false;\n        if ((int)c.size() < 2 || (int)c.size() > L) return false;\n\n        string key = subset_key(c);\n        if (usedSubset.count(key)) return false;\n        usedSubset.insert(key);\n\n        queries.push_back({gid, c, exactSmall});\n        return true;\n    };\n\n    // Exact whole-group queries for small groups.\n    vector<int> smallIds;\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n        if (3 <= g && g <= L) smallIds.push_back(gid);\n    }\n\n    sort(smallIds.begin(), smallIds.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    for (int gid : smallIds) {\n        add_query(gid, groups[gid], true);\n    }\n\n    // Large groups: local nearest-neighbor / long-edge queries.\n    vector<int> largeIds;\n    for (int gid = 0; gid < M; gid++) {\n        if ((int)groups[gid].size() > L) largeIds.push_back(gid);\n    }\n\n    sort(largeIds.begin(), largeIds.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    vector<vector<pair<double,pair<int,int>>>> longEdges(M);\n    for (int gid : largeIds) {\n        for (auto [a, b] : backupEdges[gid]) {\n            longEdges[gid].push_back({edist(a, b), {a, b}});\n        }\n        sort(longEdges[gid].begin(), longEdges[gid].end(), [](auto& x, auto& y) {\n            return x.first > y.first;\n        });\n    }\n\n    int round = 0;\n    while ((int)queries.size() < Q && !largeIds.empty()) {\n        bool any = false;\n\n        for (int gid : largeIds) {\n            if ((int)queries.size() >= Q) break;\n\n            int g = groups[gid].size();\n            vector<int> sub;\n\n            if (round % 2 == 0) {\n                int idx = (round / 2) % g;\n                int seed = groups[gid][idx];\n                sub = nearest_subset_to_seed(groups[gid], seed);\n            } else {\n                int idx = (round / 2);\n                if (idx < (int)longEdges[gid].size()) {\n                    auto [a, b] = longEdges[gid][idx].second;\n                    sub = nearest_subset_to_edge(groups[gid], a, b);\n                } else {\n                    int seed = groups[gid][idx % g];\n                    sub = nearest_subset_to_seed(groups[gid], seed);\n                }\n            }\n\n            if (add_query(gid, sub, false)) any = true;\n        }\n\n        round++;\n        if (!any && round > 2 * N + 20) break;\n    }\n\n    // Execute queries.\n    for (auto& qu : queries) {\n        auto ret = do_query(qu.cities);\n        int gid = qu.gid;\n\n        for (auto [a, b] : ret) {\n            oracleEdges[gid][ekey(a, b)]++;\n        }\n\n        if (qu.exactSmall) {\n            finalEdges[gid] = ret;\n        }\n    }\n\n    // Construct final road sets.\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n\n        if (g <= 1) {\n            finalEdges[gid].clear();\n        } else if (g == 2) {\n            finalEdges[gid] = {{groups[gid][0], groups[gid][1]}};\n        } else if (g <= L && !finalEdges[gid].empty()) {\n            // Exact MST already obtained.\n        } else {\n            struct EdgeCand {\n                double w;\n                int a, b;\n            };\n\n            vector<EdgeCand> cand;\n\n            for (auto& kv : oracleEdges[gid]) {\n                auto [a, b] = decode_key(kv.first);\n                int cnt = kv.second;\n                double factor = 0.62 - 0.04 * min(4, cnt - 1);\n                cand.push_back({edist(a, b) * factor, a, b});\n            }\n\n            for (auto [a, b] : backupEdges[gid]) {\n                cand.push_back({edist(a, b), a, b});\n            }\n\n            // Add a few nearest-neighbor backup edges inside the group.\n            // This gives Kruskal more choices when oracle edges are sparse.\n            for (int a : groups[gid]) {\n                vector<pair<double,int>> near;\n                for (int b : groups[gid]) {\n                    if (a == b) continue;\n                    near.push_back({edist(a, b), b});\n                }\n                sort(near.begin(), near.end());\n                int lim = min(3, (int)near.size());\n                for (int i = 0; i < lim; i++) {\n                    int b = near[i].second;\n                    cand.push_back({near[i].first * 1.03, a, b});\n                }\n            }\n\n            sort(cand.begin(), cand.end(), [](const EdgeCand& x, const EdgeCand& y) {\n                if (x.w != y.w) return x.w < y.w;\n                if (x.a != y.a) return x.a < y.a;\n                return x.b < y.b;\n            });\n\n            DSU dsu(N);\n            vector<pair<int,int>> tree;\n            tree.reserve(g - 1);\n\n            for (auto& e : cand) {\n                if (dsu.unite(e.a, e.b)) {\n                    tree.push_back({e.a, e.b});\n                    if ((int)tree.size() == g - 1) break;\n                }\n            }\n\n            if ((int)tree.size() != g - 1) {\n                tree = backupEdges[gid];\n            }\n\n            finalEdges[gid] = tree;\n        }\n    }\n\n    cout << \"!\" << '\\n';\n\n    for (int gid = 0; gid < M; gid++) {\n        for (int i = 0; i < (int)groups[gid].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[gid][i];\n        }\n        cout << '\\n';\n\n        for (auto [a, b] : finalEdges[gid]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Act {\n    char a, d;\n};\n\nconst int MAXC = 400;\nconst int INF = 1e9;\n\nint N, M;\nvector<int> pos_id;\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\ninline int id(int r, int c) { return r * N + c; }\ninline int rr(int x) { return x / N; }\ninline int cc(int x) { return x % N; }\ninline bool inside(int r, int c) { return 0 <= r && r < N && 0 <= c && c < N; }\n\nstruct BFSRes {\n    array<int, MAXC> dist;\n    array<int, MAXC> par;\n    array<char, MAXC> pact;\n    array<char, MAXC> pdir;\n};\n\nbool blocked(const bitset<MAXC>& g, int r, int c) {\n    if (!inside(r, c)) return true;\n    return g[id(r, c)];\n}\n\nint slide_stop(const bitset<MAXC>& g, int s, int dir) {\n    int r = rr(s), c = cc(s);\n    while (true) {\n        int nr = r + dr[dir], nc = c + dc[dir];\n        if (blocked(g, nr, nc)) break;\n        r = nr;\n        c = nc;\n    }\n    return id(r, c);\n}\n\n// forbid_stop: this cell must not be stopped on / moved onto as an intermediate target.\n// Sliding over it is allowed.\nBFSRes forward_bfs(const bitset<MAXC>& g, int start, int forbid_stop = -1) {\n    BFSRes res;\n    res.dist.fill(INF);\n    res.par.fill(-1);\n    res.pact.fill(0);\n    res.pdir.fill(0);\n\n    queue<int> q;\n    res.dist[start] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            // Move\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (to != forbid_stop && res.dist[to] == INF) {\n                    res.dist[to] = res.dist[v] + 1;\n                    res.par[to] = v;\n                    res.pact[to] = 'M';\n                    res.pdir[to] = dch[d];\n                    q.push(to);\n                }\n            }\n\n            // Slide\n            int to = slide_stop(g, v, d);\n            if (to != v && to != forbid_stop && res.dist[to] == INF) {\n                res.dist[to] = res.dist[v] + 1;\n                res.par[to] = v;\n                res.pact[to] = 'S';\n                res.pdir[to] = dch[d];\n                q.push(to);\n            }\n        }\n    }\n\n    return res;\n}\n\narray<int, MAXC> reverse_bfs_dist(const bitset<MAXC>& g, int target) {\n    array<int, MAXC> dist;\n    dist.fill(INF);\n    if (g[target]) return dist;\n\n    queue<int> q;\n    dist[target] = 0;\n    q.push(target);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            // Reverse of Move d: predecessor is v - d\n            int pr = r - dr[d], pc = c - dc[d];\n            if (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n            }\n\n            // Reverse of Slide d.\n            // v can be a slide stop in direction d only if the next cell is blocked/outside.\n            int br = r + dr[d], bc = c + dc[d];\n            if (!blocked(g, br, bc)) continue;\n\n            pr = r - dr[d];\n            pc = c - dc[d];\n            while (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n                pr -= dr[d];\n                pc -= dc[d];\n            }\n        }\n    }\n\n    return dist;\n}\n\nvector<Act> restore_forward(const BFSRes& bfs, int start, int goal) {\n    vector<Act> rev;\n    int cur = goal;\n    while (cur != start) {\n        rev.push_back({bfs.pact[cur], bfs.pdir[cur]});\n        cur = bfs.par[cur];\n        if (cur < 0) return {};\n    }\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nvector<Act> restore_by_reverse_dist(const bitset<MAXC>& g, const array<int, MAXC>& dist, int start, int target) {\n    vector<Act> ret;\n    int cur = start;\n\n    while (cur != target) {\n        bool found = false;\n        int cd = dist[cur];\n\n        for (int d = 0; d < 4 && !found; d++) {\n            int r = rr(cur), c = cc(cur);\n\n            // Move\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (dist[to] == cd - 1) {\n                    ret.push_back({'M', dch[d]});\n                    cur = to;\n                    found = true;\n                    break;\n                }\n            }\n\n            // Slide\n            int to = slide_stop(g, cur, d);\n            if (to != cur && dist[to] == cd - 1) {\n                ret.push_back({'S', dch[d]});\n                cur = to;\n                found = true;\n                break;\n            }\n        }\n\n        if (!found) {\n            // Should not happen.\n            ret.clear();\n            return ret;\n        }\n    }\n\n    return ret;\n}\n\nint dir_from_to(int p, int b) {\n    int pr = rr(p), pc = cc(p);\n    int br = rr(b), bc = cc(b);\n    for (int d = 0; d < 4; d++) {\n        if (pr + dr[d] == br && pc + dc[d] == bc) return d;\n    }\n    return -1;\n}\n\nstruct State {\n    bitset<MAXC> grid;\n    int cost;\n    vector<Act> acts;\n};\n\nstruct Option {\n    int cost;\n    int b;\n    int p;\n};\n\nvector<State> expand_state(\n    const State& st,\n    int start,\n    int target,\n    const bitset<MAXC>& future_target_mask\n) {\n    constexpr int TOP_K = 5;\n    constexpr int ALLOW_EXTRA = 4;\n\n    vector<State> res;\n\n    BFSRes bfs_normal = forward_bfs(st.grid, start, -1);\n    BFSRes bfs_avoid = forward_bfs(st.grid, start, target);\n\n    int base_cost = bfs_normal.dist[target];\n\n    // Baseline: no alteration.\n    if (base_cost < INF) {\n        State ns;\n        ns.grid = st.grid;\n        ns.acts = st.acts;\n        auto path = restore_forward(bfs_normal, start, target);\n        ns.acts.insert(ns.acts.end(), path.begin(), path.end());\n        ns.cost = (int)ns.acts.size();\n        res.push_back(std::move(ns));\n    }\n\n    vector<Option> opts;\n\n    for (int b = 0; b < N * N; b++) {\n        bool is_block = st.grid[b];\n\n        // Avoid placing a new block on current/future target squares.\n        if (!is_block && future_target_mask[b]) continue;\n\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(b);\n        if (g2[target]) continue;\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n\n        int best_cost = INF;\n        int best_p = -1;\n\n        int br = rr(b), bc = cc(b);\n        for (int d = 0; d < 4; d++) {\n            int pr = br - dr[d], pc = bc - dc[d];\n            if (!inside(pr, pc)) continue;\n\n            int p = id(pr, pc);\n            if (p == b) continue;\n            if (st.grid[p]) continue;\n            if (g2[p]) continue;\n            if (bfs_avoid.dist[p] >= INF) continue;\n            if (dist_to_target[p] >= INF) continue;\n\n            int cand = bfs_avoid.dist[p] + 1 + dist_to_target[p];\n            if (cand < best_cost) {\n                best_cost = cand;\n                best_p = p;\n            }\n        }\n\n        if (best_p == -1) continue;\n        if (base_cost < INF && best_cost > base_cost + ALLOW_EXTRA) continue;\n\n        opts.push_back({best_cost, b, best_p});\n    }\n\n    sort(opts.begin(), opts.end(), [](const Option& x, const Option& y) {\n        return x.cost < y.cost;\n    });\n    if ((int)opts.size() > TOP_K) opts.resize(TOP_K);\n\n    for (const auto& op : opts) {\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(op.b);\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n        if (dist_to_target[op.p] >= INF) continue;\n\n        State ns;\n        ns.grid = g2;\n        ns.acts = st.acts;\n\n        auto path1 = restore_forward(bfs_avoid, start, op.p);\n        ns.acts.insert(ns.acts.end(), path1.begin(), path1.end());\n\n        int ad = dir_from_to(op.p, op.b);\n        if (ad < 0) continue;\n        ns.acts.push_back({'A', dch[ad]});\n\n        auto path2 = restore_by_reverse_dist(g2, dist_to_target, op.p, target);\n        if (path2.empty() && op.p != target) continue;\n        ns.acts.insert(ns.acts.end(), path2.begin(), path2.end());\n\n        ns.cost = (int)ns.acts.size();\n        res.push_back(std::move(ns));\n    }\n\n    return res;\n}\n\nvector<Act> simple_fallback() {\n    vector<Act> ret;\n    int cur = pos_id[0];\n\n    for (int k = 1; k < M; k++) {\n        int t = pos_id[k];\n\n        int r = rr(cur), c = cc(cur);\n        int tr = rr(t), tc = cc(t);\n\n        while (r < tr) {\n            ret.push_back({'M', 'D'});\n            r++;\n        }\n        while (r > tr) {\n            ret.push_back({'M', 'U'});\n            r--;\n        }\n        while (c < tc) {\n            ret.push_back({'M', 'R'});\n            c++;\n        }\n        while (c > tc) {\n            ret.push_back({'M', 'L'});\n            c--;\n        }\n\n        cur = t;\n    }\n\n    return ret;\n}\n\nbool simulate(const vector<Act>& acts) {\n    if ((int)acts.size() > 2 * N * M) return false;\n\n    bitset<MAXC> g;\n    int cur = pos_id[0];\n    int nxt = 1;\n\n    auto dir_index = [](char c) {\n        if (c == 'U') return 0;\n        if (c == 'D') return 1;\n        if (c == 'L') return 2;\n        return 3;\n    };\n\n    for (auto [a, ch] : acts) {\n        int d = dir_index(ch);\n        int r = rr(cur), c = cc(cur);\n\n        if (a == 'M') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n            int to = id(nr, nc);\n            if (g[to]) return false;\n            cur = to;\n\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'S') {\n            while (true) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (!inside(nr, nc) || g[id(nr, nc)]) break;\n                r = nr;\n                c = nc;\n            }\n            cur = id(r, c);\n\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'A') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n            int b = id(nr, nc);\n            g.flip(b);\n        } else {\n            return false;\n        }\n    }\n\n    return nxt == M;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    pos_id.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        int r, c;\n        cin >> r >> c;\n        pos_id[k] = id(r, c);\n    }\n\n    vector<bitset<MAXC>> future_mask(M + 1);\n    for (int k = M - 1; k >= 0; k--) {\n        future_mask[k] = future_mask[k + 1];\n        future_mask[k].set(pos_id[k]);\n    }\n\n    constexpr int BEAM_W = 4;\n\n    vector<State> beam;\n    State init;\n    init.grid.reset();\n    init.cost = 0;\n    beam.push_back(init);\n\n    for (int leg = 1; leg < M; leg++) {\n        int start = pos_id[leg - 1];\n        int target = pos_id[leg];\n\n        vector<State> nxt_states;\n\n        for (const auto& st : beam) {\n            auto ex = expand_state(st, start, target, future_mask[leg]);\n            for (auto& ns : ex) nxt_states.push_back(std::move(ns));\n        }\n\n        sort(nxt_states.begin(), nxt_states.end(), [](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        vector<State> nb;\n        for (auto& st : nxt_states) {\n            bool dup = false;\n            for (const auto& kept : nb) {\n                if (kept.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (dup) continue;\n\n            nb.push_back(std::move(st));\n            if ((int)nb.size() >= BEAM_W) break;\n        }\n\n        if (nb.empty()) {\n            auto fb = simple_fallback();\n            for (auto [a, d] : fb) cout << a << ' ' << d << '\\n';\n            return 0;\n        }\n\n        beam = std::move(nb);\n    }\n\n    vector<Act> ans = beam[0].acts;\n\n    if (!simulate(ans)) {\n        ans = simple_fallback();\n    }\n\n    for (auto [a, d] : ans) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#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 Rect {\n    int a, b, c, d;\n};\n\nstruct Blocker {\n    int id;\n    int gap;\n    int limit;\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\nvector<long double> wt;\nmt19937 rng(1234567);\nTimer timer_;\n\nlong long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\ndouble score_area(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    double q = (double)min(s, r) / (double)max(s, r);\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble evaluate(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; i++) {\n        const Rect& e = rects[i];\n        if (e.a <= xs[i] && xs[i] + 1 <= e.c && e.b <= ys[i] && ys[i] + 1 <= e.d) {\n            sum += score_area(area(e), rs[i]);\n        }\n    }\n    return sum;\n}\n\nbool overlap1d(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\n/* ---------- recursive slicing construction ---------- */\n\nstruct SplitCand {\n    int axis; // 0:x, 1:y\n    int k;\n    int cut;\n    double cost;\n};\n\nvoid build_rec(const vector<int>& ids, int L, int B, int R, int T, vector<Rect>& out, int topK) {\n    int m = (int)ids.size();\n\n    if (m == 1) {\n        out[ids[0]] = {L, B, R, T};\n        return;\n    }\n\n    long double totalTarget = 0;\n    for (int id : ids) totalTarget += wt[id];\n\n    long long regionArea = 1LL * (R - L) * (T - B);\n    vector<SplitCand> cands;\n\n    for (int axis = 0; axis < 2; axis++) {\n        vector<int> v = ids;\n\n        if (axis == 0) {\n            sort(v.begin(), v.end(), [&](int p, int q) {\n                if (xs[p] != xs[q]) return xs[p] < xs[q];\n                return ys[p] < ys[q];\n            });\n        } else {\n            sort(v.begin(), v.end(), [&](int p, int q) {\n                if (ys[p] != ys[q]) return ys[p] < ys[q];\n                return xs[p] < xs[q];\n            });\n        }\n\n        vector<long double> pref(m + 1, 0);\n        for (int i = 0; i < m; i++) pref[i + 1] = pref[i] + wt[v[i]];\n\n        for (int k = 1; k < m; k++) {\n            int coordL = (axis == 0 ? xs[v[k - 1]] : ys[v[k - 1]]);\n            int coordR = (axis == 0 ? xs[v[k]] : ys[v[k]]);\n            if (coordL >= coordR) continue;\n\n            int start = (axis == 0 ? L : B);\n            int end = (axis == 0 ? R : T);\n            int otherLen = (axis == 0 ? T - B : R - L);\n            int len = end - start;\n\n            int lo = max(coordL + 1, start + 1);\n            int hi = min(coordR, end - 1);\n            if (lo > hi) continue;\n\n            long double ratio = pref[k] / totalTarget;\n            int desired = (int)llround((long double)start + ratio * len);\n            int cut = min(max(desired, lo), hi);\n\n            long long leftArea = 1LL * (cut - start) * otherLen;\n            long long rightArea = regionArea - leftArea;\n\n            long double leftTarget = pref[k];\n            long double rightTarget = totalTarget - leftTarget;\n            long double scale = (long double)regionArea / totalTarget;\n\n            double er1 = fabs((double)((long double)leftArea / leftTarget - scale));\n            double er2 = fabs((double)((long double)rightArea / rightTarget - scale));\n            double cost = er1 * (double)(leftTarget / totalTarget)\n                        + er2 * (double)(rightTarget / totalTarget);\n\n            if (k == 1) {\n                int id = v[0];\n                cost += 0.08 * (1.0 - score_area(leftArea, rs[id]));\n            }\n            if (m - k == 1) {\n                int id = v[m - 1];\n                cost += 0.08 * (1.0 - score_area(rightArea, rs[id]));\n            }\n\n            cands.push_back({axis, k, cut, cost});\n        }\n    }\n\n    if (cands.empty()) {\n        vector<int> v = ids;\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (xs[p] != xs[q]) return xs[p] < xs[q];\n            return ys[p] < ys[q];\n        });\n\n        int k = m / 2;\n        int cut = (L + R) / 2;\n        cut = min(max(cut, L + 1), R - 1);\n\n        vector<int> A(v.begin(), v.begin() + k), C(v.begin() + k, v.end());\n        build_rec(A, L, B, cut, T, out, topK);\n        build_rec(C, cut, B, R, T, out, topK);\n        return;\n    }\n\n    sort(cands.begin(), cands.end(), [](const SplitCand& x, const SplitCand& y) {\n        return x.cost < y.cost;\n    });\n\n    int pick = 0;\n    if (topK > 1) {\n        int lim = min<int>(topK, cands.size());\n        double u = uniform_real_distribution<double>(0.0, 1.0)(rng);\n        pick = min(lim - 1, (int)(u * u * lim));\n    }\n\n    SplitCand ch = cands[pick];\n\n    vector<int> v = ids;\n    if (ch.axis == 0) {\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (xs[p] != xs[q]) return xs[p] < xs[q];\n            return ys[p] < ys[q];\n        });\n    } else {\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (ys[p] != ys[q]) return ys[p] < ys[q];\n            return xs[p] < xs[q];\n        });\n    }\n\n    vector<int> left(v.begin(), v.begin() + ch.k);\n    vector<int> right(v.begin() + ch.k, v.end());\n\n    if (ch.axis == 0) {\n        build_rec(left, L, B, ch.cut, T, out, topK);\n        build_rec(right, ch.cut, B, R, T, out, topK);\n    } else {\n        build_rec(left, L, B, R, ch.cut, out, topK);\n        build_rec(right, L, ch.cut, R, T, out, topK);\n    }\n}\n\nvector<Rect> build_slicing(int topK, double noise) {\n    wt.assign(n, 0);\n\n    if (noise <= 0) {\n        for (int i = 0; i < n; i++) wt[i] = rs[i];\n    } else {\n        normal_distribution<double> nd(0.0, noise);\n        for (int i = 0; i < n; i++) {\n            double mul = exp(nd(rng));\n            mul = min(1.45, max(0.70, mul));\n            wt[i] = (long double)rs[i] * mul;\n        }\n    }\n\n    vector<Rect> res(n);\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    build_rec(ids, 0, 0, 10000, 10000, res, topK);\n    return res;\n}\n\n/* ---------- local improvement ---------- */\n\nbool shrink_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect cur = rects[id];\n        long long A = area(cur);\n        double curScore = score_area(A, rs[id]);\n\n        Rect best = cur;\n        double bestGain = 1e-15;\n\n        auto try_delta = [&](int dir, int maxd) {\n            if (maxd <= 0) return;\n\n            int len = (dir < 2 ? cur.d - cur.b : cur.c - cur.a);\n            vector<int> ds;\n\n            long long excess = A - rs[id];\n            if (excess > 0) {\n                long long q = excess / len;\n                for (long long z : {q - 2, q - 1, q, q + 1, q + 2}) {\n                    if (1 <= z && z <= maxd) ds.push_back((int)z);\n                }\n            }\n\n            ds.push_back(1);\n            ds.push_back(maxd);\n            sort(ds.begin(), ds.end());\n            ds.erase(unique(ds.begin(), ds.end()), ds.end());\n\n            for (int dlt : ds) {\n                Rect nr = cur;\n                if (dir == 0) nr.a += dlt;\n                if (dir == 1) nr.c -= dlt;\n                if (dir == 2) nr.b += dlt;\n                if (dir == 3) nr.d -= dlt;\n\n                if (!(nr.a < nr.c && nr.b < nr.d)) continue;\n                if (!(nr.a <= xs[id] && xs[id] + 1 <= nr.c && nr.b <= ys[id] && ys[id] + 1 <= nr.d)) continue;\n\n                double gain = score_area(area(nr), rs[id]) - curScore;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = nr;\n                }\n            }\n        };\n\n        try_delta(0, xs[id] - cur.a);\n        try_delta(1, cur.c - (xs[id] + 1));\n        try_delta(2, ys[id] - cur.b);\n        try_delta(3, cur.d - (ys[id] + 1));\n\n        if (bestGain > 1e-14) {\n            rects[id] = best;\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nint max_expand_delta(const vector<Rect>& rects, int id, int dir) {\n    const Rect& r = rects[id];\n    int lim;\n\n    if (dir == 0) {\n        lim = r.a;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.b, r.d, o.b, o.d) && o.c <= r.a) {\n                lim = min(lim, r.a - o.c);\n            }\n        }\n    } else if (dir == 1) {\n        lim = 10000 - r.c;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.b, r.d, o.b, o.d) && o.a >= r.c) {\n                lim = min(lim, o.a - r.c);\n            }\n        }\n    } else if (dir == 2) {\n        lim = r.b;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.a, r.c, o.a, o.c) && o.d <= r.b) {\n                lim = min(lim, r.b - o.d);\n            }\n        }\n    } else {\n        lim = 10000 - r.d;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.a, r.c, o.a, o.c) && o.b >= r.d) {\n                lim = min(lim, o.b - r.d);\n            }\n        }\n    }\n\n    return lim;\n}\n\nbool expand_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect cur = rects[id];\n        long long A = area(cur);\n        double curScore = score_area(A, rs[id]);\n\n        Rect best = cur;\n        double bestGain = 1e-15;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int maxd = max_expand_delta(rects, id, dir);\n            if (maxd <= 0) continue;\n\n            int len = (dir < 2 ? cur.d - cur.b : cur.c - cur.a);\n            vector<int> ds;\n\n            long long need = rs[id] - A;\n            if (need > 0) {\n                long long q = need / len;\n                for (long long z : {q - 2, q - 1, q, q + 1, q + 2}) {\n                    if (1 <= z && z <= maxd) ds.push_back((int)z);\n                }\n            }\n\n            ds.push_back(1);\n            ds.push_back(maxd);\n            sort(ds.begin(), ds.end());\n            ds.erase(unique(ds.begin(), ds.end()), ds.end());\n\n            for (int dlt : ds) {\n                Rect nr = cur;\n                if (dir == 0) nr.a -= dlt;\n                if (dir == 1) nr.c += dlt;\n                if (dir == 2) nr.b -= dlt;\n                if (dir == 3) nr.d += dlt;\n\n                double gain = score_area(area(nr), rs[id]) - curScore;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = nr;\n                }\n            }\n        }\n\n        if (bestGain > 1e-14) {\n            rects[id] = best;\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nbool steal_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect r = rects[id];\n        long long Ai = area(r);\n        double oldSi = score_area(Ai, rs[id]);\n\n        int bestDir = -1;\n        int bestD = 0;\n        double bestGain = 1e-13;\n\n        for (int dir = 0; dir < 4; dir++) {\n            vector<Blocker> bs;\n            int maxD;\n            int lenI = (dir < 2 ? r.d - r.b : r.c - r.a);\n\n            if (dir == 0) {\n                maxD = r.a;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.b, r.d, o.b, o.d) && o.c <= r.a) {\n                        int gap = r.a - o.c;\n                        int lim = r.a - (xs[j] + 1);\n                        bs.push_back({j, gap, lim});\n                        maxD = min(maxD, lim);\n                    }\n                }\n            } else if (dir == 1) {\n                maxD = 10000 - r.c;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.b, r.d, o.b, o.d) && o.a >= r.c) {\n                        int gap = o.a - r.c;\n                        int lim = xs[j] - r.c;\n                        bs.push_back({j, gap, lim});\n                        maxD = min(maxD, lim);\n                    }\n                }\n            } else if (dir == 2) {\n                maxD = r.b;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.a, r.c, o.a, o.c) && o.d <= r.b) {\n                        int gap = r.b - o.d;\n                        int lim = r.b - (ys[j] + 1);\n                        bs.push_back({j, gap, lim});\n                        maxD = min(maxD, lim);\n                    }\n                }\n            } else {\n                maxD = 10000 - r.d;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.a, r.c, o.a, o.c) && o.b >= r.d) {\n                        int gap = o.b - r.d;\n                        int lim = ys[j] - r.d;\n                        bs.push_back({j, gap, lim});\n                        maxD = min(maxD, lim);\n                    }\n                }\n            }\n\n            if (maxD <= 0) continue;\n\n            vector<int> cand;\n\n            auto add_one = [&](long long x) {\n                if (1 <= x && x <= maxD) cand.push_back((int)x);\n            };\n\n            auto add_near = [&](long long x) {\n                for (long long y : {x - 3, x - 2, x - 1, x, x + 1, x + 2, x + 3}) {\n                    add_one(y);\n                }\n            };\n\n            add_one(1);\n            add_one(maxD);\n            add_one(maxD / 2);\n            add_one(maxD / 3);\n            add_one(2LL * maxD / 3);\n\n            long long needI = rs[id] - Ai;\n            if (needI > 0) add_near(needI / lenI);\n\n            for (auto bl : bs) {\n                add_one(bl.gap);       // stop exactly before stealing\n                add_one(bl.gap + 1);   // start stealing\n                add_one(bl.limit);\n\n                int j = bl.id;\n                const Rect& o = rects[j];\n                int lenJ = (dir < 2 ? o.d - o.b : o.c - o.a);\n                long long Aj = area(o);\n\n                if (Aj > rs[j]) {\n                    long long red = Aj - rs[j];\n                    add_near(bl.gap + red / lenJ);\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n            for (int delta : cand) {\n                if (delta <= 0 || delta > maxD) continue;\n\n                double gain = score_area(Ai + 1LL * delta * lenI, rs[id]) - oldSi;\n\n                for (auto bl : bs) {\n                    if (delta <= bl.gap) continue;\n\n                    int j = bl.id;\n                    const Rect& o = rects[j];\n                    long long Aj = area(o);\n                    int lenJ = (dir < 2 ? o.d - o.b : o.c - o.a);\n                    long long nAj = Aj - 1LL * (delta - bl.gap) * lenJ;\n\n                    gain += score_area(nAj, rs[j]) - score_area(Aj, rs[j]);\n                }\n\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestDir = dir;\n                    bestD = delta;\n                }\n            }\n        }\n\n        if (bestDir != -1) {\n            Rect old = rects[id];\n\n            if (bestDir == 0) rects[id].a -= bestD;\n            if (bestDir == 1) rects[id].c += bestD;\n            if (bestDir == 2) rects[id].b -= bestD;\n            if (bestDir == 3) rects[id].d += bestD;\n\n            for (int j = 0; j < n; j++) if (j != id) {\n                Rect& o = rects[j];\n\n                if (bestDir == 0) {\n                    if (overlap1d(old.b, old.d, o.b, o.d) && o.c <= old.a) {\n                        int gap = old.a - o.c;\n                        if (bestD > gap) o.c = old.a - bestD;\n                    }\n                } else if (bestDir == 1) {\n                    if (overlap1d(old.b, old.d, o.b, o.d) && o.a >= old.c) {\n                        int gap = o.a - old.c;\n                        if (bestD > gap) o.a = old.c + bestD;\n                    }\n                } else if (bestDir == 2) {\n                    if (overlap1d(old.a, old.c, o.a, o.c) && o.d <= old.b) {\n                        int gap = old.b - o.d;\n                        if (bestD > gap) o.d = old.b - bestD;\n                    }\n                } else {\n                    if (overlap1d(old.a, old.c, o.a, o.c) && o.b >= old.d) {\n                        int gap = o.b - old.d;\n                        if (bestD > gap) o.b = old.d + bestD;\n                    }\n                }\n            }\n\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nvoid shrink_only(vector<Rect>& rects, double deadline) {\n    for (int it = 0; it < 20 && timer_.elapsed() < deadline; it++) {\n        if (!shrink_pass(rects, false, deadline)) break;\n    }\n}\n\nvoid improve_solution(vector<Rect>& rects, double deadline) {\n    for (int it = 0; timer_.elapsed() < deadline; it++) {\n        bool moved = false;\n        moved |= shrink_pass(rects, true, deadline);\n        moved |= steal_pass(rects, true, deadline);\n        moved |= expand_pass(rects, true, deadline);\n        if (!moved) break;\n    }\n}\n\nvector<Rect> unit_solution() {\n    vector<Rect> sol(n);\n    for (int i = 0; i < n; i++) {\n        sol[i] = {xs[i], ys[i], xs[i] + 1, ys[i] + 1};\n    }\n    return sol;\n}\n\n/* ---------- main ---------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n\n    for (int i = 0; i < n; i++) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    vector<Rect> best = unit_solution();\n    double bestScore = evaluate(best);\n\n    auto consider_best = [&](const vector<Rect>& sol) {\n        double sc = evaluate(sol);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = sol;\n        }\n    };\n\n    vector<pair<double, vector<Rect>>> tops;\n\n    auto insert_top = [&](vector<Rect> sol) {\n        double sc = evaluate(sol);\n        tops.push_back({sc, sol});\n        sort(tops.begin(), tops.end(), [](const auto& p, const auto& q) {\n            return p.first > q.first;\n        });\n        if ((int)tops.size() > 8) tops.pop_back();\n        consider_best(sol);\n    };\n\n    int cnt = 0;\n\n    while (timer_.elapsed() < 2.85) {\n        int topK;\n        if (cnt == 0) topK = 1;\n        else if (cnt % 5 == 0) topK = 3;\n        else if (cnt % 5 == 1) topK = 5;\n        else topK = 10;\n\n        double noise = 0.0;\n        if (cnt > 0) {\n            if (cnt % 3 == 0) noise = 0.06;\n            else if (cnt % 3 == 1) noise = 0.10;\n            else noise = 0.14;\n        }\n\n        vector<Rect> sol = build_slicing(topK, noise);\n        shrink_only(sol, 2.85);\n        insert_top(sol);\n\n        cnt++;\n    }\n\n    sort(tops.begin(), tops.end(), [](const auto& p, const auto& q) {\n        return p.first > q.first;\n    });\n\n    int m = (int)tops.size();\n    for (int i = 0; i < m && timer_.elapsed() < 4.76; i++) {\n        vector<Rect> sol = tops[i].second;\n        double remain = 4.76 - timer_.elapsed();\n        double deadline = timer_.elapsed() + remain / max(1, m - i);\n        improve_solution(sol, deadline);\n        consider_best(sol);\n    }\n\n    if (timer_.elapsed() < 4.90) {\n        vector<Rect> sol = unit_solution();\n        improve_solution(sol, 4.90);\n        consider_best(sol);\n    }\n\n    // Safe monotone final polishing of the currently best solution.\n    if (timer_.elapsed() < 4.96) {\n        improve_solution(best, 4.96);\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' ' << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int V = N * N;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\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\nstruct Path {\n    int score = 0;\n    vector<int> cells;\n    string moves;\n};\n\nstruct Params {\n    double wp;\n    double wd;\n    double w1;\n    double w2;\n    double noise;\n    double randomMoveProb;\n};\n\nint si, sj;\nint tile_id[V];\nint point_val[V];\nint nb[V][4];\nchar nb_dir[V][4];\n\nPath best_path;\nvector<Path> pool;\n\nParams make_params(XorShift &rng) {\n    Params p;\n    int mode = rng.nextInt(10);\n\n    if (mode == 0) {\n        p = {1.8, 4.0, 0.22, 0.08, 30.0, 0.02};\n    } else if (mode == 1) {\n        p = {1.0, -24.0, 0.12, 0.05, 45.0, 0.03};\n    } else if (mode == 2) {\n        p = {1.2, 8.0, 0.36, 0.11, 55.0, 0.04};\n    } else if (mode == 3) {\n        p = {1.0, 0.0, 0.16, 0.05, 120.0, 0.12};\n    } else if (mode == 4) {\n        p = {0.85, -34.0, 0.07, 0.03, 60.0, 0.04};\n    } else if (mode == 5) {\n        p = {1.0, 18.0, 0.46, 0.15, 45.0, 0.02};\n    } else if (mode == 6) {\n        p = {2.4, -8.0, 0.26, 0.08, 40.0, 0.02};\n    } else if (mode == 7) {\n        p = {0.9, 2.0, 0.12, 0.04, 160.0, 0.15};\n    } else if (mode == 8) {\n        p = {1.5, -16.0, 0.28, 0.12, 35.0, 0.02};\n    } else {\n        p = {1.1, 26.0, 0.35, 0.20, 65.0, 0.05};\n    }\n\n    p.wp *= 0.75 + rng.nextDouble() * 0.70;\n    p.wd *= 0.75 + rng.nextDouble() * 0.70;\n    p.w1 *= 0.70 + rng.nextDouble() * 0.80;\n    p.w2 *= 0.70 + rng.nextDouble() * 0.80;\n    p.noise *= 0.70 + rng.nextDouble() * 0.80;\n\n    return p;\n}\n\ninline int legal_degree_after(int to, const vector<int> &seen, int mark) {\n    int tid_to = tile_id[to];\n    int d = 0;\n    for (int k = 0; k < 4; k++) {\n        int v = nb[to][k];\n        if (v < 0) continue;\n        int tid = tile_id[v];\n        if (tid == tid_to) continue;\n        if (seen[tid] == mark) continue;\n        d++;\n    }\n    return d;\n}\n\ndouble eval_move(int to, const vector<int> &seen, int mark, const Params &par, XorShift &rng) {\n    int tid_to = tile_id[to];\n\n    int degree1 = 0;\n    int best_next_point = 0;\n    double best_look2 = 0.0;\n\n    for (int k = 0; k < 4; k++) {\n        int v1 = nb[to][k];\n        if (v1 < 0) continue;\n\n        int tid1 = tile_id[v1];\n        if (tid1 == tid_to) continue;\n        if (seen[tid1] == mark) continue;\n\n        degree1++;\n        best_next_point = max(best_next_point, point_val[v1]);\n\n        int degree2 = 0;\n        int best_p2 = 0;\n\n        for (int l = 0; l < 4; l++) {\n            int v2 = nb[v1][l];\n            if (v2 < 0) continue;\n\n            int tid2 = tile_id[v2];\n            if (tid2 == tid_to || tid2 == tid1) continue;\n            if (seen[tid2] == mark) continue;\n\n            degree2++;\n            best_p2 = max(best_p2, point_val[v2]);\n        }\n\n        double look2 = point_val[v1] + 8.0 * degree2 + 0.25 * best_p2;\n        best_look2 = max(best_look2, look2);\n    }\n\n    double e = 0.0;\n    e += par.wp * point_val[to];\n    e += par.wd * degree1;\n    e += par.w1 * best_next_point;\n    e += par.w2 * best_look2;\n    e += par.noise * (rng.nextDouble() - 0.5);\n    return e;\n}\n\nint choose_next(\n    int pos,\n    const vector<int> &seen,\n    int mark,\n    const Params &par,\n    XorShift &rng,\n    char &out_dir\n) {\n    int cand[4];\n    char cdir[4];\n    int cnt = 0;\n\n    for (int k = 0; k < 4; k++) {\n        int to = nb[pos][k];\n        if (to < 0) continue;\n\n        int tid = tile_id[to];\n        if (seen[tid] == mark) continue;\n\n        cand[cnt] = to;\n        cdir[cnt] = nb_dir[pos][k];\n        cnt++;\n    }\n\n    if (cnt == 0) return -1;\n\n    if (cnt == 1) {\n        out_dir = cdir[0];\n        return cand[0];\n    }\n\n    if (rng.nextDouble() < par.randomMoveProb) {\n        int id = rng.nextInt(cnt);\n        out_dir = cdir[id];\n        return cand[id];\n    }\n\n    double best_eval = -1e100;\n    int best_id = 0;\n\n    for (int i = 0; i < cnt; i++) {\n        double e = eval_move(cand[i], seen, mark, par, rng);\n        if (e > best_eval) {\n            best_eval = e;\n            best_id = i;\n        }\n    }\n\n    out_dir = cdir[best_id];\n    return cand[best_id];\n}\n\nvoid consider_path(const Path &p) {\n    if (p.score > best_path.score) {\n        best_path = p;\n    }\n\n    constexpr int POOL_SIZE = 24;\n\n    if ((int)pool.size() < POOL_SIZE) {\n        pool.push_back(p);\n    } else {\n        int worst = 0;\n        for (int i = 1; i < (int)pool.size(); i++) {\n            if (pool[i].score < pool[worst].score) worst = i;\n        }\n        if (p.score > pool[worst].score) {\n            pool[worst] = p;\n        }\n    }\n}\n\nPath build_greedy_from_prefix(\n    const Path *base,\n    int prefix_len,\n    vector<int> &seen,\n    int mark,\n    XorShift &rng\n) {\n    Path cur;\n    cur.cells.reserve(V);\n    cur.moves.reserve(V);\n\n    if (base == nullptr) {\n        int st = si * N + sj;\n        cur.cells.push_back(st);\n        cur.score = point_val[st];\n        seen[tile_id[st]] = mark;\n    } else {\n        prefix_len = max(prefix_len, 1);\n        prefix_len = min(prefix_len, (int)base->cells.size());\n\n        cur.cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n        cur.moves.assign(base->moves.begin(), base->moves.begin() + prefix_len - 1);\n\n        cur.score = 0;\n        for (int c : cur.cells) {\n            cur.score += point_val[c];\n            seen[tile_id[c]] = mark;\n        }\n    }\n\n    Params par = make_params(rng);\n\n    while (true) {\n        int pos = cur.cells.back();\n        char d = '?';\n        int nxt = choose_next(pos, seen, mark, par, rng, d);\n\n        if (nxt < 0) break;\n\n        seen[tile_id[nxt]] = mark;\n        cur.cells.push_back(nxt);\n        cur.moves.push_back(d);\n        cur.score += point_val[nxt];\n    }\n\n    return cur;\n}\n\nstruct DFSSearcher {\n    vector<int> &seen;\n    int mark;\n    XorShift &rng;\n    Timer &timer;\n    double time_limit;\n    Params par;\n\n    vector<int> cur_cells;\n    string cur_moves;\n\n    int nodes = 0;\n    int node_limit = 50000;\n\n    DFSSearcher(\n        vector<int> &seen_,\n        int mark_,\n        XorShift &rng_,\n        Timer &timer_,\n        double time_limit_\n    )\n        : seen(seen_),\n          mark(mark_),\n          rng(rng_),\n          timer(timer_),\n          time_limit(time_limit_) {\n        par = make_params(rng);\n        par.noise *= 0.45;\n        par.randomMoveProb = 0.0;\n    }\n\n    bool time_or_budget_over() {\n        if ((nodes & 2047) == 0) {\n            if (timer.elapsed() > time_limit) return true;\n        }\n        return nodes >= node_limit;\n    }\n\n    bool dfs(int pos, int score) {\n        nodes++;\n\n        if (score > best_path.score) {\n            best_path.score = score;\n            best_path.cells = cur_cells;\n            best_path.moves = cur_moves;\n        }\n\n        if (time_or_budget_over()) return true;\n\n        struct Cand {\n            int to;\n            char dir;\n            double e;\n        };\n\n        Cand cand[4];\n        int cnt = 0;\n\n        for (int k = 0; k < 4; k++) {\n            int to = nb[pos][k];\n            if (to < 0) continue;\n\n            int tid = tile_id[to];\n            if (seen[tid] == mark) continue;\n\n            cand[cnt++] = {to, nb_dir[pos][k], eval_move(to, seen, mark, par, rng)};\n        }\n\n        if (cnt == 0) return false;\n\n        sort(cand, cand + cnt, [](const Cand &a, const Cand &b) {\n            return a.e > b.e;\n        });\n\n        // Occasionally diversify the top choices.\n        if (cnt >= 2 && rng.nextInt(100) < 18) {\n            swap(cand[0], cand[rng.nextInt(cnt)]);\n        }\n\n        for (int i = 0; i < cnt; i++) {\n            int to = cand[i].to;\n            int tid = tile_id[to];\n\n            seen[tid] = mark;\n            cur_cells.push_back(to);\n            cur_moves.push_back(cand[i].dir);\n\n            bool stop = dfs(to, score + point_val[to]);\n\n            cur_moves.pop_back();\n            cur_cells.pop_back();\n            seen[tid] = 0;\n\n            if (stop) return true;\n        }\n\n        return false;\n    }\n\n    void run_from_prefix(const Path *base, int prefix_len) {\n        cur_cells.clear();\n        cur_moves.clear();\n        cur_cells.reserve(V);\n        cur_moves.reserve(V);\n\n        int score = 0;\n\n        if (base == nullptr) {\n            int st = si * N + sj;\n            cur_cells.push_back(st);\n            cur_moves.clear();\n            score = point_val[st];\n            seen[tile_id[st]] = mark;\n        } else {\n            prefix_len = max(prefix_len, 1);\n            prefix_len = min(prefix_len, (int)base->cells.size());\n\n            cur_cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n            cur_moves.assign(base->moves.begin(), base->moves.begin() + prefix_len - 1);\n\n            score = 0;\n            for (int c : cur_cells) {\n                score += point_val[c];\n                seen[tile_id[c]] = mark;\n            }\n        }\n\n        if (score > best_path.score) {\n            best_path.score = score;\n            best_path.cells = cur_cells;\n            best_path.moves = cur_moves;\n        }\n\n        int pos = cur_cells.back();\n\n        dfs(pos, score);\n    }\n};\n\nint select_prefix_len(const Path &p, XorShift &rng) {\n    int L = (int)p.cells.size();\n    if (L <= 1) return 1;\n\n    double u = rng.nextDouble();\n    double x;\n    int typ = rng.nextInt(100);\n\n    if (typ < 45) {\n        // Rebuild the tail.\n        x = sqrt(u);\n    } else if (typ < 75) {\n        // Medium cut.\n        x = u;\n    } else if (typ < 92) {\n        // Early decision change.\n        x = u * u;\n    } else {\n        // Very late local search.\n        x = 0.82 + 0.18 * u;\n    }\n\n    int prefix_len = 1 + (int)(x * (L - 1));\n    prefix_len = min(prefix_len, L - 1);\n    prefix_len = max(prefix_len, 1);\n    return prefix_len;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tid = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            int id = i * N + j;\n            tile_id[id] = x;\n            max_tid = max(max_tid, x);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> point_val[i * N + j];\n        }\n    }\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    for (int i = 0; i < V; i++) {\n        for (int k = 0; k < 4; k++) {\n            nb[i][k] = -1;\n            nb_dir[i][k] = '?';\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            for (int k = 0; k < 4; k++) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    nb[id][k] = ni * N + nj;\n                    nb_dir[id][k] = dc[k];\n                }\n            }\n        }\n    }\n\n    uint64_t seed = 123456789;\n    seed ^= (uint64_t)(si * 51 + sj + 1) * 1000003ULL;\n\n    for (int i = 0; i < V; i++) {\n        seed ^= (uint64_t)(tile_id[i] + 1) * 11995408973635179863ULL;\n        seed ^= (uint64_t)(point_val[i] + 7) * 10150724397891781847ULL;\n        seed = seed * 6364136223846793005ULL + 1442695040888963407ULL;\n    }\n\n    XorShift rng(seed);\n    Timer timer;\n\n    vector<int> seen(max_tid + 1, 0);\n    int mark = 1;\n\n    {\n        int st = si * N + sj;\n        best_path.score = point_val[st];\n        best_path.cells = {st};\n        best_path.moves = \"\";\n    }\n\n    const double TIME_LIMIT = 1.92;\n    const double GREEDY_PHASE = 0.62;\n\n    // Phase 1: randomized greedy rollouts.\n    while (timer.elapsed() < GREEDY_PHASE) {\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        Path cur;\n\n        bool fresh = pool.empty() || rng.nextInt(100) < 24;\n\n        if (fresh) {\n            cur = build_greedy_from_prefix(nullptr, 0, seen, mark, rng);\n        } else {\n            const Path *base;\n\n            if (rng.nextInt(100) < 68) {\n                base = &best_path;\n            } else {\n                base = &pool[rng.nextInt((int)pool.size())];\n            }\n\n            int prefix_len = select_prefix_len(*base, rng);\n            cur = build_greedy_from_prefix(base, prefix_len, seen, mark, rng);\n        }\n\n        consider_path(cur);\n    }\n\n    // Phase 2: DFS/local tail search from promising prefixes.\n    while (timer.elapsed() < TIME_LIMIT) {\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        const Path *base = nullptr;\n        int prefix_len = 1;\n\n        int mode = rng.nextInt(100);\n\n        if (mode < 15 || pool.empty()) {\n            base = nullptr;\n            prefix_len = 1;\n        } else if (mode < 78) {\n            base = &best_path;\n            prefix_len = select_prefix_len(*base, rng);\n        } else {\n            base = &pool[rng.nextInt((int)pool.size())];\n            prefix_len = select_prefix_len(*base, rng);\n        }\n\n        DFSSearcher dfs(seen, mark, rng, timer, TIME_LIMIT);\n\n        // Smaller budget gives more restarts; larger budget gives deeper local optimization.\n        int L = (base == nullptr ? 1 : (int)base->cells.size());\n        if (base != nullptr && prefix_len > L * 3 / 4) {\n            dfs.node_limit = 35000 + rng.nextInt(50000);\n        } else {\n            dfs.node_limit = 18000 + rng.nextInt(45000);\n        }\n\n        dfs.run_from_prefix(base, prefix_len);\n\n        // Occasionally keep DFS result in the pool as well.\n        if (rng.nextInt(100) < 25) {\n            consider_path(best_path);\n        }\n    }\n\n    cout << best_path.moves << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HEDGE = 30 * 29;\nstatic constexpr int VEDGE = 29 * 30;\nstatic constexpr int E = HEDGE + VEDGE;\nstatic constexpr int RCVAR = 60;\nstatic constexpr int SEGVAR = 120;\n\nstruct Obs {\n    array<int, RCVAR> x;\n    vector<int> edges;\n    long long y;\n};\n\nvector<Obs> observations;\n\ndouble hcost[N], vcost[N];\ndouble edge_est[E];\nint edge_freq[E];\n\nint splitH[N], splitV[N];\ndouble segH[N][2], segV[N][2];\n\nbool edge_ready = false;\nbool seg_ready = false;\n\nuint64_t rng_state = 88172645463325252ull;\n\nuint64_t xorshift() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\ndouble clamp_double(double x, double lo, double hi) {\n    return max(lo, min(hi, x));\n}\n\nint hid(int i, int j) {\n    return i * 29 + j;\n}\n\nint vid(int i, int j) {\n    return HEDGE + i * 30 + j;\n}\n\ndouble base_weight(int id) {\n    if (id < HEDGE) {\n        return hcost[id / 29];\n    } else {\n        int x = id - HEDGE;\n        return vcost[x % 30];\n    }\n}\n\ndouble segment_weight(int id) {\n    if (!seg_ready) return base_weight(id);\n\n    if (id < HEDGE) {\n        int i = id / 29;\n        int j = id % 29;\n        int p = (j < splitH[i] ? 0 : 1);\n        return segH[i][p];\n    } else {\n        int x = id - HEDGE;\n        int i = x / 30;\n        int j = x % 30;\n        int p = (i < splitV[j] ? 0 : 1);\n        return segV[j][p];\n    }\n}\n\ndouble structural_weight(int id) {\n    return segment_weight(id);\n}\n\nvoid solve_row_col_model() {\n    static double a[RCVAR][RCVAR + 1];\n\n    for (int i = 0; i < RCVAR; i++) {\n        for (int j = 0; j <= RCVAR; j++) {\n            a[i][j] = 0.0;\n        }\n    }\n\n    const double lambda = 80.0;\n\n    for (int i = 0; i < RCVAR; i++) {\n        a[i][i] += lambda;\n    }\n\n    for (const auto& ob : observations) {\n        vector<pair<int, int>> nz;\n        int len = 0;\n\n        for (int i = 0; i < RCVAR; i++) {\n            if (ob.x[i]) {\n                nz.push_back({i, ob.x[i]});\n                len += ob.x[i];\n            }\n        }\n\n        if (len == 0) continue;\n\n        double w = 400.0 / ((double)len * len);\n        double r = (double)ob.y - 5000.0 * len;\n\n        for (auto [i, xi] : nz) {\n            a[i][RCVAR] += w * xi * r;\n            for (auto [j, xj] : nz) {\n                a[i][j] += w * (double)xi * xj;\n            }\n        }\n    }\n\n    for (int col = 0; col < RCVAR; col++) {\n        int piv = col;\n\n        for (int row = col + 1; row < RCVAR; row++) {\n            if (fabs(a[row][col]) > fabs(a[piv][col])) {\n                piv = row;\n            }\n        }\n\n        if (piv != col) {\n            for (int j = col; j <= RCVAR; j++) {\n                swap(a[piv][j], a[col][j]);\n            }\n        }\n\n        double div = a[col][col];\n        if (fabs(div) < 1e-12) continue;\n\n        for (int j = col; j <= RCVAR; j++) {\n            a[col][j] /= div;\n        }\n\n        for (int row = 0; row < RCVAR; row++) {\n            if (row == col) continue;\n\n            double factor = a[row][col];\n            if (fabs(factor) < 1e-12) continue;\n\n            for (int j = col; j <= RCVAR; j++) {\n                a[row][j] -= factor * a[col][j];\n            }\n        }\n    }\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = clamp_double(5000.0 + a[i][RCVAR], 1000.0, 9000.0);\n    }\n\n    for (int j = 0; j < 30; j++) {\n        vcost[j] = clamp_double(5000.0 + a[30 + j][RCVAR], 1000.0, 9000.0);\n    }\n}\n\nvoid smooth_edge_est(double strength) {\n    static double nxt[E];\n\n    for (int id = 0; id < E; id++) {\n        nxt[id] = edge_est[id];\n    }\n\n    for (int i = 0; i < 30; i++) {\n        for (int j = 0; j < 29; j++) {\n            int id = hid(i, j);\n\n            double sum = edge_est[id] * 2.0;\n            double den = 2.0;\n\n            if (j > 0) {\n                int nid = hid(i, j - 1);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            if (j + 1 < 29) {\n                int nid = hid(i, j + 1);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            nxt[id] = edge_est[id] * (1.0 - strength) + (sum / den) * strength;\n        }\n    }\n\n    for (int i = 0; i < 29; i++) {\n        for (int j = 0; j < 30; j++) {\n            int id = vid(i, j);\n\n            double sum = edge_est[id] * 2.0;\n            double den = 2.0;\n\n            if (i > 0) {\n                int nid = vid(i - 1, j);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            if (i + 1 < 29) {\n                int nid = vid(i + 1, j);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            nxt[id] = edge_est[id] * (1.0 - strength) + (sum / den) * strength;\n        }\n    }\n\n    for (int id = 0; id < E; id++) {\n        edge_est[id] = clamp_double(nxt[id], 800.0, 9500.0);\n    }\n}\n\nvoid rebuild_edge_model(int turn) {\n    static double prior[E];\n    static double b[E], x[E], r[E], p[E], Ap[E];\n\n    for (int id = 0; id < E; id++) {\n        prior[id] = structural_weight(id);\n        b[id] = 0.0;\n        x[id] = 0.0;\n    }\n\n    vector<double> ws;\n    vector<double> rs;\n    ws.reserve(observations.size());\n    rs.reserve(observations.size());\n\n    for (const auto& ob : observations) {\n        int len = (int)ob.edges.size();\n        if (len == 0) {\n            ws.push_back(0.0);\n            rs.push_back(0.0);\n            continue;\n        }\n\n        double pred = 0.0;\n        for (int id : ob.edges) {\n            pred += prior[id];\n        }\n\n        double rr = (double)ob.y - pred;\n        double clip = max(4500.0, 0.16 * pred);\n        rr = clamp_double(rr, -clip, clip);\n\n        double w = 400.0 / ((double)len * len);\n\n        ws.push_back(w);\n        rs.push_back(rr);\n\n        for (int id : ob.edges) {\n            b[id] += w * rr;\n        }\n    }\n\n    double lambda;\n    if (turn < 250) lambda = 8.0;\n    else if (turn < 700) lambda = 6.0;\n    else lambda = 5.0;\n\n    auto matvec = [&](const double in[E], double out[E]) {\n        for (int id = 0; id < E; id++) {\n            out[id] = lambda * in[id];\n        }\n\n        int m = (int)observations.size();\n\n        for (int oi = 0; oi < m; oi++) {\n            const auto& ob = observations[oi];\n            if (ws[oi] == 0.0) continue;\n\n            double s = 0.0;\n            for (int id : ob.edges) {\n                s += in[id];\n            }\n\n            double c = ws[oi] * s;\n\n            for (int id : ob.edges) {\n                out[id] += c;\n            }\n        }\n    };\n\n    for (int id = 0; id < E; id++) {\n        r[id] = b[id];\n        p[id] = r[id];\n    }\n\n    double rsold = 0.0;\n    for (int id = 0; id < E; id++) {\n        rsold += r[id] * r[id];\n    }\n\n    int iters;\n    if (turn < 250) iters = 22;\n    else if (turn < 700) iters = 28;\n    else iters = 34;\n\n    for (int it = 0; it < iters; it++) {\n        if (rsold < 1e-7) break;\n\n        matvec(p, Ap);\n\n        double denom = 0.0;\n        for (int id = 0; id < E; id++) {\n            denom += p[id] * Ap[id];\n        }\n\n        if (fabs(denom) < 1e-12) break;\n\n        double alpha = rsold / denom;\n\n        for (int id = 0; id < E; id++) {\n            x[id] += alpha * p[id];\n            r[id] -= alpha * Ap[id];\n        }\n\n        double rsnew = 0.0;\n        for (int id = 0; id < E; id++) {\n            rsnew += r[id] * r[id];\n        }\n\n        if (rsnew < 1e-7) break;\n\n        double beta = rsnew / rsold;\n\n        for (int id = 0; id < E; id++) {\n            p[id] = r[id] + beta * p[id];\n        }\n\n        rsold = rsnew;\n    }\n\n    for (int id = 0; id < E; id++) {\n        double conf = (double)edge_freq[id] / (double)(edge_freq[id] + 7);\n        double z = x[id] * conf;\n        edge_est[id] = clamp_double(prior[id] + z, 800.0, 9500.0);\n    }\n\n    smooth_edge_est(turn < 300 ? 0.035 : 0.020);\n\n    edge_ready = true;\n}\n\nvoid update_splits_from_edge() {\n    for (int i = 0; i < 30; i++) {\n        double best = 1e100;\n        int bestx = 14;\n\n        for (int x = 1; x <= 28; x++) {\n            double sl = 0.0, wl = 0.0;\n            double sr = 0.0, wr = 0.0;\n\n            for (int j = 0; j < 29; j++) {\n                int id = hid(i, j);\n                double w = 0.4 + edge_freq[id];\n\n                if (j < x) {\n                    sl += edge_est[id] * w;\n                    wl += w;\n                } else {\n                    sr += edge_est[id] * w;\n                    wr += w;\n                }\n            }\n\n            double ml = sl / max(1e-9, wl);\n            double mr = sr / max(1e-9, wr);\n\n            double sse = 0.0;\n\n            for (int j = 0; j < 29; j++) {\n                int id = hid(i, j);\n                double w = 0.4 + edge_freq[id];\n                double m = (j < x ? ml : mr);\n                double d = edge_est[id] - m;\n                sse += w * d * d;\n            }\n\n            if (sse < best) {\n                best = sse;\n                bestx = x;\n            }\n        }\n\n        splitH[i] = bestx;\n    }\n\n    for (int j = 0; j < 30; j++) {\n        double best = 1e100;\n        int besty = 14;\n\n        for (int y = 1; y <= 28; y++) {\n            double su = 0.0, wu = 0.0;\n            double sd = 0.0, wd = 0.0;\n\n            for (int i = 0; i < 29; i++) {\n                int id = vid(i, j);\n                double w = 0.4 + edge_freq[id];\n\n                if (i < y) {\n                    su += edge_est[id] * w;\n                    wu += w;\n                } else {\n                    sd += edge_est[id] * w;\n                    wd += w;\n                }\n            }\n\n            double mu = su / max(1e-9, wu);\n            double md = sd / max(1e-9, wd);\n\n            double sse = 0.0;\n\n            for (int i = 0; i < 29; i++) {\n                int id = vid(i, j);\n                double w = 0.4 + edge_freq[id];\n                double m = (i < y ? mu : md);\n                double d = edge_est[id] - m;\n                sse += w * d * d;\n            }\n\n            if (sse < best) {\n                best = sse;\n                besty = y;\n            }\n        }\n\n        splitV[j] = besty;\n    }\n}\n\nint seg_index_from_edge(int id) {\n    if (id < HEDGE) {\n        int i = id / 29;\n        int j = id % 29;\n        int p = (j < splitH[i] ? 0 : 1);\n        return i * 2 + p;\n    } else {\n        int x = id - HEDGE;\n        int i = x / 30;\n        int j = x % 30;\n        int p = (i < splitV[j] ? 0 : 1);\n        return 60 + j * 2 + p;\n    }\n}\n\nvoid solve_segment_model(int turn) {\n    static double a[SEGVAR][SEGVAR + 1];\n\n    for (int i = 0; i < SEGVAR; i++) {\n        for (int j = 0; j <= SEGVAR; j++) {\n            a[i][j] = 0.0;\n        }\n    }\n\n    double lambda = (turn < 300 ? 65.0 : 45.0);\n    double tie = (turn < 300 ? 25.0 : 16.0);\n\n    for (int i = 0; i < 30; i++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = i * 2 + p;\n            double prior = hcost[i] - 5000.0;\n            a[idx][idx] += lambda;\n            a[idx][SEGVAR] += lambda * prior;\n        }\n\n        int a0 = i * 2;\n        int a1 = i * 2 + 1;\n        a[a0][a0] += tie;\n        a[a1][a1] += tie;\n        a[a0][a1] -= tie;\n        a[a1][a0] -= tie;\n    }\n\n    for (int j = 0; j < 30; j++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = 60 + j * 2 + p;\n            double prior = vcost[j] - 5000.0;\n            a[idx][idx] += lambda;\n            a[idx][SEGVAR] += lambda * prior;\n        }\n\n        int a0 = 60 + j * 2;\n        int a1 = 60 + j * 2 + 1;\n        a[a0][a0] += tie;\n        a[a1][a1] += tie;\n        a[a0][a1] -= tie;\n        a[a1][a0] -= tie;\n    }\n\n    static int cnt[SEGVAR];\n\n    for (const auto& ob : observations) {\n        fill(cnt, cnt + SEGVAR, 0);\n\n        int len = (int)ob.edges.size();\n        if (len == 0) continue;\n\n        for (int id : ob.edges) {\n            cnt[seg_index_from_edge(id)]++;\n        }\n\n        vector<pair<int, int>> nz;\n\n        for (int i = 0; i < SEGVAR; i++) {\n            if (cnt[i]) {\n                nz.push_back({i, cnt[i]});\n            }\n        }\n\n        double w = 400.0 / ((double)len * len);\n        double r = (double)ob.y - 5000.0 * len;\n\n        for (auto [i, xi] : nz) {\n            a[i][SEGVAR] += w * xi * r;\n            for (auto [j, xj] : nz) {\n                a[i][j] += w * (double)xi * xj;\n            }\n        }\n    }\n\n    for (int col = 0; col < SEGVAR; col++) {\n        int piv = col;\n\n        for (int row = col + 1; row < SEGVAR; row++) {\n            if (fabs(a[row][col]) > fabs(a[piv][col])) {\n                piv = row;\n            }\n        }\n\n        if (piv != col) {\n            for (int j = col; j <= SEGVAR; j++) {\n                swap(a[piv][j], a[col][j]);\n            }\n        }\n\n        double div = a[col][col];\n        if (fabs(div) < 1e-12) continue;\n\n        for (int j = col; j <= SEGVAR; j++) {\n            a[col][j] /= div;\n        }\n\n        for (int row = 0; row < SEGVAR; row++) {\n            if (row == col) continue;\n\n            double factor = a[row][col];\n            if (fabs(factor) < 1e-12) continue;\n\n            for (int j = col; j <= SEGVAR; j++) {\n                a[row][j] -= factor * a[col][j];\n            }\n        }\n    }\n\n    for (int i = 0; i < 30; i++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = i * 2 + p;\n            segH[i][p] = clamp_double(5000.0 + a[idx][SEGVAR], 900.0, 9500.0);\n        }\n    }\n\n    for (int j = 0; j < 30; j++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = 60 + j * 2 + p;\n            segV[j][p] = clamp_double(5000.0 + a[idx][SEGVAR], 900.0, 9500.0);\n        }\n    }\n\n    seg_ready = true;\n}\n\nvoid online_edge_update(long long y, const vector<int>& edges) {\n    if (!edge_ready || edges.empty()) return;\n\n    double pred = 0.0;\n\n    for (int id : edges) {\n        pred += edge_est[id];\n    }\n\n    double err = (double)y - pred;\n    double clip = max(4000.0, 0.12 * pred);\n    err = clamp_double(err, -clip, clip);\n\n    double delta = 0.006 * err / (double)edges.size();\n\n    for (int id : edges) {\n        edge_est[id] += delta;\n        edge_est[id] = clamp_double(edge_est[id], 800.0, 9500.0);\n    }\n}\n\ndouble learned_weight_raw(int id, int turn) {\n    double b = base_weight(id);\n    double s = segment_weight(id);\n\n    double seg_mix = ((double)turn - 80.0) / 420.0;\n    seg_mix = clamp_double(seg_mix, 0.0, 0.84);\n\n    double w = b * (1.0 - seg_mix) + s * seg_mix;\n\n    if (edge_ready) {\n        double edge_mix = ((double)turn - 260.0) / 760.0;\n        edge_mix = clamp_double(edge_mix, 0.0, 0.24);\n        w = w * (1.0 - edge_mix) + edge_est[id] * edge_mix;\n    }\n\n    return clamp_double(w, 800.0, 9500.0);\n}\n\ndouble model_weight_for_search(int id, int turn) {\n    double learned = learned_weight_raw(id, turn);\n\n    double rel = ((double)turn - 25.0) / 520.0;\n    rel = clamp_double(rel, 0.0, 1.0);\n\n    double w = 5000.0 * (1.0 - rel) + learned * rel;\n    return clamp_double(w, 800.0, 9500.0);\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool horizontal_first) {\n    string res;\n\n    auto add_vertical = [&]() {\n        if (si < ti) {\n            while (si < ti) {\n                res.push_back('D');\n                si++;\n            }\n        } else {\n            while (si > ti) {\n                res.push_back('U');\n                si--;\n            }\n        }\n    };\n\n    auto add_horizontal = [&]() {\n        if (sj < tj) {\n            while (sj < tj) {\n                res.push_back('R');\n                sj++;\n            }\n        } else {\n            while (sj > tj) {\n                res.push_back('L');\n                sj--;\n            }\n        }\n    };\n\n    if (horizontal_first) {\n        add_horizontal();\n        add_vertical();\n    } else {\n        add_vertical();\n        add_horizontal();\n    }\n\n    return res;\n}\n\nvoid extract_features(\n    int si,\n    int sj,\n    const string& path,\n    array<int, RCVAR>& feat,\n    vector<int>& edges\n) {\n    feat.fill(0);\n    edges.clear();\n\n    int i = si;\n    int j = sj;\n\n    for (char c : path) {\n        if (c == 'R') {\n            int id = hid(i, j);\n            edges.push_back(id);\n            feat[i]++;\n            j++;\n        } else if (c == 'L') {\n            int id = hid(i, j - 1);\n            edges.push_back(id);\n            feat[i]++;\n            j--;\n        } else if (c == 'D') {\n            int id = vid(i, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i++;\n        } else {\n            int id = vid(i - 1, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i--;\n        }\n    }\n}\n\ndouble estimated_path_cost(int si, int sj, const string& path, int turn) {\n    int i = si;\n    int j = sj;\n    double cost = 0.0;\n\n    for (char c : path) {\n        if (c == 'R') {\n            cost += model_weight_for_search(hid(i, j), turn);\n            j++;\n        } else if (c == 'L') {\n            cost += model_weight_for_search(hid(i, j - 1), turn);\n            j--;\n        } else if (c == 'D') {\n            cost += model_weight_for_search(vid(i, j), turn);\n            i++;\n        } else {\n            cost += model_weight_for_search(vid(i - 1, j), turn);\n            i--;\n        }\n    }\n\n    return cost;\n}\n\nstring choose_early_path(int si, int sj, int ti, int tj, int turn) {\n    string p1 = manhattan_path(si, sj, ti, tj, true);\n    string p2 = manhattan_path(si, sj, ti, tj, false);\n\n    if (p1 == p2) return p1;\n\n    if (turn < 45) {\n        return (xorshift() & 1) ? p1 : p2;\n    }\n\n    double c1 = estimated_path_cost(si, sj, p1, turn);\n    double c2 = estimated_path_cost(si, sj, p2, turn);\n\n    int eps = (turn < 100 ? 18 : 7);\n\n    if ((int)(xorshift() % 100) < eps) {\n        return (c1 < c2) ? p2 : p1;\n    }\n\n    return (c1 < c2) ? p1 : p2;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    const double INF = 1e100;\n\n    vector<double> dist(900, INF);\n    vector<int> parent(900, -1);\n    vector<char> pchar(900, '?');\n\n    auto node = [](int i, int j) {\n        return i * 30 + j;\n    };\n\n    priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n\n    int s = node(si, sj);\n    int t = node(ti, tj);\n\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\n        if (d != dist[u]) continue;\n        if (u == t) break;\n\n        int i = u / 30;\n        int j = u % 30;\n\n        auto relax = [&](int ni, int nj, char c, int eid) {\n            int v = node(ni, nj);\n            double nd = d + model_weight_for_search(eid, turn);\n\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                pchar[v] = c;\n                pq.push({nd, v});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, 'U', vid(i - 1, j));\n        if (i + 1 < 30) relax(i + 1, j, 'D', vid(i, j));\n        if (j > 0) relax(i, j - 1, 'L', hid(i, j - 1));\n        if (j + 1 < 30) relax(i, j + 1, 'R', hid(i, j));\n    }\n\n    string res;\n    int cur = t;\n\n    while (cur != s) {\n        res.push_back(pchar[cur]);\n        cur = parent[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = 5000.0;\n        vcost[i] = 5000.0;\n        splitH[i] = 14;\n        splitV[i] = 14;\n\n        segH[i][0] = segH[i][1] = 5000.0;\n        segV[i][0] = segV[i][1] = 5000.0;\n    }\n\n    for (int id = 0; id < E; id++) {\n        edge_est[id] = 5000.0;\n        edge_freq[id] = 0;\n    }\n\n    for (int turn = 0; turn < 1000; turn++) {\n        int si, sj, ti, tj;\n\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0;\n        }\n\n        string path;\n\n        if (turn < 100) {\n            path = choose_early_path(si, sj, ti, tj, turn);\n        } else {\n            path = dijkstra_path(si, sj, ti, tj, turn);\n        }\n\n        array<int, RCVAR> feat;\n        vector<int> edges;\n        extract_features(si, sj, path, feat, edges);\n\n        cout << path << endl;\n        cout.flush();\n\n        long long result;\n\n        if (!(cin >> result)) {\n            return 0;\n        }\n\n        Obs ob;\n        ob.x = feat;\n        ob.edges = edges;\n        ob.y = result;\n        observations.push_back(ob);\n\n        for (int id : edges) {\n            edge_freq[id]++;\n        }\n\n        if (turn < 260 || turn % 5 == 4 || turn >= 850) {\n            solve_row_col_model();\n        }\n\n        bool trigger = false;\n\n        if (turn >= 60) {\n            if (turn < 300) {\n                trigger = (turn % 12 == 11);\n            } else if (turn < 800) {\n                trigger = (turn % 24 == 23);\n            } else {\n                trigger = (turn % 14 == 13);\n            }\n        }\n\n        if (trigger) {\n            if (turn >= 75 && edge_ready) {\n                update_splits_from_edge();\n                solve_segment_model(turn);\n            }\n\n            rebuild_edge_model(turn);\n        }\n\n        online_edge_update(result, edges);\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int C = 400;\nstatic constexpr int ALPHA = 8;\nstatic constexpr long long BIG = 2000000000LL;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) { return (int)(next() % n); }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstruct KmerScorer {\n    int maxQ = 2;\n    vector<vector<int>> dense;\n    vector<unordered_map<unsigned long long, int>> sparse;\n    int mult[13] = {0, 0, 1, 2, 5, 12, 30, 80, 200, 500, 1200, 2500, 5000};\n\n    KmerScorer() {\n        dense.resize(13);\n        sparse.resize(13);\n    }\n\n    void build(const vector<string>& s) {\n        maxQ = 2;\n        for (auto& t : s) maxQ = max(maxQ, min(12, (int)t.size()));\n\n        for (int q = 2; q <= min(8, maxQ); q++) {\n            dense[q].assign(1 << (3 * q), 0);\n        }\n\n        for (auto& t : s) {\n            int L = (int)t.size();\n            vector<int> a(L);\n            for (int i = 0; i < L; i++) a[i] = t[i] - 'A';\n\n            for (int q = 2; q <= min(12, L); q++) {\n                for (int l = 0; l + q <= L; l++) {\n                    unsigned long long code = 0;\n                    for (int p = 0; p < q; p++) code = (code << 3) | a[l + p];\n                    int w = mult[q];\n                    if (q <= 8) dense[q][(int)code] += w;\n                    else sparse[q][code] += w;\n                }\n            }\n        }\n    }\n\n    inline int getWeight(int q, unsigned long long code) const {\n        if (q <= 8) return dense[q][(int)code];\n        auto it = sparse[q].find(code);\n        if (it == sparse[q].end()) return 0;\n        return it->second;\n    }\n\n    unsigned long long codeWindow(\n        const vector<unsigned char>& board,\n        int i,\n        int j,\n        int dir,\n        int q,\n        int overrideCell = -1,\n        int overrideVal = 0\n    ) const {\n        unsigned long long code = 0;\n        for (int p = 0; p < q; p++) {\n            int ni = i, nj = j;\n            if (dir == 0) nj = (j + p) % N;\n            else ni = (i + p) % N;\n\n            int cell = ni * N + nj;\n            int v = (cell == overrideCell ? overrideVal : board[cell]);\n            if (v < 0 || v >= 8) return ULLONG_MAX;\n            code = (code << 3) | (unsigned)v;\n        }\n        return code;\n    }\n\n    long long score(const vector<unsigned char>& board) const {\n        long long res = 0;\n        for (int q = 2; q <= maxQ; q++) {\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    auto c1 = codeWindow(board, i, j, 0, q);\n                    if (c1 != ULLONG_MAX) res += getWeight(q, c1);\n                    auto c2 = codeWindow(board, i, j, 1, q);\n                    if (c2 != ULLONG_MAX) res += getWeight(q, c2);\n                }\n            }\n        }\n        return res;\n    }\n\n    long long delta(const vector<unsigned char>& board, int cell, int nc) const {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        int i = cell / N;\n        int j = cell % N;\n        long long d = 0;\n\n        for (int q = 2; q <= maxQ; q++) {\n            for (int off = 0; off < q; off++) {\n                int sj = (j - off + N) % N;\n\n                auto oldCode = codeWindow(board, i, sj, 0, q);\n                auto newCode = codeWindow(board, i, sj, 0, q, cell, nc);\n                if (oldCode != ULLONG_MAX) d -= getWeight(q, oldCode);\n                if (newCode != ULLONG_MAX) d += getWeight(q, newCode);\n\n                int si = (i - off + N) % N;\n\n                oldCode = codeWindow(board, si, j, 1, q);\n                newCode = codeWindow(board, si, j, 1, q, cell, nc);\n                if (oldCode != ULLONG_MAX) d -= getWeight(q, oldCode);\n                if (newCode != ULLONG_MAX) d += getWeight(q, newCode);\n            }\n        }\n\n        return d;\n    }\n};\n\nstruct Evaluator {\n    int M;\n    vector<string> s;\n    vector<unsigned char> board;\n\n    vector<unsigned char> mis;\n    vector<array<unsigned short, 13>> hist;\n    vector<long long> val;\n    vector<vector<int>> inc;\n\n    long long obj = 0;\n    int covered = 0;\n\n    long long nearTable[13] = {\n        0,\n        1000000,\n        300000,\n        100000,\n        30000,\n        10000,\n        3000,\n        1000,\n        300,\n        100,\n        30,\n        10,\n        0\n    };\n\n    Evaluator() {}\n\n    Evaluator(const vector<string>& _s, const vector<unsigned char>& _board) {\n        s = _s;\n        M = (int)s.size();\n        board = _board;\n        build();\n    }\n\n    inline int placementCell(int sid, int idx, int p) const {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    }\n\n    inline long long calcVal(int sid) const {\n        if (hist[sid][0] > 0) return BIG + min<int>(hist[sid][0], 1000);\n        for (int d = 1; d <= 12; d++) {\n            if (hist[sid][d] > 0) return nearTable[d] + min<int>(hist[sid][d], 1000);\n        }\n        return 0;\n    }\n\n    void build() {\n        int P = M * 800;\n        mis.assign(P, 0);\n        hist.assign(M, {});\n        val.assign(M, 0);\n        inc.assign(C, {});\n\n        int reservePerCell = max(1, M * 2 * 12);\n        for (int c = 0; c < C; c++) inc[c].reserve(reservePerCell);\n\n        for (int sid = 0; sid < M; sid++) {\n            int len = (int)s[sid].size();\n\n            for (int idx = 0; idx < 800; idx++) {\n                int pid = sid * 800 + idx;\n                int mm = 0;\n\n                for (int p = 0; p < len; p++) {\n                    int cell = placementCell(sid, idx, p);\n                    int req = s[sid][p] - 'A';\n                    if (board[cell] != req) mm++;\n                    inc[cell].push_back(pid * 8 + req);\n                }\n\n                mis[pid] = (unsigned char)mm;\n                hist[sid][mm]++;\n            }\n        }\n\n        obj = 0;\n        covered = 0;\n\n        for (int sid = 0; sid < M; sid++) {\n            val[sid] = calcVal(sid);\n            obj += val[sid];\n            if (hist[sid][0] > 0) covered++;\n        }\n    }\n\n    long long applyChange(int cell, int nc) {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        long long deltaObj = 0;\n\n        for (int code : inc[cell]) {\n            int req = code & 7;\n            if (req != oc && req != nc) continue;\n\n            int pid = code >> 3;\n            int sid = pid / 800;\n\n            long long oldVal = val[sid];\n            bool oldCov = hist[sid][0] > 0;\n\n            int oldMis = mis[pid];\n            hist[sid][oldMis]--;\n\n            int nm = oldMis;\n            if (req == oc) nm++;\n            if (req == nc) nm--;\n\n            mis[pid] = (unsigned char)nm;\n            hist[sid][nm]++;\n\n            bool newCov = hist[sid][0] > 0;\n            if (oldCov && !newCov) covered--;\n            if (!oldCov && newCov) covered++;\n\n            long long newVal = calcVal(sid);\n            val[sid] = newVal;\n            deltaObj += newVal - oldVal;\n        }\n\n        board[cell] = (unsigned char)nc;\n        obj += deltaObj;\n        return deltaObj;\n    }\n\n    int minMismatchOfString(int sid) const {\n        for (int d = 0; d <= 12; d++) {\n            if (hist[sid][d] > 0) return d;\n        }\n        return 13;\n    }\n\n    int bestPlacementIndex(int sid, XorShift& rng) const {\n        int best = 100;\n        int cnt = 0;\n        int bestIdx = 0;\n        int base = sid * 800;\n\n        for (int idx = 0; idx < 800; idx++) {\n            int mm = mis[base + idx];\n\n            if (mm < best) {\n                best = mm;\n                cnt = 1;\n                bestIdx = idx;\n            } else if (mm == best) {\n                cnt++;\n                if (rng.nextInt(cnt) == 0) bestIdx = idx;\n            }\n        }\n\n        return bestIdx;\n    }\n};\n\nstruct BestState {\n    int covered = -1;\n    long long obj = LLONG_MIN;\n    vector<unsigned char> board;\n\n    void update(const Evaluator& ev) {\n        if (ev.covered > covered || (ev.covered == covered && ev.obj > obj)) {\n            covered = ev.covered;\n            obj = ev.obj;\n            board = ev.board;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    int inputN, M;\n    cin >> inputN >> M;\n\n    vector<string> s(M);\n    for (int i = 0; i < M; i++) cin >> s[i];\n\n    XorShift rng(123456789);\n\n    auto elapsedSec = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    KmerScorer ksc;\n    ksc.build(s);\n\n    vector<int> freq(ALPHA, 1);\n    for (auto& t : s) {\n        for (char ch : t) freq[ch - 'A']++;\n    }\n\n    vector<int> pref(ALPHA);\n    pref[0] = freq[0];\n    for (int i = 1; i < ALPHA; i++) pref[i] = pref[i - 1] + freq[i];\n    int fsum = pref.back();\n\n    auto randomChar = [&]() {\n        int r = rng.nextInt(fsum);\n        return (unsigned char)(lower_bound(pref.begin(), pref.end(), r + 1) - pref.begin());\n    };\n\n    auto placementCellRaw = [&](int idx, int p) {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    };\n\n    vector<unsigned char> boardStamp(C);\n    for (int i = 0; i < C; i++) boardStamp[i] = randomChar();\n\n    auto conflictOfPlacement = [&](const vector<unsigned char>& b, const string& t, int idx) {\n        int conf = 0;\n        int len = (int)t.size();\n\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            int req = t[p] - 'A';\n            if (b[cell] != req) conf++;\n        }\n\n        return conf;\n    };\n\n    auto stampRaw = [&](vector<unsigned char>& b, const string& t, int idx) {\n        int len = (int)t.size();\n\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            b[cell] = (unsigned char)(t[p] - 'A');\n        }\n    };\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n\n    for (int pass = 0; pass < 6; pass++) {\n        if (pass == 5) {\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return s[a].size() < s[b].size();\n            });\n        } else {\n            shuffle(order.begin(), order.end(), mt19937((unsigned)rng.next()));\n        }\n\n        for (int sid : order) {\n            int bestConf = 100;\n            int bestIdx = 0;\n            int cnt = 0;\n\n            for (int idx = 0; idx < 800; idx++) {\n                int conf = conflictOfPlacement(boardStamp, s[sid], idx);\n\n                if (conf < bestConf) {\n                    bestConf = conf;\n                    bestIdx = idx;\n                    cnt = 1;\n                } else if (conf == bestConf) {\n                    cnt++;\n                    if (rng.nextInt(cnt) == 0) bestIdx = idx;\n                }\n            }\n\n            stampRaw(boardStamp, s[sid], bestIdx);\n        }\n    }\n\n    BestState best;\n\n    auto doSearch = [&](Evaluator& ev, bool useKmer, double endTime) {\n        long long curK = 0;\n        if (useKmer) curK = ksc.score(ev.board);\n\n        vector<pair<int, int>> changed;\n        int iter = 0;\n\n        best.update(ev);\n\n        while (true) {\n            if ((iter & 7) == 0 && elapsedSec() > endTime) break;\n\n            double progress = min(1.0, elapsedSec() / endTime);\n            double temp = useKmer\n                ? (1500000.0 * (1.0 - progress) + 20000.0 * progress)\n                : (200000.0 * (1.0 - progress) + 2000.0 * progress);\n\n            long long kScale = 0;\n            if (useKmer) kScale = (ev.covered < M ? 220 : 30);\n\n            if (ev.covered < M && iter % 5 == 0) {\n                int bestSid = -1;\n                int bestMM = 100;\n                int cnt = 0;\n\n                for (int sid = 0; sid < M; sid++) {\n                    if (ev.hist[sid][0] == 0) {\n                        int mm = ev.minMismatchOfString(sid);\n\n                        if (mm < bestMM) {\n                            bestMM = mm;\n                            bestSid = sid;\n                            cnt = 1;\n                        } else if (mm == bestMM) {\n                            cnt++;\n                            if (rng.nextInt(cnt) == 0) bestSid = sid;\n                        }\n                    }\n                }\n\n                if (bestSid != -1) {\n                    int idx = ev.bestPlacementIndex(bestSid, rng);\n\n                    changed.clear();\n\n                    long long oldObj = ev.obj;\n                    long long oldK = curK;\n\n                    int len = (int)s[bestSid].size();\n\n                    for (int p = 0; p < len; p++) {\n                        int cell = ev.placementCell(bestSid, idx, p);\n                        int req = s[bestSid][p] - 'A';\n\n                        if (ev.board[cell] != req) {\n                            int old = ev.board[cell];\n                            changed.push_back({cell, old});\n\n                            if (useKmer) {\n                                long long kd = ksc.delta(ev.board, cell, req);\n                                curK += kd;\n                            }\n\n                            ev.applyChange(cell, req);\n                        }\n                    }\n\n                    long long exactD = ev.obj - oldObj;\n                    long long kD = curK - oldK;\n                    long long combD = exactD + kScale * kD;\n\n                    bool accept = false;\n                    if (combD >= 0) {\n                        accept = true;\n                    } else if (exactD > -BIG / 2) {\n                        double prob = exp((double)combD / temp);\n                        if (rng.nextDouble() < prob) accept = true;\n                    }\n\n                    if (!accept) {\n                        for (int i = (int)changed.size() - 1; i >= 0; i--) {\n                            int cell = changed[i].first;\n                            int old = changed[i].second;\n\n                            if (useKmer) {\n                                long long kd = ksc.delta(ev.board, cell, old);\n                                curK += kd;\n                            }\n\n                            ev.applyChange(cell, old);\n                        }\n                    } else {\n                        best.update(ev);\n                    }\n                }\n            } else {\n                int cell = rng.nextInt(C);\n                int old = ev.board[cell];\n\n                long long bestComb = 0;\n                long long bestK = 0;\n                int bestChar = old;\n\n                for (int nc = 0; nc < ALPHA; nc++) {\n                    if (nc == old) continue;\n\n                    long long kd = 0;\n                    if (useKmer) kd = ksc.delta(ev.board, cell, nc);\n\n                    long long ed = ev.applyChange(cell, nc);\n                    ev.applyChange(cell, old);\n\n                    long long cd = ed + kScale * kd;\n\n                    if (cd > bestComb) {\n                        bestComb = cd;\n                        bestK = kd;\n                        bestChar = nc;\n                    }\n                }\n\n                if (bestChar != old) {\n                    if (useKmer) curK += bestK;\n                    ev.applyChange(cell, bestChar);\n                    best.update(ev);\n                } else {\n                    int nc = rng.nextInt(ALPHA);\n                    if (nc == old) nc = (nc + 1) % ALPHA;\n\n                    long long kd = 0;\n                    if (useKmer) kd = ksc.delta(ev.board, cell, nc);\n\n                    long long ed = ev.applyChange(cell, nc);\n                    long long cd = ed + kScale * kd;\n\n                    bool accept = false;\n                    if (cd >= 0) {\n                        accept = true;\n                    } else if (ed > -BIG / 2) {\n                        double prob = exp((double)cd / temp);\n                        if (rng.nextDouble() < prob) accept = true;\n                    }\n\n                    if (accept) {\n                        if (useKmer) curK += kd;\n                        best.update(ev);\n                    } else {\n                        ev.applyChange(cell, old);\n                    }\n                }\n            }\n\n            iter++;\n        }\n    };\n\n    // Exact-cover search from greedy board. This recovers many cases where k-mer guidance is harmful.\n    Evaluator evExact(s, boardStamp);\n    doSearch(evExact, false, 1.10);\n\n    // Independent k-mer candidate for diversity.\n    vector<unsigned char> boardKmer(C);\n    for (int i = 0; i < C; i++) boardKmer[i] = randomChar();\n\n    long long kScore = ksc.score(boardKmer);\n\n    while (elapsedSec() < 1.55) {\n        int cell = rng.nextInt(C);\n        int old = boardKmer[cell];\n\n        long long bestD = 0;\n        int bestC = old;\n\n        for (int nc = 0; nc < ALPHA; nc++) {\n            if (nc == old) continue;\n            long long d = ksc.delta(boardKmer, cell, nc);\n\n            if (d > bestD) {\n                bestD = d;\n                bestC = nc;\n            }\n        }\n\n        if (bestC != old) {\n            boardKmer[cell] = (unsigned char)bestC;\n            kScore += bestD;\n        } else {\n            int nc = rng.nextInt(ALPHA);\n            if (nc == old) nc = (nc + 1) % ALPHA;\n\n            long long d = ksc.delta(boardKmer, cell, nc);\n            if (d >= 0 || rng.nextDouble() < exp((double)d / 30.0)) {\n                boardKmer[cell] = (unsigned char)nc;\n                kScore += d;\n            }\n        }\n    }\n\n    Evaluator evKmer(s, boardKmer);\n    best.update(evKmer);\n\n    vector<unsigned char> startCombined;\n\n    if (evKmer.covered > best.covered ||\n        (evKmer.covered == best.covered && ksc.score(evKmer.board) > ksc.score(best.board))) {\n        startCombined = evKmer.board;\n    } else {\n        startCombined = best.board;\n    }\n\n    // K-mer-assisted exact search, but best exact board is always preserved.\n    Evaluator evCombined(s, startCombined);\n    doSearch(evCombined, true, 2.82);\n\n    vector<unsigned char> answer = best.board;\n\n    // If perfect coverage was achieved, greedily erase unnecessary cells.\n    if (best.covered == M) {\n        Evaluator evFinal(s, answer);\n\n        vector<int> cells(C);\n        iota(cells.begin(), cells.end(), 0);\n        shuffle(cells.begin(), cells.end(), mt19937((unsigned)rng.next()));\n\n        for (int cell : cells) {\n            int old = evFinal.board[cell];\n            if (old == 8) continue;\n\n            evFinal.applyChange(cell, 8);\n\n            if (evFinal.covered < M) {\n                evFinal.applyChange(cell, old);\n            }\n        }\n\n        answer = evFinal.board;\n    }\n\n    for (int i = 0; i < N; i++) {\n        string out;\n\n        for (int j = 0; j < N; j++) {\n            int v = answer[i * N + j];\n\n            if (v == 8) out.push_back('.');\n            else out.push_back(char('A' + v));\n        }\n\n        cout << out << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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 HopcroftKarp {\n    int nL, nR;\n    vector<vector<int>> adj;\n    vector<int> pairU, pairV, dist;\n\n    HopcroftKarp(int nL_=0, int nR_=0) : nL(nL_), nR(nR_) {\n        adj.assign(nL, {});\n        pairU.assign(nL, -1);\n        pairV.assign(nR, -1);\n        dist.assign(nL, 0);\n    }\n\n    bool bfs() {\n        queue<int> q;\n        bool found = false;\n\n        for (int u = 0; u < nL; u++) {\n            if (pairU[u] == -1) {\n                dist[u] = 0;\n                q.push(u);\n            } else {\n                dist[u] = -1;\n            }\n        }\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (int v : adj[u]) {\n                int u2 = pairV[v];\n                if (u2 == -1) {\n                    found = true;\n                } else if (dist[u2] == -1) {\n                    dist[u2] = dist[u] + 1;\n                    q.push(u2);\n                }\n            }\n        }\n\n        return found;\n    }\n\n    bool dfs(int u) {\n        for (int v : adj[u]) {\n            int u2 = pairV[v];\n            if (u2 == -1 || (dist[u2] == dist[u] + 1 && dfs(u2))) {\n                pairU[u] = v;\n                pairV[v] = u;\n                return true;\n            }\n        }\n        dist[u] = -1;\n        return false;\n    }\n\n    int max_matching() {\n        int matching = 0;\n        while (bfs()) {\n            for (int u = 0; u < nL; u++) {\n                if (pairU[u] == -1 && dfs(u)) matching++;\n            }\n        }\n        return matching;\n    }\n\n    pair<vector<char>, vector<char>> min_vertex_cover() {\n        vector<char> visL(nL, 0), visR(nR, 0);\n        queue<int> q;\n\n        for (int u = 0; u < nL; u++) {\n            if (pairU[u] == -1) {\n                visL[u] = 1;\n                q.push(u);\n            }\n        }\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (int v : adj[u]) {\n                if (pairU[u] == v) continue;\n                if (visR[v]) continue;\n\n                visR[v] = 1;\n                int u2 = pairV[v];\n                if (u2 != -1 && !visL[u2]) {\n                    visL[u2] = 1;\n                    q.push(u2);\n                }\n            }\n        }\n\n        vector<char> coverL(nL, 0), coverR(nR, 0);\n        for (int u = 0; u < nL; u++) coverL[u] = !visL[u];\n        for (int v = 0; v < nR; v++) coverR[v] = visR[v];\n        return {coverL, coverR};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<int> ri, rj, cost;\n\n    int R = 0;\n    int startRid = -1;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R++;\n                ri.push_back(i);\n                rj.push_back(j);\n                cost.push_back(grid[i][j] - '0');\n\n                if (i == si && j == sj) startRid = id[i][j];\n            }\n        }\n    }\n\n    int W = (R + 63) >> 6;\n\n    vector<int> hid(R), vid(R);\n    vector<vector<int>> hCells, vCells;\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n\n            vector<int> cells;\n            while (j < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                j++;\n            }\n\n            int h = (int)hCells.size();\n            for (int x : cells) hid[x] = h;\n            hCells.push_back(cells);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n\n            vector<int> cells;\n            while (i < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                i++;\n            }\n\n            int v = (int)vCells.size();\n            for (int x : cells) vid[x] = v;\n            vCells.push_back(cells);\n        }\n    }\n\n    int H = (int)hCells.size();\n    int V = (int)vCells.size();\n\n    vector<uint64_t> coverBits((ll)R * W, 0);\n\n    for (int x = 0; x < R; x++) {\n        uint64_t* bs = &coverBits[(ll)x * W];\n\n        for (int y : hCells[hid[x]]) {\n            bs[y >> 6] |= 1ULL << (y & 63);\n        }\n        for (int y : vCells[vid[x]]) {\n            bs[y >> 6] |= 1ULL << (y & 63);\n        }\n    }\n\n    vector<uint64_t> fullMask(W, 0);\n    for (int x = 0; x < R; x++) {\n        fullMask[x >> 6] |= 1ULL << (x & 63);\n    }\n\n    auto is_full_bits = [&](const vector<uint64_t>& bs) -> bool {\n        for (int w = 0; w < W; w++) {\n            if ((bs[w] & fullMask[w]) != fullMask[w]) return false;\n        }\n        return true;\n    };\n\n    auto pop_and = [&](const uint64_t* a, const vector<uint64_t>& b) -> int {\n        int res = 0;\n        for (int w = 0; w < W; w++) {\n            res += __builtin_popcountll(a[w] & b[w]);\n        }\n        return res;\n    };\n\n    auto erase_cover_from_uncovered = [&](vector<uint64_t>& uncovered, int x) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W; w++) {\n            uncovered[w] &= ~bs[w];\n        }\n    };\n\n    auto reduce_selected = [&](vector<int> selected) {\n        sort(selected.begin(), selected.end());\n        selected.erase(unique(selected.begin(), selected.end()), selected.end());\n        selected.erase(remove(selected.begin(), selected.end(), startRid), selected.end());\n\n        vector<int> cnt(R, 0);\n\n        auto addCoverCount = [&](int x, int delta) {\n            const uint64_t* bs = &coverBits[(ll)x * W];\n\n            for (int w = 0; w < W; w++) {\n                uint64_t v = bs[w];\n\n                while (v) {\n                    int b = __builtin_ctzll(v);\n                    int y = (w << 6) + b;\n                    if (y < R) cnt[y] += delta;\n                    v &= v - 1;\n                }\n            }\n        };\n\n        addCoverCount(startRid, 1);\n        for (int x : selected) addCoverCount(x, 1);\n\n        vector<int> kept;\n\n        for (int idx = (int)selected.size() - 1; idx >= 0; idx--) {\n            int x = selected[idx];\n            bool removable = true;\n\n            const uint64_t* bs = &coverBits[(ll)x * W];\n\n            for (int w = 0; w < W && removable; w++) {\n                uint64_t v = bs[w];\n\n                while (v) {\n                    int b = __builtin_ctzll(v);\n                    int y = (w << 6) + b;\n\n                    if (y < R && cnt[y] <= 1) {\n                        removable = false;\n                        break;\n                    }\n\n                    v &= v - 1;\n                }\n            }\n\n            if (removable) {\n                addCoverCount(x, -1);\n            } else {\n                kept.push_back(x);\n            }\n        }\n\n        reverse(kept.begin(), kept.end());\n        return kept;\n    };\n\n    auto selected_covers_all = [&](const vector<int>& selected) {\n        vector<uint64_t> bs(W, 0);\n\n        const uint64_t* sbs = &coverBits[(ll)startRid * W];\n        for (int w = 0; w < W; w++) bs[w] |= sbs[w];\n\n        for (int x : selected) {\n            const uint64_t* cbs = &coverBits[(ll)x * W];\n            for (int w = 0; w < W; w++) bs[w] |= cbs[w];\n        }\n\n        return is_full_bits(bs);\n    };\n\n    // Candidate 1: robust greedy set cover.\n    vector<int> greedySelected;\n    {\n        vector<uint64_t> uncovered = fullMask;\n        erase_cover_from_uncovered(uncovered, startRid);\n\n        vector<char> selectedFlag(R, 0);\n\n        auto anyUncovered = [&]() -> bool {\n            for (uint64_t x : uncovered) {\n                if (x) return true;\n            }\n            return false;\n        };\n\n        while (anyUncovered()) {\n            int best = -1;\n            int bestGain = -1;\n            int bestTie = INT_MIN;\n\n            for (int x = 0; x < R; x++) {\n                if (selectedFlag[x]) continue;\n\n                const uint64_t* bs = &coverBits[(ll)x * W];\n                int gain = pop_and(bs, uncovered);\n                if (gain <= 0) continue;\n\n                int hLen = (int)hCells[hid[x]].size();\n                int vLen = (int)vCells[vid[x]].size();\n\n                int tie =\n                    10 * (hLen + vLen)\n                    - abs(ri[x] - si)\n                    - abs(rj[x] - sj);\n\n                if (gain > bestGain || (gain == bestGain && tie > bestTie)) {\n                    bestGain = gain;\n                    bestTie = tie;\n                    best = x;\n                }\n            }\n\n            if (best == -1) break;\n\n            selectedFlag[best] = 1;\n            greedySelected.push_back(best);\n            erase_cover_from_uncovered(uncovered, best);\n        }\n\n        greedySelected = reduce_selected(greedySelected);\n    }\n\n    // Candidate 2: bipartite minimum vertex cover converted into cells.\n    vector<int> mvcSelected;\n    bool mvcValid = false;\n    {\n        int hs = hid[startRid];\n        int vs = vid[startRid];\n\n        HopcroftKarp hk(H, V);\n\n        unordered_map<ll, int> edgeCell;\n        edgeCell.reserve(R * 2 + 10);\n\n        for (int x = 0; x < R; x++) {\n            int h = hid[x], v = vid[x];\n            edgeCell[(ll)h * V + v] = x;\n\n            if (h == hs || v == vs) continue;\n            hk.adj[h].push_back(v);\n        }\n\n        for (int h = 0; h < H; h++) {\n            sort(hk.adj[h].begin(), hk.adj[h].end());\n            hk.adj[h].erase(unique(hk.adj[h].begin(), hk.adj[h].end()), hk.adj[h].end());\n        }\n\n        hk.max_matching();\n        auto [coverH, coverV] = hk.min_vertex_cover();\n\n        HopcroftKarp hk2(H, V);\n        for (int x = 0; x < R; x++) {\n            int h = hid[x], v = vid[x];\n            if (coverH[h] && coverV[v]) {\n                hk2.adj[h].push_back(v);\n            }\n        }\n\n        for (int h = 0; h < H; h++) {\n            sort(hk2.adj[h].begin(), hk2.adj[h].end());\n            hk2.adj[h].erase(unique(hk2.adj[h].begin(), hk2.adj[h].end()), hk2.adj[h].end());\n        }\n\n        hk2.max_matching();\n\n        vector<char> doneH(H, 0), doneV(V, 0);\n\n        for (int h = 0; h < H; h++) {\n            int v = hk2.pairU[h];\n            if (v != -1 && coverH[h] && coverV[v]) {\n                auto it = edgeCell.find((ll)h * V + v);\n                if (it != edgeCell.end()) {\n                    mvcSelected.push_back(it->second);\n                    doneH[h] = 1;\n                    doneV[v] = 1;\n                }\n            }\n        }\n\n        auto best_cell_in_list = [&](const vector<int>& cells) {\n            int best = cells[0];\n            int bestScore = INT_MAX;\n\n            for (int x : cells) {\n                int score =\n                    10 * (abs(ri[x] - si) + abs(rj[x] - sj))\n                    - (int)hCells[hid[x]].size()\n                    - (int)vCells[vid[x]].size();\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = x;\n                }\n            }\n\n            return best;\n        };\n\n        for (int h = 0; h < H; h++) {\n            if (coverH[h] && !doneH[h]) {\n                mvcSelected.push_back(best_cell_in_list(hCells[h]));\n                doneH[h] = 1;\n            }\n        }\n\n        for (int v = 0; v < V; v++) {\n            if (coverV[v] && !doneV[v]) {\n                mvcSelected.push_back(best_cell_in_list(vCells[v]));\n                doneV[v] = 1;\n            }\n        }\n\n        mvcSelected = reduce_selected(mvcSelected);\n        mvcValid = selected_covers_all(mvcSelected);\n    }\n\n    // Build union node set for all candidate waypoints.\n    vector<int> nodeRid;\n    nodeRid.push_back(startRid);\n\n    vector<int> ridToNode(R, -1);\n    ridToNode[startRid] = 0;\n\n    auto add_nodes = [&](const vector<int>& selected) {\n        for (int x : selected) {\n            if (ridToNode[x] == -1) {\n                ridToNode[x] = (int)nodeRid.size();\n                nodeRid.push_back(x);\n            }\n        }\n    };\n\n    add_nodes(greedySelected);\n    if (mvcValid) add_nodes(mvcSelected);\n\n    int G = (int)nodeRid.size();\n\n    vector<vector<pair<int,int>>> adj(R);\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n\n    for (int x = 0; x < R; x++) {\n        int i = ri[x], j = rj[x];\n\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d];\n            int nj = j + dj[d];\n\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && id[ni][nj] != -1) {\n                int y = id[ni][nj];\n                adj[x].push_back({y, cost[y]});\n            }\n        }\n    }\n\n    const int INF = 1e9;\n\n    vector<vector<int>> distMat(G, vector<int>(G, INF));\n    vector<vector<short>> prevNode(G, vector<short>(R, -1));\n\n    for (int s = 0; s < G; s++) {\n        int src = nodeRid[s];\n\n        vector<int> dist(R, INF);\n        vector<short> pre(R, -1);\n\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n\n        dist[src] = 0;\n        pq.push({0, src});\n\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top();\n            pq.pop();\n\n            if (cd != dist[v]) continue;\n\n            for (auto [to, w] : adj[v]) {\n                int nd = cd + w;\n\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pre[to] = (short)v;\n                    pq.push({nd, to});\n                }\n            }\n        }\n\n        prevNode[s].swap(pre);\n\n        for (int t = 0; t < G; t++) {\n            distMat[s][t] = dist[nodeRid[t]];\n        }\n    }\n\n    vector<int> nodeCost(G);\n    for (int i = 0; i < G; i++) nodeCost[i] = cost[nodeRid[i]];\n\n    auto cycleCost = [&](const vector<int>& cyc) -> ll {\n        ll res = 0;\n        int m = (int)cyc.size();\n\n        for (int i = 0; i < m; i++) {\n            res += distMat[cyc[i]][cyc[(i + 1) % m]];\n        }\n\n        return res;\n    };\n\n    auto symDist = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        return distMat[a][b] + nodeCost[a];\n    };\n\n    auto improve_cycle = [&](vector<int>& cycle, double endTime) {\n        if ((int)cycle.size() > 760) return;\n\n        while (timer.elapsed() < endTime) {\n            int m = (int)cycle.size();\n\n            ll bestDelta = 0;\n            int bestType = 0;\n            int bestL = -1, bestR = -1;\n            int bestI = -1, bestPos = -1;\n\n            // 2-opt. Valid because dist(u,v)+cost(u) is symmetric.\n            for (int l = 1; l < m - 1; l++) {\n                if ((l & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                for (int r = l + 1; r < m; r++) {\n                    int a = cycle[l - 1];\n                    int b = cycle[l];\n                    int c = cycle[r];\n                    int d = cycle[(r + 1) % m];\n\n                    ll delta =\n                        (ll)symDist(a, c) + symDist(b, d)\n                        - symDist(a, b) - symDist(c, d);\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 1;\n                        bestL = l;\n                        bestR = r;\n                    }\n                }\n            }\n\n            // Single-node relocation.\n            for (int i = 1; i < m; i++) {\n                if ((i & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                int x = cycle[i];\n                int a = cycle[i - 1];\n                int b = cycle[(i + 1) % m];\n\n                ll removeDelta =\n                    (ll)distMat[a][b]\n                    - distMat[a][x]\n                    - distMat[x][b];\n\n                for (int pos = 0; pos < m; pos++) {\n                    if (pos == i || pos == i - 1) continue;\n\n                    int c = cycle[pos];\n                    int d = cycle[(pos + 1) % m];\n\n                    ll delta =\n                        removeDelta\n                        + (ll)distMat[c][x]\n                        + distMat[x][d]\n                        - distMat[c][d];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 2;\n                        bestI = i;\n                        bestPos = pos;\n                    }\n                }\n            }\n\n            if (bestType == 0) break;\n\n            if (bestType == 1) {\n                reverse(cycle.begin() + bestL, cycle.begin() + bestR + 1);\n            } else {\n                int x = cycle[bestI];\n                cycle.erase(cycle.begin() + bestI);\n\n                int insertIdx;\n                if (bestPos < bestI) insertIdx = bestPos + 1;\n                else insertIdx = bestPos;\n\n                cycle.insert(cycle.begin() + insertIdx, x);\n            }\n        }\n    };\n\n    auto construct_cycle = [&](const vector<int>& selected) {\n        vector<int> localNodes;\n        localNodes.push_back(0);\n\n        for (int x : selected) {\n            int g = ridToNode[x];\n            if (g > 0) localNodes.push_back(g);\n        }\n\n        sort(localNodes.begin() + 1, localNodes.end());\n        localNodes.erase(unique(localNodes.begin(), localNodes.end()), localNodes.end());\n\n        int M = (int)localNodes.size();\n\n        vector<int> cycle;\n\n        if (M == 1) {\n            cycle = {0};\n        } else if (M <= 430) {\n            cycle = {0};\n\n            vector<int> unused;\n            for (int i = 1; i < M; i++) unused.push_back(localNodes[i]);\n\n            while (!unused.empty()) {\n                int bestUIdx = -1;\n                int bestPos = -1;\n                int bestDelta = INF;\n\n                for (int ui = 0; ui < (int)unused.size(); ui++) {\n                    int x = unused[ui];\n                    int m = (int)cycle.size();\n\n                    for (int p = 0; p < m; p++) {\n                        int a = cycle[p];\n                        int b = cycle[(p + 1) % m];\n\n                        int delta =\n                            distMat[a][x]\n                            + distMat[x][b]\n                            - distMat[a][b];\n\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestUIdx = ui;\n                            bestPos = p;\n                        }\n                    }\n                }\n\n                int x = unused[bestUIdx];\n                cycle.insert(cycle.begin() + bestPos + 1, x);\n                unused.erase(unused.begin() + bestUIdx);\n            }\n        } else {\n            vector<char> used(G, 0);\n            cycle = {0};\n            used[0] = 1;\n\n            int cur = 0;\n\n            for (int step = 1; step < M; step++) {\n                int best = -1;\n                int bd = INF;\n\n                for (int x : localNodes) {\n                    if (!used[x] && distMat[cur][x] < bd) {\n                        bd = distMat[cur][x];\n                        best = x;\n                    }\n                }\n\n                used[best] = 1;\n                cycle.push_back(best);\n                cur = best;\n            }\n        }\n\n        return cycle;\n    };\n\n    vector<int> greedyCycle = construct_cycle(greedySelected);\n    vector<int> mvcCycle;\n\n    if (mvcValid) {\n        mvcCycle = construct_cycle(mvcSelected);\n    }\n\n    // Light optimization for candidate comparison.\n    if (mvcValid) {\n        improve_cycle(greedyCycle, min(1.45, timer.elapsed() + 0.35));\n        improve_cycle(mvcCycle, min(1.85, timer.elapsed() + 0.35));\n    }\n\n    vector<int> cycle;\n\n    if (mvcValid && cycleCost(mvcCycle) < cycleCost(greedyCycle)) {\n        cycle = mvcCycle;\n    } else {\n        cycle = greedyCycle;\n    }\n\n    // Spend remaining time optimizing the selected candidate.\n    improve_cycle(cycle, 2.10);\n\n    auto reconstructPath = [&](int srcNode, int dstNode) {\n        vector<int> path;\n\n        int src = nodeRid[srcNode];\n        int dst = nodeRid[dstNode];\n\n        int cur = dst;\n\n        while (cur != src) {\n            path.push_back(cur);\n            cur = prevNode[srcNode][cur];\n\n            if (cur < 0) break;\n        }\n\n        path.push_back(src);\n        reverse(path.begin(), path.end());\n\n        return path;\n    };\n\n    struct EdgeCache {\n        int G, W, R;\n        const vector<int>& nodeRid;\n        const vector<vector<short>>& prevNode;\n        const vector<uint64_t>& coverBits;\n        vector<uint64_t> data;\n        vector<unsigned char> done;\n\n        EdgeCache(\n            int G_,\n            int W_,\n            int R_,\n            const vector<int>& nodeRid_,\n            const vector<vector<short>>& prevNode_,\n            const vector<uint64_t>& coverBits_\n        )\n            : G(G_), W(W_), R(R_), nodeRid(nodeRid_),\n              prevNode(prevNode_), coverBits(coverBits_) {\n            data.assign((ll)G * G * W, 0);\n            done.assign((ll)G * G, 0);\n        }\n\n        uint64_t* get(int a, int b) {\n            ll idx = (ll)a * G + b;\n            uint64_t* ret = &data[idx * W];\n\n            if (done[idx]) return ret;\n            done[idx] = 1;\n\n            int src = nodeRid[a];\n            int dst = nodeRid[b];\n\n            vector<int> path;\n            int cur = dst;\n\n            while (cur != src) {\n                path.push_back(cur);\n                cur = prevNode[a][cur];\n\n                if (cur < 0) break;\n            }\n\n            path.push_back(src);\n\n            for (int x : path) {\n                const uint64_t* bs = &coverBits[(ll)x * W];\n\n                for (int w = 0; w < W; w++) {\n                    ret[w] |= bs[w];\n                }\n            }\n\n            return ret;\n        }\n    };\n\n    // Remove redundant waypoints if actual shortest-path route still sees all cells.\n    if (G <= 600 && timer.elapsed() < 2.22) {\n        EdgeCache cache(G, W, R, nodeRid, prevNode, coverBits);\n\n        while ((int)cycle.size() > 1 && timer.elapsed() < 2.78) {\n            int m = (int)cycle.size();\n\n            vector<uint64_t> pref((ll)(m + 1) * W, 0);\n            vector<uint64_t> suff((ll)(m + 1) * W, 0);\n\n            for (int e = 0; e < m; e++) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n\n                for (int w = 0; w < W; w++) {\n                    pref[(ll)(e + 1) * W + w] =\n                        pref[(ll)e * W + w] | ec[w];\n                }\n            }\n\n            for (int e = m - 1; e >= 0; e--) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n\n                for (int w = 0; w < W; w++) {\n                    suff[(ll)e * W + w] =\n                        suff[(ll)(e + 1) * W + w] | ec[w];\n                }\n            }\n\n            int bestP = -1;\n            ll bestSave = 0;\n            vector<uint64_t> tmp(W);\n\n            for (int p = 1; p < m; p++) {\n                int prv = cycle[p - 1];\n                int x = cycle[p];\n                int nxt = cycle[(p + 1) % m];\n\n                ll save =\n                    (ll)distMat[prv][x]\n                    + distMat[x][nxt]\n                    - distMat[prv][nxt];\n\n                if (save <= bestSave) continue;\n\n                uint64_t* ec = cache.get(prv, nxt);\n\n                for (int w = 0; w < W; w++) {\n                    tmp[w] =\n                        pref[(ll)(p - 1) * W + w]\n                        | suff[(ll)(p + 1) * W + w]\n                        | ec[w];\n                }\n\n                bool ok = true;\n\n                for (int w = 0; w < W; w++) {\n                    if ((tmp[w] & fullMask[w]) != fullMask[w]) {\n                        ok = false;\n                        break;\n                    }\n                }\n\n                if (ok) {\n                    bestSave = save;\n                    bestP = p;\n                }\n            }\n\n            if (bestP == -1) break;\n\n            cycle.erase(cycle.begin() + bestP);\n        }\n    }\n\n    string ans;\n\n    auto moveChar = [&](int a, int b) -> char {\n        int da = ri[b] - ri[a];\n        int db = rj[b] - rj[a];\n\n        if (da == -1) return 'U';\n        if (da == 1) return 'D';\n        if (db == -1) return 'L';\n        return 'R';\n    };\n\n    int m = (int)cycle.size();\n\n    for (int e = 0; e < m; e++) {\n        int a = cycle[e];\n        int b = cycle[(e + 1) % m];\n\n        vector<int> path = reconstructPath(a, b);\n\n        for (int k = 1; k < (int)path.size(); k++) {\n            ans.push_back(moveChar(path[k - 1], path[k]));\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Record {\n    int task;\n    int dur;\n};\n\nint N, M, K, R;\nvector<vector<int>> D;\nvector<vector<int>> children_;\nvector<int> remdep;\nvector<int> status_; // -1:not started, 0:running, 1:done\n\nvector<vector<int>> skill_est;\nvector<vector<Record>> records_;\nvector<int> member_task;\nvector<int> member_start;\n\nvector<double> bottom_priority;\nvector<double> min_cost, avg_cost;\nvector<double> reach_score;\n\nconst int MAX_SKILL = 70;\n\ndouble base_skill;\nconst double PRIOR_COMP = 0.008;\nconst double PRIOR_NORM = 0.003;\nconst double NORM_TARGET = 40.0;\n\ninline double obsPenalty(int w, int t) {\n    static const double p1[5] = {\n        0.0,\n        -log(4.0 / 7.0),\n        -log(3.0 / 7.0),\n        -log(2.0 / 7.0),\n        -log(1.0 / 7.0)\n    };\n\n    if (t == 1) {\n        if (w <= 4) return p1[w];\n        double x = w - 4;\n        return 3.0 + 2.0 * x * x;\n    } else {\n        if (w == 0) {\n            return 5.0 + 1.0 * t * t;\n        }\n        int lo = max(1, t - 3);\n        int hi = t + 3;\n        if (w < lo) {\n            double x = lo - w;\n            return 2.0 * x * x;\n        }\n        if (w > hi) {\n            double x = w - hi;\n            return 2.0 * x * x;\n        }\n        return 1.0 + 0.04 * abs(w - t);\n    }\n}\n\ninline int calcWTaskSkill(int task, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; k++) {\n        if (D[task][k] > s[k]) w += D[task][k] - s[k];\n    }\n    return w;\n}\n\ninline double expectedDurationFromWInt(int w) {\n    if (w == 0) return 1.0;\n    if (w == 1) return 13.0 / 7.0;\n    if (w == 2) return 17.0 / 7.0;\n    if (w == 3) return 22.0 / 7.0;\n    return (double)w;\n}\n\ninline double expectedDurationFromWDouble(double w) {\n    if (w <= 0.0) return 1.0;\n\n    static const double table[5] = {\n        1.0,\n        13.0 / 7.0,\n        17.0 / 7.0,\n        22.0 / 7.0,\n        4.0\n    };\n\n    if (w < 4.0) {\n        int a = (int)floor(w);\n        double f = w - a;\n        return table[a] * (1.0 - f) + table[a + 1] * f;\n    }\n\n    return w;\n}\n\ninline double memberConfidence(int mem) {\n    int c = (int)records_[mem].size();\n\n    // Conservative early, almost fully trusted after sufficient observations.\n    return (double)c / ((double)c + 3.5);\n}\n\ninline double expectedDuration(int task, int mem) {\n    const auto& s = skill_est[mem];\n\n    double conf = memberConfidence(mem);\n    double w = 0.0;\n\n    for (int k = 0; k < K; k++) {\n        double eff_skill = base_skill + conf * ((double)s[k] - base_skill);\n        if ((double)D[task][k] > eff_skill) {\n            w += (double)D[task][k] - eff_skill;\n        }\n    }\n\n    return expectedDurationFromWDouble(w);\n}\n\nvoid optimizeMember(int mem) {\n    auto& recs = records_[mem];\n    if (recs.empty()) return;\n\n    vector<int>& s = skill_est[mem];\n    int Rm = (int)recs.size();\n\n    vector<int> curW(Rm, 0);\n    for (int r = 0; r < Rm; r++) {\n        curW[r] = calcWTaskSkill(recs[r].task, s);\n    }\n\n    double sumsq = 0.0;\n    for (int k = 0; k < K; k++) sumsq += 1.0 * s[k] * s[k];\n\n    int passes = 3;\n    if (Rm >= 12) passes = 4;\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool changed_any = false;\n\n        for (int k = 0; k < K; k++) {\n            int old = s[k];\n\n            double bestObj = 1e100;\n            int bestVal = old;\n\n            for (int val = 0; val <= MAX_SKILL; val++) {\n                double obj = 0.0;\n\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    int oldContrib = max(0, D[task][k] - old);\n                    int newContrib = max(0, D[task][k] - val);\n                    int nw = curW[r] - oldContrib + newContrib;\n                    obj += obsPenalty(nw, recs[r].dur);\n                }\n\n                double compPrior = PRIOR_COMP * (val - base_skill) * (val - base_skill);\n\n                double nsumsq = sumsq - 1.0 * old * old + 1.0 * val * val;\n                double norm = sqrt(nsumsq);\n                double normPrior = PRIOR_NORM * (norm - NORM_TARGET) * (norm - NORM_TARGET);\n\n                obj += compPrior + normPrior;\n\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestVal = val;\n                }\n            }\n\n            if (bestVal != old) {\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    curW[r] -= max(0, D[task][k] - old);\n                    curW[r] += max(0, D[task][k] - bestVal);\n                }\n\n                sumsq = sumsq - 1.0 * old * old + 1.0 * bestVal * bestVal;\n                s[k] = bestVal;\n                changed_any = true;\n            }\n        }\n\n        if (!changed_any) break;\n    }\n}\n\nvoid precomputeReachScore() {\n    vector<double> dp(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        double v = 0.0;\n\n        for (int c : children_[i]) {\n            v += 1.0 + dp[c];\n            if (v > 1e6) {\n                v = 1e6;\n                break;\n            }\n        }\n\n        dp[i] = v;\n    }\n\n    reach_score.assign(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        reach_score[i] = log1p(dp[i]);\n    }\n}\n\nvoid recomputePriorities() {\n    min_cost.assign(N, 0.0);\n    avg_cost.assign(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        if (status_[i] == 1) {\n            min_cost[i] = avg_cost[i] = 0.0;\n            continue;\n        }\n\n        double mn = 1e100;\n        double sum = 0.0;\n\n        for (int j = 0; j < M; j++) {\n            double e = expectedDuration(i, j);\n            mn = min(mn, e);\n            sum += e;\n        }\n\n        min_cost[i] = mn;\n        avg_cost[i] = sum / M;\n    }\n\n    bottom_priority.assign(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        if (status_[i] == 1) {\n            bottom_priority[i] = 0.0;\n            continue;\n        }\n\n        double nodeCost = 0.7 * min_cost[i] + 0.3 * avg_cost[i];\n\n        double mx = 0.0;\n        for (int c : children_[i]) {\n            mx = max(mx, bottom_priority[c]);\n        }\n\n        bottom_priority[i] = nodeCost + mx;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K >> R;\n\n    D.assign(N, vector<int>(K));\n\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) cin >> D[i][k];\n    }\n\n    children_.assign(N, {});\n    remdep.assign(N, 0);\n\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u;\n        --v;\n\n        children_[u].push_back(v);\n        remdep[v]++;\n    }\n\n    base_skill = 35.0 / sqrt((double)K);\n    int init_skill = max(0, (int)round(base_skill));\n\n    skill_est.assign(M, vector<int>(K, init_skill));\n    records_.assign(M, {});\n\n    status_.assign(N, -1);\n    member_task.assign(M, -1);\n    member_start.assign(M, -1);\n\n    precomputeReachScore();\n\n    for (int day = 1; day <= 2000; day++) {\n        recomputePriorities();\n\n        vector<int> free_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready;\n        for (int i = 0; i < N; i++) {\n            if (status_[i] == -1 && remdep[i] == 0) ready.push_back(i);\n        }\n\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (bottom_priority[a] != bottom_priority[b]) {\n                return bottom_priority[a] > bottom_priority[b];\n            }\n            if (reach_score[a] != reach_score[b]) {\n                return reach_score[a] > reach_score[b];\n            }\n            return a < b;\n        });\n\n        vector<pair<int, int>> assignments;\n\n        while (!free_members.empty()) {\n            int bestFi = -1;\n            int bestTask = -1;\n            double bestScore = -1e100;\n\n            int limit = min((int)ready.size(), 300);\n\n            for (int fi = 0; fi < (int)free_members.size(); fi++) {\n                int mem = free_members[fi];\n\n                for (int idx = 0; idx < limit; idx++) {\n                    int task = ready[idx];\n\n                    if (status_[task] != -1) continue;\n\n                    double pred = expectedDuration(task, mem);\n\n                    double score =\n                        bottom_priority[task]\n                        + 0.15 * reach_score[task]\n                        - 0.70 * pred\n                        + 0.20 * (avg_cost[task] - pred);\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestFi = fi;\n                        bestTask = task;\n                    }\n                }\n            }\n\n            if (bestFi == -1) break;\n\n            int mem = free_members[bestFi];\n\n            status_[bestTask] = 0;\n            member_task[mem] = bestTask;\n            member_start[mem] = day;\n\n            assignments.push_back({mem, bestTask});\n\n            free_members.erase(free_members.begin() + bestFi);\n        }\n\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << mem + 1 << ' ' << task + 1;\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        for (int i = 0; i < cnt; i++) {\n            int f;\n            cin >> f;\n            --f;\n\n            int task = member_task[f];\n            if (task < 0) continue;\n\n            int dur = day - member_start[f] + 1;\n\n            status_[task] = 1;\n            member_task[f] = -1;\n            member_start[f] = -1;\n\n            records_[f].push_back({task, dur});\n            optimizeMember(f);\n\n            for (int c : children_[task]) {\n                remdep[c]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int ax, ay, cx, cy;\n    int score;\n};\n\nstruct Node {\n    int x, y;\n    int id;   // -1 depot\n    int type; // 0 pickup, 1 delivery\n};\n\nstruct InsertInfo {\n    int cost;\n    int pgap;\n    int dgap;\n};\n\nstruct State {\n    vector<Node> route;\n    vector<int> selected;\n    vector<char> used;\n    int cost;\n};\n\nstatic const int N = 1000;\nstatic const int K = 50;\nstatic const int DEP = 400;\nstatic const int INF = 1e9;\n\nvector<Order> ords;\nchrono::steady_clock::time_point start_time;\n\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\ninline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline int ndist(const Node& a, const Node& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\ninline Node pickupNode(int id) {\n    return Node{ords[id].ax, ords[id].ay, id, 0};\n}\n\ninline Node deliveryNode(int id) {\n    return Node{ords[id].cx, ords[id].cy, id, 1};\n}\n\nint routeCost(const vector<Node>& route) {\n    int res = 0;\n    for (int i = 0; i + 1 < (int)route.size(); i++) {\n        res += ndist(route[i], route[i + 1]);\n    }\n    return res;\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    double nextDouble() {\n        return (next() + 0.5) / 4294967296.0;\n    }\n\n    int randint(int l, int r) {\n        return l + (int)(next() % (uint32_t)(r - l + 1));\n    }\n};\n\nXorShift rng;\n\nInsertInfo bestInsert(const vector<Node>& route, int oid) {\n    const int L = (int)route.size();\n\n    const int px = ords[oid].ax;\n    const int py = ords[oid].ay;\n    const int dx = ords[oid].cx;\n    const int dy = ords[oid].cy;\n\n    int best = INF;\n    int bestP = -1;\n    int bestD = -1;\n\n    for (int i = 0; i <= L - 2; i++) {\n        const Node& A = route[i];\n        const Node& B = route[i + 1];\n\n        int directAB = ndist(A, B);\n\n        int val = mdist(A.x, A.y, px, py)\n                + mdist(px, py, dx, dy)\n                + mdist(dx, dy, B.x, B.y)\n                - directAB;\n\n        if (val < best) {\n            best = val;\n            bestP = i;\n            bestD = i;\n        }\n\n        int addPickup = mdist(A.x, A.y, px, py)\n                      + mdist(px, py, B.x, B.y)\n                      - directAB;\n\n        for (int j = i + 1; j <= L - 2; j++) {\n            const Node& C = route[j];\n            const Node& D = route[j + 1];\n\n            int addDelivery = mdist(C.x, C.y, dx, dy)\n                            + mdist(dx, dy, D.x, D.y)\n                            - ndist(C, D);\n\n            val = addPickup + addDelivery;\n\n            if (val < best) {\n                best = val;\n                bestP = i;\n                bestD = j;\n            }\n        }\n    }\n\n    return InsertInfo{best, bestP, bestD};\n}\n\nvoid applyInsert(vector<Node>& route, int oid, const InsertInfo& ins) {\n    vector<Node> nr;\n    nr.reserve(route.size() + 2);\n\n    Node P = pickupNode(oid);\n    Node D = deliveryNode(oid);\n\n    for (int i = 0; i < (int)route.size(); i++) {\n        nr.push_back(route[i]);\n\n        if (i == ins.pgap) {\n            nr.push_back(P);\n            if (ins.dgap == ins.pgap) {\n                nr.push_back(D);\n            }\n        }\n\n        if (ins.dgap > ins.pgap && i == ins.dgap) {\n            nr.push_back(D);\n        }\n    }\n\n    route.swap(nr);\n}\n\nvector<Node> removeOrder(const vector<Node>& route, int oid) {\n    vector<Node> nr;\n    nr.reserve(route.size() - 2);\n    for (const auto& v : route) {\n        if (v.id != oid) nr.push_back(v);\n    }\n    return nr;\n}\n\nbool feasibleReverse(const vector<Node>& route, int l, int r) {\n    static int p[N], d[N];\n    fill(p, p + N, -1);\n    fill(d, d + N, -1);\n\n    int n = (int)route.size();\n\n    for (int i = 1; i <= n - 2; i++) {\n        int ni = i;\n        if (l <= i && i <= r) ni = l + r - i;\n\n        const Node& v = route[i];\n        if (v.type == 0) p[v.id] = ni;\n        else d[v.id] = ni;\n    }\n\n    for (int i = 1; i <= n - 2; i++) {\n        int id = route[i].id;\n        if (p[id] != -1 && d[id] != -1 && p[id] > d[id]) {\n            return false;\n        }\n    }\n\n    return true;\n}\n\nbool feasibleSwap(const vector<Node>& route, int a, int b) {\n    static int p[N], d[N];\n    fill(p, p + N, -1);\n    fill(d, d + N, -1);\n\n    int n = (int)route.size();\n\n    for (int i = 1; i <= n - 2; i++) {\n        int ni = i;\n        if (i == a) ni = b;\n        else if (i == b) ni = a;\n\n        const Node& v = route[i];\n        if (v.type == 0) p[v.id] = ni;\n        else d[v.id] = ni;\n    }\n\n    for (int i = 1; i <= n - 2; i++) {\n        int id = route[i].id;\n        if (p[id] != -1 && d[id] != -1 && p[id] > d[id]) {\n            return false;\n        }\n    }\n\n    return true;\n}\n\nbool pairReinsertOptimize(State& st, double limitTime, int maxPass = 4) {\n    bool any = false;\n\n    for (int pass = 0; pass < maxPass && elapsed() < limitTime; pass++) {\n        bool improved = false;\n\n        for (int oid : st.selected) {\n            if (elapsed() >= limitTime) break;\n\n            vector<Node> rem = removeOrder(st.route, oid);\n            int remCost = routeCost(rem);\n\n            InsertInfo ins = bestInsert(rem, oid);\n            int newCost = remCost + ins.cost;\n\n            if (newCost < st.cost) {\n                st.route.swap(rem);\n                applyInsert(st.route, oid, ins);\n                st.cost = newCost;\n                improved = true;\n                any = true;\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nbool twoOptOptimize(State& st, double limitTime) {\n    bool any = false;\n    int n = (int)st.route.size();\n\n    while (elapsed() < limitTime) {\n        int bestDelta = 0;\n        int bestL = -1;\n        int bestR = -1;\n\n        for (int l = 1; l <= n - 3; l++) {\n            for (int r = l + 1; r <= n - 2; r++) {\n                int delta = ndist(st.route[l - 1], st.route[r])\n                          + ndist(st.route[l], st.route[r + 1])\n                          - ndist(st.route[l - 1], st.route[l])\n                          - ndist(st.route[r], st.route[r + 1]);\n\n                if (delta < bestDelta && feasibleReverse(st.route, l, r)) {\n                    bestDelta = delta;\n                    bestL = l;\n                    bestR = r;\n                }\n            }\n        }\n\n        if (bestDelta >= 0) break;\n\n        reverse(st.route.begin() + bestL, st.route.begin() + bestR + 1);\n        st.cost += bestDelta;\n        any = true;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nbool swapOptimize(State& st, double limitTime) {\n    bool any = false;\n    int n = (int)st.route.size();\n\n    while (elapsed() < limitTime) {\n        int bestDelta = 0;\n        int bestI = -1;\n        int bestJ = -1;\n\n        for (int i = 1; i <= n - 3; i++) {\n            for (int j = i + 1; j <= n - 2; j++) {\n                int delta;\n\n                if (i + 1 == j) {\n                    delta = ndist(st.route[i - 1], st.route[j])\n                          + ndist(st.route[j], st.route[i])\n                          + ndist(st.route[i], st.route[j + 1])\n                          - ndist(st.route[i - 1], st.route[i])\n                          - ndist(st.route[i], st.route[j])\n                          - ndist(st.route[j], st.route[j + 1]);\n                } else {\n                    delta = ndist(st.route[i - 1], st.route[j])\n                          + ndist(st.route[j], st.route[i + 1])\n                          + ndist(st.route[j - 1], st.route[i])\n                          + ndist(st.route[i], st.route[j + 1])\n                          - ndist(st.route[i - 1], st.route[i])\n                          - ndist(st.route[i], st.route[i + 1])\n                          - ndist(st.route[j - 1], st.route[j])\n                          - ndist(st.route[j], st.route[j + 1]);\n                }\n\n                if (delta < bestDelta && feasibleSwap(st.route, i, j)) {\n                    bestDelta = delta;\n                    bestI = i;\n                    bestJ = j;\n                }\n            }\n        }\n\n        if (bestDelta >= 0) break;\n\n        swap(st.route[bestI], st.route[bestJ]);\n        st.cost += bestDelta;\n        any = true;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nvoid routeLocalOptimize(State& st, double limitTime, bool heavy) {\n    while (elapsed() < limitTime) {\n        int before = st.cost;\n\n        pairReinsertOptimize(st, limitTime, 3);\n        twoOptOptimize(st, limitTime);\n\n        if (heavy) {\n            swapOptimize(st, limitTime);\n            twoOptOptimize(st, limitTime);\n            pairReinsertOptimize(st, limitTime, 2);\n        }\n\n        st.cost = routeCost(st.route);\n\n        if (st.cost >= before) break;\n    }\n}\n\nState constructGreedy(const vector<int>& pool, int randomTop) {\n    Node depot{DEP, DEP, -1, -1};\n\n    State st;\n    st.route = {depot, depot};\n    st.used.assign(N, 0);\n    st.selected.clear();\n    st.cost = 0;\n\n    struct Choice {\n        int cost;\n        int oid;\n        InsertInfo ins;\n    };\n\n    for (int step = 0; step < K; step++) {\n        vector<Choice> top;\n        top.reserve(randomTop);\n\n        for (int oid : pool) {\n            if (st.used[oid]) continue;\n\n            InsertInfo ins = bestInsert(st.route, oid);\n            Choice ch{ins.cost, oid, ins};\n\n            if ((int)top.size() < randomTop) {\n                top.push_back(ch);\n            } else {\n                int worst = 0;\n                for (int i = 1; i < (int)top.size(); i++) {\n                    if (top[i].cost > top[worst].cost) worst = i;\n                }\n                if (ch.cost < top[worst].cost) top[worst] = ch;\n            }\n        }\n\n        sort(top.begin(), top.end(), [](const Choice& a, const Choice& b) {\n            return a.cost < b.cost;\n        });\n\n        int idx = 0;\n        if (randomTop > 1 && (int)top.size() > 1) {\n            int lim = (int)top.size();\n            double u = rng.nextDouble();\n            idx = min(lim - 1, (int)(u * u * lim));\n        }\n\n        Choice ch = top[idx];\n\n        applyInsert(st.route, ch.oid, ch.ins);\n        st.used[ch.oid] = 1;\n        st.selected.push_back(ch.oid);\n        st.cost += ch.ins.cost;\n    }\n\n    st.cost = routeCost(st.route);\n    return st;\n}\n\nvector<int> makeClusterPool(int cx, int cy, int M) {\n    vector<pair<int, int>> v;\n    v.reserve(N);\n\n    for (int i = 0; i < N; i++) {\n        int cluster = mdist(ords[i].ax, ords[i].ay, cx, cy)\n                    + mdist(ords[i].cx, ords[i].cy, cx, cy);\n\n        int center = mdist(ords[i].ax, ords[i].ay, DEP, DEP)\n                   + mdist(ords[i].cx, ords[i].cy, DEP, DEP);\n\n        int paird = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        int sc = cluster * 10 + center * 3 + paird;\n        v.push_back({sc, i});\n    }\n\n    if (M < N) {\n        nth_element(v.begin(), v.begin() + M, v.end());\n        v.resize(M);\n    }\n\n    sort(v.begin(), v.end());\n\n    vector<int> pool;\n    pool.reserve(v.size());\n    for (auto [_, id] : v) pool.push_back(id);\n\n    return pool;\n}\n\nvoid replaceOptimize(State& st, const vector<int>& candList, double limitTime) {\n    while (elapsed() < limitTime) {\n        int bestNewCost = st.cost;\n        int bestRemove = -1;\n        int bestAdd = -1;\n\n        int checks = 0;\n        bool timeout = false;\n\n        for (int remOid : st.selected) {\n            vector<Node> remRoute = removeOrder(st.route, remOid);\n            int remCost = routeCost(remRoute);\n\n            for (int addOid : candList) {\n                if (st.used[addOid]) continue;\n\n                InsertInfo ins = bestInsert(remRoute, addOid);\n                int newCost = remCost + ins.cost;\n\n                if (newCost < bestNewCost) {\n                    bestNewCost = newCost;\n                    bestRemove = remOid;\n                    bestAdd = addOid;\n                }\n\n                if ((++checks & 255) == 0 && elapsed() > limitTime) {\n                    timeout = true;\n                    break;\n                }\n            }\n\n            if (timeout) break;\n        }\n\n        if (bestRemove == -1) break;\n\n        vector<Node> remRoute = removeOrder(st.route, bestRemove);\n        InsertInfo ins = bestInsert(remRoute, bestAdd);\n\n        st.route.swap(remRoute);\n        applyInsert(st.route, bestAdd, ins);\n\n        st.used[bestRemove] = 0;\n        st.used[bestAdd] = 1;\n\n        for (int& x : st.selected) {\n            if (x == bestRemove) {\n                x = bestAdd;\n                break;\n            }\n        }\n\n        st.cost = routeCost(st.route);\n        routeLocalOptimize(st, min(limitTime, elapsed() + 0.08), false);\n\n        if (timeout) break;\n    }\n\n    st.cost = routeCost(st.route);\n}\n\nvoid destroyRepairOptimize(State& best, const vector<int>& candList, double limitTime) {\n    vector<int> cand;\n    int lim = min((int)candList.size(), 650);\n    cand.reserve(lim);\n    for (int i = 0; i < lim; i++) cand.push_back(candList[i]);\n\n    while (elapsed() < limitTime) {\n        State cur = best;\n\n        int q = rng.randint(2, 5);\n\n        vector<pair<int, int>> saving;\n        saving.reserve(K);\n\n        for (int oid : cur.selected) {\n            vector<Node> rem = removeOrder(cur.route, oid);\n            int rc = routeCost(rem);\n            saving.push_back({cur.cost - rc, oid});\n        }\n\n        sort(saving.begin(), saving.end(), greater<pair<int, int>>());\n\n        vector<int> removed;\n        vector<char> remFlag(N, 0);\n\n        int topRange = min((int)saving.size(), 18);\n\n        for (int t = 0; t < q; t++) {\n            int idx;\n            if (rng.nextDouble() < 0.70) {\n                idx = rng.randint(0, topRange - 1);\n            } else {\n                idx = rng.randint(0, (int)saving.size() - 1);\n            }\n\n            int oid = saving[idx].second;\n            if (remFlag[oid]) {\n                t--;\n                continue;\n            }\n\n            remFlag[oid] = 1;\n            removed.push_back(oid);\n        }\n\n        vector<Node> nr;\n        nr.reserve(cur.route.size() - 2 * removed.size());\n\n        for (const Node& v : cur.route) {\n            if (v.id != -1 && remFlag[v.id]) continue;\n            nr.push_back(v);\n        }\n\n        cur.route.swap(nr);\n\n        vector<int> ns;\n        ns.reserve(K);\n        for (int oid : cur.selected) {\n            if (!remFlag[oid]) ns.push_back(oid);\n            else cur.used[oid] = 0;\n        }\n        cur.selected.swap(ns);\n        cur.cost = routeCost(cur.route);\n\n        while ((int)cur.selected.size() < K && elapsed() < limitTime) {\n            int bestAdd = -1;\n            InsertInfo bestIns{INF, -1, -1};\n\n            for (int oid : cand) {\n                if (cur.used[oid]) continue;\n\n                InsertInfo ins = bestInsert(cur.route, oid);\n\n                if (ins.cost < bestIns.cost) {\n                    bestIns = ins;\n                    bestAdd = oid;\n                }\n            }\n\n            if (bestAdd == -1) break;\n\n            applyInsert(cur.route, bestAdd, bestIns);\n            cur.used[bestAdd] = 1;\n            cur.selected.push_back(bestAdd);\n            cur.cost += bestIns.cost;\n        }\n\n        if ((int)cur.selected.size() != K) continue;\n\n        cur.cost = routeCost(cur.route);\n        routeLocalOptimize(cur, min(limitTime, elapsed() + 0.05), false);\n\n        if (cur.cost < best.cost) {\n            best = cur;\n        }\n    }\n\n    best.cost = routeCost(best.route);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    ords.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> ords[i].ax >> ords[i].ay >> ords[i].cx >> ords[i].cy;\n\n        int centerSum = mdist(DEP, DEP, ords[i].ax, ords[i].ay)\n                      + mdist(DEP, DEP, ords[i].cx, ords[i].cy);\n\n        int pairDist = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        ords[i].score = centerSum + pairDist / 2;\n    }\n\n    vector<int> allIds(N);\n    iota(allIds.begin(), allIds.end(), 0);\n\n    vector<int> sortedIds = allIds;\n    sort(sortedIds.begin(), sortedIds.end(), [](int a, int b) {\n        return ords[a].score < ords[b].score;\n    });\n\n    State best = constructGreedy(allIds, 1);\n    routeLocalOptimize(best, 0.35, true);\n\n    vector<int> centerPool;\n    for (int i = 0; i < 700; i++) centerPool.push_back(sortedIds[i]);\n\n    int iter = 0;\n\n    while (elapsed() < 1.05) {\n        vector<int> pool;\n\n        if (iter % 4 == 0) {\n            int base = sortedIds[rng.randint(0, 499)];\n            int cx = (ords[base].ax + ords[base].cx) / 2 + rng.randint(-80, 80);\n            int cy = (ords[base].ay + ords[base].cy) / 2 + rng.randint(-80, 80);\n\n            cx = max(150, min(650, cx));\n            cy = max(150, min(650, cy));\n\n            pool = makeClusterPool(cx, cy, 420);\n        } else if (iter % 4 == 1) {\n            pool = makeClusterPool(\n                400 + rng.randint(-160, 160),\n                400 + rng.randint(-160, 160),\n                420\n            );\n        } else {\n            pool = centerPool;\n        }\n\n        State cur = constructGreedy(pool, 7);\n        routeLocalOptimize(cur, min(1.20, elapsed() + 0.05), false);\n\n        if (cur.cost < best.cost) {\n            best = cur;\n        }\n\n        iter++;\n    }\n\n    routeLocalOptimize(best, 1.35, true);\n\n    vector<int> replaceCand;\n    for (int i = 0; i < 850; i++) replaceCand.push_back(sortedIds[i]);\n\n    replaceOptimize(best, replaceCand, 1.80);\n\n    destroyRepairOptimize(best, replaceCand, 1.92);\n\n    routeLocalOptimize(best, 1.97, true);\n\n    cout << K;\n    for (int oid : best.selected) {\n        cout << ' ' << oid + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (const Node& v : best.route) {\n        cout << ' ' << v.x << ' ' << v.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 400;\nstatic constexpr int M = 1995;\nstatic constexpr int SAMPLES = 24;\nstatic constexpr long long INF = (1LL << 60);\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n};\n\nstruct DSU {\n    int p[N];\n    int sz[N];\n\n    void init() {\n        for (int i = 0; i < N; i++) {\n            p[i] = i;\n            sz[i] = 1;\n        }\n    }\n\n    int find(int x) const {\n        while (p[x] != x) x = p[x];\n        return x;\n    }\n\n    bool same(int a, int b) const {\n        return find(a) == find(b);\n    }\n\n    bool unite(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n        if (ra == rb) return false;\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<int> u(M), v(M), d(M);\n    for (int i = 0; i < M; i++) {\n        cin >> u[i] >> v[i];\n\n        long long dx = x[u[i]] - x[v[i]];\n        long long dy = y[u[i]] - y[v[i]];\n        d[i] = int(floor(sqrt(double(dx * dx + dy * dy)) + 0.5));\n    }\n\n    XorShift rng;\n\n    vector<vector<int>> sampled_w(SAMPLES, vector<int>(M));\n    vector<vector<int>> order(SAMPLES, vector<int>(M));\n\n    for (int s = 0; s < SAMPLES; s++) {\n        for (int i = 0; i < M; i++) {\n            sampled_w[s][i] = rng.randint(d[i], 3 * d[i]);\n            order[s][i] = i;\n        }\n\n        sort(order[s].begin(), order[s].end(), [&](int a, int b) {\n            if (sampled_w[s][a] != sampled_w[s][b]) {\n                return sampled_w[s][a] < sampled_w[s][b];\n            }\n            return a < b;\n        });\n    }\n\n    DSU accepted;\n    accepted.init();\n\n    int accepted_edges = 0;\n\n    for (int cur = 0; cur < M; cur++) {\n        int len;\n        cin >> len;\n\n        int answer = 0;\n\n        if (!accepted.same(u[cur], v[cur])) {\n            int base_components = N - accepted_edges;\n\n            long long sum_delta = 0;\n            bool reject_impossible = false;\n\n            for (int s = 0; s < SAMPLES; s++) {\n                DSU dsu_reject = accepted;\n                DSU dsu_accept = accepted;\n\n                int comp_reject = base_components;\n                int comp_accept = base_components;\n\n                long long cost_reject = 0;\n                long long cost_accept = len;\n\n                if (dsu_accept.unite(u[cur], v[cur])) {\n                    comp_accept--;\n                }\n\n                for (int pos = 0; pos < M; pos++) {\n                    if (comp_reject == 1 && comp_accept == 1) break;\n\n                    int e = order[s][pos];\n                    if (e <= cur) continue;\n\n                    int a = u[e];\n                    int b = v[e];\n                    int w = sampled_w[s][e];\n\n                    if (comp_reject > 1 && dsu_reject.unite(a, b)) {\n                        cost_reject += w;\n                        comp_reject--;\n                    }\n\n                    if (comp_accept > 1 && dsu_accept.unite(a, b)) {\n                        cost_accept += w;\n                        comp_accept--;\n                    }\n                }\n\n                if (comp_reject > 1) {\n                    reject_impossible = true;\n                    break;\n                }\n\n                if (comp_accept > 1) {\n                    cost_accept = INF;\n                }\n\n                sum_delta += cost_accept - cost_reject;\n            }\n\n            if (reject_impossible || sum_delta < 0) {\n                answer = 1;\n                accepted.unite(u[cur], v[cur]);\n                accepted_edges++;\n            }\n        }\n\n        cout << answer << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct Task {\n    int sx, sy;\n    int wx, wy;\n};\n\nstruct Plan {\n    // kind: 0 = corner rectangle, 1 = strip\n    // corner ori: 0 TL, 1 TR, 2 BL, 3 BR\n    // strip  ori: 0 top, 1 bottom, 2 left, 3 right\n    int kind = 0;\n    int ori = 0;\n    int H = 10;\n    int W = 10;\n    int plannedPets = 0;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\n\nbool wall_[31][31];\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char mvChar[4] = {'U', 'D', 'L', 'R'};\nconst char buildChar[4] = {'u', 'd', 'l', 'r'};\n\nPlan plan_;\nint x1_, x2_, y1_, y2_;\nvector<Task> tasks;\n\nbool inBoard(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nbool passable(int x, int y) {\n    return inBoard(x, y) && !wall_[x][y];\n}\n\nvoid getBoundsParam(const Plan &p, int &x1, int &x2, int &y1, int &y2) {\n    if (p.kind == 0) {\n        int H = p.H;\n        int W = p.W;\n\n        if (p.ori == 0) {\n            x1 = 1;\n            x2 = H;\n            y1 = 1;\n            y2 = W;\n        } else if (p.ori == 1) {\n            x1 = 1;\n            x2 = H;\n            y1 = 31 - W;\n            y2 = 30;\n        } else if (p.ori == 2) {\n            x1 = 31 - H;\n            x2 = 30;\n            y1 = 1;\n            y2 = W;\n        } else {\n            x1 = 31 - H;\n            x2 = 30;\n            y1 = 31 - W;\n            y2 = 30;\n        }\n    } else {\n        int S = p.H;\n\n        if (p.ori == 0) {\n            x1 = 1;\n            x2 = S;\n            y1 = 1;\n            y2 = 30;\n        } else if (p.ori == 1) {\n            x1 = 31 - S;\n            x2 = 30;\n            y1 = 1;\n            y2 = 30;\n        } else if (p.ori == 2) {\n            x1 = 1;\n            x2 = 30;\n            y1 = 1;\n            y2 = S;\n        } else {\n            x1 = 1;\n            x2 = 30;\n            y1 = 31 - S;\n            y2 = 30;\n        }\n    }\n}\n\nvoid setRegionBounds() {\n    getBoundsParam(plan_, x1_, x2_, y1_, y2_);\n}\n\nbool insideRegion(int x, int y) {\n    return x1_ <= x && x <= x2_ && y1_ <= y && y <= y2_;\n}\n\nbool insideParam(int x, int y, const Plan &p) {\n    int a, b, c, d;\n    getBoundsParam(p, a, b, c, d);\n    return a <= x && x <= b && c <= y && y <= d;\n}\n\nint areaOfPlan(const Plan &p) {\n    if (p.kind == 0) return p.H * p.W;\n    return p.H * 30;\n}\n\nint taskCountOfPlan(const Plan &p) {\n    if (p.kind == 0) return p.H + p.W;\n    return 30;\n}\n\nint distToRegion(int x, int y, const Plan &p) {\n    int a, b, c, d;\n    getBoundsParam(p, a, b, c, d);\n\n    int res = 0;\n    if (x < a) res += a - x;\n    if (x > b) res += x - b;\n    if (y < c) res += c - y;\n    if (y > d) res += y - d;\n    return res;\n}\n\nint petsInsidePlan(const Plan &p) {\n    int cnt = 0;\n    for (auto &pet : pets) {\n        if (insideParam(pet.x, pet.y, p)) cnt++;\n    }\n    return cnt;\n}\n\nint petsInsideCurrent() {\n    int cnt = 0;\n    for (auto &pet : pets) {\n        if (insideRegion(pet.x, pet.y)) cnt++;\n    }\n    return cnt;\n}\n\nvoid makeTasks() {\n    tasks.clear();\n    setRegionBounds();\n\n    if (plan_.kind == 0) {\n        int H = plan_.H;\n        int W = plan_.W;\n\n        if (plan_.ori == 0) {\n            // top-left\n            for (int c = 1; c <= W; c++) {\n                tasks.push_back({H, c, H + 1, c});\n            }\n            for (int r = 1; r <= H; r++) {\n                tasks.push_back({r, W, r, W + 1});\n            }\n        } else if (plan_.ori == 1) {\n            // top-right\n            int L = 31 - W;\n            for (int c = L; c <= 30; c++) {\n                tasks.push_back({H, c, H + 1, c});\n            }\n            for (int r = 1; r <= H; r++) {\n                tasks.push_back({r, L, r, L - 1});\n            }\n        } else if (plan_.ori == 2) {\n            // bottom-left\n            int U = 31 - H;\n            for (int c = 1; c <= W; c++) {\n                tasks.push_back({U, c, U - 1, c});\n            }\n            for (int r = U; r <= 30; r++) {\n                tasks.push_back({r, W, r, W + 1});\n            }\n        } else {\n            // bottom-right\n            int U = 31 - H;\n            int L = 31 - W;\n            for (int c = L; c <= 30; c++) {\n                tasks.push_back({U, c, U - 1, c});\n            }\n            for (int r = U; r <= 30; r++) {\n                tasks.push_back({r, L, r, L - 1});\n            }\n        }\n    } else {\n        int S = plan_.H;\n\n        if (plan_.ori == 0) {\n            // top strip, rows [1,S], wall row S+1\n            for (int c = 1; c <= 30; c++) {\n                tasks.push_back({S, c, S + 1, c});\n            }\n        } else if (plan_.ori == 1) {\n            // bottom strip\n            int U = 31 - S;\n            for (int c = 1; c <= 30; c++) {\n                tasks.push_back({U, c, U - 1, c});\n            }\n        } else if (plan_.ori == 2) {\n            // left strip\n            for (int r = 1; r <= 30; r++) {\n                tasks.push_back({r, S, r, S + 1});\n            }\n        } else {\n            // right strip\n            int L = 31 - S;\n            for (int r = 1; r <= 30; r++) {\n                tasks.push_back({r, L, r, L - 1});\n            }\n        }\n    }\n}\n\ndouble evaluatePlan(const Plan &p, bool conservativeStripPenalty) {\n    int pcnt = petsInsidePlan(p);\n\n    double avgDist = 0;\n    for (auto &h : humans) {\n        avgDist += distToRegion(h.x, h.y, p);\n    }\n    avgDist /= M;\n\n    int area = areaOfPlan(p);\n    int taskCnt = taskCountOfPlan(p);\n\n    double val = area * pow(0.5, pcnt)\n               - 1.8 * avgDist\n               - 0.35 * taskCnt;\n\n    if (p.kind == 1 && conservativeStripPenalty) {\n        // Strips have large openings while under construction,\n        // so pets, especially dogs/cats, may enter before completion.\n        val -= 25.0;\n        if (pcnt >= 3) val -= 100.0;\n    }\n\n    return val;\n}\n\nvoid selectPlan(bool allowAdvanced) {\n    Plan bestSquare;\n    double bestSquareVal = -1e100;\n\n    // Original stable baseline: corner squares.\n    for (int ori = 0; ori < 4; ori++) {\n        for (int S = 8; S <= 18; S++) {\n            Plan p;\n            p.kind = 0;\n            p.ori = ori;\n            p.H = S;\n            p.W = S;\n            p.plannedPets = petsInsidePlan(p);\n\n            double val = evaluatePlan(p, false);\n\n            if (val > bestSquareVal) {\n                bestSquareVal = val;\n                bestSquare = p;\n            }\n        }\n    }\n\n    Plan best = bestSquare;\n    double bestVal = bestSquareVal;\n\n    if (allowAdvanced) {\n        // Conservative corner rectangles.\n        for (int ori = 0; ori < 4; ori++) {\n            for (int H = 6; H <= 18; H++) {\n                for (int W = 6; W <= 18; W++) {\n                    int mn = min(H, W);\n                    int mx = max(H, W);\n                    if (mn * 2 < mx) continue; // avoid too thin rectangles\n\n                    Plan p;\n                    p.kind = 0;\n                    p.ori = ori;\n                    p.H = H;\n                    p.W = W;\n                    p.plannedPets = petsInsidePlan(p);\n\n                    double val = evaluatePlan(p, false);\n\n                    // Do not replace the stable square baseline unless clearly better.\n                    if (val > bestVal + 18.0) {\n                        bestVal = val;\n                        best = p;\n                    }\n                }\n            }\n        }\n\n        // One-wall strip candidates.\n        // They can score very well if only 0-2 pets are inside,\n        // but are risky, so use them only if clearly better.\n        for (int ori = 0; ori < 4; ori++) {\n            for (int S = 8; S <= 22; S++) {\n                Plan p;\n                p.kind = 1;\n                p.ori = ori;\n                p.H = S;\n                p.W = 30;\n                p.plannedPets = petsInsidePlan(p);\n\n                if (p.plannedPets > 2) continue;\n\n                double val = evaluatePlan(p, true);\n\n                if (val > bestVal + 40.0) {\n                    bestVal = val;\n                    best = p;\n                }\n            }\n        }\n    }\n\n    best.plannedPets = petsInsidePlan(best);\n    plan_ = best;\n    makeTasks();\n}\n\nbool allHumansInside() {\n    for (auto &h : humans) {\n        if (!insideRegion(h.x, h.y)) return false;\n    }\n    return true;\n}\n\nbool allTasksDone() {\n    for (auto &t : tasks) {\n        if (!wall_[t.wx][t.wy]) return false;\n    }\n    return true;\n}\n\nchar dirFromTo(int x1, int y1, int x2, int y2, bool build) {\n    for (int d = 0; d < 4; d++) {\n        if (x1 + dx[d] == x2 && y1 + dy[d] == y2) {\n            return build ? buildChar[d] : mvChar[d];\n        }\n    }\n    return '.';\n}\n\nbool validBuildTarget(\n    int x,\n    int y,\n    const bool occH[31][31],\n    const bool occP[31][31]\n) {\n    if (!inBoard(x, y)) return false;\n    if (occH[x][y]) return false;\n    if (occP[x][y]) return false;\n\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n\n        if (inBoard(nx, ny) && occP[nx][ny]) return false;\n    }\n\n    return true;\n}\n\nchar bfsMove(\n    int sx,\n    int sy,\n    const vector<pair<int,int>> &targets,\n    const bool avoid[31][31],\n    bool restrictInside\n) {\n    if (targets.empty()) return '.';\n\n    bool isTarget[31][31] = {};\n    for (auto [x, y] : targets) {\n        if (!inBoard(x, y)) continue;\n        if (!passable(x, y)) continue;\n        if (restrictInside && !insideRegion(x, y)) continue;\n        isTarget[x][y] = true;\n    }\n\n    if (isTarget[sx][sy]) return '.';\n\n    int dist[31][31];\n    char first[31][31];\n\n    for (int i = 1; i <= 30; i++) {\n        for (int j = 1; j <= 30; j++) {\n            dist[i][j] = -1;\n            first[i][j] = '.';\n        }\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();\n        q.pop();\n\n        if (isTarget[x][y]) {\n            return first[x][y];\n        }\n\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n\n            if (!inBoard(nx, ny)) continue;\n            if (!passable(nx, ny)) continue;\n            if (avoid[nx][ny]) continue;\n            if (restrictInside && !insideRegion(nx, ny)) continue;\n            if (dist[nx][ny] != -1) continue;\n\n            dist[nx][ny] = dist[x][y] + 1;\n            first[nx][ny] = (x == sx && y == sy) ? mvChar[d] : first[x][y];\n            q.push({nx, ny});\n        }\n    }\n\n    return '.';\n}\n\nvector<pair<int,int>> insideCells() {\n    vector<pair<int,int>> res;\n\n    for (int x = x1_; x <= x2_; x++) {\n        for (int y = y1_; y <= y2_; y++) {\n            if (passable(x, y)) {\n                res.push_back({x, y});\n            }\n        }\n    }\n\n    return res;\n}\n\npair<int,int> centerCell() {\n    return {(x1_ + x2_) / 2, (y1_ + y2_) / 2};\n}\n\nvoid applyHumanActions(const string &ans) {\n    for (int i = 0; i < M; i++) {\n        char a = ans[i];\n\n        if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n            for (int d = 0; d < 4; d++) {\n                if (a == mvChar[d]) {\n                    humans[i].x += dx[d];\n                    humans[i].y += dy[d];\n                }\n            }\n        } else if (a == 'u' || a == 'd' || a == 'l' || a == 'r') {\n            for (int d = 0; d < 4; d++) {\n                if (a == buildChar[d]) {\n                    int wx = humans[i].x + dx[d];\n                    int wy = humans[i].y + dy[d];\n\n                    if (inBoard(wx, wy)) {\n                        wall_[wx][wy] = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid readPetMoves() {\n    for (int i = 0; i < N; i++) {\n        string s;\n        if (!(cin >> s)) exit(0);\n\n        if (s == \".\") continue;\n\n        for (char c : s) {\n            if (c == 'U') pets[i].x--;\n            else if (c == 'D') pets[i].x++;\n            else if (c == 'L') pets[i].y--;\n            else if (c == 'R') pets[i].y++;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pets.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n\n    cin >> M;\n    humans.resize(M);\n\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    memset(wall_, false, sizeof(wall_));\n\n    selectPlan(true);\n\n    bool startedBuild = false;\n    bool replanned = false;\n\n    for (int turn = 0; turn < 300; turn++) {\n        bool occH[31][31] = {};\n        bool occP[31][31] = {};\n\n        for (auto &h : humans) occH[h.x][h.y] = true;\n        for (auto &p : pets) occP[p.x][p.y] = true;\n\n        string ans(M, '.');\n        bool avoid[31][31] = {};\n\n        if (!startedBuild && !replanned && turn >= 80 && allHumansInside() && petsInsideCurrent() >= 2) {\n            // If the initially selected region has become bad before any wall is built,\n            // reselect once using the current pet positions.\n            replanned = true;\n            selectPlan(true);\n        }\n\n        if (!allHumansInside()) {\n            auto targets = insideCells();\n\n            for (int i = 0; i < M; i++) {\n                ans[i] = bfsMove(\n                    humans[i].x,\n                    humans[i].y,\n                    targets,\n                    avoid,\n                    false\n                );\n            }\n        } else {\n            if (!startedBuild) {\n                int curPets = petsInsideCurrent();\n\n                if (plan_.plannedPets == 0) {\n                    // Same idea as the strongest previous version:\n                    // wait for a clean region, but not too long.\n                    if (curPets == 0 || turn >= 105) {\n                        startedBuild = true;\n                    }\n                } else {\n                    // If the plan intentionally accepts pets, close quickly.\n                    if (turn >= 35 || curPets <= plan_.plannedPets) {\n                        startedBuild = true;\n                    }\n                }\n            }\n\n            if (!startedBuild) {\n                auto c = centerCell();\n                vector<pair<int,int>> targets = {c};\n\n                for (int i = 0; i < M; i++) {\n                    ans[i] = bfsMove(\n                        humans[i].x,\n                        humans[i].y,\n                        targets,\n                        avoid,\n                        true\n                    );\n                }\n            } else if (!allTasksDone()) {\n                bool scheduledWall[31][31] = {};\n\n                // Build immediately if a human is already at a construction cell.\n                for (int i = 0; i < M; i++) {\n                    int hx = humans[i].x;\n                    int hy = humans[i].y;\n\n                    for (auto &t : tasks) {\n                        if (wall_[t.wx][t.wy]) continue;\n                        if (scheduledWall[t.wx][t.wy]) continue;\n                        if (t.sx != hx || t.sy != hy) continue;\n                        if (!validBuildTarget(t.wx, t.wy, occH, occP)) continue;\n\n                        ans[i] = dirFromTo(hx, hy, t.wx, t.wy, true);\n                        scheduledWall[t.wx][t.wy] = true;\n                        avoid[t.wx][t.wy] = true;\n                        break;\n                    }\n                }\n\n                vector<pair<int,int>> goodTargets;\n                vector<pair<int,int>> fallbackTargets;\n\n                for (auto &t : tasks) {\n                    if (wall_[t.wx][t.wy]) continue;\n                    if (scheduledWall[t.wx][t.wy]) continue;\n\n                    fallbackTargets.push_back({t.sx, t.sy});\n\n                    if (validBuildTarget(t.wx, t.wy, occH, occP)) {\n                        goodTargets.push_back({t.sx, t.sy});\n                    }\n                }\n\n                if (goodTargets.empty()) goodTargets = fallbackTargets;\n\n                for (int i = 0; i < M; i++) {\n                    if (ans[i] != '.') continue;\n\n                    ans[i] = bfsMove(\n                        humans[i].x,\n                        humans[i].y,\n                        goodTargets,\n                        avoid,\n                        true\n                    );\n                }\n            } else {\n                auto c = centerCell();\n                vector<pair<int,int>> targets = {c};\n\n                for (int i = 0; i < M; i++) {\n                    ans[i] = bfsMove(\n                        humans[i].x,\n                        humans[i].y,\n                        targets,\n                        avoid,\n                        true\n                    );\n                }\n            }\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        applyHumanActions(ans);\n        readPetMoves();\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int V = 400;\nstatic const int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble p_fail, p_succ;\nstring hwall[20], vwall[19];\n\nint start_id, target_id;\nint nxt_cell[4][V];\nint dist_to_t[V];\n\nfloat potential_value[MAXL + 1][V];\n\nconst string DIRS = \"UDLR\";\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos_of(int x) {\n    return {x / N, x % N};\n}\n\nint dir_id(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\nstruct Node {\n    array<float, V> prob;\n    double score;\n    double eval;\n    string path;\n};\n\nvoid build_graph() {\n    for (int x = 0; x < V; x++) {\n        auto [i, j] = pos_of(x);\n\n        if (i == 0 || vwall[i - 1][j] == '1') nxt_cell[0][x] = x;\n        else nxt_cell[0][x] = id(i - 1, j);\n\n        if (i == N - 1 || vwall[i][j] == '1') nxt_cell[1][x] = x;\n        else nxt_cell[1][x] = id(i + 1, j);\n\n        if (j == 0 || hwall[i][j - 1] == '1') nxt_cell[2][x] = x;\n        else nxt_cell[2][x] = id(i, j - 1);\n\n        if (j == N - 1 || hwall[i][j] == '1') nxt_cell[3][x] = x;\n        else nxt_cell[3][x] = id(i, j + 1);\n    }\n}\n\nvoid bfs_distance() {\n    const int INF = 1e9;\n    fill(dist_to_t, dist_to_t + V, INF);\n\n    queue<int> q;\n    dist_to_t[target_id] = 0;\n    q.push(target_id);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int to = nxt_cell[d][v];\n            if (to == v) continue;\n\n            if (dist_to_t[to] > dist_to_t[v] + 1) {\n                dist_to_t[to] = dist_to_t[v] + 1;\n                q.push(to);\n            }\n        }\n    }\n}\n\nvoid build_potential() {\n    static double hit_prob[MAXL + 1][MAXL + 1];\n    static double hit_ksum[MAXL + 1][MAXL + 1];\n\n    for (int rem = 0; rem <= MAXL; rem++) {\n        hit_prob[rem][0] = 1.0;\n        hit_ksum[rem][0] = 0.0;\n\n        for (int d = 1; d <= rem; d++) {\n            double pr = pow(p_succ, d);\n            double psum = 0.0;\n            double ksum = 0.0;\n\n            for (int k = d; k <= rem; k++) {\n                psum += pr;\n                ksum += pr * k;\n\n                if (k < rem) {\n                    pr *= (double)k / (double)(k - d + 1) * p_fail;\n                }\n            }\n\n            hit_prob[rem][d] = psum;\n            hit_ksum[rem][d] = ksum;\n        }\n    }\n\n    for (int t = 0; t <= MAXL; t++) {\n        int rem = MAXL - t;\n\n        for (int c = 0; c < V; c++) {\n            int d = dist_to_t[c];\n\n            if (d > rem || d > MAXL) {\n                potential_value[t][c] = 0.0f;\n                continue;\n            }\n\n            double nb = (401.0 - t) * hit_prob[rem][d] - hit_ksum[rem][d];\n\n            double mean = 401.0 - t - d / p_succ;\n            if (mean < 0.0) mean = 0.0;\n\n            // Mostly finite-horizon negative-binomial estimate,\n            // with a small optimistic mean-time component for beam diversity.\n            double val = 0.82 * nb + 0.18 * mean;\n\n            if (val < 0.0) val = 0.0;\n            potential_value[t][c] = (float)val;\n        }\n    }\n}\n\ndouble evaluate_string(const string& s) {\n    static double cur[V], nxt[V];\n\n    for (int i = 0; i < V; i++) cur[i] = 0.0;\n    cur[start_id] = 1.0;\n\n    double score = 0.0;\n\n    for (int t = 0; t < (int)s.size(); t++) {\n        int dir = dir_id(s[t]);\n\n        for (int i = 0; i < V; i++) nxt[i] = 0.0;\n\n        double arrive = 0.0;\n        double remain = 0.0;\n\n        for (int c = 0; c < V; c++) {\n            double pr = cur[c];\n            if (pr < 1e-18) continue;\n\n            int to = nxt_cell[dir][c];\n\n            if (to == target_id) {\n                arrive += pr * p_succ;\n                nxt[c] += pr * p_fail;\n            } else if (to == c) {\n                nxt[c] += pr;\n            } else {\n                nxt[c] += pr * p_fail;\n                nxt[to] += pr * p_succ;\n            }\n        }\n\n        score += arrive * (400 - t);\n\n        for (int i = 0; i < V; i++) {\n            cur[i] = nxt[i];\n            remain += cur[i];\n        }\n\n        if (remain < 1e-18) break;\n    }\n\n    return score;\n}\n\nstring beam_search() {\n    const int BEAM_WIDTH = 320;\n\n    vector<Node> beam;\n    beam.reserve(BEAM_WIDTH);\n\n    Node init;\n    init.prob.fill(0.0f);\n    init.prob[start_id] = 1.0f;\n    init.score = 0.0;\n    init.eval = potential_value[0][start_id];\n    init.path.clear();\n\n    beam.push_back(init);\n\n    for (int depth = 0; depth < MAXL; depth++) {\n        vector<Node> cand;\n        cand.reserve(beam.size() * 4);\n\n        for (const Node& par : beam) {\n            for (int dir = 0; dir < 4; dir++) {\n                Node ch;\n                ch.prob.fill(0.0f);\n\n                float arrive = 0.0f;\n\n                for (int c = 0; c < V; c++) {\n                    float pr = par.prob[c];\n                    if (pr < 1e-12f) continue;\n\n                    int to = nxt_cell[dir][c];\n\n                    if (to == target_id) {\n                        arrive += pr * (float)p_succ;\n                        ch.prob[c] += pr * (float)p_fail;\n                    } else if (to == c) {\n                        ch.prob[c] += pr;\n                    } else {\n                        ch.prob[c] += pr * (float)p_fail;\n                        ch.prob[to] += pr * (float)p_succ;\n                    }\n                }\n\n                int nt = depth + 1;\n                ch.score = par.score + arrive * (400 - depth);\n\n                double pot = 0.0;\n                for (int c = 0; c < V; c++) {\n                    float pr = ch.prob[c];\n                    if (pr < 1e-12f) continue;\n                    pot += pr * potential_value[nt][c];\n                }\n\n                ch.eval = ch.score + pot;\n                ch.path = par.path;\n                ch.path.push_back(DIRS[dir]);\n\n                cand.push_back(std::move(ch));\n            }\n        }\n\n        if ((int)cand.size() > BEAM_WIDTH) {\n            nth_element(\n                cand.begin(),\n                cand.begin() + BEAM_WIDTH,\n                cand.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            );\n            cand.resize(BEAM_WIDTH);\n        }\n\n        beam.swap(cand);\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)beam.size(); i++) {\n        if (beam[i].score > beam[best].score) best = i;\n    }\n\n    return beam[best].path;\n}\n\nstring shortest_path_by_order(const vector<int>& order) {\n    string res;\n    int cur = start_id;\n\n    while (cur != target_id && (int)res.size() < MAXL) {\n        bool moved = false;\n\n        for (int d : order) {\n            int to = nxt_cell[d][cur];\n            if (to != cur && dist_to_t[to] == dist_to_t[cur] - 1) {\n                res.push_back(DIRS[d]);\n                cur = to;\n                moved = true;\n                break;\n            }\n        }\n\n        if (!moved) break;\n    }\n\n    return res;\n}\n\nstring make_cycle_pattern(const string& base) {\n    string s;\n    if (base.empty()) return string(MAXL, 'D');\n\n    int k = 0;\n    while ((int)s.size() < MAXL) {\n        s.push_back(base[k]);\n        k++;\n        if (k == (int)base.size()) k = 0;\n    }\n\n    return s;\n}\n\nstring make_repeat_each_pattern(const string& base, int rep) {\n    string s;\n    if (base.empty()) return string(MAXL, 'D');\n\n    while ((int)s.size() < MAXL) {\n        for (char c : base) {\n            for (int r = 0; r < rep && (int)s.size() < MAXL; r++) {\n                s.push_back(c);\n            }\n            if ((int)s.size() >= MAXL) break;\n        }\n    }\n\n    return s;\n}\n\nvector<string> generate_path_candidates() {\n    vector<string> cand;\n\n    vector<int> perm = {0, 1, 2, 3};\n\n    sort(perm.begin(), perm.end());\n    do {\n        string p = shortest_path_by_order(perm);\n        if (p.empty()) continue;\n\n        cand.push_back(make_cycle_pattern(p));\n\n        for (int r = 2; r <= 6; r++) {\n            cand.push_back(make_repeat_each_pattern(p, r));\n        }\n    } while (next_permutation(perm.begin(), perm.end()));\n\n    return cand;\n}\n\nvoid local_improve(string& ans, chrono::steady_clock::time_point start_time) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    double best_score = evaluate_string(ans);\n\n    bool improved = true;\n\n    while (improved && elapsed() < 1.82) {\n        improved = false;\n\n        // Single-character replacement.\n        for (int p = 0; p < (int)ans.size(); p++) {\n            if (elapsed() > 1.86) break;\n\n            char orig = ans[p];\n            char best_char = orig;\n            double local_best = best_score;\n\n            for (char c : DIRS) {\n                if (c == orig) continue;\n\n                ans[p] = c;\n                double sc = evaluate_string(ans);\n\n                if (sc > local_best + 1e-11) {\n                    local_best = sc;\n                    best_char = c;\n                }\n            }\n\n            ans[p] = best_char;\n\n            if (best_char != orig) {\n                best_score = local_best;\n                improved = true;\n            }\n        }\n\n        // Adjacent swap.\n        for (int p = 0; p + 1 < (int)ans.size(); p++) {\n            if (elapsed() > 1.88) break;\n            if (ans[p] == ans[p + 1]) continue;\n\n            swap(ans[p], ans[p + 1]);\n            double sc = evaluate_string(ans);\n\n            if (sc > best_score + 1e-11) {\n                best_score = sc;\n                improved = true;\n            } else {\n                swap(ans[p], ans[p + 1]);\n            }\n        }\n    }\n\n    // Small stochastic 2-position improvement.\n    mt19937 rng(\n        1234567u\n        ^ (unsigned)(si_ * 100000 + sj_ * 10000 + ti_ * 1000 + tj_ * 100)\n        ^ (unsigned)(p_fail * 1000)\n    );\n\n    int iter = 0;\n    while (elapsed() < 1.92) {\n        iter++;\n\n        int a = rng() % ans.size();\n        int b = rng() % ans.size();\n        if (a == b) continue;\n\n        char oa = ans[a], ob = ans[b];\n\n        char na = DIRS[rng() % 4];\n        char nb = DIRS[rng() % 4];\n\n        if (na == oa && nb == ob) continue;\n\n        ans[a] = na;\n        ans[b] = nb;\n\n        double sc = evaluate_string(ans);\n\n        if (sc > best_score + 1e-11) {\n            best_score = sc;\n        } else {\n            ans[a] = oa;\n            ans[b] = ob;\n        }\n\n        if ((iter & 15) == 0 && elapsed() > 1.92) break;\n    }\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    cin >> si_ >> sj_ >> ti_ >> tj_ >> p_fail;\n    p_succ = 1.0 - p_fail;\n\n    for (int i = 0; i < 20; i++) cin >> hwall[i];\n    for (int i = 0; i < 19; i++) cin >> vwall[i];\n\n    start_id = id(si_, sj_);\n    target_id = id(ti_, tj_);\n\n    build_graph();\n    bfs_distance();\n    build_potential();\n\n    string ans = beam_search();\n    double best_score = evaluate_string(ans);\n\n    vector<string> candidates = generate_path_candidates();\n\n    for (const string& s : candidates) {\n        double sc = evaluate_string(s);\n        if (sc > best_score) {\n            best_score = sc;\n            ans = s;\n        }\n    }\n\n    local_improve(ans, start_time);\n\n    if ((int)ans.size() > MAXL) ans.resize(MAXL);\n\n    while ((int)ans.size() < MAXL) {\n        ans.push_back('D');\n    }\n\n    cout << ans << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int MAXP = 2000;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nconst int pieceCntOf[8] = {1,1,1,1,2,2,1,1};\n\nconst int A[8][2] = {\n    {0, -1},\n    {0, -1},\n    {2, -1},\n    {1, -1},\n    {0, 2},\n    {0, 1},\n    {0, -1},\n    {1, -1},\n};\n\nconst int B[8][2] = {\n    {1, -1},\n    {3, -1},\n    {3, -1},\n    {2, -1},\n    {1, 3},\n    {3, 2},\n    {2, -1},\n    {3, -1},\n};\n\nint parent_[MAXP], sz_[MAXP], open_[MAXP];\nint sidePid[V][4];\n\nint findp(int x) {\n    while (parent_[x] != x) {\n        parent_[x] = parent_[parent_[x]];\n        x = parent_[x];\n    }\n    return x;\n}\n\nvoid unite(int a, int b) {\n    int ra = findp(a), rb = findp(b);\n    if (ra == rb) return;\n    if (sz_[ra] < sz_[rb]) swap(ra, rb);\n    parent_[rb] = ra;\n    sz_[ra] += sz_[rb];\n}\n\nstruct Eval {\n    long long actual = 0;\n    int l1 = 0;\n    int l2 = 0;\n    double energy = 0;\n};\n\nEval evaluate(const uint8_t state[V]) {\n    for (int k = 0; k < V; k++) {\n        sidePid[k][0] = sidePid[k][1] = sidePid[k][2] = sidePid[k][3] = -1;\n    }\n\n    int pc = 0;\n\n    for (int k = 0; k < V; k++) {\n        int t = state[k];\n        int c = pieceCntOf[t];\n\n        for (int p = 0; p < c; p++) {\n            int id = pc++;\n            parent_[id] = id;\n            sz_[id] = 1;\n            open_[id] = 0;\n\n            int a = A[t][p];\n            int b = B[t][p];\n            sidePid[k][a] = id;\n            sidePid[k][b] = id;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            if (j + 1 < N) {\n                int a = sidePid[k][2];\n                int b = sidePid[k + 1][0];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n\n            if (i + 1 < N) {\n                int a = sidePid[k][3];\n                int b = sidePid[k + N][1];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            for (int d = 0; d < 4; d++) {\n                int id = sidePid[k][d];\n                if (id == -1) continue;\n\n                int ni = i + di[d];\n                int nj = j + dj[d];\n\n                bool bad = false;\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    bad = true;\n                } else {\n                    int nk = ni * N + nj;\n                    int od = (d + 2) & 3;\n                    if (sidePid[nk][od] == -1) bad = true;\n                }\n\n                if (bad) open_[findp(id)]++;\n            }\n        }\n    }\n\n    Eval res;\n    double potential = 0.0;\n\n    for (int id = 0; id < pc; id++) {\n        int r = findp(id);\n        if (r != id) continue;\n\n        int s = sz_[r];\n        int op = open_[r];\n\n        if (op == 0) {\n            if (s > res.l1) {\n                res.l2 = res.l1;\n                res.l1 = s;\n            } else if (s > res.l2) {\n                res.l2 = s;\n            }\n        } else {\n            potential += (double)s * s / (op + 1);\n        }\n    }\n\n    if (res.l2 > 0) res.actual = 1LL * res.l1 * res.l2;\n\n    res.energy =\n        55.0 * res.actual\n        + 2.0 * res.l1 * res.l1\n        + 4.5 * res.l2 * res.l2\n        + 0.75 * potential;\n\n    return res;\n}\n\nint rotateTile(int t, int r) {\n    if (t < 4) return (t + r) & 3;\n    if (t < 6) return 4 + ((t - 4 + r) & 1);\n    return 6 + ((t - 6 + r) & 1);\n}\n\nint outsideCountState(int k, int t) {\n    int i = k / N;\n    int j = k % N;\n\n    bool has[4] = {};\n    for (int p = 0; p < pieceCntOf[t]; p++) {\n        has[A[t][p]] = true;\n        has[B[t][p]] = true;\n    }\n\n    int cnt = 0;\n    for (int d = 0; d < 4; d++) {\n        if (!has[d]) continue;\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) cnt++;\n    }\n    return cnt;\n}\n\nint stateForPair(int base, int d1, int d2) {\n    if (d1 > d2) swap(d1, d2);\n\n    if (base >= 6) {\n        if (d1 == 0 && d2 == 2) return 6;\n        return 7;\n    }\n\n    bool dbl = (base >= 4);\n\n    int s = 0;\n    if (d1 == 0 && d2 == 1) s = 0;\n    else if (d1 == 0 && d2 == 3) s = 1;\n    else if (d1 == 2 && d2 == 3) s = 2;\n    else s = 3;\n\n    if (!dbl) return s;\n\n    if (s == 0 || s == 2) return 4;\n    return 5;\n}\n\nstruct Cycle {\n    vector<int> cells;\n    vector<uint8_t> states;\n    array<uint64_t, 15> mask{};\n    int len = 0;\n};\n\nvoid buildMask(Cycle& c) {\n    c.mask.fill(0);\n    for (int k : c.cells) {\n        c.mask[k >> 6] |= 1ULL << (k & 63);\n    }\n}\n\nbool disjointCycle(const Cycle& a, const Cycle& b) {\n    for (int i = 0; i < 15; i++) {\n        if (a.mask[i] & b.mask[i]) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto timeStart = chrono::steady_clock::now();\n\n    string input[N];\n    for (int i = 0; i < N; i++) cin >> input[i];\n\n    uint64_t seed = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        for (char c : input[i]) {\n            seed ^= (uint64_t)c;\n            seed *= 1099511628211ULL;\n        }\n    }\n    XorShift rng(seed);\n\n    uint8_t base[V];\n    int dom[V][4], domCnt[V];\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n            int t = input[i][j] - '0';\n            base[k] = t;\n\n            vector<int> states;\n            if (t < 4) states = {0, 1, 2, 3};\n            else if (t < 6) states = {4, 5};\n            else states = {6, 7};\n\n            bool border = (i == 0 || i == N - 1 || j == 0 || j == N - 1);\n\n            if (border) {\n                int bestOut = 100;\n                for (int s : states) bestOut = min(bestOut, outsideCountState(k, s));\n\n                vector<int> filtered;\n                for (int s : states) {\n                    if (outsideCountState(k, s) == bestOut) filtered.push_back(s);\n                }\n                states = filtered;\n            }\n\n            domCnt[k] = (int)states.size();\n            for (int x = 0; x < domCnt[k]; x++) dom[k][x] = states[x];\n        }\n    }\n\n    vector<Cycle> cycles;\n    cycles.reserve(1800);\n\n    static int posStamp[V * 4], posIdx[V * 4];\n    static int cellStamp[V];\n\n    int stamp = 1;\n\n    const int MAX_CYCLES = 1600;\n    auto collectEnd = timeStart + chrono::milliseconds(430);\n\n    while (chrono::steady_clock::now() < collectEnd) {\n        stamp++;\n        if (stamp > 1000000000) {\n            memset(posStamp, 0, sizeof(posStamp));\n            memset(cellStamp, 0, sizeof(cellStamp));\n            stamp = 1;\n        }\n\n        int sk = rng.nextInt(V);\n        int sd = rng.nextInt(4);\n\n        vector<int> ks;\n        vector<int> ds;\n        vector<int> es;\n        ks.reserve(512);\n        ds.reserve(512);\n        es.reserve(512);\n\n        int k = sk;\n        int d = sd;\n\n        for (int step = 0; step < 1200; step++) {\n            int node = k * 4 + d;\n\n            if (posStamp[node] == stamp) break;\n\n            posStamp[node] = stamp;\n            posIdx[node] = (int)ks.size();\n            cellStamp[k] = stamp;\n\n            ks.push_back(k);\n            ds.push_back(d);\n\n            int t = base[k];\n\n            int cand[2];\n            int cc = 0;\n\n            if (t >= 6) {\n                cand[cc++] = (d + 2) & 3;\n            } else {\n                cand[cc++] = (d + 1) & 3;\n                cand[cc++] = (d + 3) & 3;\n                if (rng.nextInt(2)) swap(cand[0], cand[1]);\n            }\n\n            int chosen = -1;\n            int chosenNextK = -1;\n            int chosenNextD = -1;\n\n            for (int ci = 0; ci < cc; ci++) {\n                int e = cand[ci];\n                int ni = k / N + di[e];\n                int nj = k % N + dj[e];\n\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n\n                int nk = ni * N + nj;\n                int nd = (e + 2) & 3;\n                int nn = nk * 4 + nd;\n\n                if (posStamp[nn] == stamp) {\n                    int p = posIdx[nn];\n                    int len = (int)ks.size() - p;\n                    if (len >= 8) {\n                        chosen = e;\n                        chosenNextK = nk;\n                        chosenNextD = nd;\n                        break;\n                    }\n                }\n\n                if (cellStamp[nk] == stamp) continue;\n\n                if (chosen == -1 || rng.nextInt(2)) {\n                    chosen = e;\n                    chosenNextK = nk;\n                    chosenNextD = nd;\n                }\n            }\n\n            if (chosen == -1) break;\n\n            es.push_back(chosen);\n\n            int nextNode = chosenNextK * 4 + chosenNextD;\n\n            if (posStamp[nextNode] == stamp) {\n                int p = posIdx[nextNode];\n                int q = (int)ks.size();\n                int len = q - p;\n\n                if (len >= 8) {\n                    Cycle c;\n                    c.len = len;\n                    c.cells.reserve(len);\n                    c.states.reserve(len);\n\n                    bool ok = true;\n                    static int usedCell[V];\n                    static int usedStamp = 1;\n                    usedStamp++;\n\n                    for (int idx = p; idx < q; idx++) {\n                        int ck = ks[idx];\n                        if (usedCell[ck] == usedStamp) {\n                            ok = false;\n                            break;\n                        }\n                        usedCell[ck] = usedStamp;\n\n                        int cd = ds[idx];\n                        int ce = es[idx];\n                        int cb = base[ck];\n\n                        if (cb >= 6) {\n                            if (((cd + 2) & 3) != ce) {\n                                ok = false;\n                                break;\n                            }\n                        } else {\n                            if (((cd + 2) & 3) == ce || cd == ce) {\n                                ok = false;\n                                break;\n                            }\n                        }\n\n                        c.cells.push_back(ck);\n                        c.states.push_back((uint8_t)stateForPair(cb, cd, ce));\n                    }\n\n                    if (ok) {\n                        buildMask(c);\n\n                        if ((int)cycles.size() < MAX_CYCLES) {\n                            cycles.push_back(std::move(c));\n                        } else {\n                            int mn = 0;\n                            for (int x = 1; x < (int)cycles.size(); x++) {\n                                if (cycles[x].len < cycles[mn].len) mn = x;\n                            }\n                            if (c.len > cycles[mn].len) cycles[mn] = std::move(c);\n                        }\n                    }\n                }\n\n                break;\n            }\n\n            k = chosenNextK;\n            d = chosenNextD;\n        }\n    }\n\n    uint8_t cur[V], best[V], startState[V];\n\n    Eval bestEval;\n    bestEval.actual = -1;\n\n    Eval bestEnergyEval;\n    bestEnergyEval.energy = -1e100;\n\n    auto registerCandidate = [&](const uint8_t s[V]) {\n        Eval ev = evaluate(s);\n\n        if (ev.energy > bestEnergyEval.energy) {\n            bestEnergyEval = ev;\n            memcpy(startState, s, V);\n        }\n\n        if (\n            ev.actual > bestEval.actual ||\n            (ev.actual == bestEval.actual && ev.energy > bestEval.energy)\n        ) {\n            bestEval = ev;\n            memcpy(best, s, V);\n        }\n    };\n\n    for (int k = 0; k < V; k++) {\n        cur[k] = dom[k][rng.nextInt(domCnt[k])];\n    }\n\n    if (!cycles.empty()) {\n        sort(cycles.begin(), cycles.end(), [](const Cycle& a, const Cycle& b) {\n            return a.len > b.len;\n        });\n\n        struct PairCand {\n            long long prod;\n            int i;\n            int j;\n            bool operator<(const PairCand& other) const {\n                return prod > other.prod;\n            }\n        };\n\n        priority_queue<PairCand> pq;\n        const int KEEP_PAIRS = 25;\n\n        int C = (int)cycles.size();\n\n        for (int i = 0; i < C; i++) {\n            if (!pq.empty() && (int)pq.size() >= KEEP_PAIRS &&\n                1LL * cycles[i].len * cycles[i].len <= pq.top().prod) {\n                break;\n            }\n\n            for (int j = i + 1; j < C; j++) {\n                long long p = 1LL * cycles[i].len * cycles[j].len;\n\n                if (!pq.empty() && (int)pq.size() >= KEEP_PAIRS && p <= pq.top().prod) {\n                    break;\n                }\n\n                if (!disjointCycle(cycles[i], cycles[j])) continue;\n\n                if ((int)pq.size() < KEEP_PAIRS) {\n                    pq.push({p, i, j});\n                } else if (p > pq.top().prod) {\n                    pq.pop();\n                    pq.push({p, i, j});\n                }\n            }\n        }\n\n        vector<PairCand> pairs;\n        while (!pq.empty()) {\n            pairs.push_back(pq.top());\n            pq.pop();\n        }\n        sort(pairs.begin(), pairs.end(), [](const PairCand& a, const PairCand& b) {\n            return a.prod > b.prod;\n        });\n\n        for (auto pr : pairs) {\n            for (int rep = 0; rep < 2; rep++) {\n                for (int k = 0; k < V; k++) {\n                    cur[k] = dom[k][rng.nextInt(domCnt[k])];\n                }\n\n                for (int x = 0; x < cycles[pr.i].len; x++) {\n                    cur[cycles[pr.i].cells[x]] = cycles[pr.i].states[x];\n                }\n                for (int x = 0; x < cycles[pr.j].len; x++) {\n                    cur[cycles[pr.j].cells[x]] = cycles[pr.j].states[x];\n                }\n\n                registerCandidate(cur);\n            }\n        }\n\n        int lim = min<int>(45, cycles.size());\n\n        for (int cidx = 0; cidx < lim; cidx++) {\n            for (int k = 0; k < V; k++) {\n                cur[k] = dom[k][rng.nextInt(domCnt[k])];\n            }\n\n            for (int x = 0; x < cycles[cidx].len; x++) {\n                cur[cycles[cidx].cells[x]] = cycles[cidx].states[x];\n            }\n\n            registerCandidate(cur);\n        }\n    }\n\n    constexpr int INIT_TRIALS = 500;\n\n    for (int tr = 0; tr < INIT_TRIALS; tr++) {\n        for (int k = 0; k < V; k++) {\n            cur[k] = dom[k][rng.nextInt(domCnt[k])];\n        }\n        registerCandidate(cur);\n    }\n\n    memcpy(cur, startState, V);\n    Eval curEval = evaluate(cur);\n\n    const double TL = 1.93;\n    const double T0 = 2500.0;\n    const double T1 = 1.0;\n\n    double temp = T0;\n    int iter = 0;\n\n    while (true) {\n        iter++;\n\n        if ((iter & 511) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - timeStart).count();\n            if (elapsed >= TL) break;\n\n            double progress = elapsed / TL;\n            temp = T0 * pow(T1 / T0, progress);\n        }\n\n        int m = 1;\n        int r = rng.nextInt(100);\n        if (r < 8) m = 2;\n        if (r == 0) m = 3;\n\n        int pos[3];\n        uint8_t oldVal[3];\n\n        bool okMove = true;\n\n        for (int x = 0; x < m; x++) {\n            int k = -1;\n\n            for (int tries = 0; tries < 50; tries++) {\n                int cand = rng.nextInt(V);\n                if (domCnt[cand] <= 1) continue;\n\n                bool used = false;\n                for (int y = 0; y < x; y++) {\n                    if (pos[y] == cand) used = true;\n                }\n\n                if (!used) {\n                    k = cand;\n                    break;\n                }\n            }\n\n            if (k == -1) {\n                okMove = false;\n                break;\n            }\n\n            pos[x] = k;\n            oldVal[x] = cur[k];\n\n            int nd;\n            do {\n                nd = dom[k][rng.nextInt(domCnt[k])];\n            } while (nd == cur[k]);\n\n            cur[k] = nd;\n        }\n\n        if (!okMove) {\n            for (int x = 0; x < m; x++) cur[pos[x]] = oldVal[x];\n            continue;\n        }\n\n        Eval ne = evaluate(cur);\n        double diff = ne.energy - curEval.energy;\n\n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double p = exp(diff / temp);\n            if (rng.nextDouble() < p) accept = true;\n        }\n\n        if (\n            ne.actual > bestEval.actual ||\n            (ne.actual == bestEval.actual && ne.energy > bestEval.energy)\n        ) {\n            bestEval = ne;\n            memcpy(best, cur, V);\n        }\n\n        if (accept) {\n            curEval = ne;\n        } else {\n            for (int x = 0; x < m; x++) cur[pos[x]] = oldVal[x];\n        }\n    }\n\n    string ans;\n    ans.reserve(V);\n\n    for (int k = 0; k < V; k++) {\n        int b = base[k];\n        int target = best[k];\n\n        int rr = 0;\n        for (int r = 0; r < 4; r++) {\n            if (rotateTile(b, r) == target) {\n                rr = r;\n                break;\n            }\n        }\n\n        ans.push_back(char('0' + rr));\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint N, T, M, FULLV;\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nint hexval(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nchar move_char_from_blank_to_tile(int blank, int tile) {\n    if (tile == blank - N) return 'U';\n    if (tile == blank + N) return 'D';\n    if (tile == blank - 1) return 'L';\n    return 'R';\n}\n\nint move_blank_pos(int blank, char c) {\n    if (c == 'U') return blank - N;\n    if (c == 'D') return blank + N;\n    if (c == 'L') return blank - 1;\n    return blank + 1;\n}\n\nbool legal_move(int blank, char c) {\n    int r = blank / N, col = blank % N;\n    if (c == 'U') return r > 0;\n    if (c == 'D') return r + 1 < N;\n    if (c == 'L') return col > 0;\n    return col + 1 < N;\n}\n\nvoid apply_move(array<unsigned char, 100>& b, int& blank, char c) {\n    int nb = move_blank_pos(blank, c);\n    swap(b[blank], b[nb]);\n    blank = nb;\n}\n\nvector<int> neighbors_of(int p) {\n    vector<int> ns;\n    int r = p / N, c = p % N;\n    if (r > 0) ns.push_back(p - N);\n    if (r + 1 < N) ns.push_back(p + N);\n    if (c > 0) ns.push_back(p - 1);\n    if (c + 1 < N) ns.push_back(p + 1);\n    return ns;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                                  Evaluation                                  */\n/* -------------------------------------------------------------------------- */\n\nstruct Eval {\n    int s;\n    int maxComp;\n    int cyc;\n};\n\nstruct DSU {\n    int p[100], sz[100], ed[100];\n\n    void init(const array<unsigned char, 100>& b) {\n        for (int i = 0; i < M; i++) {\n            if (b[i]) {\n                p[i] = i;\n                sz[i] = 1;\n                ed[i] = 0;\n            } else {\n                p[i] = -1;\n                sz[i] = 0;\n                ed[i] = 0;\n            }\n        }\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    void add_edge(int a, int b) {\n        int ra = find(a), rb = find(b);\n        if (ra == rb) {\n            ed[ra]++;\n            return;\n        }\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        ed[ra] += ed[rb] + 1;\n    }\n};\n\nEval eval_board(const array<unsigned char, 100>& b) {\n    DSU d;\n    d.init(b);\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            if (b[p] == 0) continue;\n\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) d.add_edge(p, p + 1);\n            }\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) d.add_edge(p, p + N);\n            }\n        }\n    }\n\n    Eval ev{0, 0, 0};\n\n    for (int i = 0; i < M; i++) {\n        if (b[i] == 0) continue;\n        if (d.find(i) != i) continue;\n\n        ev.maxComp = max(ev.maxComp, d.sz[i]);\n\n        if (d.ed[i] == d.sz[i] - 1) {\n            ev.s = max(ev.s, d.sz[i]);\n        } else if (d.ed[i] >= d.sz[i]) {\n            ev.cyc += d.ed[i] - d.sz[i] + 1;\n        }\n    }\n\n    return ev;\n}\n\nint estimated_score(int S, int K) {\n    if (S < FULLV) {\n        return (int)llround(500000.0 * S / FULLV);\n    } else {\n        return (int)llround(500000.0 * (2.0 - (double)K / T));\n    }\n}\n\npair<int, int> eval_answer(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    const string& ans\n) {\n    array<unsigned char, 100> b = init;\n    int blank = initBlank;\n\n    for (char c : ans) {\n        if (!legal_move(blank, c)) return {-1, -1};\n        apply_move(b, blank, c);\n    }\n\n    Eval ev = eval_board(b);\n    return {ev.s, estimated_score(ev.s, (int)ans.size())};\n}\n\n/* -------------------------------------------------------------------------- */\n/*                            Tree target reconstruction                       */\n/* -------------------------------------------------------------------------- */\n\nstruct Edge {\n    int a, b;\n    int ba, bb;\n};\n\nint dir_bit(int from, int to) {\n    if (to == from - 1) return 1;\n    if (to == from - N) return 2;\n    if (to == from + 1) return 4;\n    return 8;\n}\n\nstruct SmallDSU {\n    vector<int> p, sz;\n\n    SmallDSU(int n = 0) : p(n), sz(n, 1) {\n        iota(p.begin(), p.end(), 0);\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = find(a), 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 ReconState {\n    vector<int> mask;\n    vector<int> cnt;\n    vector<char> tree;\n    vector<vector<pair<int, int>>> adj;\n    int diff;\n};\n\nvoid adj_add(vector<vector<pair<int, int>>>& adj, int u, int v, int eid) {\n    adj[u].push_back({v, eid});\n    adj[v].push_back({u, eid});\n}\n\nvoid adj_remove(vector<vector<pair<int, int>>>& adj, int u, int v, int eid) {\n    auto erase_one = [&](int x, int y) {\n        auto& vec = adj[x];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i].first == y && vec[i].second == eid) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n    erase_one(u, v);\n    erase_one(v, u);\n}\n\nbool reconstruct_target_any(\n    const vector<int>& targetCnt,\n    array<unsigned char, 100>& target,\n    double time_limit\n) {\n    int emptyPos = M - 1;\n\n    vector<int> posToVid(M, -1), vidToPos;\n    for (int p = 0; p < M; p++) {\n        if (p == emptyPos) continue;\n        posToVid[p] = (int)vidToPos.size();\n        vidToPos.push_back(p);\n    }\n\n    int V = (int)vidToPos.size();\n\n    vector<Edge> edges;\n    for (int p = 0; p < M; p++) {\n        if (p == emptyPos) continue;\n\n        int r = p / N, c = p % N;\n\n        if (c + 1 < N && p + 1 != emptyPos) {\n            int q = p + 1;\n            edges.push_back({posToVid[p], posToVid[q], dir_bit(p, q), dir_bit(q, p)});\n        }\n        if (r + 1 < N && p + N != emptyPos) {\n            int q = p + N;\n            edges.push_back({posToVid[p], posToVid[q], dir_bit(p, q), dir_bit(q, p)});\n        }\n    }\n\n    int E = edges.size();\n    mt19937 rng(712367821);\n\n    auto calc_diff = [&](const vector<int>& cnt) {\n        int d = 0;\n        for (int i = 0; i < 16; i++) d += abs(cnt[i] - targetCnt[i]);\n        return d;\n    };\n\n    auto build_random_tree = [&]() {\n        ReconState st;\n        st.mask.assign(V, 0);\n        st.cnt.assign(16, 0);\n        st.tree.assign(E, 0);\n        st.adj.assign(V, {});\n\n        vector<int> ord(E);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n\n        SmallDSU dsu(V);\n        int used = 0;\n\n        for (int id : ord) {\n            auto& e = edges[id];\n\n            if (dsu.unite(e.a, e.b)) {\n                st.tree[id] = 1;\n                st.mask[e.a] |= e.ba;\n                st.mask[e.b] |= e.bb;\n                adj_add(st.adj, e.a, e.b, id);\n\n                used++;\n                if (used == V - 1) break;\n            }\n        }\n\n        for (int x : st.mask) st.cnt[x]++;\n        st.diff = calc_diff(st.cnt);\n        return st;\n    };\n\n    ReconState best;\n    best.diff = INT_MAX;\n\n    while (elapsed_sec() < time_limit) {\n        ReconState st = build_random_tree();\n\n        if (st.diff < best.diff) best = st;\n        if (st.diff == 0) {\n            best = st;\n            break;\n        }\n\n        double local_start = elapsed_sec();\n\n        while (elapsed_sec() < time_limit) {\n            double progress = (elapsed_sec() - local_start) / max(0.001, time_limit - local_start);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 3.5 * (1.0 - progress) + 0.03 * progress;\n\n            int addId = -1;\n            for (int tries = 0; tries < 25; tries++) {\n                int id = rng() % E;\n                if (!st.tree[id]) {\n                    addId = id;\n                    break;\n                }\n            }\n            if (addId == -1) continue;\n\n            int s = edges[addId].a;\n            int g = edges[addId].b;\n\n            vector<int> par(V, -1), parEdge(V, -1);\n            queue<int> q;\n            q.push(s);\n            par[s] = s;\n\n            while (!q.empty() && par[g] == -1) {\n                int v = q.front();\n                q.pop();\n\n                for (auto [to, eid] : st.adj[v]) {\n                    if (par[to] == -1) {\n                        par[to] = v;\n                        parEdge[to] = eid;\n                        q.push(to);\n                    }\n                }\n            }\n\n            vector<int> pathEdges;\n            int cur = g;\n            while (cur != s) {\n                pathEdges.push_back(parEdge[cur]);\n                cur = par[cur];\n            }\n\n            int remId = pathEdges[rng() % pathEdges.size()];\n\n            vector<int> nmask = st.mask;\n            vector<int> ncnt = st.cnt;\n\n            auto& ae = edges[addId];\n            auto& re = edges[remId];\n\n            nmask[ae.a] |= ae.ba;\n            nmask[ae.b] |= ae.bb;\n            nmask[re.a] &= ~re.ba;\n            nmask[re.b] &= ~re.bb;\n\n            int affected[4] = {ae.a, ae.b, re.a, re.b};\n            sort(affected, affected + 4);\n            int len = unique(affected, affected + 4) - affected;\n\n            int ndiff = st.diff;\n\n            for (int i = 0; i < len; i++) {\n                int v = affected[i];\n                int oldm = st.mask[v];\n                int newm = nmask[v];\n\n                if (oldm == newm) continue;\n\n                ndiff -= abs(ncnt[oldm] - targetCnt[oldm]);\n                ncnt[oldm]--;\n                ndiff += abs(ncnt[oldm] - targetCnt[oldm]);\n\n                ndiff -= abs(ncnt[newm] - targetCnt[newm]);\n                ncnt[newm]++;\n                ndiff += abs(ncnt[newm] - targetCnt[newm]);\n            }\n\n            bool accept = false;\n\n            if (ndiff <= st.diff) {\n                accept = true;\n            } else {\n                double prob = exp((double)(st.diff - ndiff) / temp);\n                double rr = (double)rng() / (double)UINT_MAX;\n                if (rr < prob) accept = true;\n            }\n\n            if (accept) {\n                st.diff = ndiff;\n                st.mask.swap(nmask);\n                st.cnt.swap(ncnt);\n\n                st.tree[addId] = 1;\n                st.tree[remId] = 0;\n\n                adj_add(st.adj, ae.a, ae.b, addId);\n                adj_remove(st.adj, re.a, re.b, remId);\n\n                if (st.diff < best.diff) best = st;\n\n                if (st.diff == 0) {\n                    best = st;\n                    goto finish_reconstruction;\n                }\n            }\n        }\n    }\n\nfinish_reconstruction:\n    if (best.diff == INT_MAX) return false;\n\n    target.fill(0);\n    target[emptyPos] = 0;\n\n    for (int v = 0; v < V; v++) {\n        target[vidToPos[v]] = (unsigned char)best.mask[v];\n    }\n\n    return best.diff == 0;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                       Partial greedy solver to target                       */\n/* -------------------------------------------------------------------------- */\n\nbool find_path_to_place(\n    const array<unsigned char, 100>& board,\n    int blank,\n    const vector<char>& fixed,\n    int pos,\n    int val,\n    string& path\n) {\n    path.clear();\n\n    if (board[pos] == val) return true;\n\n    int total = M * M;\n    vector<int> pre(total, -2);\n    vector<char> prem(total, 0);\n    queue<int> q;\n\n    for (int p = 0; p < M; p++) {\n        if (fixed[p]) continue;\n        if (p == blank) continue;\n        if (board[p] == val) {\n            int id = p * M + blank;\n            pre[id] = -1;\n            q.push(id);\n        }\n    }\n\n    int goal = -1;\n\n    while (!q.empty()) {\n        int id = q.front();\n        q.pop();\n\n        int tile = id / M;\n        int z = id % M;\n\n        if (tile == pos) {\n            goal = id;\n            break;\n        }\n\n        for (int nb : neighbors_of(z)) {\n            if (fixed[nb]) continue;\n\n            int ntile = tile;\n            if (nb == tile) ntile = z;\n\n            int nz = nb;\n            int nid = ntile * M + nz;\n\n            if (pre[nid] != -2) continue;\n\n            pre[nid] = id;\n            prem[nid] = move_char_from_blank_to_tile(z, nb);\n            q.push(nid);\n        }\n    }\n\n    if (goal == -1) return false;\n\n    int cur = goal;\n    while (pre[cur] != -1) {\n        path.push_back(prem[cur]);\n        cur = pre[cur];\n    }\n\n    reverse(path.begin(), path.end());\n    return true;\n}\n\nuint64_t encode9(const array<unsigned char, 100>& b, const vector<int>& cells) {\n    uint64_t x = 0;\n    for (int i = 0; i < 9; i++) {\n        x |= (uint64_t)b[cells[i]] << (4 * i);\n    }\n    return x;\n}\n\nint zero_index9(uint64_t x) {\n    for (int i = 0; i < 9; i++) {\n        if (((x >> (4 * i)) & 15) == 0) return i;\n    }\n    return -1;\n}\n\nuint64_t swap_nibble(uint64_t x, int a, int b) {\n    uint64_t va = (x >> (4 * a)) & 15;\n    uint64_t vb = (x >> (4 * b)) & 15;\n\n    x &= ~(15ULL << (4 * a));\n    x &= ~(15ULL << (4 * b));\n\n    x |= va << (4 * b);\n    x |= vb << (4 * a);\n\n    return x;\n}\n\nbool solve_final_3x3(\n    array<unsigned char, 100>& board,\n    int& blank,\n    const array<unsigned char, 100>& target,\n    string& ans\n) {\n    vector<int> cells;\n\n    for (int r = N - 3; r < N; r++) {\n        for (int c = N - 3; c < N; c++) {\n            cells.push_back(r * N + c);\n        }\n    }\n\n    bool blankInside = false;\n    for (int p : cells) {\n        if (p == blank) blankInside = true;\n    }\n    if (!blankInside) return false;\n\n    uint64_t start = encode9(board, cells);\n    uint64_t goal = encode9(target, cells);\n\n    if (start == goal) return true;\n\n    unordered_map<uint64_t, pair<uint64_t, char>> pre;\n    pre.reserve(400000);\n\n    queue<uint64_t> q;\n    q.push(start);\n    pre[start] = {UINT64_MAX, 0};\n\n    bool ok = false;\n    uint64_t found = 0;\n\n    while (!q.empty()) {\n        uint64_t x = q.front();\n        q.pop();\n\n        int zi = zero_index9(x);\n        int zr = zi / 3, zc = zi % 3;\n\n        const int dr[4] = {-1, 1, 0, 0};\n        const int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = zr + dr[k];\n            int nc = zc + dc[k];\n\n            if (nr < 0 || nr >= 3 || nc < 0 || nc >= 3) continue;\n\n            int ni = nr * 3 + nc;\n            uint64_t y = swap_nibble(x, zi, ni);\n\n            if (pre.count(y)) continue;\n\n            char mv = move_char_from_blank_to_tile(cells[zi], cells[ni]);\n            pre[y] = {x, mv};\n\n            if (y == goal) {\n                found = y;\n                ok = true;\n                while (!q.empty()) q.pop();\n                break;\n            }\n\n            q.push(y);\n        }\n    }\n\n    if (!ok) return false;\n\n    string path;\n    uint64_t cur = found;\n\n    while (pre[cur].first != UINT64_MAX) {\n        path.push_back(pre[cur].second);\n        cur = pre[cur].first;\n    }\n\n    reverse(path.begin(), path.end());\n\n    if ((int)ans.size() + (int)path.size() > T) return false;\n\n    for (char c : path) {\n        apply_move(board, blank, c);\n        ans.push_back(c);\n    }\n\n    return true;\n}\n\nstring partial_solve_to_target(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    const array<unsigned char, 100>& target\n) {\n    array<unsigned char, 100> board = init;\n    int blank = initBlank;\n\n    vector<char> fixed(M, 0);\n\n    string ans;\n    string bestAns;\n\n    Eval ev0 = eval_board(board);\n    int bestScore = estimated_score(ev0.s, 0);\n    bestAns = \"\";\n\n    vector<int> order;\n\n    for (int r = 0; r < N - 3; r++) {\n        for (int c = 0; c < N; c++) {\n            order.push_back(r * N + c);\n        }\n    }\n\n    for (int r = N - 3; r < N; r++) {\n        for (int c = 0; c < N - 3; c++) {\n            order.push_back(r * N + c);\n        }\n    }\n\n    for (int pos : order) {\n        int val = target[pos];\n\n        if (val == 0) break;\n\n        string path;\n\n        if (!find_path_to_place(board, blank, fixed, pos, val, path)) break;\n        if ((int)ans.size() + (int)path.size() > T) break;\n\n        for (char c : path) {\n            apply_move(board, blank, c);\n            ans.push_back(c);\n        }\n\n        if (board[pos] != val) break;\n\n        fixed[pos] = 1;\n\n        Eval ev = eval_board(board);\n        int sc = estimated_score(ev.s, (int)ans.size());\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestAns = ans;\n        }\n\n        if (ev.s == FULLV) return ans;\n    }\n\n    {\n        array<unsigned char, 100> b2 = board;\n        int z2 = blank;\n        string a2 = ans;\n\n        if (solve_final_3x3(b2, z2, target, a2)) {\n            Eval ev = eval_board(b2);\n            int sc = estimated_score(ev.s, (int)a2.size());\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestAns = a2;\n            }\n        }\n    }\n\n    return bestAns;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                                Beam fallback                                */\n/* -------------------------------------------------------------------------- */\n\null zob[100][16];\n\ninline bool edge_adj(const array<unsigned char, 100>& b, int x, int y) {\n    if (y == x - 1) return (b[x] & 1) && (b[y] & 4);\n    if (y == x + 1) return (b[x] & 4) && (b[y] & 1);\n    if (y == x - N) return (b[x] & 2) && (b[y] & 8);\n    if (y == x + N) return (b[x] & 8) && (b[y] & 2);\n    return false;\n}\n\nint local_edges(const array<unsigned char, 100>& b, int a, int c) {\n    int cells[2] = {a, c};\n    int keys[8];\n    int kc = 0;\n    int res = 0;\n\n    for (int ii = 0; ii < 2; ii++) {\n        int x = cells[ii];\n\n        for (int y : neighbors_of(x)) {\n            int u = min(x, y);\n            int v = max(x, y);\n            int key = u * 100 + v;\n\n            bool seen = false;\n            for (int t = 0; t < kc; t++) {\n                if (keys[t] == key) {\n                    seen = true;\n                    break;\n                }\n            }\n\n            if (seen) continue;\n\n            keys[kc++] = key;\n\n            if (edge_adj(b, x, y)) res++;\n        }\n    }\n\n    return res;\n}\n\nint total_edges(const array<unsigned char, 100>& b) {\n    int e = 0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n\n            if (b[p] == 0) continue;\n\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) e++;\n            }\n\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) e++;\n            }\n        }\n    }\n\n    return e;\n}\n\nstruct Node {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    unsigned char prev;\n    ull hash;\n};\n\nstruct Cand {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    short maxComp;\n    short cyc;\n    unsigned char prev;\n    ull hash;\n    long long h;\n};\n\nchar inv_move(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return 0;\n}\n\nstring restore_path(const vector<Node>& pool, int idx) {\n    string res;\n\n    while (pool[idx].parent != -1) {\n        res.push_back((char)pool[idx].prev);\n        idx = pool[idx].parent;\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nstring beam_fallback(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    ull initHash\n) {\n    int W;\n\n    if (N == 6) W = 2600;\n    else if (N == 7) W = 1850;\n    else if (N == 8) W = 1250;\n    else if (N == 9) W = 850;\n    else W = 600;\n\n    vector<Node> pool;\n    pool.reserve((size_t)W * min(T + 2, 900));\n\n    Node root;\n    root.b = init;\n    root.parent = -1;\n    root.blank = initBlank;\n    root.e = total_edges(init);\n    root.prev = 0;\n    root.hash = initHash;\n\n    Eval rootEv = eval_board(init);\n    root.s = rootEv.s;\n\n    pool.push_back(root);\n\n    if (rootEv.s == FULLV) return \"\";\n\n    vector<int> beam{0};\n\n    int bestIdx = 0;\n    int bestS = rootEv.s;\n    int bestScore = estimated_score(rootEv.s, 0);\n\n    const char mvChar[4] = {'U', 'D', 'L', 'R'};\n\n    for (int step = 1; step <= T; step++) {\n        if (elapsed_sec() > 2.87) break;\n\n        vector<Cand> cand;\n        cand.reserve(beam.size() * 3 + 10);\n\n        for (int idx : beam) {\n            const Node& nd = pool[idx];\n            int z = nd.blank;\n\n            for (int dir = 0; dir < 4; dir++) {\n                char mc = mvChar[dir];\n\n                if (nd.prev && inv_move((char)nd.prev) == mc) continue;\n                if (!legal_move(z, mc)) continue;\n\n                int nz = move_blank_pos(z, mc);\n\n                Cand x;\n                x.b = nd.b;\n\n                int before = local_edges(x.b, z, nz);\n\n                unsigned char tile = x.b[nz];\n                x.b[z] = tile;\n                x.b[nz] = 0;\n\n                int after = local_edges(x.b, z, nz);\n\n                x.e = nd.e - before + after;\n                x.parent = idx;\n                x.blank = nz;\n                x.prev = (unsigned char)mc;\n                x.s = 0;\n                x.maxComp = 0;\n                x.cyc = 0;\n\n                ull h = nd.hash;\n                h ^= zob[z][0];\n                h ^= zob[nz][tile];\n                h ^= zob[z][tile];\n                h ^= zob[nz][0];\n                x.hash = h;\n\n                cand.push_back(std::move(x));\n            }\n        }\n\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.hash != b.hash) return a.hash < b.hash;\n            return a.e > b.e;\n        });\n\n        int write = 0;\n\n        for (int i = 0; i < (int)cand.size();) {\n            int j = i + 1;\n            int best = i;\n\n            while (j < (int)cand.size() && cand[j].hash == cand[i].hash) {\n                if (cand[j].e > cand[best].e) best = j;\n                j++;\n            }\n\n            cand[write++] = std::move(cand[best]);\n            i = j;\n        }\n\n        cand.resize(write);\n\n        int preLimit = min((int)cand.size(), max(W, 3 * W / 2));\n\n        if ((int)cand.size() > preLimit) {\n            nth_element(\n                cand.begin(),\n                cand.begin() + preLimit,\n                cand.end(),\n                [](const Cand& a, const Cand& b) {\n                    return a.e > b.e;\n                }\n            );\n            cand.resize(preLimit);\n        }\n\n        for (Cand& x : cand) {\n            Eval ev = eval_board(x.b);\n\n            x.s = ev.s;\n            x.maxComp = ev.maxComp;\n            x.cyc = ev.cyc;\n\n            x.h = 0;\n            x.h += 135000LL * x.s;\n            x.h += 1500LL * x.s * x.s;\n            x.h += 8200LL * x.e;\n            x.h += 900LL * x.maxComp;\n            x.h -= 21000LL * x.cyc;\n            x.h += (long long)(x.hash & 4095ULL);\n\n            int sc = estimated_score(x.s, step);\n\n            if (sc > bestScore) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n\n                pool.push_back(tmp);\n                bestIdx = (int)pool.size() - 1;\n                bestS = x.s;\n                bestScore = sc;\n            }\n\n            if (x.s == FULLV) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n\n                pool.push_back(tmp);\n                return restore_path(pool, (int)pool.size() - 1);\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.h != b.h) return a.h > b.h;\n            return a.e > b.e;\n        });\n\n        int keep = min(W, (int)cand.size());\n\n        vector<int> nextBeam;\n        nextBeam.reserve(keep);\n\n        for (int i = 0; i < keep; i++) {\n            Node nd;\n            nd.b = cand[i].b;\n            nd.parent = cand[i].parent;\n            nd.blank = cand[i].blank;\n            nd.e = cand[i].e;\n            nd.s = cand[i].s;\n            nd.prev = cand[i].prev;\n            nd.hash = cand[i].hash;\n\n            pool.push_back(nd);\n\n            int ni = (int)pool.size() - 1;\n            nextBeam.push_back(ni);\n\n            int sc = estimated_score(nd.s, step);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestS = nd.s;\n                bestIdx = ni;\n            }\n        }\n\n        beam.swap(nextBeam);\n    }\n\n    return restore_path(pool, bestIdx);\n}\n\n/* -------------------------------------------------------------------------- */\n/*                                    Main                                    */\n/* -------------------------------------------------------------------------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    cin >> N >> T;\n\n    M = N * N;\n    FULLV = M - 1;\n\n    mt19937_64 rng(123456789);\n\n    for (int i = 0; i < 100; i++) {\n        for (int v = 0; v < 16; v++) {\n            zob[i][v] = rng();\n        }\n    }\n\n    array<unsigned char, 100> init{};\n    int initBlank = -1;\n    ull initHash = 0;\n\n    vector<int> targetCnt(16, 0);\n\n    for (int r = 0; r < N; r++) {\n        string s;\n        cin >> s;\n\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            int v = hexval(s[c]);\n\n            init[p] = (unsigned char)v;\n\n            if (v == 0) initBlank = p;\n            else targetCnt[v]++;\n\n            initHash ^= zob[p][v];\n        }\n    }\n\n    string bestAns = \"\";\n    auto initEval = eval_board(init);\n    int bestScore = estimated_score(initEval.s, 0);\n\n    array<unsigned char, 100> target{};\n\n    double reconLimit;\n    if (N <= 7) reconLimit = 0.62;\n    else if (N == 8) reconLimit = 0.72;\n    else reconLimit = 0.82;\n\n    bool haveTarget = reconstruct_target_any(targetCnt, target, reconLimit);\n\n    if (haveTarget || elapsed_sec() < 1.05) {\n        string targetAns = partial_solve_to_target(init, initBlank, target);\n        auto [S, sc] = eval_answer(init, initBlank, targetAns);\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestAns = targetAns;\n        }\n\n        if (S == FULLV && (int)targetAns.size() <= T) {\n            cout << targetAns << '\\n';\n            return 0;\n        }\n    }\n\n    string beamAns = beam_fallback(init, initBlank, initHash);\n\n    if ((int)beamAns.size() > T) beamAns.resize(T);\n\n    auto [beamS, beamScore] = eval_answer(init, initBlank, beamAns);\n\n    if (beamScore > bestScore) {\n        bestScore = beamScore;\n        bestAns = beamAns;\n    }\n\n    if ((int)bestAns.size() > T) bestAns.resize(T);\n\n    cout << bestAns << '\\n';\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Line {\n    double a, b, c;\n};\n\nstruct EvalResult {\n    int matched;\n    int diff;\n    array<int, 11> hist;\n    long long value() const {\n        return 100000LL * matched - diff;\n    }\n};\n\nstruct GridCand {\n    double theta;\n    vector<double> cu, cv;\n    long long val;\n};\n\nstruct Key {\n    uint64_t lo, hi;\n    bool operator==(const Key& o) const {\n        return lo == o.lo && hi == o.hi;\n    }\n};\n\nstruct KeyHash {\n    size_t operator()(const Key& k) const {\n        uint64_t x = k.lo ^ (k.hi + 0x9e3779b97f4a7c15ULL + (k.lo << 6) + (k.lo >> 2));\n        x ^= x >> 30;\n        x *= 0xbf58476d1ce4e5b9ULL;\n        x ^= x >> 27;\n        x *= 0x94d049bb133111ebULL;\n        x ^= x >> 31;\n        return (size_t)x;\n    }\n};\n\nstruct Partition {\n    vector<int> pid;\n    vector<int> cnt;\n    vector<vector<int>> members;\n    array<int, 11> hist;\n    EvalResult eval;\n};\n\nstruct CandidateLine {\n    Line line;\n    double priority;\n    int staticIndex;\n};\n\nstatic const double PI = acos(-1.0);\nstatic const double R = 10000.0;\n\nint N, K;\narray<int, 11> targetA;\nvector<Point> pts;\nchrono::steady_clock::time_point st;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n}\n\nEvalResult make_eval_from_hist(const array<int, 11>& hist) {\n    EvalResult res;\n    res.hist = hist;\n    res.matched = 0;\n    res.diff = 0;\n    for (int d = 1; d <= 10; d++) {\n        res.matched += min(targetA[d], hist[d]);\n        res.diff += abs(targetA[d] - hist[d]);\n    }\n    return res;\n}\n\nEvalResult eval_grid(double theta, const vector<double>& cu, const vector<double>& cv) {\n    int gx = (int)cu.size() + 1;\n    int gy = (int)cv.size() + 1;\n    vector<int> cnt(gx * gy, 0);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double u = p.x * cs + p.y * sn;\n        double v = -p.x * sn + p.y * cs;\n        int ix = int(upper_bound(cu.begin(), cu.end(), u) - cu.begin());\n        int iy = int(upper_bound(cv.begin(), cv.end(), v) - cv.begin());\n        cnt[ix * gy + iy]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n    for (int c : cnt) {\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n\n    return make_eval_from_hist(hist);\n}\n\nEvalResult eval_lines(const vector<Line>& lines) {\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(N * 2);\n\n    int L = (int)lines.size();\n\n    for (const auto& p : pts) {\n        uint64_t lo = 0, hi = 0;\n\n        for (int i = 0; i < L; i++) {\n            double v = lines[i].a * p.x + lines[i].b * p.y - lines[i].c;\n            if (v > 0) {\n                if (i < 64) lo |= 1ULL << i;\n                else hi |= 1ULL << (i - 64);\n            }\n        }\n\n        mp[{lo, hi}]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n\n    for (auto& kv : mp) {\n        int c = kv.second;\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n\n    return make_eval_from_hist(hist);\n}\n\nPartition build_partition(const vector<Line>& lines, bool needMembers) {\n    Partition part;\n    part.pid.assign(N, -1);\n    part.cnt.clear();\n    part.members.clear();\n    part.hist.fill(0);\n\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(N * 2);\n\n    int L = (int)lines.size();\n\n    for (int i = 0; i < N; i++) {\n        const auto& p = pts[i];\n\n        uint64_t lo = 0, hi = 0;\n\n        for (int j = 0; j < L; j++) {\n            double v = lines[j].a * p.x + lines[j].b * p.y - lines[j].c;\n            if (v > 0) {\n                if (j < 64) lo |= 1ULL << j;\n                else hi |= 1ULL << (j - 64);\n            }\n        }\n\n        Key key{lo, hi};\n        auto it = mp.find(key);\n\n        int id;\n        if (it == mp.end()) {\n            id = (int)part.cnt.size();\n            mp[key] = id;\n            part.cnt.push_back(0);\n            if (needMembers) part.members.emplace_back();\n        } else {\n            id = it->second;\n        }\n\n        part.pid[i] = id;\n        part.cnt[id]++;\n        if (needMembers) part.members[id].push_back(i);\n    }\n\n    for (int c : part.cnt) {\n        if (1 <= c && c <= 10) part.hist[c]++;\n    }\n\n    part.eval = make_eval_from_hist(part.hist);\n    return part;\n}\n\nvector<Line> build_grid_lines(double theta, const vector<double>& cu, const vector<double>& cv) {\n    vector<Line> lines;\n    lines.reserve(cu.size() + cv.size());\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (double c : cu) lines.push_back({cs, sn, c});\n    for (double c : cv) lines.push_back({-sn, cs, c});\n\n    return lines;\n}\n\nvector<double> uniform_cuts(int g) {\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    for (int i = 1; i < g; i++) {\n        cuts.push_back(-R + 2.0 * R * i / g);\n    }\n\n    return cuts;\n}\n\nvector<double> projection_quantile_cuts(double theta, int g, bool second_axis) {\n    vector<double> vals;\n    vals.reserve(N);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double z;\n        if (!second_axis) z = p.x * cs + p.y * sn;\n        else z = -p.x * sn + p.y * cs;\n        vals.push_back(z);\n    }\n\n    sort(vals.begin(), vals.end());\n\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    for (int i = 1; i < g; i++) {\n        int r = (long long)N * i / g;\n        r = min(max(r, 1), N - 1);\n\n        double c = (vals[r - 1] + vals[r]) * 0.5;\n        if (fabs(vals[r] - vals[r - 1]) < 1e-9) c = vals[r] + 1e-7;\n\n        c = max(-R + 1e-6, min(R - 1e-6, c));\n        cuts.push_back(c);\n    }\n\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nvector<double> random_dirichlet_cuts(int g, double alpha, mt19937& rng) {\n    vector<double> w(g);\n\n    if (alpha > 500.0) {\n        for (int i = 0; i < g; i++) w[i] = 1.0;\n    } else {\n        gamma_distribution<double> gd(alpha, 1.0);\n        for (int i = 0; i < g; i++) w[i] = max(1e-12, gd(rng));\n    }\n\n    double sum = accumulate(w.begin(), w.end(), 0.0);\n\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    double cur = -R;\n    for (int i = 0; i + 1 < g; i++) {\n        cur += 2.0 * R * w[i] / sum;\n        cuts.push_back(cur);\n    }\n\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nlong long local_split_value(const Partition& part, int c, int p) {\n    if (p <= 0 || p >= c) return LLONG_MIN / 4;\n\n    int q = c - p;\n\n    array<int, 11> hist = part.hist;\n\n    if (1 <= c && c <= 10) hist[c]--;\n    if (1 <= p && p <= 10) hist[p]++;\n    if (1 <= q && q <= 10) hist[q]++;\n\n    return make_eval_from_hist(hist).value() - part.eval.value();\n}\n\nvector<CandidateLine> generate_cell_candidate_lines(const Partition& part, mt19937& rng, int maxCand) {\n    vector<int> ids(part.cnt.size());\n    iota(ids.begin(), ids.end(), 0);\n\n    auto cell_priority = [&](int id) {\n        int c = part.cnt[id];\n        int pr = 0;\n\n        if (c > 10) pr += 100000 + c;\n        else if (part.hist[c] > targetA[c]) pr += 50000 + c;\n        else pr += c;\n\n        return pr;\n    };\n\n    sort(ids.begin(), ids.end(), [&](int x, int y) {\n        return cell_priority(x) > cell_priority(y);\n    });\n\n    vector<double> angles;\n    for (int i = 0; i < 16; i++) angles.push_back(PI * i / 16.0);\n\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n    for (int i = 0; i < 8; i++) angles.push_back(ur01(rng) * PI);\n\n    vector<CandidateLine> cand;\n    cand.reserve(maxCand * 2);\n\n    int usedCells = 0;\n\n    for (int id : ids) {\n        int c = part.cnt[id];\n        if (c <= 1) continue;\n\n        bool interesting = false;\n        if (c > 10) interesting = true;\n        if (c <= 10 && part.hist[c] > targetA[c]) interesting = true;\n        if (!interesting && usedCells >= 10) continue;\n\n        usedCells++;\n        if (usedCells > 45) break;\n\n        vector<int> ranks;\n\n        for (int d = 1; d <= 10; d++) {\n            if (targetA[d] > part.hist[d]) {\n                if (1 <= d && d < c) ranks.push_back(d);\n                if (1 <= c - d && c - d < c) ranks.push_back(c - d);\n            }\n        }\n\n        for (int d = 1; d <= min(10, c - 1); d++) {\n            ranks.push_back(d);\n            ranks.push_back(c - d);\n        }\n\n        if (c <= 22) {\n            for (int r = 1; r < c; r++) {\n                if (local_split_value(part, c, r) >= -100000) ranks.push_back(r);\n            }\n        }\n\n        sort(ranks.begin(), ranks.end());\n        ranks.erase(unique(ranks.begin(), ranks.end()), ranks.end());\n\n        if (ranks.empty()) continue;\n\n        for (double th : angles) {\n            double a = cos(th), b = sin(th);\n\n            vector<double> proj;\n            proj.reserve(c);\n\n            for (int idx : part.members[id]) {\n                const auto& p = pts[idx];\n                proj.push_back(a * p.x + b * p.y);\n            }\n\n            sort(proj.begin(), proj.end());\n\n            for (int r : ranks) {\n                if (r <= 0 || r >= c) continue;\n                if (fabs(proj[r] - proj[r - 1]) < 1e-9) continue;\n\n                double cc = (proj[r - 1] + proj[r]) * 0.5;\n\n                long long lv1 = local_split_value(part, c, r);\n                long long lv2 = local_split_value(part, c, c - r);\n                long long lv = max(lv1, lv2);\n\n                double priority = (double)lv + (c > 10 ? 30000.0 : 0.0) + c;\n\n                cand.push_back({{a, b, cc}, priority, -1});\n            }\n        }\n    }\n\n    sort(cand.begin(), cand.end(), [](const CandidateLine& x, const CandidateLine& y) {\n        return x.priority > y.priority;\n    });\n\n    if ((int)cand.size() > maxCand) cand.resize(maxCand);\n    return cand;\n}\n\nvector<Line> generate_static_extra_candidate_lines(mt19937& rng) {\n    vector<Line> cand;\n\n    int nang = 30;\n    int nq = 70;\n\n    for (int ai = 0; ai < nang; ai++) {\n        double theta = PI * ai / nang;\n        double a = cos(theta), b = sin(theta);\n\n        vector<double> vals;\n        vals.reserve(N);\n\n        for (const auto& p : pts) vals.push_back(a * p.x + b * p.y);\n        sort(vals.begin(), vals.end());\n\n        for (int q = 1; q < nq; q++) {\n            int r = (long long)N * q / nq;\n            r = min(max(r, 1), N - 1);\n\n            double c = (vals[r - 1] + vals[r]) * 0.5;\n            if (fabs(vals[r] - vals[r - 1]) < 1e-9) c = vals[r] + 1e-7;\n\n            cand.push_back({a, b, c});\n        }\n\n        for (int u = 1; u < 35; u++) {\n            double c = -R + 2.0 * R * u / 35.0;\n            cand.push_back({a, b, c});\n        }\n    }\n\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n\n    for (int t = 0; t < 500; t++) {\n        double theta = ur01(rng) * PI;\n        double a = cos(theta), b = sin(theta);\n\n        int id1 = rng() % N;\n        int id2 = rng() % N;\n\n        double c1 = a * pts[id1].x + b * pts[id1].y;\n        double c2 = a * pts[id2].x + b * pts[id2].y;\n        double c = (c1 + c2) * 0.5;\n        c = max(-R + 1e-6, min(R - 1e-6, c));\n\n        cand.push_back({a, b, c});\n    }\n\n    return cand;\n}\n\nlong long eval_add_line_fast(const Line& ln, const Partition& part, vector<int>& pos, vector<int>& touched) {\n    touched.clear();\n\n    for (int i = 0; i < N; i++) {\n        const auto& p = pts[i];\n        double v = ln.a * p.x + ln.b * p.y - ln.c;\n\n        if (v > 0) {\n            int id = part.pid[i];\n            if (pos[id] == 0) touched.push_back(id);\n            pos[id]++;\n        }\n    }\n\n    array<int, 11> hist = part.hist;\n\n    for (int id : touched) {\n        int p = pos[id];\n        int c = part.cnt[id];\n        int q = c - p;\n\n        if (p != 0 && q != 0) {\n            if (1 <= c && c <= 10) hist[c]--;\n            if (1 <= p && p <= 10) hist[p]++;\n            if (1 <= q && q <= 10) hist[q]++;\n        }\n\n        pos[id] = 0;\n    }\n\n    return make_eval_from_hist(hist).value();\n}\n\nvoid greedy_add_lines(vector<Line>& lines, long long& bestValue, double timeLimit, mt19937& rng) {\n    if ((int)lines.size() >= K) return;\n\n    vector<Line> staticCand = generate_static_extra_candidate_lines(rng);\n    vector<char> staticUsed(staticCand.size(), 0);\n\n    while ((int)lines.size() < K && elapsed_sec() < timeLimit) {\n        Partition part = build_partition(lines, true);\n        long long curVal = part.eval.value();\n\n        int dynamicLimit = 2600;\n        vector<CandidateLine> cand = generate_cell_candidate_lines(part, rng, dynamicLimit);\n\n        for (int i = 0; i < (int)staticCand.size(); i++) {\n            if (!staticUsed[i]) cand.push_back({staticCand[i], 0.0, i});\n        }\n\n        vector<int> pos(part.cnt.size(), 0);\n        vector<int> touched;\n        touched.reserve(part.cnt.size());\n\n        long long bestCandVal = curVal;\n        int bestIdx = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (elapsed_sec() > timeLimit) break;\n\n            long long v = eval_add_line_fast(cand[i].line, part, pos, touched);\n\n            if (v > bestCandVal) {\n                bestCandVal = v;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx == -1) break;\n\n        lines.push_back(cand[bestIdx].line);\n\n        if (cand[bestIdx].staticIndex >= 0) {\n            staticUsed[cand[bestIdx].staticIndex] = 1;\n        }\n\n        bestValue = max(bestValue, bestCandVal);\n    }\n}\n\nlong long extgcd(long long a, long long b, long long& x, long long& y) {\n    if (b == 0) {\n        x = (a >= 0 ? 1 : -1);\n        y = 0;\n        return llabs(a);\n    }\n\n    long long x1, y1;\n    long long g = extgcd(b, a % b, x1, y1);\n\n    x = y1;\n    y = x1 - (a / b) * y1;\n\n    return g;\n}\n\nbool collinear_any_coeff(long long A, long long B, long long C) {\n    for (const auto& p : pts) {\n        __int128 v = (__int128)A * p.x + (__int128)B * p.y;\n        if (v == C) return true;\n    }\n    return false;\n}\n\narray<long long, 4> line_to_integer_points(const Line& ln) {\n    const long long LIM = 1000000000LL;\n    const long long SCALE = 1000003LL;\n\n    double norm = hypot(ln.a, ln.b);\n    double aa = ln.a / norm;\n    double bb = ln.b / norm;\n    double cc = ln.c / norm;\n\n    long long A = llround(aa * SCALE);\n    long long B = llround(bb * SCALE);\n\n    if (A == 0 && B == 0) A = 1;\n    if (A == 0) A = 1;\n    if (B == 0) B = 1;\n\n    for (int t = 0; std::gcd(llabs(A), llabs(B)) != 1 && t < 20; t++) {\n        if (llabs(A) < llabs(B)) A += (A >= 0 ? 1 : -1);\n        else B += (B >= 0 ? 1 : -1);\n    }\n\n    if (std::gcd(llabs(A), llabs(B)) != 1) {\n        A += 1;\n        while (std::gcd(llabs(A), llabs(B)) != 1) A++;\n    }\n\n    long double len = sqrt((long double)A * A + (long double)B * B);\n    long long C = llround((long double)cc * len);\n\n    for (int t = 0; t < 50 && collinear_any_coeff(A, B, C); t++) {\n        C += (t % 2 == 0 ? 1 : -2);\n    }\n\n    long long xg, yg;\n    extgcd(llabs(A), llabs(B), xg, yg);\n\n    if (A < 0) xg = -xg;\n    if (B < 0) yg = -yg;\n\n    __int128 x0 = (__int128)xg * C;\n    __int128 y0 = (__int128)yg * C;\n\n    long double px = aa * cc;\n    long double py = bb * cc;\n\n    long double dx = B;\n    long double dy = -A;\n    long double denom = dx * dx + dy * dy;\n\n    long double tr = ((px - (long double)x0) * dx + (py - (long double)y0) * dy) / denom;\n    long long t0 = llround(tr);\n\n    __int128 x1b = x0 + (__int128)t0 * B;\n    __int128 y1b = y0 - (__int128)t0 * A;\n\n    long long x1 = (long long)x1b;\n    long long y1 = (long long)y1b;\n\n    long long stepMax = max(llabs(A), llabs(B));\n    long long T = max(1LL, min(900LL, (LIM - 1000000LL) / max(1LL, stepMax)));\n\n    long long x2 = x1 + B * T;\n    long long y2 = y1 - A * T;\n\n    if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) {\n        x2 = x1 - B * T;\n        y2 = y1 + A * T;\n    }\n\n    while ((x1 < -LIM || x1 > LIM || y1 < -LIM || y1 > LIM ||\n            x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) && T > 1) {\n        T /= 2;\n\n        x2 = x1 + B * T;\n        y2 = y1 - A * T;\n\n        if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) {\n            x2 = x1 - B * T;\n            y2 = y1 + A * T;\n        }\n    }\n\n    if (x1 < -LIM || x1 > LIM || y1 < -LIM || y1 > LIM ||\n        x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM ||\n        (x1 == x2 && y1 == y2)) {\n        x1 = -100000000;\n        y1 = llround(cc);\n        x2 = 100000000;\n        y2 = y1 + 1;\n    }\n\n    x1 = max(-LIM, min(LIM, x1));\n    y1 = max(-LIM, min(LIM, y1));\n    x2 = max(-LIM, min(LIM, x2));\n    y2 = max(-LIM, min(LIM, y2));\n\n    if (x1 == x2 && y1 == y2) {\n        if (x2 < LIM) x2++;\n        else x2--;\n    }\n\n    return {x1, y1, x2, y2};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st = chrono::steady_clock::now();\n\n    cin >> N >> K;\n\n    targetA.fill(0);\n\n    int M = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> targetA[d];\n        M += targetA[d];\n    }\n\n    pts.resize(N);\n    for (int i = 0; i < N; i++) cin >> pts[i].x >> pts[i].y;\n\n    mt19937 rng(1234567);\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n\n    vector<Line> bestLines;\n    long long bestValue = LLONG_MIN;\n\n    vector<GridCand> topGrids;\n\n    auto register_grid = [&](double theta, const vector<double>& cu, const vector<double>& cv) {\n        if ((int)cu.size() + (int)cv.size() > K) return;\n\n        EvalResult er = eval_grid(theta, cu, cv);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = build_grid_lines(theta, cu, cv);\n        }\n\n        topGrids.push_back({theta, cu, cv, val});\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n\n        if ((int)topGrids.size() > 18) topGrids.pop_back();\n    };\n\n    auto register_lines = [&](const vector<Line>& lines) {\n        if ((int)lines.size() > K) return;\n\n        EvalResult er = eval_lines(lines);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = lines;\n        }\n    };\n\n    double baseUniformProduct = 4.0 * M / PI;\n\n    vector<double> factors = {0.45, 0.55, 0.65, 0.78, 0.90, 1.00, 1.12, 1.28, 1.50, 1.75, 2.05};\n    vector<double> aspects = {0.50, 0.62, 0.75, 0.88, 1.00, 1.15, 1.33, 1.60, 2.00};\n\n    vector<double> thetas;\n    for (int i = 0; i < 12; i++) thetas.push_back(PI * i / 24.0);\n\n    for (double fac : factors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, baseUniformProduct * fac);\n\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            auto cu = uniform_cuts(gx);\n            auto cv = uniform_cuts(gy);\n\n            for (double th : thetas) register_grid(th, cu, cv);\n        }\n    }\n\n    vector<double> qFactors = {0.50, 0.62, 0.75, 0.88, 1.00, 1.15, 1.32, 1.55, 1.85};\n\n    for (double fac : qFactors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, M * fac);\n\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            for (double th : thetas) {\n                auto cu = projection_quantile_cuts(th, gx, false);\n                auto cv = projection_quantile_cuts(th, gy, true);\n\n                register_grid(th, cu, cv);\n            }\n        }\n    }\n\n    for (int rep = 0; rep < 40 && elapsed_sec() < 1.1; rep++) {\n        double hbase = sqrt(max(1.0, M / 3.0));\n        double scale = 0.55 + 0.035 * rep;\n\n        int g = max(2, (int)llround(hbase * scale));\n        g = min(g, 34);\n\n        double th0 = (rep % 15) * PI / 45.0;\n\n        vector<Line> lines;\n\n        for (int f = 0; f < 3; f++) {\n            double th = th0 + f * PI / 3.0;\n            double a = cos(th), b = sin(th);\n\n            auto cuts = uniform_cuts(g);\n\n            for (double c : cuts) lines.push_back({a, b, c});\n        }\n\n        register_lines(lines);\n    }\n\n    vector<double> alphaList = {0.25, 0.35, 0.50, 0.75, 1.00, 1.50, 2.50, 5.00, 1000.0};\n\n    while (elapsed_sec() < 1.42) {\n        double logFac = log(0.45) + ur01(rng) * (log(2.15) - log(0.45));\n        double logAsp = log(0.45) + ur01(rng) * (log(2.20) - log(0.45));\n\n        double fac = exp(logFac);\n        double asp = exp(logAsp);\n\n        double prod = max(1.0, baseUniformProduct * fac);\n\n        int gx = max(1, (int)llround(sqrt(prod * asp)));\n        int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n        while (gx + gy - 2 > K) {\n            if (gx > gy) gx--;\n            else gy--;\n        }\n\n        double ax = alphaList[rng() % alphaList.size()];\n        double ay = alphaList[rng() % alphaList.size()];\n\n        auto cu = random_dirichlet_cuts(gx, ax, rng);\n        auto cv = random_dirichlet_cuts(gy, ay, rng);\n\n        double th = ur01(rng) * PI / 2.0;\n\n        register_grid(th, cu, cv);\n    }\n\n    auto improve_grid = [&](GridCand start, double timeLimit) {\n        GridCand cur = start;\n        GridCand best = start;\n\n        double begin = elapsed_sec();\n\n        while (elapsed_sec() < timeLimit) {\n            double now = elapsed_sec();\n            double progress = (now - begin) / max(1e-9, timeLimit - begin);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 30000.0 * (1.0 - progress) + 300.0;\n\n            GridCand nxt = cur;\n            int typ = rng() % 10;\n\n            if ((typ < 4 && !nxt.cu.empty()) || nxt.cv.empty()) {\n                int m = nxt.cu.size();\n                int id = rng() % m;\n\n                double lo = (id == 0 ? -R + 1e-6 : nxt.cu[id - 1] + 1e-6);\n                double hi = (id + 1 == m ? R - 1e-6 : nxt.cu[id + 1] - 1e-6);\n                double width = hi - lo;\n\n                double nv;\n                if (typ == 0) {\n                    normal_distribution<double> nd(0.0, width * 0.08);\n                    nv = nxt.cu[id] + nd(rng);\n                } else {\n                    nv = lo + ur01(rng) * width;\n                }\n\n                nxt.cu[id] = max(lo, min(hi, nv));\n            } else if (typ < 8 && !nxt.cv.empty()) {\n                int m = nxt.cv.size();\n                int id = rng() % m;\n\n                double lo = (id == 0 ? -R + 1e-6 : nxt.cv[id - 1] + 1e-6);\n                double hi = (id + 1 == m ? R - 1e-6 : nxt.cv[id + 1] - 1e-6);\n                double width = hi - lo;\n\n                double nv;\n                if (typ == 4) {\n                    normal_distribution<double> nd(0.0, width * 0.08);\n                    nv = nxt.cv[id] + nd(rng);\n                } else {\n                    nv = lo + ur01(rng) * width;\n                }\n\n                nxt.cv[id] = max(lo, min(hi, nv));\n            } else if (typ == 8) {\n                normal_distribution<double> nd(0.0, 0.015 * (1.0 - progress) + 0.002);\n\n                nxt.theta += nd(rng);\n                while (nxt.theta < 0) nxt.theta += PI;\n                while (nxt.theta >= PI) nxt.theta -= PI;\n            } else {\n                bool axis = rng() & 1;\n                double scale = exp((ur01(rng) - 0.5) * 0.12 * (1.0 - progress));\n\n                vector<double>& arr = axis ? nxt.cu : nxt.cv;\n\n                for (double& x : arr) x = max(-R + 1e-6, min(R - 1e-6, x * scale));\n\n                sort(arr.begin(), arr.end());\n\n                for (int i = 1; i < (int)arr.size(); i++) {\n                    if (arr[i] <= arr[i - 1] + 1e-6) arr[i] = arr[i - 1] + 1e-6;\n                }\n\n                for (double& x : arr) x = max(-R + 1e-6, min(R - 1e-6, x));\n            }\n\n            EvalResult er = eval_grid(nxt.theta, nxt.cu, nxt.cv);\n            nxt.val = er.value();\n\n            long long delta = nxt.val - cur.val;\n\n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else {\n                double prob = exp((double)delta / temp);\n                if (ur01(rng) < prob) accept = true;\n            }\n\n            if (accept) cur = nxt;\n\n            if (nxt.val > best.val) {\n                best = nxt;\n\n                if (nxt.val > bestValue) {\n                    bestValue = nxt.val;\n                    bestLines = build_grid_lines(nxt.theta, nxt.cu, nxt.cv);\n                }\n            }\n        }\n\n        return best;\n    };\n\n    int idx = 0;\n\n    while (elapsed_sec() < 2.34 && idx < (int)topGrids.size()) {\n        double remaining = 2.34 - elapsed_sec();\n        int left = (int)topGrids.size() - idx;\n\n        double slice = min(0.19, max(0.035, remaining / max(1, left)));\n\n        GridCand improved = improve_grid(topGrids[idx], min(2.34, elapsed_sec() + slice));\n        topGrids[idx] = improved;\n\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n\n        idx++;\n    }\n\n    while (elapsed_sec() < 2.42 && !topGrids.empty()) {\n        GridCand improved = improve_grid(topGrids[0], min(2.42, elapsed_sec() + 0.05));\n        topGrids[0] = improved;\n\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n    }\n\n    greedy_add_lines(bestLines, bestValue, 2.86, rng);\n\n    if (bestLines.empty()) {\n        auto cu = uniform_cuts(25);\n        auto cv = uniform_cuts(25);\n        bestLines = build_grid_lines(0.01, cu, cv);\n    }\n\n    if ((int)bestLines.size() > K) bestLines.resize(K);\n\n    cout << bestLines.size() << '\\n';\n\n    for (const auto& ln : bestLines) {\n        auto e = line_to_integer_points(ln);\n        cout << e[0] << ' ' << e[1] << ' ' << e[2] << ' ' << e[3] << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 61;\n\nint N, M;\nint Weight[MAXN][MAXN];\nint maxWeightGlobal;\nvector<pair<int,int>> initialDots;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int mod) {\n        if (mod <= 0) return 0;\n        return int(next() % mod);\n    }\n};\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nint dx8[8] = {1, 0, -1, 0, 1, -1, -1, 1};\nint dy8[8] = {0, 1, 0, -1, 1, 1, -1, -1};\n\npair<int,int> dirPairs[8] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0},\n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ninline int enc(int x, int y) {\n    return x * N + y;\n}\n\ninline int stepLen(int ax, int ay, int bx, int by) {\n    return max(abs(ax - bx), abs(ay - by));\n}\n\nstruct State {\n    bool dot[MAXN][MAXN];\n    bool seg[4][MAXN][MAXN];\n    vector<Move> ops;\n    long long totalWeight;\n\n    void init() {\n        memset(dot, 0, sizeof(dot));\n        memset(seg, 0, sizeof(seg));\n        ops.clear();\n        ops.reserve(N * N);\n        totalWeight = 0;\n\n        for (auto [x, y] : initialDots) {\n            dot[x][y] = true;\n            totalWeight += Weight[x][y];\n        }\n    }\n\n    int segType(int x1, int y1, int x2, int y2, int &sx, int &sy) const {\n        int dx = x2 - x1;\n        int dy = y2 - y1;\n\n        if (dy == 0) {\n            sx = min(x1, x2);\n            sy = y1;\n            return 0;\n        }\n        if (dx == 0) {\n            sx = x1;\n            sy = min(y1, y2);\n            return 1;\n        }\n        if (dx == dy) {\n            sx = min(x1, x2);\n            sy = min(y1, y2);\n            return 2;\n        }\n\n        sx = min(x1, x2);\n        sy = min(y1, y2);\n        return 3;\n    }\n\n    bool unitUsed(int x1, int y1, int x2, int y2) const {\n        int sx, sy;\n        int t = segType(x1, y1, x2, y2, sx, sy);\n        return seg[t][sx][sy];\n    }\n\n    void markUnit(int x1, int y1, int x2, int y2) {\n        int sx, sy;\n        int t = segType(x1, y1, x2, y2, sx, sy);\n        seg[t][sx][sy] = true;\n    }\n\n    bool edgeFree(int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i < len; i++) {\n            int nx = x + dx;\n            int ny = y + dy;\n            if (unitUsed(x, y, nx, ny)) return false;\n            x = nx;\n            y = ny;\n        }\n        return true;\n    }\n\n    void markEdge(int ax, int ay, int bx, int by) {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i < len; i++) {\n            int nx = x + dx;\n            int ny = y + dy;\n            markUnit(x, y, nx, ny);\n            x = nx;\n            y = ny;\n        }\n    }\n\n    bool rectEdgesFree(const Move &m) const {\n        return edgeFree(m.x1, m.y1, m.x2, m.y2)\n            && edgeFree(m.x2, m.y2, m.x3, m.y3)\n            && edgeFree(m.x3, m.y3, m.x4, m.y4)\n            && edgeFree(m.x4, m.y4, m.x1, m.y1);\n    }\n\n    bool isAllowedDotOnPerimeter(int x, int y, const Move &m) const {\n        return (x == m.x2 && y == m.y2)\n            || (x == m.x3 && y == m.y3)\n            || (x == m.x4 && y == m.y4);\n    }\n\n    bool edgeDotsOk(int ax, int ay, int bx, int by, const Move &m) const {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i <= len; i++) {\n            if (dot[x][y] && !isAllowedDotOnPerimeter(x, y, m)) return false;\n            x += dx;\n            y += dy;\n        }\n        return true;\n    }\n\n    bool validMove(const Move &m) const {\n        if (!inside(m.x1, m.y1) || !inside(m.x2, m.y2)\n         || !inside(m.x3, m.y3) || !inside(m.x4, m.y4)) {\n            return false;\n        }\n\n        if (dot[m.x1][m.y1]) return false;\n        if (!dot[m.x2][m.y2] || !dot[m.x3][m.y3] || !dot[m.x4][m.y4]) return false;\n\n        int ax = m.x2 - m.x1;\n        int ay = m.y2 - m.y1;\n        int bx = m.x4 - m.x1;\n        int by = m.y4 - m.y1;\n\n        if (ax == 0 && ay == 0) return false;\n        if (bx == 0 && by == 0) return false;\n\n        if (m.x3 != m.x2 + m.x4 - m.x1) return false;\n        if (m.y3 != m.y2 + m.y4 - m.y1) return false;\n\n        if (ax * bx + ay * by != 0) return false;\n\n        auto allowedVec = [](int x, int y) {\n            if (x == 0 && y != 0) return true;\n            if (y == 0 && x != 0) return true;\n            if (abs(x) == abs(y) && x != 0) return true;\n            return false;\n        };\n\n        if (!allowedVec(ax, ay) || !allowedVec(bx, by)) return false;\n\n        if (!rectEdgesFree(m)) return false;\n\n        if (!edgeDotsOk(m.x1, m.y1, m.x2, m.y2, m)) return false;\n        if (!edgeDotsOk(m.x2, m.y2, m.x3, m.y3, m)) return false;\n        if (!edgeDotsOk(m.x3, m.y3, m.x4, m.y4, m)) return false;\n        if (!edgeDotsOk(m.x4, m.y4, m.x1, m.y1, m)) return false;\n\n        return true;\n    }\n\n    void apply(const Move &m) {\n        markEdge(m.x1, m.y1, m.x2, m.y2);\n        markEdge(m.x2, m.y2, m.x3, m.y3);\n        markEdge(m.x3, m.y3, m.x4, m.y4);\n        markEdge(m.x4, m.y4, m.x1, m.y1);\n\n        dot[m.x1][m.y1] = true;\n        totalWeight += Weight[m.x1][m.y1];\n        ops.push_back(m);\n    }\n};\n\nstruct Param {\n    int wcoef;\n    int pcoef;\n    int qcoef;\n    int dcoef;\n    int ocoef;\n    int acoef;\n    int rcoef;\n    int noise;\n    int topR;\n    int phase;\n};\n\nstruct Result {\n    long long score;\n    vector<Move> ops;\n};\n\nstruct Candidate {\n    long long key;\n    Move mv;\n};\n\nvoid insertTop(vector<Candidate> &top, int R, const Candidate &cand) {\n    if ((int)top.size() < R) {\n        top.push_back(cand);\n        return;\n    }\n\n    int worst = 0;\n    for (int i = 1; i < R; i++) {\n        if (top[i].key < top[worst].key) worst = i;\n    }\n\n    if (cand.key > top[worst].key) {\n        top[worst] = cand;\n    }\n}\n\nState greedyFill(State st, const Param &param, XorShift &rng, const Timer &timer, double deadline) {\n    static short nearestDot[8][MAXN][MAXN];\n\n    while (true) {\n        if (timer.elapsed() > deadline) break;\n\n        for (int d = 0; d < 8; d++) {\n            int xs = dx8[d] > 0 ? N - 1 : 0;\n            int xe = dx8[d] > 0 ? -1 : N;\n            int xi = dx8[d] > 0 ? -1 : 1;\n\n            int ys = dy8[d] > 0 ? N - 1 : 0;\n            int ye = dy8[d] > 0 ? -1 : N;\n            int yi = dy8[d] > 0 ? -1 : 1;\n\n            for (int x = xs; x != xe; x += xi) {\n                for (int y = ys; y != ye; y += yi) {\n                    int nx = x + dx8[d];\n                    int ny = y + dy8[d];\n\n                    if (!inside(nx, ny)) {\n                        nearestDot[d][x][y] = -1;\n                    } else if (st.dot[nx][ny]) {\n                        nearestDot[d][x][y] = enc(nx, ny);\n                    } else {\n                        nearestDot[d][x][y] = nearestDot[d][nx][ny];\n                    }\n                }\n            }\n        }\n\n        bool found = false;\n        Move bestMove{};\n        long long bestKey = LLONG_MIN;\n        vector<Candidate> top;\n\n        if (param.topR > 1) top.reserve(param.topR);\n\n        int opCount = (int)st.ops.size();\n\n        long long pEff = param.pcoef;\n        if (param.phase == 1) {\n            pEff = 1LL * param.pcoef * 260 / (260 + opCount);\n        } else if (param.phase == 2) {\n            pEff = 1LL * param.pcoef * (120 + min(opCount, 400)) / 120;\n        }\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                if (st.dot[x][y]) continue;\n\n                int degree = 0;\n                if (param.dcoef != 0) {\n                    for (int d = 0; d < 8; d++) {\n                        if (nearestDot[d][x][y] >= 0) degree++;\n                    }\n                }\n\n                int opp = 0;\n                if (param.ocoef != 0) {\n                    for (auto [d1, d2] : dirPairs) {\n                        if (nearestDot[d1][x][y] >= 0 && nearestDot[d2][x][y] >= 0) {\n                            opp++;\n                        }\n                    }\n                }\n\n                for (auto [d1, d2] : dirPairs) {\n                    int e2 = nearestDot[d1][x][y];\n                    int e4 = nearestDot[d2][x][y];\n\n                    if (e2 < 0 || e4 < 0) continue;\n\n                    int x2 = e2 / N, y2 = e2 % N;\n                    int x4 = e4 / N, y4 = e4 % N;\n\n                    int x3 = x2 + x4 - x;\n                    int y3 = y2 + y4 - y;\n\n                    if (!inside(x3, y3)) continue;\n                    if (!st.dot[x3][y3]) continue;\n\n                    int e3 = enc(x3, y3);\n                    if (nearestDot[d2][x2][y2] != e3) continue;\n                    if (nearestDot[d1][x4][y4] != e3) continue;\n\n                    Move mv{x, y, x2, y2, x3, y3, x4, y4};\n                    if (!st.rectEdgesFree(mv)) continue;\n\n                    int perim = stepLen(x, y, x2, y2)\n                              + stepLen(x2, y2, x3, y3)\n                              + stepLen(x3, y3, x4, y4)\n                              + stepLen(x4, y4, x, y);\n\n                    int area = abs((x2 - x) * (y4 - y) - (y2 - y) * (x4 - x));\n\n                    long long key = 0;\n                    key += 1LL * Weight[x][y] * param.wcoef;\n                    key -= 1LL * perim * pEff;\n                    key -= 1LL * perim * perim * param.qcoef;\n                    key += 1LL * degree * param.dcoef;\n                    key += 1LL * opp * param.ocoef;\n                    key += 1LL * area * param.acoef;\n\n                    if (param.rcoef != 0) {\n                        key += 1LL * param.rcoef * (10000LL * Weight[x][y] / (perim + 4));\n                    }\n\n                    if (param.noise > 0) key += rng.nextInt(param.noise);\n\n                    if (param.topR <= 1) {\n                        if (!found || key > bestKey || (key == bestKey && rng.nextInt(2))) {\n                            found = true;\n                            bestKey = key;\n                            bestMove = mv;\n                        }\n                    } else {\n                        insertTop(top, param.topR, Candidate{key, mv});\n                    }\n                }\n            }\n        }\n\n        if (param.topR > 1) {\n            if (top.empty()) break;\n\n            sort(top.begin(), top.end(), [](const Candidate &a, const Candidate &b) {\n                return a.key > b.key;\n            });\n\n            int r = (int)top.size();\n            int idx;\n            if (r == 1) {\n                idx = 0;\n            } else {\n                int a = rng.nextInt(r);\n                int b = rng.nextInt(r);\n                idx = 1LL * a * b / r;\n                if (idx >= r) idx = r - 1;\n            }\n\n            bestMove = top[idx].mv;\n            found = true;\n        }\n\n        if (!found) break;\n\n        st.apply(bestMove);\n    }\n\n    return st;\n}\n\nState makePerturbedState(const vector<Move> &baseOps, XorShift &rng, int mode) {\n    State st;\n    st.init();\n\n    int K = (int)baseOps.size();\n\n    int prefix = K;\n    int blockL = K + 1;\n    int blockR = K + 1;\n    int dropPct = 0;\n\n    if (mode == 0) {\n        dropPct = 4 + rng.nextInt(16);\n    } else if (mode == 1) {\n        prefix = K * (35 + rng.nextInt(55)) / 100;\n    } else if (mode == 2) {\n        if (K > 0) {\n            blockL = rng.nextInt(K);\n            int len = max(1, K * (5 + rng.nextInt(22)) / 100);\n            blockR = min(K, blockL + len);\n        }\n    }\n\n    for (int i = 0; i < K; i++) {\n        bool keep = true;\n\n        const Move &m = baseOps[i];\n\n        if (mode == 0) {\n            if (rng.nextInt(100) < dropPct) keep = false;\n        } else if (mode == 1) {\n            if (i >= prefix) keep = false;\n        } else if (mode == 2) {\n            if (blockL <= i && i < blockR) keep = false;\n        } else {\n            // Prefer deleting relatively low-value inner dots.\n            int w = Weight[m.x1][m.y1];\n            int low = maxWeightGlobal - w;\n            int prob = 3 + 28 * low / max(1, maxWeightGlobal);\n            if (rng.nextInt(100) < prob) keep = false;\n        }\n\n        if (!keep) continue;\n\n        if (st.validMove(m)) {\n            st.apply(m);\n        }\n    }\n\n    return st;\n}\n\nvoid updateElites(vector<Result> &elites, const Result &cand) {\n    elites.push_back(cand);\n\n    sort(elites.begin(), elites.end(), [](const Result &a, const Result &b) {\n        if (a.score != b.score) return a.score > b.score;\n        return a.ops.size() > b.ops.size();\n    });\n\n    vector<Result> filtered;\n    for (auto &e : elites) {\n        bool dup = false;\n        for (auto &f : filtered) {\n            if (e.score == f.score && e.ops.size() == f.ops.size()) {\n                dup = true;\n                break;\n            }\n        }\n        if (!dup) filtered.push_back(e);\n        if ((int)filtered.size() >= 6) break;\n    }\n\n    elites.swap(filtered);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    initialDots.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initialDots[i].first >> initialDots[i].second;\n    }\n\n    int c = (N - 1) / 2;\n    maxWeightGlobal = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            Weight[x][y] = (x - c) * (x - c) + (y - c) * (y - c) + 1;\n            maxWeightGlobal = max(maxWeightGlobal, Weight[x][y]);\n        }\n    }\n\n    Timer timer;\n    const double DEADLINE = 4.72;\n\n    vector<Param> params = {\n        // Previous strong baseline variants.\n        {1000,    0,   0,     0,     0,    0, 0,      0,  1, 0},\n        {1000,   20,   0,     0,     0,    0, 0,  20000,  1, 0},\n        {1000,   80,   0,     0,     0,    0, 0,  50000,  1, 0},\n        {1000,  200,   0,     0,     0,    0, 0, 100000,  1, 0},\n        {1000,  -20,   0,     0,     0,    0, 0,  50000,  1, 0},\n        {1000,  -80,   0,     0,     0,    0, 0, 100000,  1, 0},\n        {1000,    0,   0,     0,     0,    0, 0, 200000,  1, 0},\n        {1000,  400,   0,     0,     0,    0, 0, 200000,  1, 0},\n\n        // Perimeter/visibility variants.\n        {1000, 1000,   0,     0,     0,    0, 0,  50000,  4, 1},\n        {1000, 1800,   0,     0,     0,  -15, 0,  80000,  6, 1},\n        {1000, 3000,   0,     0,     0,  -30, 0, 100000,  8, 1},\n        { 950, 4500,   0,     0,     0,  -45, 0, 120000, 10, 1},\n\n        {1000, 1000,   0, 10000,  8000,    0, 0,  70000,  6, 1},\n        {1000, 2000,   0, 20000, 12000,  -15, 0, 100000,  8, 1},\n        { 900, 3500,   0, 35000, 18000,  -30, 0, 130000, 12, 1},\n        { 800, 5000,   0, 50000, 25000,  -45, 0, 160000, 16, 1},\n\n        // Efficient short-edge variants.\n        { 900,  500,  10, 10000, 10000,    0, 2,  80000,  6, 1},\n        { 800,  800,  18, 20000, 15000,  -10, 3, 100000,  8, 1},\n        { 750, 1200,  25, 30000, 20000,  -20, 4, 130000, 10, 1},\n        { 700, 1600,  35, 40000, 25000,  -30, 5, 150000, 12, 1},\n\n        // Aggressive expansion variants.\n        {1000, -300,   0,     0,     0,   20, 0,  80000,  5, 0},\n        {1000, -800,   0,     0,     0,   45, 0, 120000,  8, 0},\n\n        // Late-game tightening.\n        {1000,  800,   0, 10000,  8000,    0, 0,  70000,  6, 2},\n        {1000, 1600,   0, 25000, 15000,  -15, 0, 100000, 10, 2},\n    };\n\n    vector<Param> repairParams = {\n        {1000,    0,   0,     0,     0,    0, 0, 100000,  1, 0},\n        {1000, 1000,   0, 10000, 10000,    0, 0,  70000,  6, 1},\n        {1000, 2000,   0, 20000, 12000,  -15, 0, 100000,  8, 1},\n        { 900, 3500,   0, 35000, 18000,  -30, 0, 130000, 12, 1},\n        {1000, -300,   0,     0,     0,   20, 0, 100000,  6, 0},\n        { 850,  800,  15, 20000, 15000,  -10, 3, 110000,  8, 1},\n        { 750, 1300,  25, 30000, 20000,  -25, 4, 140000, 12, 1},\n    };\n\n    Result best{-1, {}};\n    vector<Result> elites;\n\n    int iter = 0;\n    int normalIter = 0;\n    int repairIter = 0;\n\n    while (timer.elapsed() < DEADLINE) {\n        uint64_t seed = 123456789ULL\n                      + 1000003ULL * iter\n                      + 998244353ULL * N\n                      + 19260817ULL * M;\n\n        XorShift rng(seed);\n\n        State start;\n        Param p;\n\n        bool doRepair = false;\n        if (!elites.empty() && normalIter >= (int)params.size() && iter % 3 == 2) {\n            doRepair = true;\n        }\n\n        if (!doRepair) {\n            start.init();\n            p = params[normalIter % params.size()];\n            normalIter++;\n        } else {\n            int eliteIndex = 0;\n            if ((int)elites.size() >= 2 && rng.nextInt(100) >= 65) {\n                eliteIndex = rng.nextInt((int)elites.size());\n            }\n\n            int mode = rng.nextInt(4);\n            start = makePerturbedState(elites[eliteIndex].ops, rng, mode);\n            p = repairParams[repairIter % repairParams.size()];\n            repairIter++;\n        }\n\n        State fin = greedyFill(std::move(start), p, rng, timer, DEADLINE);\n\n        Result cand{fin.totalWeight, fin.ops};\n\n        if (cand.score > best.score) {\n            best = cand;\n        }\n\n        updateElites(elites, cand);\n\n        iter++;\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (const auto &m : best.ops) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed = 2463534242u) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n};\n\nusing Board = array<unsigned char, 100>;\n\nint F[101];\nint cntFlavor[4];\n\nint anchorR[4], anchorC[4];\nint distCell[4][100];\nint targetCell[100];\n\nconst int cornerR[4] = {0, 0, 9, 9};\nconst int cornerC[4] = {0, 9, 0, 9};\n\nchar dirChar[4] = {'F', 'B', 'L', 'R'};\n\nBoard tiltBoard(const Board& b, int dir) {\n    Board nb{};\n    nb.fill(0);\n\n    if (dir == 0) {\n        for (int c = 0; c < 10; c++) {\n            int w = 0;\n            for (int r = 0; r < 10; r++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w++ * 10 + c] = v;\n            }\n        }\n    } else if (dir == 1) {\n        for (int c = 0; c < 10; c++) {\n            int w = 9;\n            for (int r = 9; r >= 0; r--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w-- * 10 + c] = v;\n            }\n        }\n    } else if (dir == 2) {\n        for (int r = 0; r < 10; r++) {\n            int w = 0;\n            for (int c = 0; c < 10; c++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w++] = v;\n            }\n        }\n    } else {\n        for (int r = 0; r < 10; r++) {\n            int w = 9;\n            for (int c = 9; c >= 0; c--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w--] = v;\n            }\n        }\n    }\n\n    return nb;\n}\n\nvoid placeCandyByP(Board& b, int p, int flavor) {\n    int k = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            k++;\n            if (k == p) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n        }\n    }\n}\n\nvoid placeRandomCandy(Board& b, int emptyCnt, int flavor, XorShift& rng) {\n    int k = rng.randint(emptyCnt);\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            if (k == 0) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n            k--;\n        }\n    }\n}\n\nlong long componentRawScore(const Board& b) {\n    bool vis[100] = {};\n    long long res = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int q[100];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            int r = v / 10;\n            int c = v % 10;\n\n            if (r > 0) {\n                int ni = v - 10;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (r < 9) {\n                int ni = v + 10;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (c > 0) {\n                int ni = v - 1;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (c < 9) {\n                int ni = v + 1;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        res += 1LL * sz * sz;\n    }\n\n    return res;\n}\n\nlong long evalBoard(const Board& b) {\n    bool vis[100] = {};\n    long long comp = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int q[100];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            int r = v / 10;\n            int c = v % 10;\n\n            if (r > 0) {\n                int ni = v - 10;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (r < 9) {\n                int ni = v + 10;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (c > 0) {\n                int ni = v - 1;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n            if (c < 9) {\n                int ni = v + 1;\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        comp += 1LL * sz * sz;\n    }\n\n    int sameAdj = 0;\n    int diffAdj = 0;\n    int pref = 0;\n    int targetMatch = 0;\n\n    for (int r = 0; r < 10; r++) {\n        for (int c = 0; c < 10; c++) {\n            int id = r * 10 + c;\n            int fl = b[id];\n            if (fl == 0) continue;\n\n            pref += 18 - distCell[fl][id];\n            if (targetCell[id] == fl) targetMatch++;\n\n            if (r + 1 < 10) {\n                int fl2 = b[(r + 1) * 10 + c];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n            if (c + 1 < 10) {\n                int fl2 = b[r * 10 + c + 1];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n        }\n    }\n\n    return comp * 100 + sameAdj * 220 - diffAdj * 60 + pref * 28 + targetMatch * 300;\n}\n\nvoid buildTarget() {\n    for (int fl = 1; fl <= 3; fl++) {\n        for (int id = 0; id < 100; id++) {\n            int r = id / 10;\n            int c = id % 10;\n            distCell[fl][id] = abs(r - anchorR[fl]) + abs(c - anchorC[fl]);\n        }\n    }\n\n    fill(targetCell, targetCell + 100, 0);\n\n    struct Item {\n        int dist;\n        int fl;\n        int id;\n    };\n\n    vector<Item> items;\n    items.reserve(300);\n\n    for (int id = 0; id < 100; id++) {\n        for (int fl = 1; fl <= 3; fl++) {\n            items.push_back({distCell[fl][id], fl, id});\n        }\n    }\n\n    sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.fl != b.fl) return a.fl < b.fl;\n        return a.id < b.id;\n    });\n\n    int rem[4];\n    for (int fl = 1; fl <= 3; fl++) rem[fl] = cntFlavor[fl];\n\n    for (auto& it : items) {\n        if (targetCell[it.id] == 0 && rem[it.fl] > 0) {\n            targetCell[it.id] = it.fl;\n            rem[it.fl]--;\n        }\n    }\n}\n\nint choosePolicyDir(const Board& b) {\n    int bestDir = 0;\n    long long bestVal = LLONG_MIN;\n\n    for (int d = 0; d < 4; d++) {\n        Board nb = tiltBoard(b, d);\n        long long val = evalBoard(nb);\n        if (val > bestVal) {\n            bestVal = val;\n            bestDir = d;\n        }\n    }\n\n    return bestDir;\n}\n\nlong long simulatePolicyGame(uint32_t seed) {\n    XorShift rng(seed);\n    Board b{};\n    b.fill(0);\n\n    for (int t = 1; t <= 100; t++) {\n        placeRandomCandy(b, 101 - t, F[t], rng);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long simulateRollout(Board b, int nextT, uint32_t seed) {\n    XorShift rng(seed);\n\n    for (int t = nextT; t <= 100; t++) {\n        placeRandomCandy(b, 101 - t, F[t], rng);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long exactOneStepLookahead(const Board& b, int currentT) {\n    if (currentT >= 100) return evalBoard(b);\n\n    int nt = currentT + 1;\n    int fl = F[nt];\n\n    vector<int> emp;\n    emp.reserve(100);\n\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) emp.push_back(i);\n    }\n\n    long long sum = 0;\n\n    for (int id : emp) {\n        Board tmp = b;\n        tmp[id] = (unsigned char)fl;\n\n        if (nt == 100) {\n            sum += evalBoard(tmp);\n        } else {\n            long long best = LLONG_MIN;\n            for (int d = 0; d < 4; d++) {\n                Board nb = tiltBoard(tmp, d);\n                best = max(best, evalBoard(nb));\n            }\n            sum += best;\n        }\n    }\n\n    return sum / max(1, (int)emp.size());\n}\n\nvoid selectCornerAssignment() {\n    double bestScore = -1.0;\n    int bestCorner[4] = {0, 0, 1, 2};\n\n    vector<uint32_t> seeds;\n    for (int i = 0; i < 5; i++) {\n        seeds.push_back(1234567u + i * 1000003u);\n    }\n\n    for (int mask = 0; mask < (1 << 4); mask++) {\n        if (__builtin_popcount((unsigned)mask) != 3) continue;\n\n        vector<int> cs;\n        for (int i = 0; i < 4; i++) {\n            if (mask >> i & 1) cs.push_back(i);\n        }\n\n        sort(cs.begin(), cs.end());\n\n        do {\n            for (int fl = 1; fl <= 3; fl++) {\n                int cid = cs[fl - 1];\n                anchorR[fl] = cornerR[cid];\n                anchorC[fl] = cornerC[cid];\n            }\n\n            buildTarget();\n\n            long long sum = 0;\n            for (uint32_t seed : seeds) {\n                sum += simulatePolicyGame(seed);\n            }\n\n            double avg = (double)sum / seeds.size();\n\n            if (avg > bestScore) {\n                bestScore = avg;\n                for (int fl = 1; fl <= 3; fl++) {\n                    bestCorner[fl] = cs[fl - 1];\n                }\n            }\n\n        } while (next_permutation(cs.begin(), cs.end()));\n    }\n\n    for (int fl = 1; fl <= 3; fl++) {\n        int cid = bestCorner[fl];\n        anchorR[fl] = cornerR[cid];\n        anchorC[fl] = cornerC[cid];\n    }\n\n    buildTarget();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    for (int i = 1; i <= 100; i++) {\n        cin >> F[i];\n        cntFlavor[F[i]]++;\n    }\n\n    selectCornerAssignment();\n\n    Board board{};\n    board.fill(0);\n\n    XorShift rolloutRng(987654321u);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        placeCandyByP(board, p, F[t]);\n\n        Board cand[4];\n        long long baseEval[4];\n        long long lookEval[4];\n\n        for (int d = 0; d < 4; d++) {\n            cand[d] = tiltBoard(board, d);\n            baseEval[d] = evalBoard(cand[d]);\n        }\n\n        bool canLook = true;\n        {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > 1.72) canLook = false;\n        }\n\n        for (int d = 0; d < 4; d++) {\n            if (canLook && t < 100) lookEval[d] = exactOneStepLookahead(cand[d], t);\n            else lookEval[d] = baseEval[d];\n        }\n\n        long long rolloutTotal[4] = {};\n        int samples = 0;\n\n        if (t < 100) {\n            double ratio = (double)t / 100.0;\n            double targetTime = 0.03 + 1.77 * pow(ratio, 1.25);\n            const double HARD_LIMIT = 1.86;\n\n            while (true) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - startTime).count();\n\n                if (elapsed > HARD_LIMIT) break;\n                if (elapsed > targetTime && samples >= 1) break;\n\n                uint32_t seed = rolloutRng.next();\n\n                for (int d = 0; d < 4; d++) {\n                    rolloutTotal[d] += simulateRollout(cand[d], t + 1, seed);\n                }\n\n                samples++;\n\n                if (samples >= 250) break;\n            }\n        }\n\n        int bestDir = 0;\n        double bestScore = -1e100;\n\n        for (int d = 0; d < 4; d++) {\n            double score;\n\n            if (samples > 0) {\n                double rolloutAvg = (double)rolloutTotal[d] / samples;\n                double lookPseudoRaw = (double)lookEval[d] / 100.0;\n                double basePseudoRaw = (double)baseEval[d] / 100.0;\n\n                score = rolloutAvg + 0.12 * lookPseudoRaw + 0.03 * basePseudoRaw;\n            } else {\n                score = (double)lookEval[d] + 0.1 * (double)baseEval[d];\n            }\n\n            if (score > bestScore) {\n                bestScore = score;\n                bestDir = d;\n            }\n        }\n\n        board = cand[bestDir];\n\n        cout << dirChar[bestDir] << endl;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing U64 = uint64_t;\nusing Row = array<U64, 2>;\n\nstruct FastRNG {\n    uint64_t x;\n    FastRNG(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline bool bitRow(const vector<Row>& rows, int i, int j) {\n    return (rows[i][j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline bool bitRowArr(const array<Row, 100>& rows, int i, int j) {\n    return (rows[i][j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline void setRow(vector<Row>& rows, int i, int j) {\n    rows[i][j >> 6] |= 1ULL << (j & 63);\n    rows[j][i >> 6] |= 1ULL << (i & 63);\n}\n\nstatic inline void setRowArr(array<Row, 100>& rows, int i, int j) {\n    rows[i][j >> 6] |= 1ULL << (j & 63);\n    rows[j][i >> 6] |= 1ULL << (i & 63);\n}\n\nstruct Candidate {\n    array<unsigned char, 100> deg{};\n    array<unsigned char, 100> origDeg{};\n    array<unsigned char, 100> ord{};\n    array<uint64_t, 2> mask{};\n    array<Row, 100> sortedRows{};\n    int edges = 0;\n};\n\nstruct Codebook {\n    int M = 0;\n    int N = 0;\n    double eps = 0.0;\n    vector<Candidate> code;\n    vector<string> out;\n};\n\nstatic inline bool getMaskBitRaw(const array<uint64_t, 2>& mask, int j) {\n    return (mask[j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline bool getMaskBit(const Candidate& c, int j) {\n    return (c.mask[j >> 6] >> (j & 63)) & 1ULL;\n}\n\nCandidate makeCandidate(int N, const array<uint64_t, 2>& mask) {\n    Candidate c;\n    c.mask = mask;\n\n    int suf[105];\n    suf[N] = 0;\n    for (int i = N - 1; i >= 0; i--) {\n        suf[i] = suf[i + 1] + (i == 0 ? 0 : (getMaskBitRaw(mask, i) ? 1 : 0));\n    }\n\n    vector<int> d(N);\n    int edges = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool b = (i == 0 ? false : getMaskBitRaw(mask, i));\n        d[i] = suf[i + 1] + (b ? i : 0);\n        c.origDeg[i] = (unsigned char)d[i];\n        if (b) edges += i;\n    }\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        if (d[a] != d[b]) return d[a] < d[b];\n        return a < b;\n    });\n\n    for (int i = 0; i < N; i++) {\n        c.ord[i] = (unsigned char)p[i];\n        c.deg[i] = (unsigned char)d[p[i]];\n    }\n\n    for (int i = 0; i < 100; i++) c.sortedRows[i] = Row{0ULL, 0ULL};\n\n    for (int a = 0; a < N; a++) {\n        int va = p[a];\n        for (int b = a + 1; b < N; b++) {\n            int vb = p[b];\n            bool e = getMaskBitRaw(mask, max(va, vb));\n            if (e) setRowArr(c.sortedRows, a, b);\n        }\n    }\n\n    c.edges = edges;\n    return c;\n}\n\nstring thresholdGraphString(const Candidate& c, int N) {\n    string s;\n    s.reserve(N * (N - 1) / 2);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            s.push_back(getMaskBit(c, j) ? '1' : '0');\n        }\n    }\n\n    return s;\n}\n\nint ceilLog2Int(int x) {\n    int p = 1, r = 0;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\ndouble degreeDistanceMetric(const Candidate& a, const Candidate& b, int N) {\n    double ss = 0.0;\n    double sum = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double v = (double)a.deg[i] - (double)b.deg[i];\n        ss += v * v;\n        sum += v;\n    }\n\n    double score = ss - (sum * sum) / max(1.0, 2.0 * N - 2.0);\n    if (score < 0) score = 0;\n    return score;\n}\n\nvector<Candidate> generatePool(int N, int M, double eps, FastRNG& rng) {\n    int target = max(400, min(2400, 20 * M + 350));\n\n    vector<Candidate> pool;\n    pool.reserve(target + 10);\n\n    unordered_set<string> seen;\n    seen.reserve(target * 3);\n\n    auto addCandidate = [&](const array<uint64_t, 2>& mask) {\n        Candidate c = makeCandidate(N, mask);\n\n        string key;\n        key.resize(N);\n        for (int i = 0; i < N; i++) key[i] = (char)c.deg[i];\n\n        if (seen.insert(key).second) {\n            pool.push_back(c);\n        }\n    };\n\n    if (N - 1 <= 20) {\n        uint64_t total = 1ULL << (N - 1);\n        if ((int)total <= target) {\n            for (uint64_t m = 0; m < total; m++) {\n                array<uint64_t, 2> mask{0ULL, 0ULL};\n                mask[0] = m << 1;\n                addCandidate(mask);\n            }\n            return pool;\n        }\n    }\n\n    {\n        array<uint64_t, 2> emptyMask{0ULL, 0ULL};\n        addCandidate(emptyMask);\n\n        array<uint64_t, 2> fullMask{0ULL, 0ULL};\n        for (int j = 1; j < N; j++) {\n            fullMask[j >> 6] |= 1ULL << (j & 63);\n        }\n        addCandidate(fullMask);\n    }\n\n    int attempts = 0;\n    while ((int)pool.size() < target && attempts < target * 70) {\n        attempts++;\n\n        array<uint64_t, 2> mask{0ULL, 0ULL};\n        int mode = rng.nextInt(6);\n\n        if (mode == 0) {\n            double p = rng.nextDouble();\n            for (int j = 1; j < N; j++) {\n                if (rng.nextDouble() < p) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        } else if (mode == 1) {\n            int need = rng.nextInt(N);\n            int rem = N - 1;\n            for (int j = 1; j < N; j++) {\n                if (need > 0 && rng.nextInt(rem) < need) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                    need--;\n                }\n                rem--;\n            }\n        } else if (mode == 2) {\n            int cut = 1 + rng.nextInt(N - 1);\n            for (int j = cut; j < N; j++) {\n                mask[j >> 6] |= 1ULL << (j & 63);\n            }\n            for (int t = 0; t < N / 7 + 1; t++) {\n                int j = 1 + rng.nextInt(N - 1);\n                mask[j >> 6] ^= 1ULL << (j & 63);\n            }\n        } else if (mode == 3) {\n            double p;\n            int r = rng.nextInt(7);\n            if (r == 0) p = 0.04;\n            else if (r == 1) p = 0.10;\n            else if (r == 2) p = 0.22;\n            else if (r == 3) p = 0.50;\n            else if (r == 4) p = 0.78;\n            else if (r == 5) p = 0.90;\n            else p = 0.96;\n\n            for (int j = 1; j < N; j++) {\n                if (rng.nextDouble() < p) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        } else if (mode == 4) {\n            int blocks = 2 + rng.nextInt(6);\n            bool cur = rng.nextInt(2);\n            int pos = 1;\n            for (int b = 0; b < blocks && pos < N; b++) {\n                int denom = max(1, blocks - b);\n                int len = 1 + rng.nextInt(max(1, (N - pos) / denom));\n                int to = min(N, pos + len);\n                for (int j = pos; j < to; j++) {\n                    if (cur) mask[j >> 6] |= 1ULL << (j & 63);\n                }\n                cur = !cur;\n                pos = to;\n            }\n            for (int j = pos; j < N; j++) {\n                if (cur) mask[j >> 6] |= 1ULL << (j & 63);\n            }\n        } else {\n            // Smooth random walk mask: tends to create diverse but structured degree sequences.\n            double x = rng.nextDouble();\n            double drift = (rng.nextDouble() - 0.5) * 0.08;\n            for (int j = 1; j < N; j++) {\n                x += drift + (rng.nextDouble() - 0.5) * 0.18;\n                if (x < 0) x = -x;\n                if (x > 1) x = 2 - x;\n                if (rng.nextDouble() < x) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        }\n\n        addCandidate(mask);\n    }\n\n    return pool;\n}\n\nCodebook buildCodebook(int M, int N, double eps, FastRNG& rng) {\n    vector<Candidate> pool = generatePool(N, M, eps, rng);\n    int K = (int)pool.size();\n\n    Codebook book;\n    book.M = M;\n    book.N = N;\n    book.eps = eps;\n\n    if (K < M) return book;\n\n    vector<int> starts;\n\n    int minEdge = 0, maxEdge = 0;\n    for (int i = 1; i < K; i++) {\n        if (pool[i].edges < pool[minEdge].edges) minEdge = i;\n        if (pool[i].edges > pool[maxEdge].edges) maxEdge = i;\n    }\n\n    starts.push_back(minEdge);\n    starts.push_back(maxEdge);\n    for (int t = 0; t < 3 && K > 0; t++) starts.push_back(rng.nextInt(K));\n\n    double bestMinDist = -1.0;\n    vector<Candidate> bestCode;\n\n    for (int st : starts) {\n        vector<char> used(K, 0);\n        vector<double> mind(K, 1e100);\n        vector<Candidate> cur;\n        cur.reserve(M);\n\n        for (int it = 0; it < M; it++) {\n            int best = -1;\n\n            if (it == 0) {\n                best = st;\n            } else {\n                double bv = -1;\n                for (int i = 0; i < K; i++) {\n                    if (!used[i] && mind[i] > bv) {\n                        bv = mind[i];\n                        best = i;\n                    }\n                }\n            }\n\n            used[best] = 1;\n            Candidate chosen = pool[best];\n\n            for (int i = 0; i < K; i++) {\n                if (!used[i]) {\n                    double d = degreeDistanceMetric(chosen, pool[i], N);\n                    if (d < mind[i]) mind[i] = d;\n                }\n            }\n\n            cur.push_back(chosen);\n        }\n\n        double md = 1e100;\n        for (int i = 0; i < M; i++) {\n            for (int j = i + 1; j < M; j++) {\n                md = min(md, degreeDistanceMetric(cur[i], cur[j], N));\n            }\n        }\n\n        if (md > bestMinDist) {\n            bestMinDist = md;\n            bestCode = std::move(cur);\n        }\n    }\n\n    book.code = std::move(bestCode);\n    book.out.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        book.out[k] = thresholdGraphString(book.code[k], N);\n    }\n\n    return book;\n}\n\nstruct ParsedGraph {\n    vector<Row> rows;\n    vector<int> deg;\n    vector<int> sortedDeg;\n    vector<int> ord;\n};\n\nParsedGraph parseGraph(const string& s, int N) {\n    ParsedGraph g;\n    g.rows.assign(N, Row{0ULL, 0ULL});\n    g.deg.assign(N, 0);\n\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++, idx++) {\n            if (s[idx] == '1') {\n                setRow(g.rows, i, j);\n                g.deg[i]++;\n                g.deg[j]++;\n            }\n        }\n    }\n\n    vector<int> ndSum(N, 0);\n    for (int i = 0; i < N; i++) {\n        int sum = 0;\n        for (int j = 0; j < N; j++) {\n            if (i != j && bitRow(g.rows, i, j)) sum += g.deg[j];\n        }\n        ndSum[i] = sum;\n    }\n\n    g.ord.resize(N);\n    iota(g.ord.begin(), g.ord.end(), 0);\n    sort(g.ord.begin(), g.ord.end(), [&](int a, int b) {\n        if (g.deg[a] != g.deg[b]) return g.deg[a] < g.deg[b];\n        if (ndSum[a] != ndSum[b]) return ndSum[a] < ndSum[b];\n        return a < b;\n    });\n\n    g.sortedDeg.resize(N);\n    for (int i = 0; i < N; i++) g.sortedDeg[i] = g.deg[g.ord[i]];\n\n    return g;\n}\n\ndouble scoreLambda(int N, double eps) {\n    if (eps <= 1e-12) return 0.0;\n\n    double var = max(1e-9, (N - 1) * eps * (1.0 - eps));\n    double logodds = log((1.0 - eps) / eps);\n    logodds = max(0.15, logodds);\n\n    double lambda = 1.0 / (2.0 * var * logodds);\n\n    if (lambda < 0.025) lambda = 0.025;\n    if (lambda > 0.18) lambda = 0.18;\n    return lambda;\n}\n\ndouble degreeScore(const Codebook& book, const Candidate& c, const vector<int>& obsSorted) {\n    int N = book.N;\n    double eps = book.eps;\n    double base = eps * (N - 1);\n    double scale = 1.0 - 2.0 * eps;\n\n    double ss = 0.0;\n    double sum = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double mu = base + scale * (double)c.deg[i];\n        double diff = obsSorted[i] - mu;\n        ss += diff * diff;\n        sum += diff;\n    }\n\n    if (eps <= 1e-12) return ss;\n\n    double score = ss - (sum * sum) / max(1.0, 2.0 * N - 2.0);\n    if (score < 0) score = 0;\n    return score;\n}\n\nint initialAdjCost(const ParsedGraph& h, const Candidate& c, const vector<int>& order, int N) {\n    int cost = 0;\n    for (int i = 0; i < N; i++) {\n        int vi = order[i];\n        for (int j = i + 1; j < N; j++) {\n            bool x = bitRow(h.rows, vi, order[j]);\n            bool y = bitRowArr(c.sortedRows, i, j);\n            cost += (x != y);\n        }\n    }\n    return cost;\n}\n\nint deltaSwap(const ParsedGraph& h, const Candidate& c, const vector<int>& order, int a, int b, int N) {\n    if (a == b) return 0;\n    if (a > b) swap(a, b);\n\n    int va = order[a];\n    int vb = order[b];\n\n    int oldCost = 0;\n    int newCost = 0;\n\n    for (int k = 0; k < N; k++) {\n        if (k == a || k == b) continue;\n\n        int vk = order[k];\n\n        bool h_ak = bitRow(h.rows, va, vk);\n        bool h_bk = bitRow(h.rows, vb, vk);\n\n        bool g_ak = bitRowArr(c.sortedRows, min(a, k), max(a, k));\n        bool g_bk = bitRowArr(c.sortedRows, min(b, k), max(b, k));\n\n        oldCost += (h_ak != g_ak);\n        oldCost += (h_bk != g_bk);\n\n        newCost += (h_bk != g_ak);\n        newCost += (h_ak != g_bk);\n    }\n\n    return newCost - oldCost;\n}\n\nint localAdjCost(const ParsedGraph& h, const Candidate& c, int N) {\n    vector<int> order = h.ord;\n    int cost = initialAdjCost(h, c, order, N);\n\n    int window;\n    if (N <= 30) window = 10;\n    else if (N <= 70) window = 8;\n    else window = 6;\n\n    int passes = (N <= 40 ? 4 : 3);\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool improved = false;\n\n        for (int i = 0; i + 1 < N; i++) {\n            int d = deltaSwap(h, c, order, i, i + 1, N);\n            if (d < 0) {\n                swap(order[i], order[i + 1]);\n                cost += d;\n                improved = true;\n            }\n        }\n\n        for (int i = N - 2; i >= 0; i--) {\n            int d = deltaSwap(h, c, order, i, i + 1, N);\n            if (d < 0) {\n                swap(order[i], order[i + 1]);\n                cost += d;\n                improved = true;\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            int bestJ = -1;\n            int bestD = 0;\n            int lim = min(N, i + window + 1);\n\n            for (int j = i + 2; j < lim; j++) {\n                int d = deltaSwap(h, c, order, i, j, N);\n                if (d < bestD) {\n                    bestD = d;\n                    bestJ = j;\n                }\n            }\n\n            if (bestJ != -1) {\n                swap(order[i], order[bestJ]);\n                cost += bestD;\n                improved = true;\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    return cost;\n}\n\nint decode(const Codebook& book, const ParsedGraph& h) {\n    int M = book.M;\n    int N = book.N;\n\n    vector<double> dscore(M);\n    vector<int> ham0(M);\n    vector<int> ids(M);\n    iota(ids.begin(), ids.end(), 0);\n\n    double lambda = scoreLambda(N, book.eps);\n\n    for (int k = 0; k < M; k++) {\n        dscore[k] = degreeScore(book, book.code[k], h.sortedDeg);\n    }\n\n    if (book.eps <= 1e-12) {\n        return min_element(ids.begin(), ids.end(), [&](int a, int b) {\n            return dscore[a] < dscore[b];\n        }) - ids.begin();\n    }\n\n    for (int k = 0; k < M; k++) {\n        ham0[k] = initialAdjCost(h, book.code[k], h.ord, N);\n    }\n\n    vector<int> cand;\n    vector<char> used(M, 0);\n\n    auto addTopBy = [&](auto valueFunc, int cnt) {\n        vector<int> v(M);\n        iota(v.begin(), v.end(), 0);\n        nth_element(v.begin(), v.begin() + min(cnt, M), v.end(), [&](int a, int b) {\n            return valueFunc(a) < valueFunc(b);\n        });\n        sort(v.begin(), v.begin() + min(cnt, M), [&](int a, int b) {\n            return valueFunc(a) < valueFunc(b);\n        });\n        for (int i = 0; i < min(cnt, M); i++) {\n            int k = v[i];\n            if (!used[k]) {\n                used[k] = 1;\n                cand.push_back(k);\n            }\n        }\n    };\n\n    int topD, topC, topH;\n    if (book.eps <= 0.05) {\n        topD = 6; topC = 8; topH = 4;\n    } else if (book.eps <= 0.20) {\n        topD = 8; topC = 10; topH = 5;\n    } else {\n        topD = 10; topC = 13; topH = 6;\n    }\n\n    addTopBy([&](int k) { return dscore[k]; }, topD);\n    addTopBy([&](int k) { return (double)ham0[k] + lambda * dscore[k]; }, topC);\n    addTopBy([&](int k) { return (double)ham0[k]; }, topH);\n\n    int best = cand.empty() ? 0 : cand[0];\n    double bestFinal = 1e100;\n\n    for (int k : cand) {\n        int ham = localAdjCost(h, book.code[k], N);\n        double finalScore = (double)ham + lambda * dscore[k];\n\n        // Slightly trust the cheap global ordering too, useful when local search falls into poor swap minima.\n        finalScore += 0.03 * ((double)ham0[k] + lambda * dscore[k]);\n\n        if (finalScore < bestFinal) {\n            bestFinal = finalScore;\n            best = k;\n        }\n    }\n\n    return best;\n}\n\nvector<int> simulateNoisyDegrees(const Candidate& c, int N, double eps, FastRNG& rng) {\n    vector<int> deg(N, 0);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = getMaskBit(c, j);\n            if (rng.nextDouble() < eps) e = !e;\n            if (e) {\n                deg[i]++;\n                deg[j]++;\n            }\n        }\n    }\n\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint decodeDegreeOnly(const Codebook& book, const vector<int>& obsSorted) {\n    int best = 0;\n    double bestScore = 1e100;\n\n    for (int k = 0; k < book.M; k++) {\n        double sc = degreeScore(book, book.code[k], obsSorted);\n        if (sc < bestScore) {\n            bestScore = sc;\n            best = k;\n        }\n    }\n\n    return best;\n}\n\nint simulateErrorsDegreeOnly(const Codebook& book, int T, FastRNG& rng) {\n    int err = 0;\n\n    for (int t = 0; t < T; t++) {\n        int s = rng.nextInt(book.M);\n        vector<int> obs = simulateNoisyDegrees(book.code[s], book.N, book.eps, rng);\n        int pred = decodeDegreeOnly(book, obs);\n        if (pred != s) err++;\n    }\n\n    return err;\n}\n\nvector<int> candidateNs(int M, double eps) {\n    int minN = max(4, ceilLog2Int(M) + 1);\n    vector<int> ns;\n\n    if (eps <= 1e-12) {\n        ns.push_back(minN);\n        return ns;\n    }\n\n    int maxN;\n    if (eps <= 0.01) maxN = min(100, minN + 15);\n    else if (eps <= 0.05) maxN = min(100, minN + 40);\n    else if (eps <= 0.15) maxN = 85;\n    else maxN = 100;\n\n    for (int n = minN; n <= maxN; ) {\n        ns.push_back(n);\n\n        int step;\n        if (eps <= 0.05) {\n            if (n < 30) step = 1;\n            else if (n < 60) step = 3;\n            else step = 5;\n        } else {\n            if (n < 30) step = 2;\n            else if (n < 70) step = 5;\n            else step = 10;\n        }\n\n        n += step;\n    }\n\n    if (ns.empty() || ns.back() != maxN) ns.push_back(maxN);\n    if (eps >= 0.18 && ns.back() != 100) ns.push_back(100);\n\n    sort(ns.begin(), ns.end());\n    ns.erase(unique(ns.begin(), ns.end()), ns.end());\n    return ns;\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 epsInt = (int)llround(eps * 100);\n    FastRNG rng(123456789ULL + 10007ULL * M + 1000003ULL * epsInt);\n\n    Codebook bestBook;\n    double bestValue = -1.0;\n\n    vector<int> ns = candidateNs(M, eps);\n\n    for (int N : ns) {\n        Codebook book = buildCodebook(M, N, eps, rng);\n        if ((int)book.code.size() != M) continue;\n\n        double value;\n\n        if (eps <= 1e-12) {\n            value = 1.0 / N;\n        } else {\n            int T;\n            if (eps <= 0.03) T = 260;\n            else if (eps <= 0.15) T = 210;\n            else T = 170;\n\n            int err = simulateErrorsDegreeOnly(book, T, rng);\n            double p = (err + 0.25) / (T + 0.5);\n\n            // Slightly favor larger N at high noise because the final decoder uses adjacency too.\n            value = exp(100.0 * log(max(1e-12, 1.0 - 0.1 * p))) / N;\n            if (eps >= 0.25) value *= pow((double)N / 100.0, 0.12);\n        }\n\n        if (value > bestValue) {\n            bestValue = value;\n            bestBook = std::move(book);\n        }\n    }\n\n    if ((int)bestBook.code.size() != M) {\n        int N = max(4, ceilLog2Int(M) + 1);\n        bestBook = buildCodebook(M, N, eps, rng);\n    }\n\n    cout << bestBook.N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << bestBook.out[k] << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        ParsedGraph h = parseGraph(H, bestBook.N);\n        int ans = decode(bestBook, h);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF = (1LL << 60);\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int root(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = root(a);\n        b = root(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    int mx, my;\n    ll len2;\n};\n\nstruct Adj {\n    int to, w, id;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<vector<Adj>> g;\nvector<int> X, Y;\nvector<int> degv;\nmt19937 rng(1234567);\n\nuint64_t morton_key(int x, int y) {\n    uint64_t r = 0;\n    for (int i = 0; i < 12; i++) {\n        r |= uint64_t((x >> i) & 1) << (2 * i);\n        r |= uint64_t((y >> i) & 1) << (2 * i + 1);\n    }\n    return r;\n}\n\nvoid dijkstra_fill(int s, const vector<int>* assign, int ban_day, vector<ll>& dist) {\n    fill(dist.begin(), dist.end(), INF);\n\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\n    while (!pq.empty()) {\n        auto [du, u] = pq.top();\n        pq.pop();\n\n        if (du != dist[u]) continue;\n\n        for (const auto& e : g[u]) {\n            if (assign && (*assign)[e.id] == ban_day) continue;\n\n            ll nd = du + e.w;\n            if (nd < dist[e.to]) {\n                dist[e.to] = nd;\n                pq.push({nd, e.to});\n            }\n        }\n    }\n}\n\nbool connected_day(const vector<int>& assign, int day) {\n    DSU uf(N);\n\n    for (int i = 0; i < M; i++) {\n        if (assign[i] != day) {\n            uf.unite(edges[i].u, edges[i].v);\n        }\n    }\n\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n\n    return true;\n}\n\nbool all_connected(const vector<int>& assign) {\n    for (int d = 0; d < D; d++) {\n        if (!connected_day(assign, d)) return false;\n    }\n    return true;\n}\n\nbool can_add_removal_keep_connected(const vector<int>& assign, int day, int eid) {\n    DSU uf(N);\n\n    for (int i = 0; i < M; i++) {\n        if (assign[i] == day || i == eid) continue;\n        uf.unite(edges[i].u, edges[i].v);\n    }\n\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n\n    return true;\n}\n\nvoid repair_isolated(vector<int>& assign) {\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n\n    for (int i = 0; i < M; i++) {\n        int d = assign[i];\n        load[d]++;\n        vc[edges[i].u][d]++;\n        vc[edges[i].v][d]++;\n    }\n\n    bool changed = true;\n    int loop = 0;\n\n    while (changed && loop++ < 20) {\n        changed = false;\n\n        for (int v = 0; v < N; v++) {\n            for (int d = 0; d < D; d++) {\n                if (vc[v][d] < degv[v]) continue;\n\n                int eid = -1;\n                for (auto& a : g[v]) {\n                    if (assign[a.id] == d) {\n                        eid = a.id;\n                        break;\n                    }\n                }\n\n                if (eid == -1) continue;\n\n                int u = edges[eid].u;\n                int w = edges[eid].v;\n                int best = -1;\n\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == d) continue;\n                    if (load[nd] >= K) continue;\n                    if (vc[u][nd] + 1 >= degv[u]) continue;\n                    if (vc[w][nd] + 1 >= degv[w]) continue;\n\n                    best = nd;\n                    break;\n                }\n\n                if (best == -1) {\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd != d && load[nd] < K) {\n                            best = nd;\n                            break;\n                        }\n                    }\n                }\n\n                if (best != -1) {\n                    assign[eid] = best;\n                    load[d]--;\n                    load[best]++;\n                    vc[u][d]--;\n                    vc[w][d]--;\n                    vc[u][best]++;\n                    vc[w][best]++;\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\nvoid repair_connectivity(vector<int>& assign, const Timer& timer, double limit_time) {\n    vector<int> load(D, 0);\n    for (int x : assign) load[x]++;\n\n    for (int iter = 0; iter < 200 && timer.elapsed() < limit_time; iter++) {\n        bool changed = false;\n\n        for (int day = 0; day < D && timer.elapsed() < limit_time; day++) {\n            DSU uf(N);\n\n            for (int i = 0; i < M; i++) {\n                if (assign[i] != day) {\n                    uf.unite(edges[i].u, edges[i].v);\n                }\n            }\n\n            int r0 = uf.root(0);\n            bool ok = true;\n\n            for (int i = 1; i < N; i++) {\n                if (uf.root(i) != r0) {\n                    ok = false;\n                    break;\n                }\n            }\n\n            if (ok) continue;\n\n            vector<int> cand;\n            cand.reserve(load[day]);\n\n            for (int i = 0; i < M; i++) {\n                if (assign[i] == day && uf.root(edges[i].u) != uf.root(edges[i].v)) {\n                    cand.push_back(i);\n                }\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            bool moved = false;\n\n            for (int eid : cand) {\n                int best_day = -1;\n                int best_cost = INT_MAX;\n\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == day) continue;\n                    if (load[nd] >= K) continue;\n\n                    int cost = load[nd];\n                    if (!can_add_removal_keep_connected(assign, nd, eid)) {\n                        cost += 1000000;\n                    }\n\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_day = nd;\n                    }\n                }\n\n                if (best_day != -1) {\n                    assign[eid] = best_day;\n                    load[day]--;\n                    load[best_day]++;\n                    changed = true;\n                    moved = true;\n                    break;\n                }\n            }\n\n            if (moved) break;\n        }\n\n        if (!changed) break;\n        if (all_connected(assign)) break;\n    }\n}\n\nvector<int> make_order(int type) {\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    if (type == 0) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) < morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 1) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) > morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 2) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].mx != edges[b].mx) return edges[a].mx < edges[b].mx;\n            return edges[a].my < edges[b].my;\n        });\n    } else if (type == 3) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].my != edges[b].my) return edges[a].my < edges[b].my;\n            return edges[a].mx < edges[b].mx;\n        });\n    } else if (type == 4) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx + edges[a].my < edges[b].mx + edges[b].my;\n        });\n    } else if (type == 5) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx - edges[a].my < edges[b].mx - edges[b].my;\n        });\n    } else if (type == 6) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].len2 > edges[b].len2;\n        });\n    } else {\n        int A = uniform_int_distribution<int>(-1000, 1000)(rng);\n        int B = uniform_int_distribution<int>(-1000, 1000)(rng);\n\n        if (A == 0 && B == 0) A = 1;\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ll va = 1LL * A * edges[a].mx + 1LL * B * edges[a].my;\n            ll vb = 1LL * A * edges[b].mx + 1LL * B * edges[b].my;\n\n            if (va != vb) return va < vb;\n            return a < b;\n        });\n    }\n\n    return ord;\n}\n\nvector<int> construct_cyclic(int type) {\n    vector<int> ord = make_order(type);\n\n    vector<int> perm(D);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n\n    int shift = uniform_int_distribution<int>(0, D - 1)(rng);\n\n    vector<int> assign(M);\n\n    for (int i = 0; i < M; i++) {\n        assign[ord[i]] = perm[(i + shift) % D];\n    }\n\n    repair_isolated(assign);\n    return assign;\n}\n\nvector<int> construct_greedy(int type) {\n    vector<int> ord;\n\n    if (type == 100) {\n        ord.resize(M);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n    } else {\n        ord = make_order(type);\n    }\n\n    vector<int> target(D, M / D);\n    for (int i = 0; i < M % D; i++) target[i]++;\n    shuffle(target.begin(), target.end(), rng);\n\n    vector<int> assign(M, -1);\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n\n    const int G = 18;\n    vector<vector<int>> cell(D, vector<int>(G * G, 0));\n\n    auto cid = [&](int eid) {\n        int cx = min(G - 1, max(0, edges[eid].mx * G / 2001));\n        int cy = min(G - 1, max(0, edges[eid].my * G / 2001));\n        return pair<int,int>(cx, cy);\n    };\n\n    for (int eid : ord) {\n        int u = edges[eid].u;\n        int v = edges[eid].v;\n\n        auto [cx, cy] = cid(eid);\n\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int pass = 0; pass < 2; pass++) {\n            best = -1;\n            best_cost = INT_MAX;\n\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= target[d]) continue;\n\n                if (pass == 0) {\n                    if (vc[u][d] + 1 >= degv[u]) continue;\n                    if (vc[v][d] + 1 >= degv[v]) continue;\n                }\n\n                int near = 0;\n\n                for (int dx = -1; dx <= 1; dx++) {\n                    for (int dy = -1; dy <= 1; dy++) {\n                        int nx = cx + dx;\n                        int ny = cy + dy;\n\n                        if (0 <= nx && nx < G && 0 <= ny && ny < G) {\n                            near += cell[d][nx * G + ny];\n                        }\n                    }\n                }\n\n                int cost = 0;\n                cost += (vc[u][d] + vc[v][d]) * 100000;\n                cost += near * 700;\n                cost += load[d] * 5;\n                cost += uniform_int_distribution<int>(0, 999)(rng);\n\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best = d;\n                }\n            }\n\n            if (best != -1) break;\n        }\n\n        if (best == -1) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] < target[d]) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n\n        assign[eid] = best;\n        load[best]++;\n        vc[u][best]++;\n        vc[v][best]++;\n        cell[best][cx * G + cy]++;\n    }\n\n    repair_isolated(assign);\n    return assign;\n}\n\nll score_one_day(\n    const vector<int>& assign,\n    int day,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist\n) {\n    ll score = 0;\n    vector<ll> dist(N);\n\n    for (int si = 0; si < S; si++) {\n        int s = sources[si];\n\n        dijkstra_fill(s, &assign, day, dist);\n\n        const auto& bd = base_dist[si];\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n\n            if (dist[v] >= INF / 2) {\n                score += 1000000000LL - bd[v];\n            } else {\n                score += dist[v] - bd[v];\n            }\n        }\n    }\n\n    return score;\n}\n\nll evaluate_schedule(\n    const vector<int>& assign,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist\n) {\n    vector<int> load(D, 0);\n\n    for (int x : assign) {\n        if (x < 0 || x >= D) return (ll)4e18;\n        load[x]++;\n    }\n\n    for (int d = 0; d < D; d++) {\n        if (load[d] > K) return (ll)4e18;\n    }\n\n    if (!all_connected(assign)) {\n        return (ll)3e18;\n    }\n\n    ll score = 0;\n\n    for (int day = 0; day < D; day++) {\n        score += score_one_day(assign, day, S, sources, base_dist);\n    }\n\n    return score;\n}\n\nvoid sampled_swap_local_search(\n    vector<int>& assign,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist,\n    const Timer& timer,\n    double limit_time\n) {\n    if (!all_connected(assign)) return;\n\n    vector<vector<int>> byday(D);\n    vector<int> pos(M, -1);\n\n    for (int i = 0; i < M; i++) {\n        int d = assign[i];\n        pos[i] = (int)byday[d].size();\n        byday[d].push_back(i);\n    }\n\n    vector<ll> day_cost(D, 0);\n\n    for (int d = 0; d < D; d++) {\n        if (timer.elapsed() > limit_time) return;\n        day_cost[d] = score_one_day(assign, d, S, sources, base_dist);\n    }\n\n    int accepted = 0;\n    int trials = 0;\n\n    while (timer.elapsed() < limit_time) {\n        trials++;\n\n        int a = uniform_int_distribution<int>(0, D - 1)(rng);\n        for (int t = 0; t < 3; t++) {\n            int x = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (day_cost[x] > day_cost[a]) a = x;\n        }\n\n        int b = uniform_int_distribution<int>(0, D - 1)(rng);\n        for (int t = 0; t < 3; t++) {\n            int x = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (x != a && day_cost[x] < day_cost[b]) b = x;\n        }\n\n        if (a == b) continue;\n        if (byday[a].empty() || byday[b].empty()) continue;\n\n        int ia = uniform_int_distribution<int>(0, (int)byday[a].size() - 1)(rng);\n        int ib = uniform_int_distribution<int>(0, (int)byday[b].size() - 1)(rng);\n\n        int e1 = byday[a][ia];\n        int e2 = byday[b][ib];\n\n        assign[e1] = b;\n        assign[e2] = a;\n\n        bool ok = connected_day(assign, a) && connected_day(assign, b);\n\n        if (!ok) {\n            assign[e1] = a;\n            assign[e2] = b;\n            continue;\n        }\n\n        ll old_cost = day_cost[a] + day_cost[b];\n\n        ll ca = score_one_day(assign, a, S, sources, base_dist);\n        if (timer.elapsed() >= limit_time) {\n            assign[e1] = a;\n            assign[e2] = b;\n            return;\n        }\n\n        ll cb = score_one_day(assign, b, S, sources, base_dist);\n        ll new_cost = ca + cb;\n\n        if (new_cost < old_cost) {\n            day_cost[a] = ca;\n            day_cost[b] = cb;\n\n            byday[a][ia] = e2;\n            byday[b][ib] = e1;\n            pos[e1] = ib;\n            pos[e2] = ia;\n\n            accepted++;\n        } else {\n            assign[e1] = a;\n            assign[e2] = b;\n        }\n\n        if (trials > 100000) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> D >> K;\n\n    edges.resize(M);\n    g.assign(N, {});\n    degv.assign(N, 0);\n\n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n\n        g[u].push_back({v, w, i});\n        g[v].push_back({u, w, i});\n\n        degv[u]++;\n        degv[v]++;\n    }\n\n    X.resize(N);\n    Y.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> X[i] >> Y[i];\n    }\n\n    for (int i = 0; i < M; i++) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n\n        edges[i].mx = X[u] + X[v];\n        edges[i].my = Y[u] + Y[v];\n\n        ll dx = X[u] - X[v];\n        ll dy = Y[u] - Y[v];\n\n        edges[i].len2 = dx * dx + dy * dy;\n    }\n\n    vector<int> vertices(N);\n    iota(vertices.begin(), vertices.end(), 0);\n    shuffle(vertices.begin(), vertices.end(), rng);\n\n    int Smax = min(N, 96);\n    int Ssmall = min(Smax, (D >= 20 ? 24 : 32));\n    int Sfinal = min(Smax, 72);\n    int Slocal = min(Smax, (D >= 20 ? 8 : 10));\n\n    vector<int> sources(vertices.begin(), vertices.begin() + Smax);\n\n    vector<vector<ll>> base_dist(Smax, vector<ll>(N));\n\n    for (int i = 0; i < Smax; i++) {\n        dijkstra_fill(sources[i], nullptr, -1, base_dist[i]);\n    }\n\n    vector<pair<ll, vector<int>>> top;\n\n    auto add_candidate = [&](vector<int> assign) {\n        if (!all_connected(assign) && timer.elapsed() < 4.65) {\n            repair_connectivity(assign, timer, 4.75);\n        }\n\n        ll sc = evaluate_schedule(assign, Ssmall, sources, base_dist);\n\n        if ((int)top.size() < 8) {\n            top.push_back({sc, assign});\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        } else if (sc < top.back().first) {\n            top.back() = {sc, assign};\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        }\n    };\n\n    // Stable original-style candidates.\n    for (int t = 0; t < 10 && timer.elapsed() < 4.15; t++) {\n        add_candidate(construct_cyclic(t % 8));\n    }\n\n    for (int t = 0; t < 10 && timer.elapsed() < 4.35; t++) {\n        add_candidate(construct_greedy(t % 8));\n    }\n\n    int iter = 0;\n\n    while (timer.elapsed() < 4.65) {\n        vector<int> cand;\n\n        if (iter % 3 == 0) {\n            cand = construct_greedy(100);\n        } else if (iter % 3 == 1) {\n            cand = construct_greedy(8 + iter);\n        } else {\n            cand = construct_cyclic(8 + iter);\n        }\n\n        add_candidate(std::move(cand));\n        iter++;\n    }\n\n    if (top.empty()) {\n        vector<int> fallback(M);\n        for (int i = 0; i < M; i++) fallback[i] = i % D;\n        repair_isolated(fallback);\n        top.push_back({0, fallback});\n    }\n\n    vector<int> best = top[0].second;\n    ll best_score = top[0].first;\n\n    // Re-evaluate promising schedules with a larger sample.\n    for (auto& p : top) {\n        if (timer.elapsed() > 5.10) break;\n\n        ll sc = evaluate_schedule(p.second, Sfinal, sources, base_dist);\n\n        if (sc < best_score || best_score >= (ll)3e18) {\n            best_score = sc;\n            best = p.second;\n        }\n    }\n\n    vector<int> before_local = best;\n    ll before_score = best_score;\n\n    // Direct sampled local search by connectivity-safe edge swaps.\n    vector<int> improved = best;\n\n    if (timer.elapsed() < 5.15 && all_connected(improved)) {\n        sampled_swap_local_search(improved, Slocal, sources, base_dist, timer, 5.55);\n    }\n\n    if (timer.elapsed() < 5.86) {\n        ll imp_score = evaluate_schedule(improved, Sfinal, sources, base_dist);\n\n        if (imp_score < before_score) {\n            best = improved;\n            best_score = imp_score;\n        } else {\n            best = before_local;\n            best_score = before_score;\n        }\n    }\n\n    // Emergency connectivity repair.\n    if (!all_connected(best) && timer.elapsed() < 5.78) {\n        repair_connectivity(best, timer, 5.88);\n    }\n\n    // Capacity safeguard.\n    vector<int> load(D, 0);\n    for (int x : best) load[x]++;\n\n    for (int i = 0; i < M; i++) {\n        if (load[best[i]] <= K) continue;\n\n        for (int d = 0; d < D; d++) {\n            if (load[d] < K) {\n                load[best[i]]--;\n                best[i] = d;\n                load[d]++;\n                break;\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << best[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nstring F[2][14], Rg[2][14];\n\ninline int idx3(int x, int y, int z) {\n    return x * D * D + y * D + z;\n}\n\ninline void xyz(int id, int& x, int& y, int& z) {\n    x = id / (D * D);\n    int t = id % (D * D);\n    y = t / D;\n    z = t % D;\n}\n\nuint32_t hash32(uint32_t x) {\n    x ^= x >> 16;\n    x *= 0x7feb352dU;\n    x ^= x >> 15;\n    x *= 0x846ca68bU;\n    x ^= x >> 16;\n    return x;\n}\n\nint hrand(uint32_t seed, int x, int y, int z, int mod) {\n    uint32_t v = seed;\n    v ^= (uint32_t)(x + 17) * 1000003U;\n    v ^= (uint32_t)(y + 31) * 1000033U;\n    v ^= (uint32_t)(z + 47) * 1000037U;\n    return (int)(hash32(v) % mod);\n}\n\nstruct Candidate {\n    vector<unsigned char> occ;\n    int volume = 0;\n};\n\nstruct Rod {\n    vector<int> cells;\n};\n\nstruct LineDecomp {\n    vector<Rod> rods;\n    vector<int> lens;\n    int volume = 0;\n};\n\nstruct Cuboid {\n    vector<int> cells;\n    int dx, dy, dz;\n    int key;\n    int vol;\n};\n\nstruct CuboidDecomp {\n    vector<Cuboid> cuboids;\n    int volume = 0;\n};\n\nstruct Params {\n    int extra;\n    int contW;\n    int futW;\n    int randAmp;\n    int reverse;\n    int favor;\n    uint32_t seed;\n};\n\nint cuboid_key(int dx, int dy, int dz) {\n    int a[3] = {dx, dy, dz};\n    sort(a, a + 3);\n    return a[0] * 256 + a[1] * 16 + a[2];\n}\n\nint cuboid_volume_from_key(int key) {\n    int a = key / 256;\n    int b = (key / 16) % 16;\n    int c = key % 16;\n    return a * b * c;\n}\n\nvector<pair<int,int>> solve_edge_cover(const vector<int>& X, const vector<int>& Y, int w[14][14]) {\n    int nx = (int)X.size();\n    int ny = (int)Y.size();\n    vector<pair<int,int>> res;\n\n    if (nx >= ny) {\n        int A = nx, B = ny;\n        int M = 1 << B;\n        const int NEG = -1000000000;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[i]][Y[j]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[i + 1][nm] = mask;\n                        ch[i + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int i = A; i >= 1; i--) {\n            int j = ch[i][mask];\n            int pm = pre[i][mask];\n            res.push_back({X[i - 1], Y[j]});\n            mask = pm;\n        }\n    } else {\n        int A = ny, B = nx;\n        int M = 1 << B;\n        const int NEG = -1000000000;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[j]][Y[i]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[i + 1][nm] = mask;\n                        ch[i + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int i = A; i >= 1; i--) {\n            int j = ch[i][mask];\n            int pm = pre[i][mask];\n            res.push_back({X[j], Y[i - 1]});\n            mask = pm;\n        }\n    }\n\n    return res;\n}\n\nCandidate build_candidate(int id, const Params& p) {\n    Candidate cand;\n    cand.occ.assign(D * D * D, 0);\n\n    bool prev[14][14] = {};\n\n    vector<int> zs;\n    if (!p.reverse) {\n        for (int z = 0; z < D; z++) zs.push_back(z);\n    } else {\n        for (int z = D - 1; z >= 0; z--) zs.push_back(z);\n    }\n\n    for (int ord = 0; ord < D; ord++) {\n        int z = zs[ord];\n        int zn = -1;\n        if (ord + 1 < D) zn = zs[ord + 1];\n\n        vector<int> X, Y;\n        for (int x = 0; x < D; x++) if (F[id][z][x] == '1') X.push_back(x);\n        for (int y = 0; y < D; y++) if (Rg[id][z][y] == '1') Y.push_back(y);\n\n        int w[14][14] = {};\n        for (int x : X) {\n            for (int y : Y) {\n                int val = 0;\n                if (prev[x][y]) val += p.contW;\n                if (zn != -1 && F[id][zn][x] == '1' && Rg[id][zn][y] == '1') {\n                    val += p.futW;\n                }\n                if (p.randAmp > 0) val += hrand(p.seed, x, y, z, p.randAmp);\n                w[x][y] = val;\n            }\n        }\n\n        auto base = solve_edge_cover(X, Y, w);\n\n        bool sel[14][14] = {};\n        int cnt = 0;\n\n        for (auto [x, y] : base) {\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        int maxEdges = (int)X.size() * (int)Y.size();\n        int target = min(maxEdges, max((int)X.size(), (int)Y.size()) + p.extra);\n\n        vector<tuple<int,int,int>> add;\n\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) continue;\n\n                int sc = 0;\n                if (prev[x][y]) sc += 100000;\n                if (zn != -1 && F[id][zn][x] == '1' && Rg[id][zn][y] == '1') sc += 20000;\n\n                if (p.favor == 1 || p.favor == 3) {\n                    if (x > 0 && sel[x - 1][y]) sc += 8000;\n                    if (x + 1 < D && sel[x + 1][y]) sc += 8000;\n                }\n                if (p.favor == 2 || p.favor == 3) {\n                    if (y > 0 && sel[x][y - 1]) sc += 8000;\n                    if (y + 1 < D && sel[x][y + 1]) sc += 8000;\n                }\n\n                sc += hrand(p.seed ^ 0x9e3779b9U, x, y, z, 1000);\n                add.push_back({sc, x, y});\n            }\n        }\n\n        sort(add.rbegin(), add.rend());\n\n        for (auto [sc, x, y] : add) {\n            if (cnt >= target) break;\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        memset(prev, 0, sizeof(prev));\n\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) {\n                    cand.occ[idx3(x, y, z)] = 1;\n                    prev[x][y] = true;\n                }\n            }\n        }\n    }\n\n    for (unsigned char c : cand.occ) cand.volume += c;\n    return cand;\n}\n\nLineDecomp decompose_lines_from_occ(const vector<unsigned char>& occ, int volume, int axis) {\n    LineDecomp dec;\n    dec.volume = volume;\n\n    if (axis == 0) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                int x = 0;\n                while (x < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        x++;\n                        continue;\n                    }\n                    Rod r;\n                    while (x < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        x++;\n                    }\n                    dec.lens.push_back((int)r.cells.size());\n                    dec.rods.push_back(move(r));\n                }\n            }\n        }\n    } else if (axis == 1) {\n        for (int x = 0; x < D; x++) {\n            for (int z = 0; z < D; z++) {\n                int y = 0;\n                while (y < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        y++;\n                        continue;\n                    }\n                    Rod r;\n                    while (y < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        y++;\n                    }\n                    dec.lens.push_back((int)r.cells.size());\n                    dec.rods.push_back(move(r));\n                }\n            }\n        }\n    } else {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                int z = 0;\n                while (z < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        z++;\n                        continue;\n                    }\n                    Rod r;\n                    while (z < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        z++;\n                    }\n                    dec.lens.push_back((int)r.cells.size());\n                    dec.rods.push_back(move(r));\n                }\n            }\n        }\n    }\n\n    return dec;\n}\n\nLineDecomp decompose_lines(const Candidate& cand, int axis) {\n    return decompose_lines_from_occ(cand.occ, cand.volume, axis);\n}\n\nbool box_free(const Candidate& cand, const vector<unsigned char>& used, int lo[3], int hi[3]) {\n    for (int x = lo[0]; x < hi[0]; x++) {\n        for (int y = lo[1]; y < hi[1]; y++) {\n            for (int z = lo[2]; z < hi[2]; z++) {\n                int id = idx3(x, y, z);\n                if (!cand.occ[id] || used[id]) return false;\n            }\n        }\n    }\n    return true;\n}\n\nCuboidDecomp decompose_cuboids_strategy(const Candidate& cand, array<int,3> growOrder) {\n    CuboidDecomp dec;\n    dec.volume = cand.volume;\n\n    vector<unsigned char> used(D * D * D, 0);\n\n    for (int x0 = 0; x0 < D; x0++) {\n        for (int y0 = 0; y0 < D; y0++) {\n            for (int z0 = 0; z0 < D; z0++) {\n                int start = idx3(x0, y0, z0);\n                if (!cand.occ[start] || used[start]) continue;\n\n                int lo[3] = {x0, y0, z0};\n                int hi[3] = {x0 + 1, y0 + 1, z0 + 1};\n\n                for (int ax : growOrder) {\n                    while (hi[ax] < D) {\n                        int nlo[3] = {lo[0], lo[1], lo[2]};\n                        int nhi[3] = {hi[0], hi[1], hi[2]};\n                        nhi[ax]++;\n                        if (box_free(cand, used, nlo, nhi)) {\n                            hi[ax]++;\n                        } else {\n                            break;\n                        }\n                    }\n                }\n\n                Cuboid c;\n                c.dx = hi[0] - lo[0];\n                c.dy = hi[1] - lo[1];\n                c.dz = hi[2] - lo[2];\n                c.vol = c.dx * c.dy * c.dz;\n                c.key = cuboid_key(c.dx, c.dy, c.dz);\n\n                for (int x = lo[0]; x < hi[0]; x++) {\n                    for (int y = lo[1]; y < hi[1]; y++) {\n                        for (int z = lo[2]; z < hi[2]; z++) {\n                            int id = idx3(x, y, z);\n                            used[id] = 1;\n                            c.cells.push_back(id);\n                        }\n                    }\n                }\n\n                dec.cuboids.push_back(move(c));\n            }\n        }\n    }\n\n    return dec;\n}\n\nlong double eval_lines(const LineDecomp& A, const LineDecomp& B) {\n    priority_queue<int> p, q;\n    for (int x : A.lens) p.push(x);\n    for (int x : B.lens) q.push(x);\n\n    long double score = 0;\n\n    for (int len = D; len >= 1; len--) {\n        while (!p.empty() && !q.empty() && p.top() >= len && q.top() >= len) {\n            int a = p.top(); p.pop();\n            int b = q.top(); q.pop();\n\n            score += 1.0L / len;\n\n            if (a - len > 0) p.push(a - len);\n            if (b - len > 0) q.push(b - len);\n        }\n    }\n\n    while (!p.empty()) {\n        score += p.top();\n        p.pop();\n    }\n    while (!q.empty()) {\n        score += q.top();\n        q.pop();\n    }\n\n    return score;\n}\n\nstruct HybridEval {\n    long double score;\n    int ax0;\n    int ax1;\n};\n\nHybridEval eval_cuboid_hybrid(const CuboidDecomp& A, const CuboidDecomp& B) {\n    unordered_map<int, vector<int>> ma, mb;\n    ma.reserve(512);\n    mb.reserve(512);\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) ma[A.cuboids[i].key].push_back(i);\n    for (int i = 0; i < (int)B.cuboids.size(); i++) mb[B.cuboids[i].key].push_back(i);\n\n    vector<unsigned char> usedA(A.cuboids.size(), 0), usedB(B.cuboids.size(), 0);\n\n    long double base = 0;\n\n    for (auto& kv : ma) {\n        int key = kv.first;\n        if (!mb.count(key)) continue;\n\n        int vol = cuboid_volume_from_key(key);\n        if (vol <= 1) continue;\n\n        auto& va = kv.second;\n        auto& vb = mb[key];\n\n        int m = min((int)va.size(), (int)vb.size());\n\n        for (int i = 0; i < m; i++) {\n            usedA[va[i]] = 1;\n            usedB[vb[i]] = 1;\n            base += 1.0L / vol;\n        }\n    }\n\n    vector<unsigned char> remA(D * D * D, 0), remB(D * D * D, 0);\n    int volA = 0, volB = 0;\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) {\n        if (usedA[i]) continue;\n        for (int id : A.cuboids[i].cells) {\n            remA[id] = 1;\n            volA++;\n        }\n    }\n\n    for (int i = 0; i < (int)B.cuboids.size(); i++) {\n        if (usedB[i]) continue;\n        for (int id : B.cuboids[i].cells) {\n            remB[id] = 1;\n            volB++;\n        }\n    }\n\n    array<LineDecomp, 3> la, lb;\n    for (int ax = 0; ax < 3; ax++) {\n        la[ax] = decompose_lines_from_occ(remA, volA, ax);\n        lb[ax] = decompose_lines_from_occ(remB, volB, ax);\n    }\n\n    HybridEval ret;\n    ret.score = 1e100L;\n    ret.ax0 = ret.ax1 = 0;\n\n    for (int ax0 = 0; ax0 < 3; ax0++) {\n        for (int ax1 = 0; ax1 < 3; ax1++) {\n            long double sc = base + eval_lines(la[ax0], lb[ax1]);\n            if (sc < ret.score) {\n                ret.score = sc;\n                ret.ax0 = ax0;\n                ret.ax1 = ax1;\n            }\n        }\n    }\n\n    return ret;\n}\n\nvector<vector<int>> common_components(const Candidate& A, const Candidate& B) {\n    int N = D * D * D;\n    vector<unsigned char> vis(N, 0);\n    vector<vector<int>> comps;\n\n    const int dx[6] = {1, -1, 0, 0, 0, 0};\n    const int dy[6] = {0, 0, 1, -1, 0, 0};\n    const int dz[6] = {0, 0, 0, 0, 1, -1};\n\n    for (int s = 0; s < N; s++) {\n        if (vis[s] || !A.occ[s] || !B.occ[s]) continue;\n\n        vector<int> comp;\n        queue<int> q;\n        q.push(s);\n        vis[s] = 1;\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            comp.push_back(v);\n\n            int x, y, z;\n            xyz(v, x, y, z);\n\n            for (int d = 0; d < 6; d++) {\n                int nx = x + dx[d];\n                int ny = y + dy[d];\n                int nz = z + dz[d];\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n                int ni = idx3(nx, ny, nz);\n                if (vis[ni] || !A.occ[ni] || !B.occ[ni]) continue;\n                vis[ni] = 1;\n                q.push(ni);\n            }\n        }\n\n        comps.push_back(move(comp));\n    }\n\n    return comps;\n}\n\nHybridEval eval_common_hybrid(const Candidate& A, const Candidate& B, int threshold) {\n    auto comps = common_components(A, B);\n\n    vector<unsigned char> used(D * D * D, 0);\n    long double base = 0;\n\n    for (auto& c : comps) {\n        if ((int)c.size() >= threshold) {\n            base += 1.0L / (int)c.size();\n            for (int id : c) used[id] = 1;\n        }\n    }\n\n    vector<unsigned char> remA(D * D * D, 0), remB(D * D * D, 0);\n    int volA = 0, volB = 0;\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (!used[i] && A.occ[i]) {\n            remA[i] = 1;\n            volA++;\n        }\n        if (!used[i] && B.occ[i]) {\n            remB[i] = 1;\n            volB++;\n        }\n    }\n\n    array<LineDecomp, 3> la, lb;\n    for (int ax = 0; ax < 3; ax++) {\n        la[ax] = decompose_lines_from_occ(remA, volA, ax);\n        lb[ax] = decompose_lines_from_occ(remB, volB, ax);\n    }\n\n    HybridEval ret;\n    ret.score = 1e100L;\n    ret.ax0 = ret.ax1 = 0;\n\n    for (int ax0 = 0; ax0 < 3; ax0++) {\n        for (int ax1 = 0; ax1 < 3; ax1++) {\n            long double sc = base + eval_lines(la[ax0], lb[ax1]);\n            if (sc < ret.score) {\n                ret.score = sc;\n                ret.ax0 = ax0;\n                ret.ax1 = ax1;\n            }\n        }\n    }\n\n    return ret;\n}\n\nstruct Piece {\n    int len;\n    int rod;\n    int off;\n\n    bool operator<(const Piece& other) const {\n        if (len != other.len) return len < other.len;\n        if (rod != other.rod) return rod < other.rod;\n        return off < other.off;\n    }\n};\n\nvoid mark_line_piece(vector<int>& out, const LineDecomp& dec, const Piece& p, int useLen, int blockId) {\n    const Rod& r = dec.rods[p.rod];\n    for (int i = 0; i < useLen; i++) {\n        out[r.cells[p.off + i]] = blockId;\n    }\n}\n\nvoid add_line_solution(vector<int>& outA, vector<int>& outB, const LineDecomp& A, const LineDecomp& B, int& blockId) {\n    priority_queue<Piece> p, q;\n\n    for (int i = 0; i < (int)A.rods.size(); i++) {\n        p.push({(int)A.rods[i].cells.size(), i, 0});\n    }\n    for (int i = 0; i < (int)B.rods.size(); i++) {\n        q.push({(int)B.rods[i].cells.size(), i, 0});\n    }\n\n    for (int len = D; len >= 1; len--) {\n        while (!p.empty() && !q.empty() && p.top().len >= len && q.top().len >= len) {\n            Piece a = p.top(); p.pop();\n            Piece b = q.top(); q.pop();\n\n            blockId++;\n            mark_line_piece(outA, A, a, len, blockId);\n            mark_line_piece(outB, B, b, len, blockId);\n\n            if (a.len - len > 0) p.push({a.len - len, a.rod, a.off + len});\n            if (b.len - len > 0) q.push({b.len - len, b.rod, b.off + len});\n        }\n    }\n\n    while (!p.empty()) {\n        Piece a = p.top(); p.pop();\n        blockId++;\n        mark_line_piece(outA, A, a, a.len, blockId);\n    }\n\n    while (!q.empty()) {\n        Piece b = q.top(); q.pop();\n        blockId++;\n        mark_line_piece(outB, B, b, b.len, blockId);\n    }\n}\n\nvoid print_output(int blockId, const vector<int>& outA, const vector<int>& outB) {\n    cout << blockId << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << outA[i];\n    }\n    cout << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << outB[i];\n    }\n    cout << '\\n';\n}\n\nvoid output_line_solution(const LineDecomp& A, const LineDecomp& B) {\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n    int blockId = 0;\n    add_line_solution(outA, outB, A, B, blockId);\n    print_output(blockId, outA, outB);\n}\n\nvoid mark_cuboid(vector<int>& out, const Cuboid& c, int blockId) {\n    for (int id : c.cells) out[id] = blockId;\n}\n\nvoid output_cuboid_hybrid_solution(const CuboidDecomp& A, const CuboidDecomp& B, int axA, int axB) {\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n\n    unordered_map<int, vector<int>> ma, mb;\n    ma.reserve(512);\n    mb.reserve(512);\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) ma[A.cuboids[i].key].push_back(i);\n    for (int i = 0; i < (int)B.cuboids.size(); i++) mb[B.cuboids[i].key].push_back(i);\n\n    vector<unsigned char> usedA(A.cuboids.size(), 0), usedB(B.cuboids.size(), 0);\n\n    int blockId = 0;\n\n    for (auto& kv : ma) {\n        int key = kv.first;\n        if (!mb.count(key)) continue;\n\n        int vol = cuboid_volume_from_key(key);\n        if (vol <= 1) continue;\n\n        auto& va = kv.second;\n        auto& vb = mb[key];\n\n        int m = min((int)va.size(), (int)vb.size());\n\n        for (int i = 0; i < m; i++) {\n            int ia = va[i];\n            int ib = vb[i];\n\n            usedA[ia] = 1;\n            usedB[ib] = 1;\n\n            blockId++;\n            mark_cuboid(outA, A.cuboids[ia], blockId);\n            mark_cuboid(outB, B.cuboids[ib], blockId);\n        }\n    }\n\n    vector<unsigned char> remA(D * D * D, 0), remB(D * D * D, 0);\n    int volA = 0, volB = 0;\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) {\n        if (usedA[i]) continue;\n        for (int id : A.cuboids[i].cells) {\n            remA[id] = 1;\n            volA++;\n        }\n    }\n\n    for (int i = 0; i < (int)B.cuboids.size(); i++) {\n        if (usedB[i]) continue;\n        for (int id : B.cuboids[i].cells) {\n            remB[id] = 1;\n            volB++;\n        }\n    }\n\n    LineDecomp la = decompose_lines_from_occ(remA, volA, axA);\n    LineDecomp lb = decompose_lines_from_occ(remB, volB, axB);\n\n    add_line_solution(outA, outB, la, lb, blockId);\n    print_output(blockId, outA, outB);\n}\n\nvoid output_common_hybrid_solution(const Candidate& A, const Candidate& B, int threshold, int axA, int axB) {\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n    vector<unsigned char> used(D * D * D, 0);\n\n    auto comps = common_components(A, B);\n\n    int blockId = 0;\n\n    for (auto& c : comps) {\n        if ((int)c.size() < threshold) continue;\n        blockId++;\n        for (int id : c) {\n            outA[id] = blockId;\n            outB[id] = blockId;\n            used[id] = 1;\n        }\n    }\n\n    vector<unsigned char> remA(D * D * D, 0), remB(D * D * D, 0);\n    int volA = 0, volB = 0;\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (!used[i] && A.occ[i]) {\n            remA[i] = 1;\n            volA++;\n        }\n        if (!used[i] && B.occ[i]) {\n            remB[i] = 1;\n            volB++;\n        }\n    }\n\n    LineDecomp la = decompose_lines_from_occ(remA, volA, axA);\n    LineDecomp lb = decompose_lines_from_occ(remB, volB, axB);\n\n    add_line_solution(outA, outB, la, lb, blockId);\n    print_output(blockId, outA, outB);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D;\n\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) cin >> F[i][z];\n        for (int z = 0; z < D; z++) cin >> Rg[i][z];\n    }\n\n    vector<Params> params;\n    vector<int> extras = {0, 1, 2, 4, 7, 12, 1000};\n    uint32_t baseSeed = 246813579U;\n\n    for (int e : extras) {\n        for (int rev = 0; rev < 2; rev++) {\n            for (int rep = 0; rep < 2; rep++) {\n                Params p;\n                p.extra = e;\n                p.contW = 1000 + rep * 400;\n                p.futW = 80 + rep * 80;\n                p.randAmp = 60;\n                p.reverse = rev;\n                p.favor = rep + 1;\n                p.seed = baseSeed + e * 10007U + rev * 1000003U + rep * 9176U;\n                params.push_back(p);\n            }\n        }\n    }\n\n    vector<Candidate> cand[2];\n\n    for (int id = 0; id < 2; id++) {\n        for (auto p : params) {\n            cand[id].push_back(build_candidate(id, p));\n        }\n    }\n\n    int n0 = (int)cand[0].size();\n    int n1 = (int)cand[1].size();\n\n    vector<array<LineDecomp, 3>> lines[2];\n    lines[0].resize(n0);\n    lines[1].resize(n1);\n\n    for (int id = 0; id < 2; id++) {\n        int n = (int)cand[id].size();\n        for (int i = 0; i < n; i++) {\n            for (int ax = 0; ax < 3; ax++) {\n                lines[id][i][ax] = decompose_lines(cand[id][i], ax);\n            }\n        }\n    }\n\n    vector<array<int,3>> growOrders = {\n        array<int,3>{0,1,2},\n        array<int,3>{0,2,1},\n        array<int,3>{1,0,2},\n        array<int,3>{1,2,0},\n        array<int,3>{2,0,1},\n        array<int,3>{2,1,0}\n    };\n\n    struct CubRef {\n        int candId;\n        int strat;\n        CuboidDecomp dec;\n    };\n\n    vector<CubRef> cubs[2];\n\n    for (int id = 0; id < 2; id++) {\n        for (int i = 0; i < (int)cand[id].size(); i++) {\n            for (int s = 0; s < (int)growOrders.size(); s++) {\n                CubRef cr;\n                cr.candId = i;\n                cr.strat = s;\n                cr.dec = decompose_cuboids_strategy(cand[id][i], growOrders[s]);\n                cubs[id].push_back(move(cr));\n            }\n        }\n    }\n\n    long double bestScore = 1e100L;\n    int bestMode = 0;\n\n    int bestI = 0, bestJ = 0;\n    int bestAx0 = 0, bestAx1 = 0;\n\n    int bestCubA = 0, bestCubB = 0;\n    int bestThreshold = 2;\n\n    for (int i = 0; i < n0; i++) {\n        for (int j = 0; j < n1; j++) {\n            for (int ax0 = 0; ax0 < 3; ax0++) {\n                for (int ax1 = 0; ax1 < 3; ax1++) {\n                    long double sc = eval_lines(lines[0][i][ax0], lines[1][j][ax1]);\n                    if (sc < bestScore) {\n                        bestScore = sc;\n                        bestMode = 0;\n                        bestI = i;\n                        bestJ = j;\n                        bestAx0 = ax0;\n                        bestAx1 = ax1;\n                    }\n                }\n            }\n        }\n    }\n\n    for (int ia = 0; ia < (int)cubs[0].size(); ia++) {\n        for (int ib = 0; ib < (int)cubs[1].size(); ib++) {\n            HybridEval he = eval_cuboid_hybrid(cubs[0][ia].dec, cubs[1][ib].dec);\n            if (he.score < bestScore) {\n                bestScore = he.score;\n                bestMode = 1;\n                bestCubA = ia;\n                bestCubB = ib;\n                bestAx0 = he.ax0;\n                bestAx1 = he.ax1;\n            }\n        }\n    }\n\n    vector<int> thresholds = {2, 3, 4, 6, 8};\n    for (int i = 0; i < n0; i++) {\n        for (int j = 0; j < n1; j++) {\n            for (int th : thresholds) {\n                HybridEval he = eval_common_hybrid(cand[0][i], cand[1][j], th);\n                if (he.score < bestScore) {\n                    bestScore = he.score;\n                    bestMode = 2;\n                    bestI = i;\n                    bestJ = j;\n                    bestThreshold = th;\n                    bestAx0 = he.ax0;\n                    bestAx1 = he.ax1;\n                }\n            }\n        }\n    }\n\n    if (bestMode == 0) {\n        output_line_solution(lines[0][bestI][bestAx0], lines[1][bestJ][bestAx1]);\n    } else if (bestMode == 1) {\n        output_cuboid_hybrid_solution(cubs[0][bestCubA].dec, cubs[1][bestCubB].dec, bestAx0, bestAx1);\n    } else {\n        output_common_hybrid_solution(cand[0][bestI], cand[1][bestJ], bestThreshold, bestAx0, bestAx1);\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) x = p[x] = p[p[x]];\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstatic const long long INF = (1LL << 60);\n\nint N, M, K;\nvector<int> X, Y;\nvector<Edge> edges;\nvector<int> A, RY;\n\nvector<vector<int>> cdist;\nvector<vector<pair<int,int>>> sortedRes;\n\nvector<vector<long long>> fw;\nvector<vector<int>> nxtv;\nvector<vector<int>> directEdge;\n\nchrono::steady_clock::time_point st_time;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st_time).count();\n}\n\nint ceil_sqrt_ll(long long x) {\n    long long r = sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r > 0 && (r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nvoid add_path_edges(int s, int t, vector<char>& sel) {\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n    }\n}\n\nvoid add_path_edges_mark(int s, int t, vector<char>& sel, vector<char>& inTree) {\n    inTree[s] = 1;\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n        inTree[s] = 1;\n    }\n}\n\npair<long long, vector<int>> build_best_tree(const vector<int>& P) {\n    long long bestCost = INF;\n    vector<int> bestB(M, 0);\n\n    auto consider = [&](vector<char> sel) {\n        vector<char> terminal(N, 0);\n        terminal[0] = 1;\n        for (int i = 0; i < N; i++) if (P[i] > 0) terminal[i] = 1;\n\n        vector<vector<pair<int,int>>> g(N);\n        vector<int> deg(N, 0);\n\n        for (int e = 0; e < M; e++) if (sel[e]) {\n            int u = edges[e].u, v = edges[e].v;\n            g[u].push_back({v, e});\n            g[v].push_back({u, e});\n            deg[u]++;\n            deg[v]++;\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (!terminal[i] && deg[i] <= 1) q.push(i);\n        }\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            if (terminal[v] || deg[v] != 1) continue;\n\n            for (auto [to, eid] : g[v]) {\n                if (!sel[eid]) continue;\n                sel[eid] = 0;\n                deg[v]--;\n                deg[to]--;\n                if (!terminal[to] && deg[to] == 1) q.push(to);\n                break;\n            }\n        }\n\n        long long cost = 0;\n        vector<int> B(M, 0);\n        for (int e = 0; e < M; e++) {\n            if (sel[e]) {\n                cost += edges[e].w;\n                B[e] = 1;\n            }\n        }\n\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestB = B;\n        }\n    };\n\n    vector<int> terms;\n    terms.push_back(0);\n    for (int i = 1; i < N; i++) if (P[i] > 0) terms.push_back(i);\n\n    int T = (int)terms.size();\n\n    // Metric-closure MST over terminals.\n    {\n        vector<char> sel(M, 0);\n\n        if (T >= 2) {\n            vector<long long> minD(T, INF);\n            vector<int> par(T, -1);\n            vector<char> used(T, 0);\n            minD[0] = 0;\n\n            for (int it = 0; it < T; it++) {\n                int v = -1;\n                for (int i = 0; i < T; i++) {\n                    if (!used[i] && (v == -1 || minD[i] < minD[v])) v = i;\n                }\n\n                if (v == -1) break;\n                used[v] = 1;\n\n                if (par[v] != -1) {\n                    add_path_edges(terms[v], terms[par[v]], sel);\n                }\n\n                for (int to = 0; to < T; to++) {\n                    if (!used[to] && fw[terms[v]][terms[to]] < minD[to]) {\n                        minD[to] = fw[terms[v]][terms[to]];\n                        par[to] = v;\n                    }\n                }\n            }\n        }\n\n        consider(sel);\n    }\n\n    // Union of shortest paths from root.\n    {\n        vector<char> sel(M, 0);\n        for (int i = 1; i < N; i++) {\n            if (P[i] > 0) add_path_edges(0, i, sel);\n        }\n        consider(sel);\n    }\n\n    // Ordinary graph MST, pruned.\n    {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].w < edges[b].w;\n        });\n\n        DSU dsu(N);\n        vector<char> sel(M, 0);\n\n        for (int eid : ord) {\n            if (dsu.unite(edges[eid].u, edges[eid].v)) {\n                sel[eid] = 1;\n            }\n        }\n\n        consider(sel);\n    }\n\n    // Incremental Steiner-style candidates.\n    {\n        vector<int> base;\n        for (int i = 1; i < N; i++) if (P[i] > 0) base.push_back(i);\n\n        vector<vector<int>> orders;\n\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return fw[0][a] < fw[0][b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return fw[0][a] > fw[0][b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return P[a] > P[b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return P[a] < P[b];\n            });\n            orders.push_back(v);\n        }\n\n        for (auto ord : orders) {\n            vector<char> sel(M, 0);\n            vector<char> inTree(N, 0);\n            inTree[0] = 1;\n\n            for (int t : ord) {\n                int best = -1;\n                long long bd = INF;\n\n                for (int v = 0; v < N; v++) {\n                    if (inTree[v] && fw[t][v] < bd) {\n                        bd = fw[t][v];\n                        best = v;\n                    }\n                }\n\n                if (best != -1) {\n                    add_path_edges_mark(t, best, sel, inTree);\n                }\n            }\n\n            consider(sel);\n        }\n    }\n\n    return {bestCost, bestB};\n}\n\nlong long total_cost(const vector<int>& P) {\n    long long radio = 0;\n    for (int p : P) radio += 1LL * p * p;\n\n    auto tr = build_best_tree(P);\n    return radio + tr.first;\n}\n\nbool compute_covered(const vector<int>& P, vector<char>& covered) {\n    covered.assign(K, 0);\n    int cnt = 0;\n\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                covered[k] = 1;\n                cnt++;\n                break;\n            }\n        }\n    }\n\n    return cnt == K;\n}\n\nvoid reduce_powers_order(vector<int>& P, const vector<int>& order) {\n    vector<int> coverCnt(K, 0);\n\n    for (int i = 0; i < N; i++) if (P[i] > 0) {\n        for (int k = 0; k < K; k++) {\n            if (cdist[i][k] <= P[i]) coverCnt[k]++;\n        }\n    }\n\n    bool changed = true;\n    int loop = 0;\n\n    while (changed && loop < 12) {\n        loop++;\n        changed = false;\n\n        for (int i : order) {\n            int old = P[i];\n            if (old == 0) continue;\n\n            int req = 0;\n\n            for (int k = 0; k < K; k++) {\n                if (cdist[i][k] <= old && coverCnt[k] == 1) {\n                    req = max(req, cdist[i][k]);\n                }\n            }\n\n            if (req < old) {\n                for (int k = 0; k < K; k++) {\n                    if (cdist[i][k] <= old && cdist[i][k] > req) {\n                        coverCnt[k]--;\n                    }\n                }\n\n                P[i] = req;\n                changed = true;\n            }\n        }\n    }\n}\n\nvoid reduce_powers(vector<int>& P) {\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    reduce_powers_order(P, order);\n}\n\nint lower_existing_radius(int station, int limit) {\n    int res = 0;\n    for (auto [d, k] : sortedRes[station]) {\n        if (d <= limit) res = d;\n        else break;\n    }\n    return res;\n}\n\nbool greedy_complete(\n    vector<int>& P,\n    double alpha,\n    bool dynamicConn,\n    int capStation = -1,\n    int capRadius = 5000\n) {\n    vector<char> covered(K, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; k++) {\n        bool ok = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                ok = true;\n                break;\n            }\n        }\n\n        covered[k] = ok;\n        if (!ok) uncovered++;\n    }\n\n    vector<int> activeList;\n    activeList.push_back(0);\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0 && i != 0) activeList.push_back(i);\n    }\n\n    vector<double> rootPen(N, 0.0);\n    for (int i = 0; i < N; i++) rootPen[i] = alpha * (double)fw[0][i];\n\n    while (uncovered > 0) {\n        int bestI = -1;\n        int bestR = -1;\n        int bestGain = 0;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            int old = P[i];\n\n            if (i == capStation && old >= capRadius) continue;\n\n            double connPen = 0.0;\n\n            if (old == 0) {\n                if (dynamicConn) {\n                    long long md = INF;\n                    for (int a : activeList) md = min(md, fw[i][a]);\n                    connPen = alpha * (double)md;\n                } else {\n                    connPen = rootPen[i];\n                }\n            }\n\n            int gain = 0;\n            const auto& vec = sortedRes[i];\n\n            for (int idx = 0; idx < (int)vec.size();) {\n                int r = vec[idx].first;\n\n                if (r > 5000) break;\n                if (i == capStation && r > capRadius) break;\n\n                int add = 0;\n                while (idx < (int)vec.size() && vec[idx].first == r) {\n                    int k = vec[idx].second;\n                    if (r > old && !covered[k]) add++;\n                    idx++;\n                }\n\n                if (r <= old) continue;\n\n                gain += add;\n\n                if (gain > 0) {\n                    double delta = (double)r * r - (double)old * old;\n                    if (old == 0) delta += connPen;\n\n                    double score = delta / gain;\n\n                    if (score < bestScore ||\n                        (abs(score - bestScore) < 1e-9 && gain > bestGain)) {\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestGain = gain;\n                    }\n                }\n            }\n        }\n\n        if (bestI == -1) return false;\n\n        bool wasZero = (P[bestI] == 0);\n        P[bestI] = bestR;\n\n        if (wasZero) activeList.push_back(bestI);\n\n        for (auto [r, k] : sortedRes[bestI]) {\n            if (r > bestR) break;\n            if (!covered[k]) {\n                covered[k] = 1;\n                uncovered--;\n            }\n        }\n    }\n\n    return true;\n}\n\nbool greedy_repair_active_only(vector<int>& P, const vector<char>& allowed, const vector<int>& maxR) {\n    vector<char> covered(K, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; k++) {\n        bool ok = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                ok = true;\n                break;\n            }\n        }\n        covered[k] = ok;\n        if (!ok) uncovered++;\n    }\n\n    while (uncovered > 0) {\n        int bestI = -1;\n        int bestR = -1;\n        int bestGain = 0;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            if (!allowed[i]) continue;\n\n            int old = P[i];\n            if (old >= maxR[i]) continue;\n\n            int gain = 0;\n            const auto& vec = sortedRes[i];\n\n            for (int idx = 0; idx < (int)vec.size();) {\n                int r = vec[idx].first;\n                if (r > maxR[i]) break;\n\n                int add = 0;\n                while (idx < (int)vec.size() && vec[idx].first == r) {\n                    int k = vec[idx].second;\n                    if (r > old && !covered[k]) add++;\n                    idx++;\n                }\n\n                if (r <= old) continue;\n\n                gain += add;\n\n                if (gain > 0) {\n                    double delta = (double)r * r - (double)old * old;\n                    double score = delta / gain;\n\n                    if (score < bestScore ||\n                        (abs(score - bestScore) < 1e-9 && gain > bestGain)) {\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestGain = gain;\n                    }\n                }\n            }\n        }\n\n        if (bestI == -1) return false;\n\n        P[bestI] = bestR;\n\n        for (auto [r, k] : sortedRes[bestI]) {\n            if (r > bestR) break;\n            if (!covered[k]) {\n                covered[k] = 1;\n                uncovered--;\n            }\n        }\n    }\n\n    return true;\n}\n\nvector<int> initial_nearest_solution() {\n    vector<int> P(N, 0);\n\n    for (int k = 0; k < K; k++) {\n        int bi = -1;\n        int bd = 1e9;\n\n        for (int i = 0; i < N; i++) {\n            if (cdist[i][k] <= 5000 && cdist[i][k] < bd) {\n                bd = cdist[i][k];\n                bi = i;\n            }\n        }\n\n        if (bi == -1) {\n            for (int i = 0; i < N; i++) {\n                if (cdist[i][k] < bd) {\n                    bd = cdist[i][k];\n                    bi = i;\n                }\n            }\n        }\n\n        P[bi] = max(P[bi], bd);\n    }\n\n    reduce_powers(P);\n    return P;\n}\n\nvoid optimize_reduction_orders(vector<int>& bestP, long long& bestS) {\n    vector<vector<int>> orders;\n\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return bestP[a] > bestP[b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return bestP[a] < bestP[b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return fw[0][a] < fw[0][b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return fw[0][a] > fw[0][b];\n        });\n        orders.push_back(ord);\n    }\n\n    for (auto& ord : orders) {\n        if (elapsed_sec() > 1.96) break;\n\n        vector<int> P = bestP;\n        reduce_powers_order(P, ord);\n\n        vector<char> covered;\n        if (!compute_covered(P, covered)) continue;\n\n        long long S = total_cost(P);\n        if (S < bestS) {\n            bestS = S;\n            bestP = P;\n        }\n    }\n}\n\nvoid fixed_active_local_search(vector<int>& bestP, long long& bestS, double timeLimit) {\n    while (elapsed_sec() < timeLimit) {\n        bool improved = false;\n        vector<int> nextP = bestP;\n        long long nextS = bestS;\n\n        vector<int> active;\n        vector<char> allowed(N, 0);\n\n        for (int i = 0; i < N; i++) {\n            if (bestP[i] > 0) {\n                active.push_back(i);\n                allowed[i] = 1;\n            }\n        }\n\n        sort(active.begin(), active.end(), [&](int a, int b) {\n            return bestP[a] > bestP[b];\n        });\n\n        for (int s : active) {\n            if (elapsed_sec() > timeLimit) break;\n\n            int old = bestP[s];\n            vector<int> limits;\n\n            limits.push_back(0);\n            limits.push_back(lower_existing_radius(s, old / 5));\n            limits.push_back(lower_existing_radius(s, old / 3));\n            limits.push_back(lower_existing_radius(s, old / 2));\n            limits.push_back(lower_existing_radius(s, old * 2 / 3));\n            limits.push_back(lower_existing_radius(s, old * 4 / 5));\n\n            sort(limits.begin(), limits.end());\n            limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n            for (int lim : limits) {\n                if (elapsed_sec() > timeLimit) break;\n                if (lim >= old) continue;\n\n                vector<int> P = bestP;\n                vector<int> maxR(N, 5000);\n\n                P[s] = lim;\n                maxR[s] = lim;\n\n                bool ok = greedy_repair_active_only(P, allowed, maxR);\n                if (!ok) continue;\n\n                reduce_powers(P);\n\n                vector<char> covered;\n                if (!compute_covered(P, covered)) continue;\n\n                long long S = total_cost(P);\n\n                if (S < nextS) {\n                    nextS = S;\n                    nextP = P;\n                    improved = true;\n                }\n            }\n        }\n\n        if (improved) {\n            bestP = nextP;\n            bestS = nextS;\n        } else {\n            break;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st_time = chrono::steady_clock::now();\n\n    cin >> N >> M >> K;\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n        edges[i] = {u, v, w};\n    }\n\n    A.resize(K);\n    RY.resize(K);\n    for (int k = 0; k < K; k++) cin >> A[k] >> RY[k];\n\n    fw.assign(N, vector<long long>(N, INF));\n    nxtv.assign(N, vector<int>(N, -1));\n    directEdge.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; i++) {\n        fw[i][i] = 0;\n        nxtv[i][i] = i;\n    }\n\n    for (int e = 0; e < M; e++) {\n        int u = edges[e].u;\n        int v = edges[e].v;\n        long long w = edges[e].w;\n\n        if (w < fw[u][v]) {\n            fw[u][v] = fw[v][u] = w;\n            nxtv[u][v] = v;\n            nxtv[v][u] = u;\n            directEdge[u][v] = directEdge[v][u] = e;\n        }\n    }\n\n    for (int k = 0; k < N; k++) {\n        for (int i = 0; i < N; i++) if (fw[i][k] < INF) {\n            for (int j = 0; j < N; j++) if (fw[k][j] < INF) {\n                long long nd = fw[i][k] + fw[k][j];\n\n                if (nd < fw[i][j]) {\n                    fw[i][j] = nd;\n                    nxtv[i][j] = nxtv[i][k];\n                }\n            }\n        }\n    }\n\n    cdist.assign(N, vector<int>(K));\n    sortedRes.assign(N, {});\n\n    for (int i = 0; i < N; i++) {\n        sortedRes[i].reserve(K);\n\n        for (int k = 0; k < K; k++) {\n            long long dx = X[i] - A[k];\n            long long dy = Y[i] - RY[k];\n            int d = ceil_sqrt_ll(dx * dx + dy * dy);\n\n            cdist[i][k] = d;\n\n            if (d <= 5000) {\n                sortedRes[i].push_back({d, k});\n            }\n        }\n\n        sort(sortedRes[i].begin(), sortedRes[i].end());\n    }\n\n    vector<int> bestP = initial_nearest_solution();\n    long long bestS = total_cost(bestP);\n    double bestAlpha = 0.2;\n\n    vector<double> alphas = {\n        0.0, 0.02, 0.05, 0.08, 0.12, 0.18,\n        0.27, 0.4, 0.6, 0.9, 1.3\n    };\n\n    // Static and dynamic greedy initial constructions.\n    for (double alpha : alphas) {\n        if (elapsed_sec() > 1.08) break;\n\n        for (int dyn = 0; dyn <= 1; dyn++) {\n            if (elapsed_sec() > 1.18) break;\n\n            vector<int> P(N, 0);\n            bool ok = greedy_complete(P, alpha, dyn == 1);\n\n            if (!ok) continue;\n\n            reduce_powers(P);\n            long long S = total_cost(P);\n\n            if (S < bestS) {\n                bestS = S;\n                bestP = P;\n                bestAlpha = alpha;\n            }\n        }\n    }\n\n    optimize_reduction_orders(bestP, bestS);\n\n    // New safe local search: repair only with already active stations.\n    if (elapsed_sec() < 1.40) {\n        fixed_active_local_search(bestP, bestS, 1.55);\n    }\n\n    vector<double> repairAlphas = {\n        0.0,\n        max(0.05, min(0.7, bestAlpha)),\n        0.25,\n        0.55\n    };\n\n    // Original robust local search: remove or shrink active stations, then repair globally.\n    while (elapsed_sec() < 1.86) {\n        bool improved = false;\n        vector<int> nextBestP = bestP;\n        long long nextBestS = bestS;\n\n        vector<int> active;\n        for (int i = 0; i < N; i++) {\n            if (bestP[i] > 0) active.push_back(i);\n        }\n\n        sort(active.begin(), active.end(), [&](int a, int b) {\n            long long ca = 1LL * bestP[a] * bestP[a];\n            long long cb = 1LL * bestP[b] * bestP[b];\n            return ca > cb;\n        });\n\n        for (int s : active) {\n            if (elapsed_sec() > 1.91) break;\n\n            int old = bestP[s];\n            vector<int> limits;\n\n            limits.push_back(0);\n            limits.push_back(lower_existing_radius(s, old / 4));\n            limits.push_back(lower_existing_radius(s, old / 2));\n            limits.push_back(lower_existing_radius(s, old * 3 / 4));\n\n            sort(limits.begin(), limits.end());\n            limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n            for (int lim : limits) {\n                if (elapsed_sec() > 1.93) break;\n                if (lim >= old) continue;\n\n                for (double ra : repairAlphas) {\n                    if (elapsed_sec() > 1.95) break;\n\n                    vector<int> P = bestP;\n                    P[s] = lim;\n\n                    bool ok = greedy_complete(P, ra, true, s, lim);\n                    if (!ok) continue;\n\n                    reduce_powers(P);\n                    long long S = total_cost(P);\n\n                    if (S < nextBestS) {\n                        nextBestS = S;\n                        nextBestP = P;\n                        improved = true;\n                    }\n                }\n            }\n        }\n\n        if (improved) {\n            bestS = nextBestS;\n            bestP = nextBestP;\n\n            if (elapsed_sec() < 1.88) {\n                optimize_reduction_orders(bestP, bestS);\n            }\n        } else {\n            break;\n        }\n    }\n\n    optimize_reduction_orders(bestP, bestS);\n\n    vector<char> covered;\n    if (!compute_covered(bestP, covered)) {\n        greedy_complete(bestP, 0.0, true);\n        reduce_powers(bestP);\n    }\n\n    auto tree = build_best_tree(bestP);\n    vector<int> ansB = tree.second;\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n\n    for (int e = 0; e < M; e++) {\n        if (e) cout << ' ';\n        cout << ansB[e];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = N * (N + 1) / 2;\nconstexpr int MAX_OPS = 10000;\n\nstruct Op {\n    int u, v;\n};\n\nint ID[N][N];\nint X[M], Y[M];\n\narray<int, M> initialA;\n\nvector<int> adj[M];\nvector<pair<int,int>> adjEdges;\nvector<pair<int,int>> downEdges;\nvector<vector<int>> incidentDown;\nbool isAdj[M][M];\n\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsedSec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nint calcE(const array<int, M>& a) {\n    int e = 0;\n    for (auto [p, c] : downEdges) {\n        if (a[p] > a[c]) e++;\n    }\n    return e;\n}\n\nbool isValidFinal(const array<int, M>& a) {\n    for (auto [p, c] : downEdges) {\n        if (a[p] > a[c]) return false;\n    }\n    return true;\n}\n\nstruct State {\n    array<int, M> a;\n    vector<Op> ops;\n    int E = 0;\n};\n\nint deltaSwapLocal(const array<int, M>& a, int u, int v) {\n    int ids[16], cnt = 0;\n\n    auto add = [&](int e) {\n        for (int i = 0; i < cnt; i++) {\n            if (ids[i] == e) return;\n        }\n        ids[cnt++] = e;\n    };\n\n    for (int e : incidentDown[u]) add(e);\n    for (int e : incidentDown[v]) add(e);\n\n    int before = 0;\n    int after = 0;\n\n    for (int i = 0; i < cnt; i++) {\n        auto [p, c] = downEdges[ids[i]];\n\n        before += (a[p] > a[c]);\n\n        int vp = a[p];\n        int vc = a[c];\n\n        if (p == u) vp = a[v];\n        else if (p == v) vp = a[u];\n\n        if (c == u) vc = a[v];\n        else if (c == v) vc = a[u];\n\n        after += (vp > vc);\n    }\n\n    return before - after;\n}\n\nvoid applySwap(State& s, int u, int v) {\n    int d = deltaSwapLocal(s.a, u, v);\n    s.E -= d;\n    swap(s.a[u], s.a[v]);\n    s.ops.push_back({u, v});\n}\n\nvoid applySwapWithPos(State& s, array<int, M>& pos, int u, int v) {\n    int au = s.a[u];\n    int av = s.a[v];\n\n    applySwap(s, u, v);\n\n    pos[au] = v;\n    pos[av] = u;\n}\n\nvector<Op> reduceOps(const vector<Op>& ops) {\n    vector<Op> st;\n    st.reserve(ops.size());\n\n    auto sameEdge = [](const Op& a, const Op& b) {\n        return (a.u == b.u && a.v == b.v) || (a.u == b.v && a.v == b.u);\n    };\n\n    for (auto op : ops) {\n        if (!st.empty() && sameEdge(st.back(), op)) {\n            st.pop_back();\n        } else {\n            st.push_back(op);\n        }\n    }\n\n    return st;\n}\n\nbool validateOps(const vector<Op>& ops) {\n    if ((int)ops.size() > MAX_OPS) return false;\n\n    array<int, M> a = initialA;\n\n    for (auto [u, v] : ops) {\n        if (!isAdj[u][v]) return false;\n        swap(a[u], a[v]);\n    }\n\n    return isValidFinal(a);\n}\n\nvector<int> yOrder(int x, int type) {\n    vector<int> ys;\n    for (int y = 0; y <= x; y++) ys.push_back(y);\n\n    if (type == 1) {\n        reverse(ys.begin(), ys.end());\n    } else if (type == 2) {\n        if (x & 1) reverse(ys.begin(), ys.end());\n    } else if (type == 3) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da < db;\n            return a < b;\n        });\n    } else if (type == 4) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da > db;\n            return a < b;\n        });\n    }\n\n    return ys;\n}\n\nState runHeapify(State s, int yType) {\n    for (int x = N - 2; x >= 0; x--) {\n        auto ys = yOrder(x, yType);\n\n        for (int sy : ys) {\n            int cur = ID[x][sy];\n\n            while (X[cur] + 1 < N) {\n                int cx = X[cur];\n                int cy = Y[cur];\n\n                int c1 = ID[cx + 1][cy];\n                int c2 = ID[cx + 1][cy + 1];\n\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[cur] > s.a[ch]) {\n                    applySwap(s, cur, ch);\n                    cur = ch;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    return s;\n}\n\nState runScanBubble(State s, int rowType, int yType, int limitOps) {\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        bool changed = false;\n\n        vector<int> rows;\n        if (rowType == 0) {\n            for (int x = N - 2; x >= 0; x--) rows.push_back(x);\n        } else {\n            for (int x = 0; x <= N - 2; x++) rows.push_back(x);\n        }\n\n        for (int x : rows) {\n            auto ys = yOrder(x, yType);\n\n            for (int y : ys) {\n                if ((int)s.ops.size() >= limitOps) break;\n\n                int p = ID[x][y];\n                int c1 = ID[x + 1][y];\n                int c2 = ID[x + 1][y + 1];\n\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[p] > s.a[ch]) {\n                    applySwap(s, p, ch);\n                    changed = true;\n                }\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    return s;\n}\n\nState runViolationGreedy(State s, int mode, int limitOps) {\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        int bu = -1;\n        int bv = -1;\n\n        long long bk1 = LLONG_MIN;\n        long long bk2 = LLONG_MIN;\n        long long bk3 = LLONG_MIN;\n\n        for (auto [p, c] : downEdges) {\n            if (s.a[p] <= s.a[c]) continue;\n\n            int imp = deltaSwapLocal(s.a, p, c);\n            int diff = s.a[p] - s.a[c];\n\n            long long k1, k2, k3;\n\n            if (mode == 0) {\n                k1 = imp;\n                k2 = diff;\n                k3 = -X[p];\n            } else if (mode == 1) {\n                k1 = diff;\n                k2 = imp;\n                k3 = -X[p];\n            } else if (mode == 2) {\n                k1 = -s.a[c];\n                k2 = imp;\n                k3 = diff;\n            } else {\n                k1 = -X[p];\n                k2 = imp;\n                k3 = diff;\n            }\n\n            if (\n                k1 > bk1 ||\n                (k1 == bk1 && (k2 > bk2 || (k2 == bk2 && k3 > bk3)))\n            ) {\n                bk1 = k1;\n                bk2 = k2;\n                bk3 = k3;\n                bu = p;\n                bv = c;\n            }\n        }\n\n        if (bu == -1) break;\n\n        applySwap(s, bu, bv);\n    }\n\n    return s;\n}\n\nvector<int> parentsOf(int u) {\n    vector<int> ps;\n\n    int x = X[u];\n    int y = Y[u];\n\n    if (x == 0) return ps;\n\n    if (y > 0) ps.push_back(ID[x - 1][y - 1]);\n    if (y < x) ps.push_back(ID[x - 1][y]);\n\n    return ps;\n}\n\nvector<int> childrenOf(int u) {\n    vector<int> cs;\n\n    int x = X[u];\n    int y = Y[u];\n\n    if (x + 1 >= N) return cs;\n\n    cs.push_back(ID[x + 1][y]);\n    cs.push_back(ID[x + 1][y + 1]);\n\n    return cs;\n}\n\n// New candidate: process small labels and bubble them upward.\nState runSiftUpByLabel(State s, int mode, int uptoLabel) {\n    array<int, M> pos;\n    for (int i = 0; i < M; i++) pos[s.a[i]] = i;\n\n    for (int val = 0; val < uptoLabel; val++) {\n        if ((int)s.ops.size() >= MAX_OPS) break;\n\n        while ((int)s.ops.size() < MAX_OPS) {\n            int u = pos[val];\n\n            vector<int> cand;\n            for (int p : parentsOf(u)) {\n                if (s.a[p] > val) cand.push_back(p);\n            }\n\n            if (cand.empty()) break;\n\n            int best = cand[0];\n            long long bestScore = LLONG_MIN;\n\n            for (int p : cand) {\n                long long score = 0;\n\n                if (mode == 0) {\n                    // Swap with the largest blocking parent.\n                    score = 100000LL * s.a[p] + deltaSwapLocal(s.a, u, p);\n                } else if (mode == 1) {\n                    // Swap with the smaller blocking parent.\n                    score = -100000LL * s.a[p] + deltaSwapLocal(s.a, u, p);\n                } else if (mode == 2) {\n                    // Best immediate violation reduction.\n                    score = 100000LL * deltaSwapLocal(s.a, u, p) + s.a[p];\n                } else if (mode == 3) {\n                    // Prefer central path.\n                    score = -1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                } else {\n                    // Prefer side path.\n                    score = 1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = p;\n                }\n            }\n\n            applySwapWithPos(s, pos, u, best);\n        }\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\n// New candidate: process large labels and push them downward.\nState runSiftDownByLabel(State s, int mode, int fromLabel) {\n    array<int, M> pos;\n    for (int i = 0; i < M; i++) pos[s.a[i]] = i;\n\n    for (int val = M - 1; val >= fromLabel; val--) {\n        if ((int)s.ops.size() >= MAX_OPS) break;\n\n        while ((int)s.ops.size() < MAX_OPS) {\n            int u = pos[val];\n\n            vector<int> cand;\n            for (int c : childrenOf(u)) {\n                if (s.a[c] < val) cand.push_back(c);\n            }\n\n            if (cand.empty()) break;\n\n            int best = cand[0];\n            long long bestScore = LLONG_MIN;\n\n            for (int c : cand) {\n                long long score = 0;\n\n                if (mode == 0) {\n                    // Swap with the smallest child.\n                    score = -100000LL * s.a[c] + deltaSwapLocal(s.a, u, c);\n                } else if (mode == 1) {\n                    // Swap with the larger violating child.\n                    score = 100000LL * s.a[c] + deltaSwapLocal(s.a, u, c);\n                } else if (mode == 2) {\n                    // Best immediate violation reduction.\n                    score = 100000LL * deltaSwapLocal(s.a, u, c) - s.a[c];\n                } else if (mode == 3) {\n                    // Prefer central path.\n                    score = -1000LL * abs(2 * Y[c] - X[c]) - s.a[c];\n                } else {\n                    // Prefer side path.\n                    score = 1000LL * abs(2 * Y[c] - X[c]) - s.a[c];\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = c;\n                }\n            }\n\n            applySwapWithPos(s, pos, u, best);\n        }\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nbool validWithoutRange(const vector<Op>& ops, int l, int r) {\n    array<int, M> a = initialA;\n\n    for (int i = 0; i < (int)ops.size(); i++) {\n        if (l <= i && i < r) continue;\n        auto [u, v] = ops[i];\n        swap(a[u], a[v]);\n    }\n\n    return isValidFinal(a);\n}\n\nvector<Op> lightPrune(vector<Op> ops) {\n    ops = reduceOps(ops);\n\n    if (!validateOps(ops)) return ops;\n\n    // Very light pruning only; previous heavy pruning was not cost-effective.\n    for (int pass = 0; pass < 2; pass++) {\n        if (elapsedSec() > 1.85) break;\n\n        bool changed = false;\n\n        if (pass == 0) {\n            for (int i = 0; i < (int)ops.size(); ) {\n                if (elapsedSec() > 1.90) break;\n\n                if (validWithoutRange(ops, i, i + 1)) {\n                    ops.erase(ops.begin() + i);\n                    changed = true;\n                    if (i > 0) i--;\n                } else {\n                    i++;\n                }\n            }\n        } else {\n            for (int i = 0; i + 2 <= (int)ops.size(); ) {\n                if (elapsedSec() > 1.92) break;\n\n                if (validWithoutRange(ops, i, i + 2)) {\n                    ops.erase(ops.begin() + i, ops.begin() + i + 2);\n                    changed = true;\n                    if (i > 0) i--;\n                } else {\n                    i++;\n                }\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    return reduceOps(ops);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    int id = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            ID[x][y] = id;\n            X[id] = x;\n            Y[id] = y;\n            id++;\n        }\n    }\n\n    incidentDown.assign(M, {});\n    memset(isAdj, 0, sizeof(isAdj));\n\n    auto addAdj = [&](int u, int v) {\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n        adjEdges.push_back({u, v});\n        isAdj[u][v] = isAdj[v][u] = true;\n    };\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int u = ID[x][y];\n\n            if (y + 1 <= x) {\n                int v = ID[x][y + 1];\n                addAdj(u, v);\n            }\n\n            if (x + 1 < N) {\n                int v1 = ID[x + 1][y];\n                int v2 = ID[x + 1][y + 1];\n\n                addAdj(u, v1);\n                addAdj(u, v2);\n\n                int e1 = (int)downEdges.size();\n                downEdges.push_back({u, v1});\n                incidentDown[u].push_back(e1);\n                incidentDown[v1].push_back(e1);\n\n                int e2 = (int)downEdges.size();\n                downEdges.push_back({u, v2});\n                incidentDown[u].push_back(e2);\n                incidentDown[v2].push_back(e2);\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> initialA[ID[x][y]];\n        }\n    }\n\n    State base;\n    base.a = initialA;\n    base.E = calcE(initialA);\n\n    vector<Op> bestOps;\n    bool haveBest = false;\n\n    auto tryCandidate = [&](const State& s, bool doPrune = false) {\n        if (s.E != 0) return;\n\n        vector<Op> ops = reduceOps(s.ops);\n\n        if ((int)ops.size() > MAX_OPS) return;\n        if (!validateOps(ops)) return;\n\n        if (doPrune && elapsedSec() < 1.80) {\n            vector<Op> pruned = lightPrune(ops);\n            if ((int)pruned.size() <= MAX_OPS && validateOps(pruned)) {\n                ops = move(pruned);\n            }\n        }\n\n        if (!haveBest || ops.size() < bestOps.size()) {\n            bestOps = move(ops);\n            haveBest = true;\n        }\n    };\n\n    // 1. Original robust heapify candidates.\n    for (int t = 0; t < 5; t++) {\n        State s = runHeapify(base, t);\n        tryCandidate(s, false);\n    }\n\n    // Safety fallback.\n    if (!haveBest) {\n        State s = runHeapify(base, 0);\n        bestOps = reduceOps(s.ops);\n        haveBest = true;\n    }\n\n    // 2. New full sift-up candidates.\n    if (elapsedSec() < 1.10) {\n        for (int mode = 0; mode < 5; mode++) {\n            if (elapsedSec() > 1.35) break;\n\n            State s = runSiftUpByLabel(base, mode, M);\n            tryCandidate(s, false);\n        }\n    }\n\n    // 3. New full sift-down candidates.\n    if (elapsedSec() < 1.35) {\n        for (int mode = 0; mode < 5; mode++) {\n            if (elapsedSec() > 1.55) break;\n\n            State s = runSiftDownByLabel(base, mode, 0);\n            tryCandidate(s, false);\n        }\n    }\n\n    // 4. Prefix sift-up, then heapify.\n    if (elapsedSec() < 1.55) {\n        vector<int> prefixes = {10, 20, 40, 70, 100, 150, 220, 300};\n\n        for (int p : prefixes) {\n            if (elapsedSec() > 1.75) break;\n\n            for (int mode = 0; mode < 5; mode++) {\n                if (elapsedSec() > 1.80) break;\n\n                State pre = runSiftUpByLabel(base, mode, p);\n\n                if ((int)pre.ops.size() >= (int)bestOps.size()) continue;\n\n                for (int t = 0; t < 5; t++) {\n                    if (elapsedSec() > 1.84) break;\n\n                    State s = runHeapify(pre, t);\n                    tryCandidate(s, false);\n                }\n            }\n        }\n    }\n\n    // 5. Prefix sift-down, then heapify.\n    if (elapsedSec() < 1.82) {\n        vector<int> counts = {10, 20, 40, 70, 100, 150, 220, 300};\n\n        for (int c : counts) {\n            if (elapsedSec() > 1.90) break;\n\n            int fromLabel = M - c;\n\n            for (int mode = 0; mode < 5; mode++) {\n                if (elapsedSec() > 1.92) break;\n\n                State pre = runSiftDownByLabel(base, mode, fromLabel);\n\n                if ((int)pre.ops.size() >= (int)bestOps.size()) continue;\n\n                for (int t = 0; t < 5; t++) {\n                    if (elapsedSec() > 1.94) break;\n\n                    State s = runHeapify(pre, t);\n                    tryCandidate(s, false);\n                }\n            }\n        }\n    }\n\n    // 6. Existing scan/violation variants, time permitting.\n    int bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n\n    if (bestLimit > 0 && elapsedSec() < 1.88) {\n        for (int rowType = 0; rowType < 2; rowType++) {\n            for (int yType = 0; yType < 5; yType++) {\n                if (elapsedSec() > 1.94) break;\n\n                State s = runScanBubble(base, rowType, yType, bestLimit);\n                tryCandidate(s, false);\n\n                bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n            }\n        }\n    }\n\n    bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n\n    if (bestLimit > 0 && elapsedSec() < 1.94) {\n        for (int mode = 0; mode < 4; mode++) {\n            if (elapsedSec() > 1.97) break;\n\n            State s = runViolationGreedy(base, mode, bestLimit);\n            tryCandidate(s, false);\n\n            bestLimit = min(MAX_OPS, (int)bestOps.size() - 1);\n        }\n    }\n\n    // Final small cleanup only if there is safe remaining time.\n    if (elapsedSec() < 1.80) {\n        vector<Op> pruned = lightPrune(bestOps);\n        if ((int)pruned.size() <= MAX_OPS && validateOps(pruned) && pruned.size() < bestOps.size()) {\n            bestOps = move(pruned);\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n    for (auto [u, v] : bestOps) {\n        cout << X[u] << ' ' << Y[u] << ' ' << X[v] << ' ' << Y[v] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint D, N;\nint ENT;\nvector<int> freeIds;\nbool obstacleCell[100];\nint labelAt[100];\nint rankOfCell[100];\nbool usedLabel[100];\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nint id_of(int r, int c) {\n    return r * D + c;\n}\n\npair<int,int> rc_of(int id) {\n    return {id / D, id % D};\n}\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nvector<int> neighbors(int id) {\n    auto [r, c] = rc_of(id);\n    vector<int> res;\n    for (int k = 0; k < 4; k++) {\n        int nr = r + dr[k], nc = c + dc[k];\n        if (inside(nr, nc)) res.push_back(id_of(nr, nc));\n    }\n    return res;\n}\n\ninline void set_bit(ull &lo, ull &hi, int x) {\n    if (x < 64) lo |= 1ULL << x;\n    else hi |= 1ULL << (x - 64);\n}\n\ninline bool has_bit(ull lo, ull hi, int x) {\n    if (x < 64) return (lo >> x) & 1ULL;\n    return (hi >> (x - 64)) & 1ULL;\n}\n\ninline int popcnt2(ull lo, ull hi) {\n    return __builtin_popcountll(lo) + __builtin_popcountll(hi);\n}\n\n// Check whether filling cand keeps all remaining empty cells connected to entrance.\nbool legal_fill(int cand) {\n    int totalEmptyAfter = 0;\n    for (int id : freeIds) {\n        if (id != cand && labelAt[id] == -1) totalEmptyAfter++;\n    }\n\n    queue<int> q;\n    bool vis[100] = {};\n    vis[ENT] = true;\n    q.push(ENT);\n\n    int reached = 0;\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int to : neighbors(v)) {\n            if (vis[to]) continue;\n            if (obstacleCell[to]) continue;\n            if (to == cand) continue;\n            if (to != ENT && labelAt[to] != -1) continue;\n\n            vis[to] = true;\n            q.push(to);\n            if (to != ENT) reached++;\n        }\n    }\n\n    return reached == totalEmptyAfter;\n}\n\nbool is_accessible_container(int id, const bool emptyCell[]) {\n    for (int to : neighbors(id)) {\n        if (emptyCell[to]) return true;\n    }\n    return false;\n}\n\n// Estimate final inversions if current arriving label t is placed at cand.\n// Future unknown labels are assigned optimistically to remaining cells in rank order.\nint evaluate_candidate(\n    int cand,\n    int t,\n    const vector<int>& emptySorted,\n    const vector<int>& remLabels\n) {\n    int val[100];\n    fill(val, val + 100, -1);\n\n    for (int id : freeIds) {\n        if (labelAt[id] >= 0) val[id] = labelAt[id];\n    }\n    val[cand] = t;\n\n    int p = 0;\n    for (int id : emptySorted) {\n        if (id == cand) continue;\n        val[id] = remLabels[p++];\n    }\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    vector<int> seq;\n    seq.reserve(freeIds.size());\n\n    for (int step = 0; step < (int)freeIds.size(); step++) {\n        int best = -1;\n        int bestVal = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (val[id] < bestVal ||\n                (val[id] == bestVal && (best == -1 || rankOfCell[id] < rankOfCell[best]))) {\n                bestVal = val[id];\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    bestVal = val[id];\n                    break;\n                }\n            }\n        }\n\n        seq.push_back(bestVal);\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    int inv = 0;\n    int M = seq.size();\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (seq[i] > seq[j]) inv++;\n        }\n    }\n    return inv;\n}\n\nvector<int> greedy_removal_order() {\n    int M = freeIds.size();\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    vector<int> order;\n    order.reserve(M);\n\n    for (int step = 0; step < M; step++) {\n        int best = -1;\n        int bestLabel = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (labelAt[id] < bestLabel) {\n                bestLabel = labelAt[id];\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    break;\n                }\n            }\n        }\n\n        order.push_back(best);\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    return order;\n}\n\nint inversion_count_of_order(const vector<int>& order) {\n    int M = order.size();\n    int inv = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (labelAt[order[i]] > labelAt[order[j]]) inv++;\n        }\n    }\n    return inv;\n}\n\nstruct Key {\n    ull lo, hi;\n    bool operator==(const Key& other) const {\n        return lo == other.lo && hi == other.hi;\n    }\n};\n\nstruct KeyHash {\n    static uint64_t splitmix64(uint64_t x) {\n        x += 0x9e3779b97f4a7c15ULL;\n        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;\n        return x ^ (x >> 31);\n    }\n\n    size_t operator()(const Key& k) const {\n        return splitmix64(k.lo) ^ (splitmix64(k.hi) << 1);\n    }\n};\n\nstruct BeamState {\n    ull lo, hi;\n    ull flo, fhi;\n    int cost;\n    int prev;\n    int add;\n    int score;\n};\n\n// Beam search for better final removal order.\nvector<int> beam_removal_order() {\n    int M = freeIds.size();\n\n    vector<int> idToIdx(D * D, -1);\n    vector<int> idxToId(M);\n    for (int i = 0; i < M; i++) {\n        idToIdx[freeIds[i]] = i;\n        idxToId[i] = freeIds[i];\n    }\n\n    vector<int> lab(M);\n    for (int i = 0; i < M; i++) {\n        lab[i] = labelAt[idxToId[i]];\n    }\n\n    vector<ull> adjLo(M, 0), adjHi(M, 0);\n    ull initLo = 0, initHi = 0;\n\n    for (int i = 0; i < M; i++) {\n        int id = idxToId[i];\n        for (int to : neighbors(id)) {\n            if (to == ENT) {\n                set_bit(initLo, initHi, i);\n            } else if (0 <= to && to < D * D && idToIdx[to] != -1) {\n                int j = idToIdx[to];\n                set_bit(adjLo[i], adjHi[i], j);\n            }\n        }\n    }\n\n    vector<ull> lessLo(M, 0), lessHi(M, 0);\n    for (int x = 0; x < M; x++) {\n        ull lo = 0, hi = 0;\n        for (int i = 0; i < M; i++) {\n            if (lab[i] < x) set_bit(lo, hi, i);\n        }\n        lessLo[x] = lo;\n        lessHi[x] = hi;\n    }\n\n    auto calc_score = [&](int cost, ull flo, ull fhi) {\n        int mn1 = 100, mn2 = 100;\n\n        ull b = flo;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int x = lab[t];\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n            b &= b - 1;\n        }\n\n        b = fhi;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int idx = 64 + t;\n            int x = lab[idx];\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n            b &= b - 1;\n        }\n\n        return cost * 10000 + mn1 * 100 + mn2;\n    };\n\n    const int WIDTH = 5000;\n\n    vector<vector<BeamState>> layers;\n    layers.reserve(M + 1);\n\n    BeamState start;\n    start.lo = start.hi = 0;\n    start.flo = initLo;\n    start.fhi = initHi;\n    start.cost = 0;\n    start.prev = -1;\n    start.add = -1;\n    start.score = calc_score(0, initLo, initHi);\n\n    layers.push_back(vector<BeamState>{start});\n\n    for (int depth = 0; depth < M; depth++) {\n        vector<BeamState>& cur = layers.back();\n\n        vector<BeamState> nxt;\n        nxt.reserve(min((int)cur.size() * 20, WIDTH * 40));\n\n        unordered_map<Key, int, KeyHash> mp;\n        mp.reserve(WIDTH * 50);\n\n        for (int pi = 0; pi < (int)cur.size(); pi++) {\n            const BeamState& s = cur[pi];\n\n            auto expand_one = [&](int idx) {\n                ull bitLo = 0, bitHi = 0;\n                set_bit(bitLo, bitHi, idx);\n\n                ull nlo = s.lo | bitLo;\n                ull nhi = s.hi | bitHi;\n\n                int label = lab[idx];\n                int removedLess = popcnt2(s.lo & lessLo[label], s.hi & lessHi[label]);\n                int inc = label - removedLess;\n                int ncost = s.cost + inc;\n\n                ull nflo = ((s.flo & ~bitLo) | adjLo[idx]) & ~nlo;\n                ull nfhi = ((s.fhi & ~bitHi) | adjHi[idx]) & ~nhi;\n\n                BeamState ns;\n                ns.lo = nlo;\n                ns.hi = nhi;\n                ns.flo = nflo;\n                ns.fhi = nfhi;\n                ns.cost = ncost;\n                ns.prev = pi;\n                ns.add = idx;\n                ns.score = calc_score(ncost, nflo, nfhi);\n\n                Key key{nlo, nhi};\n                auto it = mp.find(key);\n                if (it == mp.end()) {\n                    int pos = nxt.size();\n                    mp.emplace(key, pos);\n                    nxt.push_back(ns);\n                } else {\n                    int pos = it->second;\n                    if (ns.cost < nxt[pos].cost ||\n                        (ns.cost == nxt[pos].cost && ns.score < nxt[pos].score)) {\n                        nxt[pos] = ns;\n                    }\n                }\n            };\n\n            ull b = s.flo;\n            while (b) {\n                int idx = __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n\n            b = s.fhi;\n            while (b) {\n                int idx = 64 + __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n        }\n\n        if ((int)nxt.size() > WIDTH) {\n            nth_element(\n                nxt.begin(),\n                nxt.begin() + WIDTH,\n                nxt.end(),\n                [](const BeamState& a, const BeamState& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.cost < b.cost;\n                }\n            );\n            nxt.resize(WIDTH);\n        }\n\n        layers.push_back(move(nxt));\n    }\n\n    if (layers.back().empty()) {\n        return greedy_removal_order();\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)layers[M].size(); i++) {\n        if (layers[M][i].cost < layers[M][best].cost) best = i;\n    }\n\n    vector<int> idxOrder;\n    idxOrder.reserve(M);\n\n    int curIdx = best;\n    for (int depth = M; depth >= 1; depth--) {\n        const BeamState& s = layers[depth][curIdx];\n        idxOrder.push_back(s.add);\n        curIdx = s.prev;\n    }\n\n    reverse(idxOrder.begin(), idxOrder.end());\n\n    vector<int> order;\n    order.reserve(M);\n    for (int idx : idxOrder) order.push_back(idxToId[idx]);\n\n    return order;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    ENT = id_of(0, (D - 1) / 2);\n\n    fill(obstacleCell, obstacleCell + 100, false);\n    fill(labelAt, labelAt + 100, -1);\n    fill(usedLabel, usedLabel + 100, false);\n\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        obstacleCell[id_of(r, c)] = true;\n    }\n\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            int id = id_of(r, c);\n            if (id == ENT) continue;\n            if (obstacleCell[id]) continue;\n            freeIds.push_back(id);\n        }\n    }\n\n    int M = freeIds.size();\n\n    const int INF = 1e9;\n    vector<int> dist(D * D, INF);\n    queue<int> q;\n    dist[ENT] = 0;\n    q.push(ENT);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int to : neighbors(v)) {\n            if (obstacleCell[to]) continue;\n            if (dist[to] != INF) continue;\n            dist[to] = dist[v] + 1;\n            q.push(to);\n        }\n    }\n\n    int center = (D - 1) / 2;\n\n    sort(freeIds.begin(), freeIds.end(), [&](int a, int b) {\n        auto [ra, ca] = rc_of(a);\n        auto [rb, cb] = rc_of(b);\n\n        tuple<int,int,int,int> ka = {\n            dist[a],\n            abs(ca - center),\n            ra,\n            ca\n        };\n        tuple<int,int,int,int> kb = {\n            dist[b],\n            abs(cb - center),\n            rb,\n            cb\n        };\n        return ka < kb;\n    });\n\n    for (int i = 0; i < M; i++) {\n        rankOfCell[freeIds[i]] = i;\n    }\n\n    // Arrival phase.\n    for (int step = 0; step < M; step++) {\n        int t;\n        cin >> t;\n\n        vector<int> emptySorted;\n        for (int id : freeIds) {\n            if (labelAt[id] == -1) emptySorted.push_back(id);\n        }\n        sort(emptySorted.begin(), emptySorted.end(), [&](int a, int b) {\n            return rankOfCell[a] < rankOfCell[b];\n        });\n\n        vector<int> remLabels;\n        for (int x = 0; x < M; x++) {\n            if (!usedLabel[x] && x != t) remLabels.push_back(x);\n        }\n\n        vector<int> legal;\n        for (int id : emptySorted) {\n            if (legal_fill(id)) legal.push_back(id);\n        }\n\n        if (legal.empty()) {\n            legal = emptySorted;\n        }\n\n        int bestCell = legal[0];\n        long long bestScore = (1LL << 60);\n\n        for (int cand : legal) {\n            int inv = evaluate_candidate(cand, t, emptySorted, remLabels);\n\n            long long mismatch = abs(rankOfCell[cand] - t);\n            long long score = inv * 1000LL + mismatch;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestCell = cand;\n            }\n        }\n\n        labelAt[bestCell] = t;\n        usedLabel[t] = true;\n\n        auto [r, c] = rc_of(bestCell);\n        cout << r << ' ' << c << endl;\n    }\n\n    // Final removal phase.\n    vector<int> greedyOrder = greedy_removal_order();\n    int greedyInv = inversion_count_of_order(greedyOrder);\n\n    vector<int> beamOrder = beam_removal_order();\n    int beamInv = inversion_count_of_order(beamOrder);\n\n    const vector<int>& finalOrder = (beamInv <= greedyInv ? beamOrder : greedyOrder);\n\n    for (int id : finalOrder) {\n        auto [r, c] = rc_of(id);\n        cout << r << ' ' << c << '\\n';\n    }\n\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXC = 101;\nstatic const int INF = 1e9;\n\nint n, m;\nbool allowedAdj[MAXC][MAXC];\n\nstruct State {\n    vector<vector<int>> g;\n    int cnt[MAXC]{};\n    int edgeCnt[MAXC][MAXC]{};\n\n    int stamp[MAXN][MAXN]{};\n    int curStamp = 1;\n\n    State() {\n        g.assign(n, vector<int>(n, 0));\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(stamp, 0, sizeof(stamp));\n    }\n\n    static void normPair(int &a, int &b) {\n        if (a > b) swap(a, b);\n    }\n\n    bool inside(int r, int c) const {\n        return 0 <= r && r < n && 0 <= c && c < n;\n    }\n\n    void addEdgeCount(int a, int b, int v) {\n        if (a == b) return;\n        normPair(a, b);\n        edgeCnt[a][b] += v;\n    }\n\n    void init(const vector<vector<int>> &src) {\n        g = src;\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                cnt[g[i][j]]++;\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = g[i][j];\n\n                if (i == 0) addEdgeCount(c, 0, 1);\n                if (i == n - 1) addEdgeCount(c, 0, 1);\n                if (j == 0) addEdgeCount(c, 0, 1);\n                if (j == n - 1) addEdgeCount(c, 0, 1);\n\n                if (i + 1 < n) addEdgeCount(c, g[i + 1][j], 1);\n                if (j + 1 < n) addEdgeCount(c, g[i][j + 1], 1);\n            }\n        }\n    }\n\n    bool adjacentZeroOrOutside(int r, int c) const {\n        if (r == 0 || r == n - 1 || c == 0 || c == n - 1) return true;\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == 0) return true;\n        }\n        return false;\n    }\n\n    bool oldColorConnectedAfterRemoval(int r, int c, int col) {\n        vector<pair<int, int>> starts;\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) {\n                starts.push_back({nr, nc});\n            }\n        }\n\n        if (starts.size() <= 1) return true;\n\n        curStamp++;\n        if (curStamp == INT_MAX) {\n            memset(stamp, 0, sizeof(stamp));\n            curStamp = 1;\n        }\n\n        queue<pair<int, int>> q;\n        q.push(starts[0]);\n        stamp[starts[0].first][starts[0].second] = curStamp;\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dr[k], ny = y + dc[k];\n                if (!inside(nx, ny)) continue;\n                if (nx == r && ny == c) continue;\n                if (stamp[nx][ny] == curStamp) continue;\n                if (g[nx][ny] != col) continue;\n\n                stamp[nx][ny] = curStamp;\n                q.push({nx, ny});\n            }\n        }\n\n        for (auto [x, y] : starts) {\n            if (stamp[x][y] != curStamp) return false;\n        }\n        return true;\n    }\n\n    bool zeroConnectedAfterRemoval(int r, int c) const {\n        if (cnt[0] <= 1) return true;\n\n        bool vis[MAXN][MAXN]{};\n        queue<pair<int, int>> q;\n\n        auto push = [&](int x, int y) {\n            if (!inside(x, y)) return;\n            if (x == r && y == c) return;\n            if (g[x][y] != 0) return;\n            if (vis[x][y]) return;\n            vis[x][y] = true;\n            q.push({x, y});\n        };\n\n        for (int i = 0; i < n; i++) {\n            push(i, 0);\n            push(i, n - 1);\n            push(0, i);\n            push(n - 1, i);\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dr[k], ny = y + dc[k];\n                push(nx, ny);\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (i == r && j == c) continue;\n                if (g[i][j] == 0 && !vis[i][j]) return false;\n            }\n        }\n        return true;\n    }\n\n    struct Delta {\n        int a, b, d;\n    };\n\n    void addDelta(vector<Delta> &ds, int a, int b, int d) const {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n\n        for (auto &x : ds) {\n            if (x.a == a && x.b == b) {\n                x.d += d;\n                return;\n            }\n        }\n        ds.push_back({a, b, d});\n    }\n\n    vector<Delta> makeDelta(int r, int c, int to) const {\n        vector<Delta> ds;\n        int from = g[r][c];\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n\n            int nb = 0;\n            if (inside(nr, nc)) nb = g[nr][nc];\n\n            addDelta(ds, from, nb, -1);\n            addDelta(ds, to, nb, +1);\n        }\n\n        return ds;\n    }\n\n    bool touchesColor(int r, int c, int col) const {\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) return true;\n        }\n        return false;\n    }\n\n    bool validChange(int r, int c, int to) {\n        int from = g[r][c];\n        if (from == to) return false;\n\n        if (from != 0 && cnt[from] <= 1) return false;\n\n        if (to == 0) {\n            if (from == 0) return false;\n            if (!adjacentZeroOrOutside(r, c)) return false;\n        } else {\n            if (!touchesColor(r, c, to)) return false;\n        }\n\n        if (from == 0) {\n            if (!zeroConnectedAfterRemoval(r, c)) return false;\n        } else {\n            if (!oldColorConnectedAfterRemoval(r, c, from)) return false;\n        }\n\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            int now = edgeCnt[x.a][x.b] + x.d;\n\n            if (allowedAdj[x.a][x.b]) {\n                if (now <= 0) return false;\n            } else {\n                if (now != 0) return false;\n            }\n        }\n\n        return true;\n    }\n\n    void applyChange(int r, int c, int to) {\n        int from = g[r][c];\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            edgeCnt[x.a][x.b] += x.d;\n        }\n\n        cnt[from]--;\n        cnt[to]++;\n        g[r][c] = to;\n    }\n\n    vector<int> computeDistanceToZero() const {\n        vector<int> dist(n * n, INF);\n        queue<int> q;\n\n        auto id = [&](int r, int c) {\n            return r * n + c;\n        };\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int v = id(i, j);\n\n                if (g[i][j] == 0) {\n                    dist[v] = 0;\n                    q.push(v);\n                } else if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    dist[v] = 1;\n                    q.push(v);\n                }\n            }\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            int r = v / n, c = v % n;\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!inside(nr, nc)) continue;\n\n                int nv = id(nr, nc);\n                if (dist[nv] > dist[v] + 1) {\n                    dist[nv] = dist[v] + 1;\n                    q.push(nv);\n                }\n            }\n        }\n\n        return dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    vector<vector<int>> original(n, vector<int>(n));\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> original[i][j];\n        }\n    }\n\n    memset(allowedAdj, 0, sizeof(allowedAdj));\n\n    auto addAllowed = [&](int a, int b) {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n        allowedAdj[a][b] = true;\n    };\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = original[i][j];\n\n            if (i == 0) addAllowed(c, 0);\n            if (i == n - 1) addAllowed(c, 0);\n            if (j == 0) addAllowed(c, 0);\n            if (j == n - 1) addAllowed(c, 0);\n\n            if (i + 1 < n) addAllowed(c, original[i + 1][j]);\n            if (j + 1 < n) addAllowed(c, original[i][j + 1]);\n        }\n    }\n\n    State st;\n    st.init(original);\n\n    vector<vector<int>> best = st.g;\n    int bestZero = st.cnt[0];\n\n    mt19937 rng(123456789);\n\n    auto startTime = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    vector<int> cells(n * n);\n    iota(cells.begin(), cells.end(), 0);\n\n    auto updateBest = [&]() {\n        if (st.cnt[0] > bestZero) {\n            bestZero = st.cnt[0];\n            best = st.g;\n        }\n    };\n\n    auto peelPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 255) == 0 && elapsed() > 1.88) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            if (st.g[r][c] == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n            }\n        }\n\n        updateBest();\n        return changed;\n    };\n\n    auto boundaryRecolorPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 700) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n                applied++;\n                continue;\n            }\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n                used[to] = true;\n\n                int sameAround = 0;\n                for (int t = 0; t < 4; t++) {\n                    int ar = r + dr[t], ac = c + dc[t];\n                    if (st.inside(ar, ac) && st.g[ar][ac] == to) sameAround++;\n                }\n\n                cand.push_back({-sameAround, to});\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto inwardRecolorPass = [&]() {\n        bool changed = false;\n\n        auto dist = st.computeDistanceToZero();\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        stable_sort(cells.begin(), cells.end(), [&](int a, int b) {\n            return dist[a] < dist[b];\n        });\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 700) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            int cd = dist[v];\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                int nd = dist[nr * n + nc];\n\n                if (nd <= cd) {\n                    used[to] = true;\n                    cand.push_back({nd, to});\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto randomRecolorPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 350) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<int> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                used[to] = true;\n                cand.push_back(to);\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            for (int to : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    int stagnant = 0;\n\n    while (elapsed() < 1.88) {\n        int beforeBest = bestZero;\n\n        bool any = false;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        any |= boundaryRecolorPass();\n        if (elapsed() > 1.88) break;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        any |= inwardRecolorPass();\n        if (elapsed() > 1.88) break;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        updateBest();\n\n        if (bestZero == beforeBest) stagnant++;\n        else stagnant = 0;\n\n        if (stagnant >= 2) {\n            randomRecolorPass();\n            peelPass();\n            stagnant = 0;\n        }\n\n        if (!any && elapsed() < 1.88) {\n            bool r = randomRecolorPass();\n            if (!r) break;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct QueryManager {\n    int N, D, Q;\n    int used = 0;\n\n    QueryManager(int N_, int D_, int Q_) : N(N_), D(D_), Q(Q_) {}\n\n    char query(const vector<int>& L, const vector<int>& R) {\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        string s;\n        if (!(cin >> s)) exit(0);\n\n        used++;\n        return s[0];\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query(L, R);\n    }\n};\n\nint ceil_log2_int(int x) {\n    int r = 0;\n    int p = 1;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\nstruct Solver {\n    int N, D, Q;\n    QueryManager qm;\n\n    vector<double> estWeight;\n    vector<int> order;\n\n    vector<vector<int>> bins;\n    vector<double> estSum;\n    vector<int> answer;\n\n    mt19937 rng;\n\n    Solver(int N_, int D_, int Q_)\n        : N(N_), D(D_), Q(Q_), qm(N_, D_, Q_),\n          rng(1234567u + 1009u * N_ + 917u * D_ + 37u * Q_) {}\n\n    bool heavier_single(int a, int b) {\n        char c = qm.query_single(a, b);\n        return c == '>';\n    }\n\n    vector<int> merge_sort_rec(const vector<int>& v) {\n        int n = (int)v.size();\n        if (n <= 1) return v;\n\n        int mid = n / 2;\n        vector<int> L(v.begin(), v.begin() + mid);\n        vector<int> R(v.begin() + mid, v.end());\n\n        L = merge_sort_rec(L);\n        R = merge_sort_rec(R);\n\n        vector<int> res;\n        res.reserve(n);\n\n        int i = 0, j = 0;\n        while (i < (int)L.size() && j < (int)R.size()) {\n            if (heavier_single(L[i], R[j])) res.push_back(L[i++]);\n            else res.push_back(R[j++]);\n        }\n        while (i < (int)L.size()) res.push_back(L[i++]);\n        while (j < (int)R.size()) res.push_back(R[j++]);\n\n        return res;\n    }\n\n    void exact_sort_items() {\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        order = merge_sort_rec(order);\n    }\n\n    void approximate_sort_items(int targetQueries) {\n        targetQueries = min(targetQueries, Q);\n\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        vector<int> gaps;\n        for (int g = N / 2; g >= 1; g /= 2) {\n            gaps.push_back(g);\n            if (g == 1) break;\n        }\n\n        while (qm.used < targetQueries) {\n            bool anySwap = false;\n\n            for (int gap : gaps) {\n                for (int i = gap; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - gap];\n                    int b = order[i];\n\n                    char c = qm.query_single(a, b);\n                    if (c == '<') {\n                        swap(order[i - gap], order[i]);\n                        anySwap = true;\n                    }\n                }\n                if (qm.used >= targetQueries) break;\n            }\n\n            if (!anySwap) {\n                for (int i = 1; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - 1];\n                    int b = order[i];\n\n                    char c = qm.query_single(a, b);\n                    if (c == '<') swap(order[i - 1], order[i]);\n                }\n            }\n        }\n    }\n\n    void normalize_est() {\n        double s = 0.0;\n        for (double x : estWeight) s += x;\n        if (s <= 0.0) return;\n        double mul = (double)N / s;\n        for (double& x : estWeight) x *= mul;\n    }\n\n    void make_estimated_weights() {\n        estWeight.assign(N, 0.0);\n\n        vector<double> H(N + 1, 0.0);\n        for (int i = 1; i <= N; i++) H[i] = H[i - 1] + 1.0 / i;\n\n        double T = (double)N / (double)D;\n        double A = 1.0 - exp(-T);\n\n        for (int k = 0; k < N; k++) {\n            int item = order[k];\n\n            double untr = H[N] - H[k];\n\n            double p = ((double)N - (double)k - 0.5) / (double)N;\n            p = min(1.0 - 1e-12, max(1e-12, p));\n            double u = p * A;\n            u = min(1.0 - 1e-12, max(1e-12, u));\n            double trunc = -log(1.0 - u);\n\n            double alpha = 0.25;\n            if (D * 5 >= N) alpha = 0.40;\n\n            estWeight[item] = (1.0 - alpha) * untr + alpha * trunc;\n        }\n\n        normalize_est();\n    }\n\n    int compare_bins_by_est(int a, int b) const {\n        const double eps = 1e-12;\n        if (estSum[a] + eps < estSum[b]) return -1;\n        if (estSum[a] > estSum[b] + eps) return 1;\n        return 0;\n    }\n\n    int compare_bins(int a, int b, bool allowQuery = true) {\n        if (a == b) return 0;\n\n        if (allowQuery && qm.used < Q) {\n            char c = qm.query(bins[a], bins[b]);\n            if (c == '<') return -1;\n            if (c == '>') return 1;\n            return 0;\n        } else {\n            return compare_bins_by_est(a, b);\n        }\n    }\n\n    vector<int> sort_bins_est(vector<int> v) {\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            if (fabs(estSum[a] - estSum[b]) > 1e-12) return estSum[a] < estSum[b];\n            return a < b;\n        });\n        return v;\n    }\n\n    vector<int> sort_bins_with_queries_if_possible(vector<int> v) {\n        int lg = max(1, ceil_log2_int((int)v.size()));\n        int estimatedCost = (int)v.size() * lg;\n\n        if (qm.used + estimatedCost > Q) return sort_bins_est(v);\n\n        vector<int> res;\n        res.reserve(v.size());\n\n        for (int b : v) {\n            int lo = 0, hi = (int)res.size();\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int cmp = compare_bins(b, res[mid], true);\n                if (cmp <= 0) hi = mid;\n                else lo = mid + 1;\n            }\n            res.insert(res.begin() + lo, b);\n        }\n        return res;\n    }\n\n    void build_partition() {\n        bins.assign(D, {});\n        estSum.assign(D, 0.0);\n        answer.assign(N, 0);\n\n        for (int i = 0; i < D; i++) {\n            int item = order[i];\n            bins[i].push_back(item);\n            estSum[i] += estWeight[item];\n            answer[item] = i;\n        }\n\n        vector<int> binOrder(D);\n        iota(binOrder.begin(), binOrder.end(), 0);\n\n        if (qm.used < Q && Q - qm.used > D)\n            binOrder = sort_bins_with_queries_if_possible(binOrder);\n        else\n            binOrder = sort_bins_est(binOrder);\n\n        for (int idx = D; idx < N; idx++) {\n            int item = order[idx];\n\n            int b = binOrder.front();\n            binOrder.erase(binOrder.begin());\n\n            bins[b].push_back(item);\n            estSum[b] += estWeight[item];\n            answer[item] = b;\n\n            int lo = 0, hi = (int)binOrder.size();\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int cmp = compare_bins(b, binOrder[mid], true);\n                if (cmp <= 0) hi = mid;\n                else lo = mid + 1;\n            }\n            binOrder.insert(binOrder.begin() + lo, b);\n        }\n    }\n\n    bool find_min_max_bins(int& mn, int& mx) {\n        if (qm.used + 2 * (D - 1) > Q) return false;\n\n        mn = 0;\n        mx = 0;\n\n        for (int b = 1; b < D; b++) {\n            int c1 = compare_bins(b, mn, true);\n            if (c1 < 0) mn = b;\n\n            int c2 = compare_bins(b, mx, true);\n            if (c2 > 0) mx = b;\n        }\n\n        return true;\n    }\n\n    void do_move(int from, int to, int x) {\n        auto it = find(bins[from].begin(), bins[from].end(), x);\n        if (it != bins[from].end()) bins[from].erase(it);\n\n        bins[to].push_back(x);\n        estSum[from] -= estWeight[x];\n        estSum[to] += estWeight[x];\n        answer[x] = to;\n    }\n\n    void do_swap(int a, int b, int x, int y) {\n        auto itx = find(bins[a].begin(), bins[a].end(), x);\n        auto ity = find(bins[b].begin(), bins[b].end(), y);\n\n        if (itx != bins[a].end()) *itx = y;\n        if (ity != bins[b].end()) *ity = x;\n\n        estSum[a] += estWeight[y] - estWeight[x];\n        estSum[b] += estWeight[x] - estWeight[y];\n\n        answer[x] = b;\n        answer[y] = a;\n    }\n\n    bool try_safe_move(int lo, int hi) {\n        if ((int)bins[hi].size() <= 1) return false;\n\n        double diff = max(0.0, estSum[hi] - estSum[lo]);\n        double ideal = diff / 2.0;\n\n        vector<int> cand = bins[hi];\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            double da = fabs(estWeight[a] - ideal);\n            double db = fabs(estWeight[b] - ideal);\n            if (fabs(da - db) > 1e-12) return da < db;\n            return estWeight[a] > estWeight[b];\n        });\n\n        for (int x : cand) {\n            if (qm.used >= Q) break;\n            if ((int)bins[hi].size() <= 1) break;\n\n            vector<int> leftSet;\n            leftSet.reserve(bins[hi].size() - 1);\n            for (int y : bins[hi]) {\n                if (y != x) leftSet.push_back(y);\n            }\n\n            if (leftSet.empty()) continue;\n\n            // New safe condition:\n            // Let actual difference be Delta = sum(hi)-sum(lo).\n            // Moving x improves pair squared error iff x < Delta.\n            // Query (hi-x) > lo exactly verifies Delta > x.\n            char c = qm.query(leftSet, bins[lo]);\n\n            if (c == '>') {\n                do_move(hi, lo, x);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    bool try_safe_swap(int lo, int hi) {\n        if (qm.used + 2 > Q) return false;\n        if (bins[hi].empty() || bins[lo].empty()) return false;\n        if ((int)bins[hi].size() <= 1) return false;\n        if ((int)bins[lo].size() <= 1) return false;\n\n        vector<int> heavy = bins[hi];\n        vector<int> light = bins[lo];\n\n        sort(heavy.begin(), heavy.end(), [&](int a, int b) {\n            return estWeight[a] > estWeight[b];\n        });\n        sort(light.begin(), light.end(), [&](int a, int b) {\n            return estWeight[a] < estWeight[b];\n        });\n\n        int limitH = min<int>(6, heavy.size());\n        int limitL = min<int>(6, light.size());\n\n        struct Cand {\n            double score;\n            int x, y;\n        };\n        vector<Cand> cands;\n\n        double diff = max(0.0, estSum[hi] - estSum[lo]);\n        double ideal = diff / 2.0;\n\n        for (int i = 0; i < limitH; i++) {\n            for (int j = 0; j < limitL; j++) {\n                int x = heavy[i];\n                int y = light[j];\n                double delta = estWeight[x] - estWeight[y];\n                if (delta <= 1e-12) continue;\n\n                double score = fabs(delta - ideal);\n                cands.push_back({score, x, y});\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            return a.score < b.score;\n        });\n\n        for (auto [score, x, y] : cands) {\n            if (qm.used + 2 > Q) break;\n\n            // Need actual x > y.\n            char cy = qm.query_single(x, y);\n            if (cy != '>') continue;\n\n            vector<int> Lset, Rset;\n\n            // Verify Delta > x-y by comparing hi-x and lo-y.\n            for (int v : bins[hi]) {\n                if (v != x) Lset.push_back(v);\n            }\n            for (int v : bins[lo]) {\n                if (v != y) Rset.push_back(v);\n            }\n\n            if (Lset.empty() || Rset.empty()) continue;\n\n            char c = qm.query(Lset, Rset);\n\n            if (c == '>') {\n                do_swap(hi, lo, x, y);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    void local_improve() {\n        int iteration = 0;\n\n        while (qm.used < Q && iteration < 10000) {\n            iteration++;\n\n            int lo, hi;\n            if (!find_min_max_bins(lo, hi)) break;\n            if (lo == hi) break;\n\n            bool changed = false;\n\n            if (!changed && (int)bins[hi].size() > 1) {\n                changed = try_safe_move(lo, hi);\n            }\n\n            if (!changed && qm.used + 2 <= Q) {\n                changed = try_safe_swap(lo, hi);\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void spend_remaining_queries() {\n        while (qm.used < Q) {\n            qm.query_single(0, 1);\n        }\n    }\n\n    void output_answer() {\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << answer[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n\n    void solve() {\n        int lgN = ceil_log2_int(N);\n        int mergeWorst = N * lgN - (1 << lgN) + 1;\n        mergeWorst = max(0, mergeWorst);\n\n        int lgD = max(1, ceil_log2_int(D));\n        int constructionCostApprox = max(0, N - D) * lgD + D * lgD;\n\n        bool useExactSort = false;\n        int neededAfterSort = max(D, constructionCostApprox / 3);\n        if (Q >= mergeWorst + neededAfterSort) useExactSort = true;\n\n        if (useExactSort) {\n            exact_sort_items();\n        } else {\n            int reserve = min(constructionCostApprox, (int)(Q * 0.40));\n            int target = max(0, Q - reserve);\n            approximate_sort_items(target);\n        }\n\n        make_estimated_weights();\n\n        build_partition();\n\n        if (qm.used < Q) {\n            local_improve();\n        }\n\n        spend_remaining_queries();\n\n        output_answer();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    cin >> N >> D >> Q;\n\n    Solver solver(N, D, Q);\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int v, to;\n};\n\nstruct Result {\n    vector<Op> ops;\n    int energy = INT_MAX;\n    bool valid = false;\n};\n\nstatic const int N = 200;\nstatic const int M = 10;\nstatic const int INF_LABEL = 1000;\n\nint seg_max(const vector<int>& a) {\n    int mx = 0;\n    for (int x : a) mx = max(mx, x);\n    return mx;\n}\n\nint stack_min_value(const vector<int>& st) {\n    if (st.empty()) return INF_LABEL;\n    int mn = INF_LABEL;\n    for (int x : st) mn = min(mn, x);\n    return mn;\n}\n\nint stack_badness(const vector<int>& st) {\n    int bad = 0;\n    for (int i = 1; i < (int)st.size(); i++) {\n        if (st[i - 1] < st[i]) {\n            bad += st[i] - st[i - 1];\n        }\n    }\n    return bad;\n}\n\nbool has_good_destination_top(const vector<vector<int>>& stacks, int src, const vector<int>& vals) {\n    int mx = seg_max(vals);\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n        if (stacks[d].empty()) return true;\n        if (stacks[d].back() > mx) return true;\n    }\n    return false;\n}\n\nint choose_destination(\n    const vector<vector<int>>& stacks,\n    int src,\n    const vector<int>& vals,\n    int policy,\n    mt19937& rng,\n    double noise_amp\n) {\n    int mx = seg_max(vals);\n    int len = (int)vals.size();\n\n    uniform_real_distribution<double> dist(0.0, noise_amp);\n\n    int best = -1;\n    double best_score = 1e100;\n\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n\n        int h = (int)stacks[d].size();\n        bool empty = stacks[d].empty();\n\n        int top = empty ? INF_LABEL : stacks[d].back();\n        int mn = stack_min_value(stacks[d]);\n\n        bool good_top = empty || top > mx;\n        bool good_all = empty || mn > mx;\n\n        double score = 0.0;\n\n        switch (policy % 14) {\n            case 0:\n                // Patience-sorting style: smallest top that can accept the block.\n                if (good_top) score = top * 100.0 + h;\n                else score = 1e6 - top * 100.0 + h;\n                break;\n\n            case 1:\n                // Prefer low height, but still prioritize good destinations.\n                score = (good_top ? 0.0 : 100000.0) + h * 100.0 + top;\n                break;\n\n            case 2:\n                // Stronger: prefer stacks whose all boxes are larger.\n                if (good_all) score = mn * 100.0 + h;\n                else if (good_top) score = 200000.0 + top * 100.0 + h;\n                else score = 1e6 - mn * 50.0 - top * 10.0 + h;\n                break;\n\n            case 3:\n                // Prefer smallest positive gap.\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0;\n                else score = 1e6 + (mx - top) * 100.0 + h;\n                break;\n\n            case 4:\n                // Height balancing.\n                score = h * 100.0 + (good_top ? 0.0 : 50000.0) + top;\n                break;\n\n            case 5:\n                // Prefer taller good stacks.\n                if (good_top) score = top * 100.0 - h * 20.0;\n                else score = 1e6 - top * 100.0 - h * 10.0;\n                break;\n\n            case 6:\n                // Prefer large top labels.\n                score = (good_top ? 0.0 : 500000.0) - top * 100.0 + h * 10.0;\n                break;\n\n            case 7:\n                // Prefer destination with large minimum.\n                score = (good_top ? 0.0 : 300000.0) - mn * 100.0 - top * 10.0 + h;\n                break;\n\n            case 8:\n                // Explicit gap minimization.\n                if (good_top) score = (top - mx) * 200.0 + h;\n                else score = 1e6 + (mx - top) * 200.0 + h;\n                break;\n\n            case 9:\n                // Consider current disorder of destination stack.\n                if (good_top) score = top * 100.0 + h * 20.0 + stack_badness(stacks[d]) * 2.0;\n                else score = 1e6 - top * 100.0 + h * 20.0 + stack_badness(stacks[d]) * 2.0;\n                break;\n\n            case 10:\n                // Boundary-violation penalty.\n                if (empty) {\n                    score = 50000.0 + h;\n                } else {\n                    int violation = max(0, mx - top);\n                    score = violation * 10000.0 + (good_top ? top : -top) * 10.0 + h;\n                }\n                break;\n\n            case 11:\n                // Avoid empty stacks unless useful.\n                if (empty) {\n                    score = good_top ? 150000.0 : 1000000.0;\n                } else if (good_top) {\n                    score = (top - mx) * 100.0 + h * 3.0;\n                } else {\n                    score = 1e6 - top * 200.0 + h;\n                }\n                break;\n\n            case 12:\n                // Slightly prefer putting larger blocks on safer stacks.\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0 - len * 20.0;\n                else score = 1e6 + (mx - top) * 100.0 + h - len * 20.0;\n                break;\n\n            case 13:\n                // Conservative: minimize added adjacent violation.\n                if (empty) score = 10000.0 + h;\n                else {\n                    int add = max(0, mx - top);\n                    score = add * 20000.0 + abs(top - mx) * 20.0 + h;\n                }\n                break;\n        }\n\n        if (noise_amp > 0.0) score += dist(rng);\n\n        if (score < best_score) {\n            best_score = score;\n            best = d;\n        }\n    }\n\n    return best;\n}\n\nint choose_left_index(\n    const vector<vector<int>>& stacks,\n    int s,\n    int pos,\n    int split_mode\n) {\n    const auto& st = stacks[s];\n    int h = (int)st.size();\n\n    if (split_mode == 0) {\n        return pos + 1; // whole suffix above target\n    }\n\n    if (split_mode == 2) {\n        return h - 1; // single box\n    }\n\n    int run_start = h - 1;\n    while (run_start - 1 > pos && st[run_start - 1] > st[run_start]) {\n        run_start--;\n    }\n\n    if (split_mode == 1) {\n        return run_start; // maximal decreasing top-run\n    }\n\n    auto suffix_vals = [&](int l) {\n        return vector<int>(st.begin() + l, st.end());\n    };\n\n    if (split_mode == 3) {\n        // Longest suffix of the decreasing run that can be safely placed.\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            if (has_good_destination_top(stacks, s, vals)) return l;\n        }\n        return run_start;\n    }\n\n    if (split_mode == 4) {\n        // Same as mode 3, but if impossible, move the whole suffix.\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            if (has_good_destination_top(stacks, s, vals)) return l;\n        }\n        return pos + 1;\n    }\n\n    if (split_mode == 5) {\n        // Prefer safe long suffix, but be more willing to split.\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            bool good = has_good_destination_top(stacks, s, vals);\n            int len = h - l;\n            int mx = seg_max(vals);\n\n            double score = (good ? 0.0 : 100000.0 + mx * 10.0) - len * 120.0;\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 6) {\n        // If maximal run is unsafe, try a single top box.\n        vector<int> vals = suffix_vals(run_start);\n        if (has_good_destination_top(stacks, s, vals)) return run_start;\n\n        vector<int> one = suffix_vals(h - 1);\n        if (has_good_destination_top(stacks, s, one)) return h - 1;\n\n        return run_start;\n    }\n\n    return run_start;\n}\n\nResult simulate(\n    const vector<vector<int>>& initial,\n    int split_mode,\n    int policy,\n    uint32_t seed,\n    double noise_amp\n) {\n    mt19937 rng(seed);\n\n    vector<vector<int>> stacks = initial;\n    vector<Op> ops;\n    int energy = 0;\n\n    for (int cur = 1; cur <= N; cur++) {\n        int s = -1, pos = -1;\n\n        for (int i = 0; i < M; i++) {\n            for (int j = 0; j < (int)stacks[i].size(); j++) {\n                if (stacks[i][j] == cur) {\n                    s = i;\n                    pos = j;\n                }\n            }\n        }\n\n        if (s == -1) return Result{};\n\n        while (pos != (int)stacks[s].size() - 1) {\n            if ((int)ops.size() >= 5000) return Result{};\n\n            int h = (int)stacks[s].size();\n\n            int l;\n            if ((int)ops.size() > 4600) {\n                l = pos + 1;\n            } else {\n                l = choose_left_index(stacks, s, pos, split_mode);\n            }\n\n            if (l <= pos || l >= h) return Result{};\n\n            vector<int> vals(stacks[s].begin() + l, stacks[s].end());\n\n            int d = choose_destination(stacks, s, vals, policy, rng, noise_amp);\n            if (d < 0 || d == s) return Result{};\n\n            ops.push_back({vals.front(), d + 1});\n            energy += (int)vals.size() + 1;\n\n            stacks[s].erase(stacks[s].begin() + l, stacks[s].end());\n            stacks[d].insert(stacks[d].end(), vals.begin(), vals.end());\n\n            if ((int)ops.size() > 5000) return Result{};\n        }\n\n        if (stacks[s].empty() || stacks[s].back() != cur) {\n            return Result{};\n        }\n\n        ops.push_back({cur, 0});\n        stacks[s].pop_back();\n\n        if ((int)ops.size() > 5000) return Result{};\n    }\n\n    Result res;\n    res.ops = move(ops);\n    res.energy = energy;\n    res.valid = true;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> initial(M);\n\n    for (int i = 0; i < M; i++) {\n        initial[i].resize(N / M);\n        for (int j = 0; j < N / M; j++) {\n            cin >> initial[i][j];\n        }\n    }\n\n    uint32_t base_seed = 123456789u;\n    for (int i = 0; i < M; i++) {\n        for (int x : initial[i]) {\n            base_seed = base_seed * 1000003u + (uint32_t)x;\n        }\n    }\n\n    Result best;\n\n    auto try_result = [&](const Result& r) {\n        if (!r.valid) return;\n        if ((int)r.ops.size() > 5000) return;\n\n        if (!best.valid ||\n            r.energy < best.energy ||\n            (r.energy == best.energy && r.ops.size() < best.ops.size())) {\n            best = r;\n        }\n    };\n\n    auto start_time = chrono::steady_clock::now();\n\n    // Deterministic variants.\n    for (int split = 0; split <= 6; split++) {\n        for (int policy = 0; policy < 14; policy++) {\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + split * 1009u + policy * 9176u,\n                0.0\n            );\n            try_result(r);\n        }\n    }\n\n    // Additional randomized search under time budget.\n    mt19937 rng(base_seed ^ 0x9e3779b9u);\n\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.80) break;\n\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 10) split = 0;\n        else if (sr < 35) split = 1;\n        else if (sr < 45) split = 2;\n        else if (sr < 70) split = 3;\n        else if (sr < 82) split = 4;\n        else if (sr < 94) split = 5;\n        else split = 6;\n\n        int policy = rng() % 14;\n\n        double noise;\n        int nr = rng() % 7;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 3.0;\n        else if (nr == 2) noise = 10.0;\n        else if (nr == 3) noise = 30.0;\n        else if (nr == 4) noise = 100.0;\n        else if (nr == 5) noise = 400.0;\n        else noise = 1500.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 1000003u + (uint32_t)iter * 17777u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    // Fallback.\n    if (!best.valid) {\n        best = simulate(initial, 0, 0, base_seed, 0.0);\n    }\n\n    for (const auto& op : best.ops) {\n        cout << op.v << ' ' << op.to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const uint16_t INF16 = 65535;\n\nstruct Edge {\n    int to;\n    char c;\n};\n\nstruct XorShift {\n    uint32_t x = 2463534242u;\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    double real01() {\n        return (next() >> 8) * (1.0 / 16777216.0);\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    int N;\n    cin >> N;\n\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    int V = N * N;\n    vector<int> dirt(V);\n    long long sumD = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> dirt[i * N + j];\n            sumD += dirt[i * N + j];\n        }\n    }\n\n    double avgD = (double)sumD / V;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    vector<vector<Edge>> g(V);\n\n    auto add_edge = [&](int a, int b, char c1, char c2) {\n        g[a].push_back({b, c1});\n        g[b].push_back({a, c2});\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (i + 1 < N && h[i][j] == '0') {\n                add_edge(id(i, j), id(i + 1, j), 'D', 'U');\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                add_edge(id(i, j), id(i, j + 1), 'R', 'L');\n            }\n        }\n    }\n\n    auto rev_dir = [&](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    // Guaranteed legal fallback route.\n    auto make_fallback_dfs = [&]() {\n        vector<char> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n            for (const auto &e : g[cur]) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n                    route.push_back(rev_dir(e.c));\n                }\n            }\n        };\n\n        dfs(0);\n        return route;\n    };\n\n    string fallbackRoute = make_fallback_dfs();\n\n    auto legal_route = [&](const string &route) -> bool {\n        if (route.empty() || route.size() > 100000) return false;\n\n        vector<char> vis(V, 0);\n        int cur = 0;\n        vis[0] = 1;\n\n        for (char c : route) {\n            bool ok = false;\n            for (const auto &e : g[cur]) {\n                if (e.c == c) {\n                    cur = e.to;\n                    ok = true;\n                    break;\n                }\n            }\n            if (!ok) return false;\n            vis[cur] = 1;\n        }\n\n        if (cur != 0) return false;\n\n        for (int i = 0; i < V; i++) {\n            if (!vis[i]) return false;\n        }\n\n        return true;\n    };\n\n    // All-pairs shortest paths.\n    vector<uint16_t> dist((size_t)V * V, INF16);\n    vector<int> que(V);\n\n    for (int s = 0; s < V; s++) {\n        uint16_t *ds = &dist[(size_t)s * V];\n        int head = 0, tail = 0;\n        ds[s] = 0;\n        que[tail++] = s;\n\n        while (head < tail) {\n            int cur = que[head++];\n            uint16_t nd = ds[cur] + 1;\n\n            for (const auto &e : g[cur]) {\n                if (ds[e.to] == INF16) {\n                    ds[e.to] = nd;\n                    que[tail++] = e.to;\n                }\n            }\n        }\n    }\n\n    int maxDist = 0;\n    for (int i = 0; i < V; i++) {\n        for (int j = 0; j < V; j++) {\n            maxDist = max(maxDist, (int)dist[(size_t)i * V + j]);\n        }\n    }\n\n    vector<double> alphas = {1.0, 1.35, 1.7, 2.1, 2.7, 3.5};\n    vector<vector<double>> denom(alphas.size(), vector<double>(maxDist + 3));\n\n    for (int a = 0; a < (int)alphas.size(); a++) {\n        for (int d = 0; d <= maxDist + 2; d++) {\n            denom[a][d] = pow((double)max(1, d), alphas[a]);\n        }\n    }\n\n    auto score_route = [&](const string &route) -> long double {\n        int L = (int)route.size();\n        if (L <= 0 || L > 100000) return 1e100L;\n\n        vector<int> first(V, -1), prev(V, -1);\n        vector<long long> gapSum(V, 0);\n\n        auto visit = [&](int x, int t) {\n            if (first[x] == -1) {\n                first[x] = prev[x] = t;\n            } else {\n                long long gap = t - prev[x];\n                gapSum[x] += gap * (gap - 1);\n                prev[x] = t;\n            }\n        };\n\n        int cur = 0;\n        visit(0, 0);\n\n        for (int t = 1; t <= L; t++) {\n            char c = route[t - 1];\n            bool ok = false;\n\n            for (const auto &e : g[cur]) {\n                if (e.c == c) {\n                    cur = e.to;\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return 1e100L;\n\n            if (t < L) {\n                visit(cur, t);\n            }\n        }\n\n        if (cur != 0) return 1e100L;\n\n        long double total = 0.0L;\n\n        for (int x = 0; x < V; x++) {\n            if (first[x] == -1) return 1e100L;\n\n            long long gap = L - prev[x] + first[x];\n            long long s = gapSum[x] + gap * (gap - 1);\n\n            total += (long double)dirt[x] * (long double)s / (2.0L * L);\n        }\n\n        return total;\n    };\n\n    string bestRoute = fallbackRoute;\n    long double bestScore = score_route(bestRoute);\n\n    auto consider = [&](const string &route) {\n        if (route.empty() || route.size() > 100000) return;\n        if (!legal_route(route)) return;\n\n        long double sc = score_route(route);\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n        }\n    };\n\n    XorShift rng;\n\n    // ------------------------------------------------------------------\n    // DFS candidates.\n    // ------------------------------------------------------------------\n    auto make_dfs_route = [&](int mode, double rndWeight) {\n        vector<char> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n\n            vector<Edge> es = g[cur];\n\n            if (mode == 1) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] > dirt[b.to];\n                });\n            } else if (mode == 2) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] < dirt[b.to];\n                });\n            } else if (mode == 3) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return a.c < b.c;\n                });\n            } else if (mode == 4) {\n                // Safe randomized ordering: random keys are generated before sorting.\n                vector<pair<double, Edge>> keyed;\n                keyed.reserve(es.size());\n\n                for (const auto &e : es) {\n                    double key = log(1.0 + dirt[e.to]) + rndWeight * rng.real01();\n                    keyed.push_back({-key, e});\n                }\n\n                sort(keyed.begin(), keyed.end(), [](const auto &a, const auto &b) {\n                    return a.first < b.first;\n                });\n\n                es.clear();\n                for (const auto &p : keyed) es.push_back(p.second);\n            }\n\n            for (const auto &e : es) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n                    route.push_back(rev_dir(e.c));\n                }\n            }\n        };\n\n        dfs(0);\n        return route;\n    };\n\n    for (int mode = 0; mode < 4; mode++) {\n        consider(make_dfs_route(mode, 0.0));\n    }\n\n    for (int rep = 0; rep < 60 && elapsed() < 0.35; rep++) {\n        consider(make_dfs_route(4, 0.5 + 4.0 * rng.real01()));\n    }\n\n    // ------------------------------------------------------------------\n    // Shortest path appender.\n    // ------------------------------------------------------------------\n    auto append_path = [&](string &route,\n                           int &cur,\n                           int target,\n                           int &t,\n                           vector<int> &last,\n                           vector<char> &visited,\n                           int &visitedCnt) {\n        while (cur != target) {\n            uint16_t dc = dist[(size_t)cur * V + target];\n\n            int bestNext = -1;\n            char bestChar = '?';\n            double bestVal = -1e100;\n\n            for (const auto &e : g[cur]) {\n                if (dist[(size_t)e.to * V + target] + 1 == dc) {\n                    double val = 0.0;\n\n                    if (!visited[e.to]) {\n                        val += avgD * 1000000.0;\n                    }\n\n                    val += (double)dirt[e.to] * (double)(t - last[e.to] + 1);\n                    val += 0.001 * rng.real01();\n\n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestNext = e.to;\n                        bestChar = e.c;\n                    }\n                }\n            }\n\n            if (bestNext == -1) return;\n\n            route.push_back(bestChar);\n            cur = bestNext;\n            t++;\n\n            last[cur] = t;\n\n            if (!visited[cur]) {\n                visited[cur] = 1;\n                visitedCnt++;\n            }\n\n            if ((int)route.size() > 100000) return;\n        }\n    };\n\n    // ------------------------------------------------------------------\n    // Coverage first, then patrol candidates.\n    // ------------------------------------------------------------------\n    auto generate_cover_then_patrol = [&](int cap,\n                                          int covAlphaIdx,\n                                          int patAlphaIdx,\n                                          double coverBiasMul,\n                                          bool noise) {\n        string route;\n        route.reserve(min(100000, max(cap, 2 * V)));\n\n        vector<int> last(V, 0);\n        vector<char> visited(V, 0);\n\n        int visitedCnt = 1;\n        int cur = 0;\n        int t = 0;\n\n        visited[0] = 1;\n\n        double coverBias = avgD * coverBiasMul;\n\n        while (visitedCnt < V && (int)route.size() <= 100000) {\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                if (visited[x]) continue;\n\n                int ds = dist[(size_t)cur * V + x];\n                double val = (coverBias + dirt[x]) / denom[covAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n\n            if ((int)route.size() > 100000) break;\n        }\n\n        int limit = cap;\n        if (limit <= 0) limit = (int)route.size();\n        limit = min(limit, 100000);\n\n        int loop = 0;\n\n        while ((int)route.size() + dist[(size_t)cur * V + 0] < limit &&\n               (int)route.size() < 100000) {\n            if ((++loop & 255) == 0 && elapsed() > 1.82) break;\n\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                int ds = dist[(size_t)cur * V + x];\n                if (ds == 0) continue;\n\n                int ret = dist[(size_t)x * V + 0];\n\n                if ((int)route.size() + ds + ret > limit) continue;\n\n                int age = t - last[x];\n\n                double val = (double)dirt[x] * (age + 1) / denom[patAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n        }\n\n        append_path(route, cur, 0, t, last, visited, visitedCnt);\n\n        return route;\n    };\n\n    // ------------------------------------------------------------------\n    // Mixed candidates: sometimes revisit before complete coverage.\n    // ------------------------------------------------------------------\n    auto generate_mixed = [&](int cap,\n                              int alphaIdx,\n                              double unvisitedWeight,\n                              int betaMode,\n                              double forceRatio,\n                              int minPatrolDist,\n                              bool noise) {\n        string route;\n        route.reserve(min(100000, max(cap, 2 * V)));\n\n        vector<int> last(V, 0);\n        vector<char> visited(V, 0);\n\n        int visitedCnt = 1;\n        int cur = 0;\n        int t = 0;\n\n        visited[0] = 1;\n\n        int hardLimit = min(100000, cap);\n        if (hardLimit <= 0) hardLimit = 100000;\n\n        int loop = 0;\n\n        while ((int)route.size() < hardLimit) {\n            if ((++loop & 127) == 0 && elapsed() > 1.84) break;\n\n            int retNow = dist[(size_t)cur * V + 0];\n            if ((int)route.size() + retNow >= hardLimit) break;\n\n            bool forceCover = false;\n            if (visitedCnt < V && (int)route.size() > (int)(hardLimit * forceRatio)) {\n                forceCover = true;\n            }\n\n            int target = -1;\n            double bestVal = -1e100;\n\n            for (int x = 0; x < V; x++) {\n                if (x == cur) continue;\n\n                if (forceCover && visited[x]) continue;\n\n                int ds = dist[(size_t)cur * V + x];\n                int ret = dist[(size_t)x * V + 0];\n\n                if ((int)route.size() + ds + ret > hardLimit) continue;\n\n                if (visitedCnt == V && ds < minPatrolDist) continue;\n\n                int age = t - last[x];\n                double a = age + ds + 1.0;\n\n                double val;\n\n                if (betaMode == 2) {\n                    val = (double)dirt[x] * a * a / denom[alphaIdx][ds + 1];\n                } else {\n                    val = (double)dirt[x] * a / denom[alphaIdx][ds + 1];\n                }\n\n                if (!visited[x]) {\n                    double remainRatio = (double)V / max(1, V - visitedCnt);\n                    val += unvisitedWeight * avgD * remainRatio * (t + 50.0) / denom[alphaIdx][ds + 1];\n                }\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) {\n                if (visitedCnt == V && minPatrolDist > 1) {\n                    minPatrolDist = 1;\n                    continue;\n                }\n                break;\n            }\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n\n            if ((int)route.size() > 100000) break;\n        }\n\n        append_path(route, cur, 0, t, last, visited, visitedCnt);\n\n        return route;\n    };\n\n    vector<int> caps = {\n        2 * V,\n        3 * V,\n        4 * V,\n        5 * V,\n        7 * V,\n        10 * V,\n        14 * V,\n        20000,\n        30000,\n        45000,\n        65000,\n        100000\n    };\n\n    for (int &x : caps) {\n        x = min(100000, max(1, x));\n    }\n\n    sort(caps.begin(), caps.end());\n    caps.erase(unique(caps.begin(), caps.end()), caps.end());\n\n    struct CP {\n        int cap;\n        int ca;\n        int pa;\n        double bias;\n        bool noise;\n    };\n\n    vector<CP> cps;\n\n    cps.push_back({0, 4, 1, 20.0, false});\n    cps.push_back({0, 3, 1, 20.0, false});\n    cps.push_back({0, 3, 1, 5.0, false});\n    cps.push_back({0, 2, 1, 0.0, false});\n\n    for (int cap : caps) {\n        cps.push_back({cap, 3, 1, 10.0, false});\n        cps.push_back({cap, 2, 1, 5.0, false});\n    }\n\n    cps.push_back({30000, 3, 0, 10.0, false});\n    cps.push_back({60000, 3, 0, 10.0, false});\n    cps.push_back({100000, 3, 0, 10.0, false});\n    cps.push_back({60000, 3, 1, 10.0, true});\n    cps.push_back({100000, 3, 1, 10.0, true});\n\n    for (const auto &p : cps) {\n        if (elapsed() > 1.70) break;\n        consider(generate_cover_then_patrol(p.cap, p.ca, p.pa, p.bias, p.noise));\n    }\n\n    struct MP {\n        int cap;\n        int alpha;\n        double uw;\n        int beta;\n        double forceRatio;\n        int minDist;\n        bool noise;\n    };\n\n    vector<MP> mps;\n\n    for (int cap : caps) {\n        mps.push_back({cap, 2, 25.0, 1, 0.55, 3, false});\n        mps.push_back({cap, 2, 40.0, 1, 0.65, 4, false});\n    }\n\n    mps.push_back({30000, 1, 20.0, 2, 0.60, 3, false});\n    mps.push_back({45000, 1, 20.0, 2, 0.60, 4, false});\n    mps.push_back({65000, 1, 20.0, 2, 0.65, 5, false});\n    mps.push_back({100000, 1, 15.0, 2, 0.70, 6, false});\n\n    mps.push_back({30000, 2, 30.0, 1, 0.60, 3, true});\n    mps.push_back({65000, 2, 30.0, 1, 0.65, 4, true});\n    mps.push_back({100000, 2, 25.0, 1, 0.70, 5, true});\n\n    for (const auto &p : mps) {\n        if (elapsed() > 1.86) break;\n        consider(generate_mixed(p.cap, p.alpha, p.uw, p.beta, p.forceRatio, p.minDist, p.noise));\n    }\n\n    int extra = 0;\n    while (elapsed() < 1.90 && extra < 20) {\n        int cap = caps[rng.randint((int)caps.size())];\n        int ca = 2 + rng.randint(3);\n        int pa = rng.randint(3);\n        double bias = 2.0 + 25.0 * rng.real01();\n\n        consider(generate_cover_then_patrol(cap, ca, pa, bias, true));\n        extra++;\n    }\n\n    // Absolute final safety.\n    if (!legal_route(bestRoute)) {\n        bestRoute = fallbackRoute;\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\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 nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nint N, M;\nint si, sj;\nvector<string> Agrid;\nvector<string> t;\nvector<pair<int,int>> occ[26];\nint mindist_ch[26][26];\n\nconst int POW5 = 26 * 26 * 26 * 26 * 26;\nvector<int> codeId;\n\nchrono::steady_clock::time_point timeStart;\n\ndouble elapsedTime() {\n    return chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n}\n\nint manhattan(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nint wordCode(const string& s) {\n    int c = 0;\n    for (char ch : s) c = c * 26 + (ch - 'A');\n    return c;\n}\n\nint overlap_word(const string& a, const string& b) {\n    for (int k = 4; k >= 1; --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) return k;\n    }\n    return 0;\n}\n\nint overlap_suffix_string(const string& s, const string& w) {\n    int lim = min<int>(4, s.size());\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (s[(int)s.size() - k + i] != w[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nint typingCostOnly(const string& s) {\n    const int INF = 1e9;\n    vector<int> dp_prev, dp_cur;\n\n    for (int pos = 0; pos < (int)s.size(); ++pos) {\n        int c = s[pos] - 'A';\n        int C = (int)occ[c].size();\n\n        dp_cur.assign(C, INF);\n\n        if (pos == 0) {\n            pair<int,int> start = {si, sj};\n            for (int i = 0; i < C; ++i) {\n                dp_cur[i] = manhattan(start, occ[c][i]) + 1;\n            }\n        } else {\n            int pc = s[pos - 1] - 'A';\n            int P = (int)occ[pc].size();\n\n            for (int i = 0; i < C; ++i) {\n                int best = INF;\n                for (int j = 0; j < P; ++j) {\n                    best = min(best, dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1);\n                }\n                dp_cur[i] = best;\n            }\n        }\n\n        dp_prev.swap(dp_cur);\n    }\n\n    return *min_element(dp_prev.begin(), dp_prev.end());\n}\n\nint segmentCostFromChar(int prevChar, const string& w, int from) {\n    const int INF = 1e9;\n\n    vector<int> dp_prev((int)occ[prevChar].size(), 0), dp_cur;\n\n    int pc = prevChar;\n\n    for (int k = from; k < 5; ++k) {\n        int c = w[k] - 'A';\n        int C = (int)occ[c].size();\n        int P = (int)occ[pc].size();\n\n        dp_cur.assign(C, INF);\n\n        for (int i = 0; i < C; ++i) {\n            int best = INF;\n            for (int j = 0; j < P; ++j) {\n                best = min(best, dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1);\n            }\n            dp_cur[i] = best;\n        }\n\n        dp_prev.swap(dp_cur);\n        pc = c;\n    }\n\n    return *min_element(dp_prev.begin(), dp_prev.end());\n}\n\nlong long pathCost(const vector<int>& p, const vector<vector<int>>& W, const vector<int>& startCost) {\n    long long c = startCost[p[0]];\n    for (int i = 0; i + 1 < (int)p.size(); ++i) c += W[p[i]][p[i + 1]];\n    return c;\n}\n\nlong long edgeContrib(const vector<int>& p, int idx, const vector<vector<int>>& W, const vector<int>& startCost) {\n    int n = (int)p.size();\n    if (idx == -1) return startCost[p[0]];\n    if (0 <= idx && idx + 1 < n) return W[p[idx]][p[idx + 1]];\n    return 0;\n}\n\nlong long deltaSwapFast(const vector<int>& p, int a, int b, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (a == b) return 0;\n    if (a > b) swap(a, b);\n\n    int n = (int)p.size();\n    int ids[5] = {-1, a - 1, a, b - 1, b};\n    sort(ids, ids + 5);\n\n    auto nodeAfter = [&](int idx) -> int {\n        if (idx == a) return p[b];\n        if (idx == b) return p[a];\n        return p[idx];\n    };\n\n    auto newContrib = [&](int idx) -> long long {\n        if (idx == -1) return startCost[nodeAfter(0)];\n        if (0 <= idx && idx + 1 < n) return W[nodeAfter(idx)][nodeAfter(idx + 1)];\n        return 0LL;\n    };\n\n    long long oldv = 0, newv = 0;\n    int last = -100;\n\n    for (int z = 0; z < 5; ++z) {\n        int id = ids[z];\n        if (id == last) continue;\n        last = id;\n\n        oldv += edgeContrib(p, id, W, startCost);\n        newv += newContrib(id);\n    }\n\n    return newv - oldv;\n}\n\nvector<int> greedyOrder(const vector<vector<int>>& W, const vector<int>& startCost, const vector<vector<int>>& ov) {\n    vector<int> best;\n    long long bestCost = (1LL << 60);\n\n    for (int st = 0; st < M; ++st) {\n        vector<int> p;\n        vector<char> used(M, 0);\n        p.reserve(M);\n\n        p.push_back(st);\n        used[st] = 1;\n\n        for (int step = 1; step < M; ++step) {\n            int last = p.back();\n            int bj = -1;\n            pair<int,int> bestKey = {INT_MAX, INT_MAX};\n\n            for (int j = 0; j < M; ++j) if (!used[j]) {\n                pair<int,int> key = {W[last][j], -ov[last][j]};\n                if (key < bestKey) {\n                    bestKey = key;\n                    bj = j;\n                }\n            }\n\n            used[bj] = 1;\n            p.push_back(bj);\n        }\n\n        long long c = pathCost(p, W, startCost);\n        if (c < bestCost) {\n            bestCost = c;\n            best = p;\n        }\n    }\n\n    return best;\n}\n\nvoid annealOrder(\n    vector<int>& perm,\n    long long& curCost,\n    vector<int>& bestPerm,\n    long long& bestCost,\n    const vector<vector<int>>& W,\n    const vector<int>& startCost,\n    double endTime,\n    double tempStart,\n    double tempEnd,\n    XorShift& rng\n) {\n    vector<int> np;\n    np.reserve(M);\n\n    double beginTime = elapsedTime();\n    int iter = 0;\n\n    while (true) {\n        if ((iter & 1023) == 0) {\n            if (elapsedTime() > endTime) break;\n        }\n        ++iter;\n\n        double progress = (elapsedTime() - beginTime) / max(1e-9, endTime - beginTime);\n        progress = min(1.0, max(0.0, progress));\n        double temp = tempStart * pow(tempEnd / tempStart, progress);\n\n        if (rng.nextInt(100) < 55) {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            long long d = deltaSwapFast(perm, a, b, W, startCost);\n\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                swap(perm[a], perm[b]);\n                curCost += d;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        } else {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            np = perm;\n            int val = np[a];\n            np.erase(np.begin() + a);\n            np.insert(np.begin() + b, val);\n\n            long long ncost = pathCost(np, W, startCost);\n            long long d = ncost - curCost;\n\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                perm.swap(np);\n                curCost = ncost;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        }\n    }\n}\n\nstring buildStringFromOrder(const vector<int>& ord) {\n    string s;\n    s.reserve(1200);\n\n    vector<char> covered(M, 0);\n    int code = 0;\n    int seen = 0;\n\n    auto appendChar = [&](char ch) {\n        s.push_back(ch);\n        code = (code * 26 + (ch - 'A')) % POW5;\n        ++seen;\n\n        if (seen >= 5) {\n            int id = codeId[code];\n            if (id != -1) covered[id] = 1;\n        }\n    };\n\n    auto appendWord = [&](int id) {\n        if (covered[id]) return;\n        int o = overlap_suffix_string(s, t[id]);\n        for (int k = o; k < 5; ++k) appendChar(t[id][k]);\n    };\n\n    for (int id : ord) appendWord(id);\n\n    for (int i = 0; i < M; ++i) {\n        if (!covered[i]) appendWord(i);\n    }\n\n    return s;\n}\n\nbool coversAllAfterDeleting(const string& s, int delPos) {\n    vector<char> covered(M, 0);\n    int cnt = 0;\n    int code = 0;\n    int seen = 0;\n\n    for (int i = 0; i < (int)s.size(); ++i) {\n        if (i == delPos) continue;\n\n        code = (code * 26 + (s[i] - 'A')) % POW5;\n        ++seen;\n\n        if (seen >= 5) {\n            int id = codeId[code];\n            if (id != -1 && !covered[id]) {\n                covered[id] = 1;\n                ++cnt;\n                if (cnt == M) return true;\n            }\n        }\n    }\n\n    return cnt == M;\n}\n\nstring pruneStringByDeletion(string s, int& curCost) {\n    if (elapsedTime() > 1.90) return s;\n\n    bool improved = true;\n\n    while (improved && elapsedTime() < 1.93) {\n        improved = false;\n\n        for (int pos = 0; pos < (int)s.size(); ++pos) {\n            if ((pos & 15) == 0 && elapsedTime() > 1.93) break;\n\n            if (!coversAllAfterDeleting(s, pos)) continue;\n\n            string ns;\n            ns.reserve(s.size() - 1);\n            ns.append(s.begin(), s.begin() + pos);\n            ns.append(s.begin() + pos + 1, s.end());\n\n            int nc = typingCostOnly(ns);\n            if (nc < curCost) {\n                s.swap(ns);\n                curCost = nc;\n                improved = true;\n                break;\n            }\n        }\n    }\n\n    return s;\n}\n\npair<int, vector<pair<int,int>>> solveTypingDP(const string& s) {\n    const int INF = 1e9;\n    int L = (int)s.size();\n\n    vector<vector<int>> par(L);\n    vector<int> dp_prev, dp_cur;\n\n    for (int pos = 0; pos < L; ++pos) {\n        int c = s[pos] - 'A';\n        int C = (int)occ[c].size();\n\n        dp_cur.assign(C, INF);\n        par[pos].assign(C, -1);\n\n        if (pos == 0) {\n            pair<int,int> start = {si, sj};\n            for (int i = 0; i < C; ++i) {\n                dp_cur[i] = manhattan(start, occ[c][i]) + 1;\n            }\n        } else {\n            int pc = s[pos - 1] - 'A';\n            int P = (int)occ[pc].size();\n\n            for (int i = 0; i < C; ++i) {\n                for (int j = 0; j < P; ++j) {\n                    int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                    if (val < dp_cur[i]) {\n                        dp_cur[i] = val;\n                        par[pos][i] = j;\n                    }\n                }\n            }\n        }\n\n        dp_prev.swap(dp_cur);\n    }\n\n    int bestIdx = 0;\n    int bestCost = INF;\n\n    for (int i = 0; i < (int)dp_prev.size(); ++i) {\n        if (dp_prev[i] < bestCost) {\n            bestCost = dp_prev[i];\n            bestIdx = i;\n        }\n    }\n\n    vector<pair<int,int>> path(L);\n    int idx = bestIdx;\n\n    for (int pos = L - 1; pos >= 0; --pos) {\n        int c = s[pos] - 'A';\n        path[pos] = occ[c][idx];\n        idx = par[pos][idx];\n    }\n\n    return {bestCost, path};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    timeStart = chrono::steady_clock::now();\n\n    cin >> N >> M;\n    cin >> si >> sj;\n\n    Agrid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> Agrid[i];\n\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    codeId.assign(POW5, -1);\n    for (int i = 0; i < M; ++i) {\n        codeId[wordCode(t[i])] = i;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            occ[Agrid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) {\n            int best = 1e9;\n            for (auto pa : occ[a]) {\n                for (auto pb : occ[b]) {\n                    best = min(best, manhattan(pa, pb));\n                }\n            }\n            mindist_ch[a][b] = best;\n        }\n    }\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i != j) ov[i][j] = overlap_word(t[i], t[j]);\n        }\n    }\n\n    vector<vector<int>> Wapprox(M, vector<int>(M, 100000000));\n    vector<vector<int>> Wexact(M, vector<int>(M, 100000000));\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            int o = ov[i][j];\n\n            int prev = t[i][4] - 'A';\n            int cost = 0;\n\n            for (int k = o; k < 5; ++k) {\n                int c = t[j][k] - 'A';\n                cost += mindist_ch[prev][c] + 1;\n                prev = c;\n            }\n\n            Wapprox[i][j] = cost;\n            Wexact[i][j] = segmentCostFromChar(t[i][4] - 'A', t[j], o);\n        }\n    }\n\n    vector<int> startApprox(M, 0);\n    vector<int> startExact(M, 0);\n    pair<int,int> startPos = {si, sj};\n\n    for (int i = 0; i < M; ++i) {\n        int cost = 1e9;\n        int c0 = t[i][0] - 'A';\n\n        for (auto p : occ[c0]) {\n            cost = min(cost, manhattan(startPos, p) + 1);\n        }\n\n        for (int k = 1; k < 5; ++k) {\n            int a = t[i][k - 1] - 'A';\n            int b = t[i][k] - 'A';\n            cost += mindist_ch[a][b] + 1;\n        }\n\n        startApprox[i] = cost;\n        startExact[i] = typingCostOnly(t[i]);\n    }\n\n    vector<string> candidates;\n\n    vector<int> perm = greedyOrder(Wapprox, startApprox, ov);\n    long long curCost = pathCost(perm, Wapprox, startApprox);\n    vector<int> bestPerm = perm;\n    long long bestCost = curCost;\n\n    XorShift rng;\n\n    // Preserve the strongest original search as much as possible.\n    annealOrder(\n        perm,\n        curCost,\n        bestPerm,\n        bestCost,\n        Wapprox,\n        startApprox,\n        1.78,\n        18.0,\n        0.03,\n        rng\n    );\n\n    candidates.push_back(buildStringFromOrder(bestPerm));\n\n    // Pure overlap candidate.\n    vector<vector<int>> Wover(M, vector<int>(M, 1000000));\n    vector<int> zeroStart(M, 0);\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            Wover[i][j] = 5 - ov[i][j];\n        }\n    }\n\n    candidates.push_back(buildStringFromOrder(greedyOrder(Wover, zeroStart, ov)));\n\n    // Exact short-DP edge model candidate.\n    if (elapsedTime() < 1.84) {\n        vector<int> eperm = greedyOrder(Wexact, startExact, ov);\n        long long ecur = pathCost(eperm, Wexact, startExact);\n        vector<int> ebestPerm = eperm;\n        long long ebest = ecur;\n\n        annealOrder(\n            eperm,\n            ecur,\n            ebestPerm,\n            ebest,\n            Wexact,\n            startExact,\n            1.88,\n            12.0,\n            0.05,\n            rng\n        );\n\n        candidates.push_back(buildStringFromOrder(ebestPerm));\n    }\n\n    // A few deterministic fallbacks.\n    vector<int> lexPerm(M);\n    iota(lexPerm.begin(), lexPerm.end(), 0);\n    candidates.push_back(buildStringFromOrder(lexPerm));\n\n    reverse(lexPerm.begin(), lexPerm.end());\n    candidates.push_back(buildStringFromOrder(lexPerm));\n\n    // Mildly overlap-biased approximate candidates.\n    if (elapsedTime() < 1.90) {\n        for (int bonus : {2, 4}) {\n            vector<vector<int>> Wb = Wapprox;\n\n            for (int i = 0; i < M; ++i) {\n                for (int j = 0; j < M; ++j) if (i != j) {\n                    Wb[i][j] = Wapprox[i][j] - bonus * ov[i][j];\n                }\n            }\n\n            candidates.push_back(buildStringFromOrder(greedyOrder(Wb, startApprox, ov)));\n        }\n    }\n\n    sort(candidates.begin(), candidates.end());\n    candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n    int bestStringCost = INT_MAX;\n    string bestString;\n\n    for (const string& s : candidates) {\n        int c = typingCostOnly(s);\n        if (c < bestStringCost) {\n            bestStringCost = c;\n            bestString = s;\n        }\n    }\n\n    // Safe post-processing: delete characters only when exact cost improves.\n    if (elapsedTime() < 1.90) {\n        bestString = pruneStringByDeletion(bestString, bestStringCost);\n    }\n\n    auto answer = solveTypingDP(bestString);\n    vector<pair<int,int>> answerPath = move(answer.second);\n\n    if ((int)answerPath.size() > 5000) {\n        answerPath.resize(5000);\n    }\n\n    for (auto [i, j] : answerPath) {\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXC = 400;\n\nint N, M, C;\ndouble EPSV;\nint MAX_OPS;\nint op_cnt = 0;\n\nstruct Placement {\n    vector<int> cells;\n    bitset<MAXC> mask;\n};\n\nstruct Obs {\n    bitset<MAXC> mask;\n    int k;\n    double target;\n    double weight;\n    bool drill;\n    int cell;\n    int value;\n};\n\nstruct State {\n    vector<int> pos;\n    double score;\n    bitset<MAXC> uni;\n};\n\nvector<vector<pair<int,int>>> shapes;\nvector<vector<Placement>> placements;\nvector<Obs> observations;\n\nvector<int> drilled; // -1 unknown, otherwise exact v(i,j)\n\nmt19937 rng(1234567);\nauto time_start = chrono::steady_clock::now();\n\ndouble elapsed_ms() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double, milli>(now - time_start).count();\n}\n\nint id_of(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> coord_of(int id) {\n    return {id / N, id % N};\n}\n\nint ask_query(const vector<int>& cells) {\n    cout << \"q \" << cells.size();\n    for (int id : cells) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n    return res;\n}\n\nbool ask_answer(bitset<MAXC> mask) {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] > 0) mask.set(id);\n    }\n\n    vector<int> ans;\n    for (int id = 0; id < C; id++) {\n        if (mask.test(id)) ans.push_back(id);\n    }\n\n    cout << \"a \" << ans.size();\n    for (int id : ans) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n    if (res == 1) exit(0);\n    return false;\n}\n\nvoid add_divination_observation(const vector<int>& cells, int y) {\n    Obs obs;\n    obs.mask.reset();\n    for (int id : cells) obs.mask.set(id);\n    obs.k = (int)cells.size();\n    obs.drill = false;\n    obs.cell = -1;\n    obs.value = -1;\n\n    double a = 1.0 - 2.0 * EPSV;\n    double target = (y - obs.k * EPSV) / max(1e-9, a);\n    target = max(0.0, min(target, (double)M * obs.k));\n\n    double var = obs.k * EPSV * (1.0 - EPSV) + 0.35;\n    double weight = a * a / max(1e-9, var);\n\n    obs.target = target;\n    obs.weight = weight;\n    observations.push_back(obs);\n}\n\nvoid add_drill_observation(int cell, int val) {\n    Obs obs;\n    obs.mask.reset();\n    obs.mask.set(cell);\n    obs.k = 1;\n    obs.target = val;\n    obs.weight = 10000.0;\n    obs.drill = true;\n    obs.cell = cell;\n    obs.value = val;\n    observations.push_back(obs);\n}\n\nvoid do_divination(const vector<int>& cells) {\n    if ((int)cells.size() < 2) return;\n    int y = ask_query(cells);\n    add_divination_observation(cells, y);\n}\n\nint do_drill(int cell) {\n    vector<int> q = {cell};\n    int v = ask_query(q);\n    drilled[cell] = v;\n    add_drill_observation(cell, v);\n    return v;\n}\n\nvoid build_placements() {\n    placements.assign(M, {});\n\n    for (int m = 0; m < M; m++) {\n        int imax = 0, jmax = 0;\n        for (auto [i, j] : shapes[m]) {\n            imax = max(imax, i);\n            jmax = max(jmax, j);\n        }\n\n        for (int di = 0; di + imax < N; di++) {\n            for (int dj = 0; dj + jmax < N; dj++) {\n                Placement p;\n                p.mask.reset();\n                for (auto [i, j] : shapes[m]) {\n                    int id = id_of(di + i, dj + j);\n                    p.cells.push_back(id);\n                    p.mask.set(id);\n                }\n                placements[m].push_back(p);\n            }\n        }\n    }\n}\n\nvoid initial_queries() {\n    // Whole grid: almost free and gives total amount.\n    vector<int> all;\n    for (int id = 0; id < C; id++) all.push_back(id);\n    do_divination(all);\n\n    // Rows.\n    for (int i = 0; i < N; i++) {\n        vector<int> cells;\n        for (int j = 0; j < N; j++) cells.push_back(id_of(i, j));\n        do_divination(cells);\n    }\n\n    // Columns.\n    for (int j = 0; j < N; j++) {\n        vector<int> cells;\n        for (int i = 0; i < N; i++) cells.push_back(id_of(i, j));\n        do_divination(cells);\n    }\n\n    // Coarse blocks.\n    int B = 4;\n    for (int si = 0; si < N; si += B) {\n        for (int sj = 0; sj < N; sj += B) {\n            vector<int> cells;\n            for (int i = si; i < min(N, si + B); i++) {\n                for (int j = sj; j < min(N, sj + B); j++) {\n                    cells.push_back(id_of(i, j));\n                }\n            }\n            if ((int)cells.size() >= 2) do_divination(cells);\n        }\n    }\n\n    // Random half-grid masks. Cheap global linear measurements.\n    int R = (N <= 10 ? 18 : 30);\n    vector<int> ids(C);\n    iota(ids.begin(), ids.end(), 0);\n    for (int r = 0; r < R; r++) {\n        shuffle(ids.begin(), ids.end(), rng);\n        vector<int> cells;\n        int sz = max(2, C / 2);\n        for (int t = 0; t < sz; t++) cells.push_back(ids[t]);\n        do_divination(cells);\n    }\n}\n\nbitset<MAXC> union_of_state(const vector<int>& pos) {\n    bitset<MAXC> res;\n    res.reset();\n    for (int m = 0; m < M; m++) {\n        res |= placements[m][pos[m]].mask;\n    }\n    return res;\n}\n\nbool union_consistent_with_drills(const bitset<MAXC>& mask) {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) continue;\n        if (drilled[id] == 0 && mask.test(id)) return false;\n        if (drilled[id] > 0 && !mask.test(id)) return false;\n    }\n    return true;\n}\n\nstring mask_key(const bitset<MAXC>& mask) {\n    string s;\n    s.reserve(C);\n    for (int id = 0; id < C; id++) s.push_back(mask.test(id) ? '1' : '0');\n    return s;\n}\n\nvector<State> find_candidates(int want, int time_ms) {\n    int O = observations.size();\n\n    vector<vector<vector<unsigned char>>> contrib(M);\n    for (int m = 0; m < M; m++) {\n        int P = placements[m].size();\n        contrib[m].assign(P, vector<unsigned char>(O, 0));\n        for (int p = 0; p < P; p++) {\n            for (int o = 0; o < O; o++) {\n                bitset<MAXC> b = placements[m][p].mask & observations[o].mask;\n                contrib[m][p][o] = (unsigned char)b.count();\n            }\n        }\n    }\n\n    auto score_of_sums = [&](const vector<int>& sums) {\n        double sc = 0.0;\n        for (int o = 0; o < O; o++) {\n            double e = sums[o] - observations[o].target;\n            sc += observations[o].weight * e * e;\n        }\n        return sc;\n    };\n\n    vector<State> result;\n    auto deadline = chrono::steady_clock::now() + chrono::milliseconds(max(5, time_ms));\n\n    int restarts = 0;\n    while (restarts < 3 || chrono::steady_clock::now() < deadline) {\n        restarts++;\n\n        vector<int> pos(M);\n        for (int m = 0; m < M; m++) {\n            uniform_int_distribution<int> dist(0, (int)placements[m].size() - 1);\n            pos[m] = dist(rng);\n        }\n\n        vector<int> sums(O, 0);\n        for (int m = 0; m < M; m++) {\n            for (int o = 0; o < O; o++) {\n                sums[o] += contrib[m][pos[m]][o];\n            }\n        }\n\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n\n        for (int sweep = 0; sweep < 7; sweep++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool changed = false;\n\n            for (int mm = 0; mm < M; mm++) {\n                int m = order[mm];\n                int oldp = pos[m];\n\n                for (int o = 0; o < O; o++) {\n                    sums[o] -= contrib[m][oldp][o];\n                }\n\n                int bestp = oldp;\n                double bestsc = numeric_limits<double>::infinity();\n\n                int P = placements[m].size();\n                for (int p = 0; p < P; p++) {\n                    double sc = 0.0;\n                    for (int o = 0; o < O; o++) {\n                        double v = sums[o] + contrib[m][p][o];\n                        double e = v - observations[o].target;\n                        sc += observations[o].weight * e * e;\n                        if (sc >= bestsc) break;\n                    }\n                    if (sc < bestsc) {\n                        bestsc = sc;\n                        bestp = p;\n                    }\n                }\n\n                pos[m] = bestp;\n                for (int o = 0; o < O; o++) {\n                    sums[o] += contrib[m][bestp][o];\n                }\n\n                if (bestp != oldp) changed = true;\n            }\n\n            if (!changed) break;\n        }\n\n        State st;\n        st.pos = pos;\n        st.score = score_of_sums(sums);\n        st.uni = union_of_state(pos);\n        result.push_back(st);\n\n        if (elapsed_ms() > 2700.0) break;\n    }\n\n    sort(result.begin(), result.end(), [](const State& a, const State& b) {\n        return a.score < b.score;\n    });\n\n    vector<State> uniq;\n    unordered_set<string> seen;\n    for (auto &st : result) {\n        string key = mask_key(st.uni);\n        if (seen.insert(key).second) {\n            uniq.push_back(st);\n            if ((int)uniq.size() >= want) break;\n        }\n    }\n\n    return uniq;\n}\n\nint choose_drill_cell(const vector<State>& cand, int wrong_same_count) {\n    int K = cand.size();\n    vector<int> freq(C, 0);\n\n    for (auto &st : cand) {\n        for (int id = 0; id < C; id++) {\n            if (st.uni.test(id)) freq[id]++;\n        }\n    }\n\n    int best = -1;\n    int bestScore = -1;\n\n    // Prefer uncertain cells among candidate unions.\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] != -1) continue;\n        int f = freq[id];\n        if (f == 0 || f == K) continue;\n        int score = min(f, K - f);\n        if (score > bestScore) {\n            bestScore = score;\n            best = id;\n        }\n    }\n\n    if (best != -1) return best;\n\n    // If all candidates agree, verify predicted positives and nearby negatives.\n    if (!cand.empty()) {\n        const bitset<MAXC>& mask = cand[0].uni;\n\n        if (wrong_same_count % 2 == 0) {\n            for (int id = 0; id < C; id++) {\n                if (drilled[id] == -1 && mask.test(id)) return id;\n            }\n        }\n\n        // Boundary negatives.\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] != -1 || mask.test(id)) continue;\n            int i = id / N, j = id % N;\n            bool near = false;\n            const int di[4] = {-1, 1, 0, 0};\n            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 (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    if (mask.test(id_of(ni, nj))) near = true;\n                }\n            }\n            if (near) return id;\n        }\n\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] == -1 && !mask.test(id)) return id;\n        }\n    }\n\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) return id;\n    }\n\n    return -1;\n}\n\nvoid fallback_drill_all_and_answer() {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) {\n            do_drill(id);\n        }\n    }\n\n    bitset<MAXC> ans;\n    ans.reset();\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] > 0) ans.set(id);\n    }\n\n    ask_answer(ans);\n    exit(0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> EPSV;\n    C = N * N;\n    MAX_OPS = 2 * C;\n\n    shapes.resize(M);\n    for (int m = 0; m < M; m++) {\n        int d;\n        cin >> d;\n        shapes[m].resize(d);\n        for (int k = 0; k < d; k++) {\n            cin >> shapes[m][k].first >> shapes[m][k].second;\n        }\n    }\n\n    drilled.assign(C, -1);\n    build_placements();\n\n    initial_queries();\n\n    unordered_set<string> guessed;\n    int heuristic_drills = 0;\n    int guesses = 0;\n    int wrong_same_count = 0;\n\n    while (true) {\n        int unknown = 0;\n        for (int id = 0; id < C; id++) if (drilled[id] == -1) unknown++;\n\n        // Keep enough operations to drill everything and submit.\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        if (elapsed_ms() > 2700.0 || heuristic_drills >= 55) {\n            fallback_drill_all_and_answer();\n        }\n\n        int tlim = 90;\n        if (heuristic_drills == 0) tlim = 350;\n        if (elapsed_ms() > 2200.0) tlim = 20;\n\n        vector<State> cand = find_candidates(10, tlim);\n        if (cand.empty()) {\n            fallback_drill_all_and_answer();\n        }\n\n        bitset<MAXC> bestMask = cand[0].uni;\n        string key = mask_key(bestMask);\n\n        bool can_try_answer =\n            guesses < 25 &&\n            op_cnt + unknown + 2 <= MAX_OPS &&\n            guessed.find(key) == guessed.end() &&\n            union_consistent_with_drills(bestMask);\n\n        if (can_try_answer) {\n            guessed.insert(key);\n            guesses++;\n            bool ok = ask_answer(bestMask);\n            if (ok) return 0;\n            wrong_same_count++;\n        }\n\n        unknown = 0;\n        for (int id = 0; id < C; id++) if (drilled[id] == -1) unknown++;\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        int cell = choose_drill_cell(cand, wrong_same_count);\n        if (cell == -1) {\n            fallback_drill_all_and_answer();\n        }\n\n        do_drill(cell);\n        heuristic_drills++;\n    }\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int W = 1000;\nusing ll = long long;\nusing ull = unsigned long long;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nstruct Option {\n    int l, r;\n    int h;\n    ll cost;\n    bool stat;\n};\n\nint D, N;\nvector<vector<int>> A;\nvector<int> maxA;\n\ninline int ceil_div(int x, int y) {\n    return (x + y - 1) / y;\n}\n\nvector<vector<Rect>> make_empty_solution() {\n    return vector<vector<Rect>>(D, vector<Rect>(N));\n}\n\nbool valid_solution(const vector<vector<Rect>>& sol) {\n    if ((int)sol.size() != D) return false;\n    for (int d = 0; d < D; d++) {\n        if ((int)sol[d].size() != N) return false;\n        for (int k = 0; k < N; k++) {\n            auto r = sol[d][k];\n            if (!(0 <= r.i0 && r.i0 < r.i1 && r.i1 <= W)) return false;\n            if (!(0 <= r.j0 && r.j0 < r.j1 && r.j1 <= W)) return false;\n        }\n    }\n    return true;\n}\n\nstruct Scorer {\n    int HN = 999 * 1000;\n    int VN = 1000 * 999;\n    int HW, VW;\n\n    Scorer() {\n        HW = (HN + 63) >> 6;\n        VW = (VN + 63) >> 6;\n    }\n\n    inline void setbit(vector<ull>& b, int idx) const {\n        b[idx >> 6] |= 1ULL << (idx & 63);\n    }\n\n    ll score(const vector<vector<Rect>>& sol) const {\n        vector<ull> prevH(HW, 0), prevV(VW, 0), curH(HW), curV(VW);\n        ll total = 0;\n\n        for (int d = 0; d < D; d++) {\n            fill(curH.begin(), curH.end(), 0);\n            fill(curV.begin(), curV.end(), 0);\n\n            for (int k = 0; k < N; k++) {\n                const Rect& r = sol[d][k];\n\n                ll area = 1LL * (r.i1 - r.i0) * (r.j1 - r.j0);\n                if (area < A[d][k]) total += 100LL * (A[d][k] - area);\n\n                if (r.i0 > 0) {\n                    int row = r.i0 - 1;\n                    for (int x = r.j0; x < r.j1; x++) setbit(curH, row * 1000 + x);\n                }\n                if (r.i1 < W) {\n                    int row = r.i1 - 1;\n                    for (int x = r.j0; x < r.j1; x++) setbit(curH, row * 1000 + x);\n                }\n                if (r.j0 > 0) {\n                    int col = r.j0 - 1;\n                    for (int y = r.i0; y < r.i1; y++) setbit(curV, y * 999 + col);\n                }\n                if (r.j1 < W) {\n                    int col = r.j1 - 1;\n                    for (int y = r.i0; y < r.i1; y++) setbit(curV, y * 999 + col);\n                }\n            }\n\n            if (d > 0) {\n                for (int i = 0; i < HW; i++) total += __builtin_popcountll(prevH[i] ^ curH[i]);\n                for (int i = 0; i < VW; i++) total += __builtin_popcountll(prevV[i] ^ curV[i]);\n            }\n\n            prevH.swap(curH);\n            prevV.swap(curV);\n        }\n\n        return total;\n    }\n};\n\nstruct TreemapPacker {\n    vector<int> weight;\n    vector<Rect> out;\n\n    ll sum_weight(const vector<int>& ids) {\n        ll s = 0;\n        for (int id : ids) s += weight[id];\n        return s;\n    }\n\n    void rec(const vector<int>& ids, int x, int y, int w, int h) {\n        int m = ids.size();\n\n        if (m == 1) {\n            int id = ids[0];\n            out[id] = {y, x, y + h, x + w};\n            return;\n        }\n\n        ll total = sum_weight(ids);\n        ll area = 1LL * w * h;\n\n        vector<vector<int>> orders;\n\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (weight[a] != weight[b]) return weight[a] < weight[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (weight[a] != weight[b]) return weight[a] > weight[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end());\n            orders.push_back(v);\n        }\n\n        struct Cand {\n            ll score;\n            bool vertical;\n            int cut;\n            vector<int> a, b;\n        };\n\n        vector<Cand> cands;\n        set<pair<unsigned long long, int>> seen;\n\n        auto add_candidate = [&](vector<int> left) {\n            if (left.empty() || (int)left.size() == m) return;\n\n            sort(left.begin(), left.end());\n\n            unsigned long long mask = 0;\n            for (int id : left) mask |= 1ULL << id;\n\n            vector<int> right;\n            right.reserve(m - left.size());\n            for (int id : ids) {\n                if (!(mask >> id & 1ULL)) right.push_back(id);\n            }\n\n            if (right.empty()) return;\n\n            ll s1 = 0, s2 = 0;\n            for (int id : left) s1 += weight[id];\n            for (int id : right) s2 += weight[id];\n\n            int n1 = left.size();\n            int n2 = right.size();\n\n            // vertical split\n            {\n                int lo = ceil_div(n1, h);\n                int hi = w - ceil_div(n2, h);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)w * s1 / max(1LL, total));\n                    for (int cut : {lo, hi, max(lo, min(hi, ideal)), max(lo, min(hi, ideal - 1)), max(lo, min(hi, ideal + 1))}) {\n                        if (cut < lo || cut > hi) continue;\n                        ll cap1 = 1LL * cut * h;\n                        ll cap2 = 1LL * (w - cut) * h;\n                        ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - cap2);\n                        ll dev = llabs(cap1 * total - s1 * area) / max(1LL, total);\n                        ll aspect = 0;\n                        aspect += 1000LL * max(cut, h) / max(1, min(cut, h));\n                        aspect += 1000LL * max(w - cut, h) / max(1, min(w - cut, h));\n                        ll score = shortage * 1000000000LL + dev * 1000LL + aspect + abs(n1 - n2) * 10LL;\n                        cands.push_back({score, true, cut, left, right});\n                    }\n                }\n            }\n\n            // horizontal split\n            {\n                int lo = ceil_div(n1, w);\n                int hi = h - ceil_div(n2, w);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)h * s1 / max(1LL, total));\n                    for (int cut : {lo, hi, max(lo, min(hi, ideal)), max(lo, min(hi, ideal - 1)), max(lo, min(hi, ideal + 1))}) {\n                        if (cut < lo || cut > hi) continue;\n                        ll cap1 = 1LL * w * cut;\n                        ll cap2 = 1LL * w * (h - cut);\n                        ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - cap2);\n                        ll dev = llabs(cap1 * total - s1 * area) / max(1LL, total);\n                        ll aspect = 0;\n                        aspect += 1000LL * max(w, cut) / max(1, min(w, cut));\n                        aspect += 1000LL * max(w, h - cut) / max(1, min(w, h - cut));\n                        ll score = shortage * 1000000000LL + dev * 1000LL + aspect + abs(n1 - n2) * 10LL;\n                        cands.push_back({score, false, cut, left, right});\n                    }\n                }\n            }\n        };\n\n        for (auto ord : orders) {\n            vector<int> pref;\n            for (int k = 0; k + 1 < m; k++) {\n                pref.push_back(ord[k]);\n                add_candidate(pref);\n            }\n        }\n\n        // Greedy near several target fractions.\n        vector<double> targets = {0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80};\n        auto desc = ids;\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            if (weight[a] != weight[b]) return weight[a] > weight[b];\n            return a < b;\n        });\n\n        for (double t : targets) {\n            ll target = (ll)(total * t);\n            vector<int> group;\n            ll s = 0;\n            for (int id : desc) {\n                if (group.empty() || s + weight[id] <= target) {\n                    group.push_back(id);\n                    s += weight[id];\n                }\n            }\n            add_candidate(group);\n        }\n\n        if (cands.empty()) {\n            // Extremely defensive fallback: split by count along longer side.\n            vector<int> a, b;\n            for (int i = 0; i < m; i++) {\n                if (i < m / 2) a.push_back(ids[i]);\n                else b.push_back(ids[i]);\n            }\n\n            if (w >= h && w >= 2) {\n                int cut = max(1, min(w - 1, w / 2));\n                rec(a, x, y, cut, h);\n                rec(b, x + cut, y, w - cut, h);\n            } else {\n                int cut = max(1, min(h - 1, h / 2));\n                rec(a, x, y, w, cut);\n                rec(b, x, y + cut, w, h - cut);\n            }\n            return;\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            return a.score < b.score;\n        });\n\n        const Cand& best = cands[0];\n\n        if (best.vertical) {\n            rec(best.a, x, y, best.cut, h);\n            rec(best.b, x + best.cut, y, w - best.cut, h);\n        } else {\n            rec(best.a, x, y, w, best.cut);\n            rec(best.b, x, y + best.cut, w, h - best.cut);\n        }\n    }\n\n    vector<Rect> pack(const vector<int>& wgt) {\n        weight = wgt;\n        out.assign(N, {-1, -1, -1, -1});\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        rec(ids, 0, 0, W, W);\n        return out;\n    }\n};\n\nvector<vector<Rect>> treemap_dynamic_solution() {\n    auto sol = make_empty_solution();\n    for (int d = 0; d < D; d++) {\n        TreemapPacker tp;\n        auto r = tp.pack(A[d]);\n        for (int k = 0; k < N; k++) sol[d][k] = r[k];\n    }\n    return sol;\n}\n\nvector<vector<Rect>> treemap_static_max_solution() {\n    auto sol = make_empty_solution();\n    TreemapPacker tp;\n    auto r = tp.pack(maxA);\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) sol[d][k] = r[k];\n    }\n    return sol;\n}\n\nvector<vector<Rect>> treemap_static_avg_solution() {\n    vector<int> avg(N);\n    for (int k = 0; k < N; k++) {\n        ll s = 0;\n        for (int d = 0; d < D; d++) s += A[d][k];\n        avg[k] = max(1, (int)((s + D - 1) / D));\n    }\n\n    auto sol = make_empty_solution();\n    TreemapPacker tp;\n    auto r = tp.pack(avg);\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) sol[d][k] = r[k];\n    }\n    return sol;\n}\n\nbool pack_bfd(const vector<int>& widths, int h, vector<vector<int>>& rows) {\n    rows.clear();\n    if (h <= 0 || h > 1000) return false;\n\n    int maxRows = 1000 / h;\n    if (maxRows <= 0) return false;\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 (widths[x] != widths[y]) return widths[x] > widths[y];\n        return x < y;\n    });\n\n    vector<int> rem;\n\n    for (int id : ids) {\n        int w = widths[id];\n        if (w <= 0 || w > 1000) return false;\n\n        int best = -1;\n        int bestRem = 1000000;\n\n        for (int r = 0; r < (int)rows.size(); r++) {\n            if (rem[r] >= w && rem[r] - w < bestRem) {\n                bestRem = rem[r] - w;\n                best = r;\n            }\n        }\n\n        if (best == -1) {\n            if ((int)rows.size() >= maxRows) return false;\n            rows.push_back(vector<int>{id});\n            rem.push_back(1000 - w);\n        } else {\n            rows[best].push_back(id);\n            rem[best] -= w;\n        }\n    }\n\n    for (auto& row : rows) sort(row.begin(), row.end());\n\n    sort(rows.begin(), rows.end(), [](const vector<int>& a, const vector<int>& b) {\n        return a.front() < b.front();\n    });\n\n    return true;\n}\n\nvector<vector<Rect>> build_from_rows_dynamic_height(\n    const vector<vector<vector<int>>>& allRows,\n    const vector<int>& hs\n) {\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        int h = hs[d];\n        int y = 0;\n\n        for (const auto& row : allRows[d]) {\n            int x = 0;\n            for (int t = 0; t < (int)row.size(); t++) {\n                int k = row[t];\n                int w;\n                if (t + 1 == (int)row.size()) w = W - x;\n                else w = ceil_div(A[d][k], h);\n                if (w <= 0) w = 1;\n                sol[d][k] = {y, x, y + h, x + w};\n                x += w;\n            }\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> static_bfd_solution() {\n    ll bestEst = (1LL << 60);\n    int bestH = -1;\n    vector<vector<int>> bestRows;\n\n    for (int h = 1; h <= 1000; h++) {\n        vector<int> widths(N);\n        bool ok = true;\n        for (int k = 0; k < N; k++) {\n            widths[k] = ceil_div(maxA[k], h);\n            if (widths[k] > 1000) ok = false;\n        }\n        if (!ok) continue;\n\n        vector<vector<int>> rows;\n        if (!pack_bfd(widths, h, rows)) continue;\n\n        ll est = 1LL * rows.size() * h;\n        if (est < bestEst) {\n            bestEst = est;\n            bestH = h;\n            bestRows = rows;\n        }\n    }\n\n    if (bestH == -1) return {};\n\n    auto sol = make_empty_solution();\n    int y = 0;\n\n    for (const auto& row : bestRows) {\n        int x = 0;\n        for (int t = 0; t < (int)row.size(); t++) {\n            int k = row[t];\n            int w;\n            if (t + 1 == (int)row.size()) w = W - x;\n            else w = ceil_div(maxA[k], bestH);\n\n            for (int d = 0; d < D; d++) {\n                sol[d][k] = {y, x, y + bestH, x + w};\n            }\n            x += w;\n        }\n        y += bestH;\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> per_day_bfd_solution() {\n    vector<vector<vector<int>>> allRows(D);\n    vector<int> hs(D, -1);\n\n    for (int d = 0; d < D; d++) {\n        ll bestEst = (1LL << 60);\n        int bestH = -1;\n        vector<vector<int>> bestRows;\n\n        for (int h = 1; h <= 1000; h++) {\n            vector<int> widths(N);\n            bool ok = true;\n            for (int k = 0; k < N; k++) {\n                widths[k] = ceil_div(A[d][k], h);\n                if (widths[k] > 1000) ok = false;\n            }\n            if (!ok) continue;\n\n            vector<vector<int>> rows;\n            if (!pack_bfd(widths, h, rows)) continue;\n\n            int R = (int)rows.size();\n            ll est = 1000LL * max(0, R - 1) + 1LL * h * max(0, N - R);\n            est += abs(h - 50);\n\n            if (est < bestEst) {\n                bestEst = est;\n                bestH = h;\n                bestRows = rows;\n            }\n        }\n\n        if (bestH == -1) return {};\n        hs[d] = bestH;\n        allRows[d] = bestRows;\n    }\n\n    return build_from_rows_dynamic_height(allRows, hs);\n}\n\nvector<vector<Rect>> fixed_h_bfd_solution(int h) {\n    vector<vector<vector<int>>> allRows(D);\n    vector<int> hs(D, h);\n\n    for (int d = 0; d < D; d++) {\n        vector<int> widths(N);\n        bool ok = true;\n        for (int k = 0; k < N; k++) {\n            widths[k] = ceil_div(A[d][k], h);\n            if (widths[k] > 1000) ok = false;\n        }\n        if (!ok) return {};\n\n        vector<vector<int>> rows;\n        if (!pack_bfd(widths, h, rows)) return {};\n        allRows[d] = rows;\n    }\n\n    return build_from_rows_dynamic_height(allRows, hs);\n}\n\nvector<int> promising_fixed_heights() {\n    vector<pair<ll,int>> cand;\n\n    for (int h = 1; h <= 1000; h++) {\n        bool allok = true;\n        ll est = 0;\n\n        for (int d = 0; d < D; d++) {\n            vector<int> widths(N);\n            bool ok = true;\n            for (int k = 0; k < N; k++) {\n                widths[k] = ceil_div(A[d][k], h);\n                if (widths[k] > 1000) ok = false;\n            }\n            if (!ok) {\n                allok = false;\n                break;\n            }\n\n            vector<vector<int>> rows;\n            if (!pack_bfd(widths, h, rows)) {\n                allok = false;\n                break;\n            }\n\n            int R = (int)rows.size();\n            est += 1000LL * max(0, R - 1);\n            est += 1LL * h * max(0, N - R);\n        }\n\n        if (allok) {\n            est += (1000 % h);\n            cand.push_back({est, h});\n        }\n    }\n\n    sort(cand.begin(), cand.end());\n\n    vector<int> res;\n    for (auto [e, h] : cand) {\n        bool close = false;\n        for (int x : res) if (abs(x - h) <= 2) close = true;\n        if (!close) res.push_back(h);\n        if ((int)res.size() >= 8) break;\n    }\n\n    return res;\n}\n\nvector<vector<Rect>> stable_shelf_dp() {\n    int K = N + 1;\n    int HD = 1001;\n\n    vector<int> pref(HD * D * K, 0);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) {\n                P(h, d, k + 1) = P(h, d, k) + ceil_div(A[d][k], h);\n            }\n        }\n    }\n\n    vector<int> prefMax(HD * K, 0);\n    auto PM = [&](int h, int k) -> int& {\n        return prefMax[h * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        PM(h, 0) = 0;\n        for (int k = 0; k < N; k++) {\n            PM(h, k + 1) = PM(h, k) + ceil_div(maxA[k], h);\n        }\n    }\n\n    auto dyn_feasible = [&](int l, int r, int h) {\n        for (int d = 0; d < D; d++) {\n            int s = P(h, d, r + 1) - P(h, d, l);\n            if (s > W) return false;\n        }\n        return true;\n    };\n\n    auto stat_feasible = [&](int l, int r, int h) {\n        int s = PM(h, r + 1) - PM(h, l);\n        return s <= W;\n    };\n\n    auto dyn_cost = [&](int l, int r, int h) -> ll {\n        int m = r - l + 1;\n        if (m <= 1) return 0;\n\n        ll res = 0;\n        vector<int> a, b;\n        a.reserve(m - 1);\n        b.reserve(m - 1);\n\n        for (int d = 1; d < D; d++) {\n            a.clear();\n            b.clear();\n\n            for (int t = l; t < r; t++) {\n                a.push_back(P(h, d - 1, t + 1) - P(h, d - 1, l));\n                b.push_back(P(h, d, t + 1) - P(h, d, l));\n            }\n\n            int i = 0, j = 0, common = 0;\n            while (i < (int)a.size() && j < (int)b.size()) {\n                if (a[i] == b[j]) {\n                    common++;\n                    i++;\n                    j++;\n                } else if (a[i] < b[j]) i++;\n                else j++;\n            }\n\n            int sym = 2 * (m - 1) - 2 * common;\n            res += 1LL * sym * h;\n        }\n\n        return res;\n    };\n\n    vector<Option> opts;\n    vector<vector<int>> byStart(N);\n\n    for (int l = 0; l < N; l++) {\n        for (int r = l; r < N; r++) {\n            int hmin = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (dyn_feasible(l, r, h)) {\n                    hmin = h;\n                    break;\n                }\n            }\n            if (hmin == -1) continue;\n\n            vector<Option> tmp;\n\n            auto add_dyn = [&](int h) {\n                if (h < hmin || h > 1000) return;\n                if (!dyn_feasible(l, r, h)) return;\n                tmp.push_back({l, r, h, dyn_cost(l, r, h), false});\n            };\n\n            add_dyn(hmin);\n            for (int x = 1; x <= 8; x++) add_dyn(hmin + x);\n\n            vector<pair<int,int>> fs = {\n                {11,10}, {6,5}, {5,4}, {4,3}, {3,2},\n                {2,1}, {5,2}, {3,1}, {4,1}, {5,1},\n                {6,1}, {8,1}, {10,1}\n            };\n            for (auto [num, den] : fs) {\n                int h = (hmin * num + den - 1) / den;\n                add_dyn(h);\n            }\n\n            int hs = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (stat_feasible(l, r, h)) {\n                    hs = h;\n                    break;\n                }\n            }\n            if (hs != -1) tmp.push_back({l, r, hs, 0, true});\n\n            sort(tmp.begin(), tmp.end(), [](const Option& a, const Option& b) {\n                if (a.h != b.h) return a.h < b.h;\n                if (a.cost != b.cost) return a.cost < b.cost;\n                return a.stat > b.stat;\n            });\n\n            vector<Option> uniq;\n            for (auto& op : tmp) {\n                if (uniq.empty() || uniq.back().h != op.h) uniq.push_back(op);\n                else if (op.cost < uniq.back().cost) uniq.back() = op;\n            }\n\n            ll best = (1LL << 60);\n            for (auto& op : uniq) {\n                if (op.cost < best) {\n                    best = op.cost;\n                    int id = (int)opts.size();\n                    opts.push_back(op);\n                    byStart[l].push_back(id);\n                }\n            }\n        }\n    }\n\n    const ll INF = (1LL << 60);\n    vector<vector<ll>> dp(N + 1, vector<ll>(1001, INF));\n    vector<vector<int>> parH(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parK(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parO(N + 1, vector<int>(1001, -1));\n\n    dp[0][0] = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int used = 0; used <= 1000; used++) {\n            if (dp[i][used] == INF) continue;\n\n            for (int id : byStart[i]) {\n                const Option& op = opts[id];\n                int nu = used + op.h;\n                if (nu > 1000) continue;\n\n                int ni = op.r + 1;\n                ll nv = dp[i][used] + op.cost;\n                if (nv < dp[ni][nu]) {\n                    dp[ni][nu] = nv;\n                    parH[ni][nu] = used;\n                    parK[ni][nu] = i;\n                    parO[ni][nu] = id;\n                }\n            }\n        }\n    }\n\n    int bestH = -1;\n    ll bestV = INF;\n    for (int h = 0; h <= 1000; h++) {\n        if (dp[N][h] < bestV) {\n            bestV = dp[N][h];\n            bestH = h;\n        }\n    }\n\n    if (bestH == -1 || bestV == INF) return {};\n\n    vector<Option> rows;\n    int curK = N, curH = bestH;\n    while (curK > 0) {\n        int id = parO[curK][curH];\n        if (id < 0) return {};\n        rows.push_back(opts[id]);\n\n        int pk = parK[curK][curH];\n        int ph = parH[curK][curH];\n        curK = pk;\n        curH = ph;\n    }\n\n    reverse(rows.begin(), rows.end());\n\n    auto sol = make_empty_solution();\n\n    int y = 0;\n    for (auto& op : rows) {\n        int l = op.l, r = op.r, h = op.h;\n\n        if (op.stat) {\n            vector<int> widths(r - l + 1);\n            int sum = 0;\n            for (int k = l; k < r; k++) {\n                widths[k - l] = ceil_div(maxA[k], h);\n                sum += widths[k - l];\n            }\n            widths[r - l] = W - sum;\n\n            for (int d = 0; d < D; d++) {\n                int x = 0;\n                for (int k = l; k <= r; k++) {\n                    int w = widths[k - l];\n                    sol[d][k] = {y, x, y + h, x + w};\n                    x += w;\n                }\n            }\n        } else {\n            for (int d = 0; d < D; d++) {\n                vector<int> widths(r - l + 1);\n                int sum = 0;\n                for (int k = l; k < r; k++) {\n                    widths[k - l] = ceil_div(A[d][k], h);\n                    sum += widths[k - l];\n                }\n                widths[r - l] = W - sum;\n\n                int x = 0;\n                for (int k = l; k <= r; k++) {\n                    int w = widths[k - l];\n                    sol[d][k] = {y, x, y + h, x + w};\n                    x += w;\n                }\n            }\n        }\n\n        y += h;\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> day_shelf_solution() {\n    int K = N + 1;\n    int HD = 1001;\n\n    vector<int> pref(HD * D * K, 0);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) {\n                P(h, d, k + 1) = P(h, d, k) + ceil_div(A[d][k], h);\n            }\n        }\n    }\n\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        vector<vector<int>> hmin(N, vector<int>(N, -1));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l; r < N; r++) {\n                for (int h = 1; h <= 1000; h++) {\n                    int s = P(h, d, r + 1) - P(h, d, l);\n                    if (s <= W) {\n                        hmin[l][r] = h;\n                        break;\n                    }\n                }\n            }\n        }\n\n        const int INF = 1e9;\n        vector<int> dp(N + 1, INF), par(N + 1, -1);\n        dp[0] = 0;\n\n        for (int i = 0; i < N; i++) {\n            if (dp[i] == INF) continue;\n            for (int r = i; r < N; r++) {\n                int h = hmin[i][r];\n                if (h < 0) continue;\n                if (dp[i] + h < dp[r + 1]) {\n                    dp[r + 1] = dp[i] + h;\n                    par[r + 1] = i;\n                }\n            }\n        }\n\n        if (dp[N] > 1000) return {};\n\n        vector<pair<int,int>> rows;\n        int cur = N;\n        while (cur > 0) {\n            int p = par[cur];\n            if (p < 0) return {};\n            rows.push_back({p, cur - 1});\n            cur = p;\n        }\n        reverse(rows.begin(), rows.end());\n\n        int y = 0;\n        for (auto [l, r] : rows) {\n            int h = hmin[l][r];\n\n            int x = 0;\n            for (int k = l; k < r; k++) {\n                int w = ceil_div(A[d][k], h);\n                sol[d][k] = {y, x, y + h, x + w};\n                x += w;\n            }\n            sol[d][r] = {y, x, y + h, W};\n\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\nvector<int> allocate_single_day_heights(int d) {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) -> int {\n        int rem = A[d][k] - h[k] * W;\n        if (rem <= 0) return 0;\n        return min(W, rem);\n    };\n\n    priority_queue<pair<int,int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n        if (b <= 0) break;\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<int> allocate_static_heights() {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) -> int {\n        int res = 0;\n        for (int d = 0; d < D; d++) {\n            int rem = A[d][k] - h[k] * W;\n            if (rem > 0) res += min(W, rem);\n        }\n        return res;\n    };\n\n    priority_queue<pair<int,int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n        if (b <= 0) break;\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<vector<Rect>> singleton_dynamic_solution() {\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        vector<int> h = allocate_single_day_heights(d);\n        int y = 0;\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> singleton_static_solution() {\n    auto sol = make_empty_solution();\n    vector<int> h = allocate_static_heights();\n\n    for (int d = 0; d < D; d++) {\n        int y = 0;\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inputW;\n    cin >> inputW >> D >> N;\n\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    maxA.assign(N, 0);\n    for (int k = 0; k < N; k++) {\n        for (int d = 0; d < D; d++) {\n            maxA[k] = max(maxA[k], A[d][k]);\n        }\n    }\n\n    vector<vector<vector<Rect>>> candidates;\n\n    auto add_candidate = [&](vector<vector<Rect>> s) {\n        if (valid_solution(s)) candidates.push_back(move(s));\n    };\n\n    add_candidate(stable_shelf_dp());\n    add_candidate(static_bfd_solution());\n    add_candidate(per_day_bfd_solution());\n\n    for (int h : promising_fixed_heights()) {\n        add_candidate(fixed_h_bfd_solution(h));\n    }\n\n    add_candidate(day_shelf_solution());\n\n    // New robust candidates against catastrophic area shortage.\n    add_candidate(treemap_dynamic_solution());\n    add_candidate(treemap_static_max_solution());\n    add_candidate(treemap_static_avg_solution());\n\n    add_candidate(singleton_dynamic_solution());\n    add_candidate(singleton_static_solution());\n\n    Scorer scorer;\n    ll bestScore = (1LL << 62);\n    int bestId = 0;\n\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        ll sc = scorer.score(candidates[i]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestId = i;\n        }\n    }\n\n    const auto& ans = candidates[bestId];\n\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            const Rect& r = ans[d][k];\n            cout << r.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 K = 81;\nstatic constexpr int MOD = 998244353;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int nextInt(int n) {\n        return int(next() % n);\n    }\n};\n\nstruct Action {\n    int m, p, q;\n    int cell[9];\n    int val[9];\n    uint64_t lo, hi;\n};\n\nstruct State {\n    array<int, 81> board;\n    array<int, 81> seq;\n    long long score;\n};\n\nclass Solver {\nprivate:\n    int inN, M, inK;\n    int stamp[20][3][3];\n\n    vector<Action> actions;\n    int DUMMY;\n\n    array<int, 81> initBoard;\n    long long initScore = 0;\n\n    chrono::steady_clock::time_point startTime;\n    static constexpr double TIME_LIMIT = 1.86;\n\n    XorShift rng;\n\n    inline double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    }\n\n    inline bool timeOver() const {\n        return elapsed() >= TIME_LIMIT;\n    }\n\n    inline bool overlapAction(int a, int b) const {\n        if (a == DUMMY || b == DUMMY) return false;\n        return ((actions[a].lo & actions[b].lo) | (actions[a].hi & actions[b].hi)) != 0;\n    }\n\n    inline long long gainAdd(const array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long g = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv + a.val[k];\n            if (nv >= MOD) nv -= MOD;\n            g += (long long)nv - oldv;\n        }\n\n        return g;\n    }\n\n    inline long long gainRemove(const array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long g = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv - a.val[k];\n            if (nv < 0) nv += MOD;\n            g += (long long)nv - oldv;\n        }\n\n        return g;\n    }\n\n    inline long long applyAdd(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv + a.val[k];\n            if (nv >= MOD) nv -= MOD;\n            board[c] = nv;\n            diff += (long long)nv - oldv;\n        }\n\n        return diff;\n    }\n\n    inline long long applyRemove(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = 0;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int oldv = board[c];\n            int nv = oldv - a.val[k];\n            if (nv < 0) nv += MOD;\n            board[c] = nv;\n            diff += (long long)nv - oldv;\n        }\n\n        return diff;\n    }\n\n    State emptyState() const {\n        State st;\n        st.board = initBoard;\n        st.seq.fill(DUMMY);\n        st.score = initScore;\n        return st;\n    }\n\n    template<int C>\n    inline void insertTop(array<int, C>& ids, array<long long, C>& gs, int id, long long g) {\n        if (g <= gs[C - 1]) return;\n\n        int pos = C - 1;\n        while (pos > 0 && g > gs[pos - 1]) {\n            ids[pos] = ids[pos - 1];\n            gs[pos] = gs[pos - 1];\n            pos--;\n        }\n        ids[pos] = id;\n        gs[pos] = g;\n    }\n\n    int bestAction(const array<int, 81>& board) const {\n        long long bestG = 0;\n        int bestId = DUMMY;\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(board, id);\n            if (g > bestG) {\n                bestG = g;\n                bestId = id;\n            }\n        }\n\n        return bestId;\n    }\n\n    State greedyState() {\n        State st = emptyState();\n\n        for (int t = 0; t < K; t++) {\n            int id = bestAction(st.board);\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    State randomizedGreedyState(int topC) {\n        State st = emptyState();\n        topC = min(topC, 32);\n\n        for (int t = 0; t < K; t++) {\n            array<int, 32> ids;\n            array<long long, 32> gs;\n            ids.fill(DUMMY);\n            gs.fill(LLONG_MIN / 4);\n\n            auto ins = [&](int id, long long g) {\n                if (g <= gs[topC - 1]) return;\n                int pos = topC - 1;\n                while (pos > 0 && g > gs[pos - 1]) {\n                    ids[pos] = ids[pos - 1];\n                    gs[pos] = gs[pos - 1];\n                    pos--;\n                }\n                ids[pos] = id;\n                gs[pos] = g;\n            };\n\n            ins(DUMMY, 0);\n\n            for (int id = 0; id < DUMMY; id++) {\n                ins(id, gainAdd(st.board, id));\n            }\n\n            int r;\n            int x = rng.nextInt(100);\n\n            if (x < 55) r = 0;\n            else if (x < 75) r = min(1, topC - 1);\n            else if (x < 88) r = min(2, topC - 1);\n            else r = rng.nextInt(topC);\n\n            int id = ids[r];\n            if (gs[r] < 0) id = DUMMY;\n\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    void shuffleOrder(array<int, 81>& ord) {\n        for (int i = K - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    void coordinateDescent(State& st, int maxPass) {\n        array<int, 81> ord;\n        for (int i = 0; i < K; i++) ord[i] = i;\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            if (timeOver()) return;\n\n            shuffleOrder(ord);\n            bool changed = false;\n\n            for (int oi = 0; oi < K; oi++) {\n                if ((oi & 7) == 0 && timeOver()) return;\n\n                int idx = ord[oi];\n                int oldId = st.seq[idx];\n\n                st.score += applyRemove(st.board, oldId);\n\n                long long bestG = 0;\n                int bestId = DUMMY;\n\n                for (int id = 0; id < DUMMY; id++) {\n                    long long g = gainAdd(st.board, id);\n                    if (g > bestG) {\n                        bestG = g;\n                        bestId = id;\n                    }\n                }\n\n                st.seq[idx] = bestId;\n                st.score += applyAdd(st.board, bestId);\n\n                if (bestId != oldId) changed = true;\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    int weakSlot(const State& st, int samples = 18) {\n        int bestIdx = rng.nextInt(K);\n        long long bestRemoveGain = gainRemove(st.board, st.seq[bestIdx]);\n\n        for (int t = 1; t < samples; t++) {\n            int idx = rng.nextInt(K);\n            long long g = gainRemove(st.board, st.seq[idx]);\n\n            if (g > bestRemoveGain) {\n                bestRemoveGain = g;\n                bestIdx = idx;\n            }\n        }\n\n        return bestIdx;\n    }\n\n    int weakSlotExcept(const State& st, int except, int refAction, int samples = 24) {\n        int bestIdx = -1;\n        long long bestValue = LLONG_MIN / 4;\n\n        for (int t = 0; t < samples; t++) {\n            int idx = rng.nextInt(K);\n            if (idx == except) continue;\n\n            long long v = gainRemove(st.board, st.seq[idx]);\n\n            if (overlapAction(refAction, st.seq[idx])) {\n                v += MOD / 2;\n            }\n\n            if (v > bestValue) {\n                bestValue = v;\n                bestIdx = idx;\n            }\n        }\n\n        if (bestIdx == -1) {\n            bestIdx = rng.nextInt(K - 1);\n            if (bestIdx >= except) bestIdx++;\n        }\n\n        return bestIdx;\n    }\n\n    void randomPerturb(State& st, int strength) {\n        for (int r = 0; r < strength; r++) {\n            int idx = rng.nextInt(K);\n            int oldId = st.seq[idx];\n\n            st.score += applyRemove(st.board, oldId);\n\n            int newId = rng.nextInt(DUMMY);\n            st.seq[idx] = newId;\n            st.score += applyAdd(st.board, newId);\n        }\n    }\n\n    void ruinRecreate(State& st, int strength, bool weak) {\n        bool used[81] = {};\n        vector<int> slots;\n        slots.reserve(strength);\n\n        while ((int)slots.size() < strength) {\n            int idx;\n\n            if (weak) {\n                idx = -1;\n                long long best = LLONG_MIN / 4;\n\n                for (int t = 0; t < 25; t++) {\n                    int cand = rng.nextInt(K);\n                    if (used[cand]) continue;\n\n                    long long g = gainRemove(st.board, st.seq[cand]);\n                    if (g > best) {\n                        best = g;\n                        idx = cand;\n                    }\n                }\n\n                if (idx == -1) idx = rng.nextInt(K);\n            } else {\n                idx = rng.nextInt(K);\n            }\n\n            if (!used[idx]) {\n                used[idx] = true;\n                slots.push_back(idx);\n\n                st.score += applyRemove(st.board, st.seq[idx]);\n                st.seq[idx] = DUMMY;\n            }\n        }\n\n        for (int i = (int)slots.size() - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(slots[i], slots[j]);\n        }\n\n        for (int idx : slots) {\n            int id = bestAction(st.board);\n            st.seq[idx] = id;\n            st.score += applyAdd(st.board, id);\n        }\n    }\n\n    bool pairAttempt(State& st) {\n        int x = weakSlot(st, 16);\n        int y = weakSlotExcept(st, x, st.seq[x], 26);\n\n        int oldX = st.seq[x];\n        int oldY = st.seq[y];\n\n        long long originalScore = st.score;\n\n        st.score += applyRemove(st.board, oldX);\n        st.score += applyRemove(st.board, oldY);\n\n        long long baseScore = st.score;\n\n        static constexpr int C = 28;\n\n        array<int, C> firstIds;\n        array<long long, C> firstGs;\n        firstIds.fill(DUMMY);\n        firstGs.fill(LLONG_MIN / 4);\n\n        insertTop<C>(firstIds, firstGs, DUMMY, 0);\n\n        for (int id = 0; id < DUMMY; id++) {\n            insertTop<C>(firstIds, firstGs, id, gainAdd(st.board, id));\n        }\n\n        long long bestTotal = 0;\n        int bestA = DUMMY;\n        int bestB = DUMMY;\n\n        auto evalFirst = [&](int a) {\n            long long g1 = gainAdd(st.board, a);\n            applyAdd(st.board, a);\n\n            long long bestG2 = 0;\n            int b = DUMMY;\n\n            for (int id = 0; id < DUMMY; id++) {\n                long long g2 = gainAdd(st.board, id);\n                if (g2 > bestG2) {\n                    bestG2 = g2;\n                    b = id;\n                }\n            }\n\n            long long total = g1 + bestG2;\n\n            if (total > bestTotal) {\n                bestTotal = total;\n                bestA = a;\n                bestB = b;\n            }\n\n            applyRemove(st.board, a);\n        };\n\n        for (int i = 0; i < C; i++) evalFirst(firstIds[i]);\n\n        evalFirst(oldX);\n        evalFirst(oldY);\n\n        for (int i = 0; i < 5; i++) {\n            evalFirst(rng.nextInt(DUMMY));\n        }\n\n        if (baseScore + bestTotal > originalScore) {\n            st.seq[x] = bestA;\n            st.seq[y] = bestB;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, bestA);\n            st.score += applyAdd(st.board, bestB);\n\n            return true;\n        } else {\n            st.seq[x] = oldX;\n            st.seq[y] = oldY;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, oldX);\n            st.score += applyAdd(st.board, oldY);\n\n            return false;\n        }\n    }\n\n    bool tripleAttempt(State& st) {\n        int x = weakSlot(st, 14);\n        int y = weakSlotExcept(st, x, st.seq[x], 20);\n\n        int z = -1;\n        for (int t = 0; t < 30; t++) {\n            int cand = rng.nextInt(K);\n            if (cand != x && cand != y) {\n                if (z == -1) {\n                    z = cand;\n                } else {\n                    long long vc = gainRemove(st.board, st.seq[cand]);\n                    long long vz = gainRemove(st.board, st.seq[z]);\n                    if (vc > vz) z = cand;\n                }\n            }\n        }\n\n        if (z == -1) {\n            z = rng.nextInt(K);\n            while (z == x || z == y) z = rng.nextInt(K);\n        }\n\n        int oldX = st.seq[x];\n        int oldY = st.seq[y];\n        int oldZ = st.seq[z];\n\n        long long originalScore = st.score;\n\n        st.score += applyRemove(st.board, oldX);\n        st.score += applyRemove(st.board, oldY);\n        st.score += applyRemove(st.board, oldZ);\n\n        long long baseScore = st.score;\n\n        static constexpr int C1 = 12;\n        static constexpr int C2 = 7;\n\n        array<int, C1> firstIds;\n        array<long long, C1> firstGs;\n        firstIds.fill(DUMMY);\n        firstGs.fill(LLONG_MIN / 4);\n\n        insertTop<C1>(firstIds, firstGs, DUMMY, 0);\n\n        for (int id = 0; id < DUMMY; id++) {\n            insertTop<C1>(firstIds, firstGs, id, gainAdd(st.board, id));\n        }\n\n        long long bestTotal = 0;\n        int bestA = DUMMY;\n        int bestB = DUMMY;\n        int bestC = DUMMY;\n\n        auto evalFirst = [&](int a) {\n            long long g1 = gainAdd(st.board, a);\n            applyAdd(st.board, a);\n\n            array<int, C2> secondIds;\n            array<long long, C2> secondGs;\n            secondIds.fill(DUMMY);\n            secondGs.fill(LLONG_MIN / 4);\n\n            insertTop<C2>(secondIds, secondGs, DUMMY, 0);\n\n            for (int id = 0; id < DUMMY; id++) {\n                insertTop<C2>(secondIds, secondGs, id, gainAdd(st.board, id));\n            }\n\n            for (int bi = 0; bi < C2; bi++) {\n                int b = secondIds[bi];\n                long long g2 = gainAdd(st.board, b);\n                applyAdd(st.board, b);\n\n                long long bestG3 = 0;\n                int c = DUMMY;\n\n                for (int id = 0; id < DUMMY; id++) {\n                    long long g3 = gainAdd(st.board, id);\n                    if (g3 > bestG3) {\n                        bestG3 = g3;\n                        c = id;\n                    }\n                }\n\n                long long total = g1 + g2 + bestG3;\n\n                if (total > bestTotal) {\n                    bestTotal = total;\n                    bestA = a;\n                    bestB = b;\n                    bestC = c;\n                }\n\n                applyRemove(st.board, b);\n            }\n\n            applyRemove(st.board, a);\n        };\n\n        for (int i = 0; i < C1; i++) evalFirst(firstIds[i]);\n\n        evalFirst(oldX);\n        evalFirst(oldY);\n        evalFirst(oldZ);\n\n        for (int i = 0; i < 3; i++) {\n            evalFirst(rng.nextInt(DUMMY));\n        }\n\n        if (baseScore + bestTotal > originalScore) {\n            st.seq[x] = bestA;\n            st.seq[y] = bestB;\n            st.seq[z] = bestC;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, bestA);\n            st.score += applyAdd(st.board, bestB);\n            st.score += applyAdd(st.board, bestC);\n\n            return true;\n        } else {\n            st.seq[x] = oldX;\n            st.seq[y] = oldY;\n            st.seq[z] = oldZ;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, oldX);\n            st.score += applyAdd(st.board, oldY);\n            st.score += applyAdd(st.board, oldZ);\n\n            return false;\n        }\n    }\n\n    void pairLocalSearch(State& st, int attempts) {\n        int improved = 0;\n\n        for (int t = 0; t < attempts; t++) {\n            if ((t & 3) == 0 && timeOver()) return;\n\n            if (pairAttempt(st)) {\n                improved++;\n\n                if ((improved & 7) == 0) {\n                    coordinateDescent(st, 2);\n                }\n            }\n        }\n\n        if (improved > 0) coordinateDescent(st, 4);\n    }\n\n    void tripleLocalSearch(State& st, int attempts) {\n        int improved = 0;\n\n        for (int t = 0; t < attempts; t++) {\n            if (timeOver()) return;\n\n            if (tripleAttempt(st)) {\n                improved++;\n\n                if ((improved & 3) == 0) {\n                    coordinateDescent(st, 2);\n                }\n            }\n        }\n\n        if (improved > 0) coordinateDescent(st, 4);\n    }\n\npublic:\n    void readInput() {\n        cin >> inN >> M >> inK;\n\n        uint64_t seed = 123456789123ULL;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int x;\n                cin >> x;\n\n                initBoard[i * N + j] = x;\n                initScore += x;\n\n                seed ^= uint64_t(x + 1) * 1000003ULL;\n                seed = seed * 11995408973635179863ULL + 101;\n            }\n        }\n\n        for (int m = 0; m < M; m++) {\n            for (int i = 0; i < 3; i++) {\n                for (int j = 0; j < 3; j++) {\n                    cin >> stamp[m][i][j];\n\n                    seed ^= uint64_t(stamp[m][i][j] + 7) * 1000000007ULL;\n                    seed = seed * 1000003ULL + 97;\n                }\n            }\n        }\n\n        rng = XorShift(seed);\n    }\n\n    void buildActions() {\n        actions.clear();\n\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                for (int m = 0; m < M; m++) {\n                    Action a;\n                    a.m = m;\n                    a.p = p;\n                    a.q = q;\n                    a.lo = 0;\n                    a.hi = 0;\n\n                    int idx = 0;\n\n                    for (int di = 0; di < 3; di++) {\n                        for (int dj = 0; dj < 3; dj++) {\n                            int c = (p + di) * N + (q + dj);\n\n                            a.cell[idx] = c;\n                            a.val[idx] = stamp[m][di][dj];\n\n                            if (c < 64) {\n                                a.lo |= 1ULL << c;\n                            } else {\n                                a.hi |= 1ULL << (c - 64);\n                            }\n\n                            idx++;\n                        }\n                    }\n\n                    actions.push_back(a);\n                }\n            }\n        }\n\n        DUMMY = (int)actions.size();\n    }\n\n    void solve() {\n        startTime = chrono::steady_clock::now();\n\n        buildActions();\n\n        State best = greedyState();\n        coordinateDescent(best, 1000);\n\n        pairLocalSearch(best, 90);\n        tripleLocalSearch(best, 8);\n\n        int iter = 0;\n\n        while (!timeOver()) {\n            State cand;\n\n            int mode = iter % 10;\n\n            if (mode <= 3) {\n                cand = best;\n                int strength = 3 + rng.nextInt(10);\n                bool weak = (mode <= 1);\n                ruinRecreate(cand, strength, weak);\n                coordinateDescent(cand, 22);\n                pairLocalSearch(cand, 16);\n                if ((iter & 3) == 0) tripleLocalSearch(cand, 2);\n            } else if (mode <= 6) {\n                cand = best;\n                int strength = 3 + rng.nextInt(12);\n                randomPerturb(cand, strength);\n                coordinateDescent(cand, 26);\n                pairLocalSearch(cand, 14);\n                if ((iter & 7) == 0) tripleLocalSearch(cand, 2);\n            } else {\n                int topC = 6 + rng.nextInt(14);\n                cand = randomizedGreedyState(topC);\n                coordinateDescent(cand, 36);\n                pairLocalSearch(cand, 14);\n                if ((iter & 7) == 1) tripleLocalSearch(cand, 2);\n            }\n\n            if (cand.score > best.score) {\n                best = cand;\n                coordinateDescent(best, 6);\n                pairLocalSearch(best, 8);\n            }\n\n            iter++;\n        }\n\n        vector<tuple<int, int, int>> ans;\n\n        for (int i = 0; i < K; i++) {\n            int id = best.seq[i];\n            if (id == DUMMY) continue;\n\n            const Action& a = actions[id];\n            ans.emplace_back(a.m, a.p, a.q);\n        }\n\n        cout << ans.size() << '\\n';\n\n        for (auto [m, p, q] : ans) {\n            cout << m << ' ' << p << ' ' << q << '\\n';\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\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int V = 25;\n\nstruct Macro {\n    int type;\n    int sr, sc, dr, dc;\n};\n\nstruct Param {\n    int deliverMode;\n    int digMode;\n    int storeMode;\n};\n\nstruct GreedySolver {\n    vector<vector<int>> A;\n    Param param;\n\n    int grid[N][N];\n    int idx[N];\n\n    int cr = 0, cc = 0;\n    int hold = -1;\n\n    vector<string> S;\n    bool firstStep = true;\n\n    vector<int> nextNeed;\n    vector<int> delivered;\n    int deliveredCnt = 0;\n\n    GreedySolver(const vector<vector<int>>& A_, Param p) : A(A_), param(p) {\n        memset(grid, -1, sizeof(grid));\n        memset(idx, 0, sizeof(idx));\n        S.assign(N, \"\");\n        nextNeed.resize(N);\n        delivered.assign(V, 0);\n        for (int g = 0; g < N; g++) nextNeed[g] = g * N;\n    }\n\n    int dist(pair<int,int> a, pair<int,int> b) const {\n        return abs(a.first - b.first) + abs(a.second - b.second);\n    }\n\n    void step(char act) {\n        for (int r = 0; r < N; r++) {\n            bool blockedByHolding = (hold != -1 && cr == r && cc == 0);\n            if (idx[r] < N && grid[r][0] == -1 && !blockedByHolding) {\n                grid[r][0] = A[r][idx[r]];\n                idx[r]++;\n            }\n        }\n\n        S[0].push_back(act);\n        for (int i = 1; i < N; i++) {\n            if (firstStep) S[i].push_back('B');\n            else S[i].push_back('.');\n        }\n        firstStep = false;\n\n        if (act == 'P') {\n            hold = grid[cr][cc];\n            grid[cr][cc] = -1;\n        } else if (act == 'Q') {\n            grid[cr][cc] = hold;\n            hold = -1;\n        } else if (act == 'U') cr--;\n        else if (act == 'D') cr++;\n        else if (act == 'L') cc--;\n        else if (act == 'R') cc++;\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][N - 1] != -1) grid[r][N - 1] = -1;\n        }\n    }\n\n    void moveTo(int r, int c) {\n        while (cr < r) step('D');\n        while (cr > r) step('U');\n        while (cc < c) step('R');\n        while (cc > c) step('L');\n    }\n\n    void pickAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('P');\n    }\n\n    void releaseAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('Q');\n    }\n\n    void markDelivered(int id) {\n        if (!delivered[id]) {\n            delivered[id] = 1;\n            deliveredCnt++;\n        }\n\n        int g = id / N;\n        while (nextNeed[g] < (g + 1) * N && delivered[nextNeed[g]]) {\n            nextNeed[g]++;\n        }\n    }\n\n    optional<pair<int,int>> findAccessible(int id) {\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (grid[r][c] == id) return pair<int,int>{r, c};\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == id) {\n                return pair<int,int>{r, 0};\n            }\n        }\n\n        return nullopt;\n    }\n\n    int frontId(int r) const {\n        if (grid[r][0] != -1) return grid[r][0];\n        if (idx[r] < N) return A[r][idx[r]];\n        return -1;\n    }\n\n    vector<pair<int,int>> freeStorageCells() const {\n        vector<pair<int,int>> res;\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 1; c <= 3; c++) {\n                if (grid[r][c] == -1) res.push_back({r, c});\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (idx[r] >= N && grid[r][0] == -1) res.push_back({r, 0});\n        }\n\n        return res;\n    }\n\n    int estimateNextAfterDeliver(int deliveredId) {\n        int g0 = deliveredId / N;\n        int best = 20;\n\n        for (int g = 0; g < N; g++) {\n            int target = nextNeed[g];\n            if (g == g0) target++;\n            if (target >= (g + 1) * N) continue;\n\n            optional<pair<int,int>> pos;\n\n            for (int r = 0; r < N; r++) {\n                for (int c = 0; c < N; c++) {\n                    if (grid[r][c] == target && target != deliveredId) {\n                        pos = {r, c};\n                    }\n                }\n            }\n\n            for (int r = 0; r < N; r++) {\n                if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == target) {\n                    pos = {r, 0};\n                }\n            }\n\n            if (pos) {\n                best = min(best, dist({g0, N - 1}, *pos) + dist(*pos, {g, N - 1}));\n            }\n        }\n\n        return best;\n    }\n\n    int dispatchScore(int id, pair<int,int> src) {\n        int g = id / N;\n        int base = dist({cr, cc}, src) + dist(src, {g, N - 1});\n\n        if (param.deliverMode == 0) {\n            return base * 10;\n        } else if (param.deliverMode == 1) {\n            return dist({cr, cc}, src) * 15 + dist(src, {g, N - 1}) * 5;\n        } else if (param.deliverMode == 2) {\n            return base * 10 + estimateNextAfterDeliver(id) * 3;\n        } else {\n            return base * 10 - src.second * 2;\n        }\n    }\n\n    int depthToNeeded(int r) {\n        bool need[V] = {};\n        for (int g = 0; g < N; g++) {\n            if (nextNeed[g] < (g + 1) * N) need[nextNeed[g]] = true;\n        }\n\n        int d = 0;\n        if (grid[r][0] != -1) {\n            if (need[grid[r][0]]) return 0;\n            d = 1;\n        }\n\n        for (int k = idx[r]; k < N; k++, d++) {\n            if (need[A[r][k]]) return d;\n        }\n\n        return 100;\n    }\n\n    int digScore(int r) {\n        int f = frontId(r);\n        int dep = depthToNeeded(r);\n        int dcur = abs(cr - r) + cc;\n\n        int future = 0;\n        if (f != -1) {\n            int g = f / N;\n            future = abs(r - g) + 4;\n        }\n\n        if (param.digMode == 0) {\n            return dep * 100 + dcur * 5;\n        } else if (param.digMode == 1) {\n            return dep * 35 + dcur * 8 + future * 2;\n        } else if (param.digMode == 2) {\n            return dep * 25 + dcur * 15;\n        } else if (param.digMode == 3) {\n            return dep * 50 + dcur * 3 + future * 5;\n        } else {\n            return dep * 20 + dcur * 20 + r;\n        }\n    }\n\n    int chooseRowToDig() {\n        int bestRow = -1;\n        int bestScore = 1e9;\n\n        for (int r = 0; r < N; r++) {\n            int f = frontId(r);\n            if (f == -1) continue;\n\n            if (idx[r] >= N && grid[r][0] != -1) continue;\n\n            int sc = digScore(r);\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestRow = r;\n            }\n        }\n\n        if (bestRow != -1) return bestRow;\n\n        for (int r = 0; r < N; r++) {\n            if (frontId(r) != -1) return r;\n        }\n\n        return -1;\n    }\n\n    int storageScore(pair<int,int> from, pair<int,int> p, int id) {\n        int g = id / N;\n        int a = dist(from, p);\n        int b = dist(p, {g, N - 1});\n\n        if (param.storeMode == 0) {\n            return a * 10 + b * 10;\n        } else if (param.storeMode == 1) {\n            return a * 18 + b * 7;\n        } else if (param.storeMode == 2) {\n            return a * 7 + b * 18;\n        } else if (param.storeMode == 3) {\n            return a * 10 + b * 10 - p.second * 3;\n        } else {\n            return a * 10 + b * 10 + abs(p.first - g) * 5 - p.second;\n        }\n    }\n\n    pair<int,int> chooseStorageCell(pair<int,int> from, int id) {\n        auto cells = freeStorageCells();\n\n        pair<int,int> best = cells[0];\n        int bestCost = 1e9;\n\n        for (auto p : cells) {\n            int cost = storageScore(from, p, id);\n            if (cost < bestCost) {\n                bestCost = cost;\n                best = p;\n            }\n        }\n\n        return best;\n    }\n\n    void dispatchContainer(int id) {\n        auto srcOpt = findAccessible(id);\n        if (!srcOpt) return;\n\n        auto src = *srcOpt;\n        pickAt(src);\n\n        int g = id / N;\n        releaseAt({g, N - 1});\n\n        markDelivered(id);\n    }\n\n    void storeFrontContainer(int r) {\n        int id = frontId(r);\n        if (id == -1) return;\n\n        pair<int,int> src = {r, 0};\n        auto dst = chooseStorageCell(src, id);\n\n        pickAt(src);\n        releaseAt(dst);\n    }\n\n    void solve() {\n        while (deliveredCnt < V && (int)S[0].size() < 9500) {\n            int bestId = -1;\n            int bestScore = 1e9;\n\n            for (int g = 0; g < N; g++) {\n                if (nextNeed[g] >= (g + 1) * N) continue;\n\n                int id = nextNeed[g];\n                auto srcOpt = findAccessible(id);\n                if (!srcOpt) continue;\n\n                int sc = dispatchScore(id, *srcOpt);\n\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != -1) {\n                dispatchContainer(bestId);\n                continue;\n            }\n\n            auto freeCells = freeStorageCells();\n            if (!freeCells.empty()) {\n                int r = chooseRowToDig();\n                if (r != -1) {\n                    storeFrontContainer(r);\n                    continue;\n                }\n            }\n\n            step('.');\n        }\n\n        if (S[0].empty()) step('.');\n    }\n\n    vector<string> outputStrings() {\n        int T = 0;\n        for (auto &s : S) T = max(T, (int)s.size());\n        for (auto &s : S) {\n            while ((int)s.size() < T) s.push_back('.');\n        }\n        return S;\n    }\n};\n\nstruct BeamNode {\n    array<int8_t, V> cell;\n    array<int8_t, N> idx;\n    array<int8_t, N> nxt;\n    int8_t r, c;\n    int cost;\n    int parent;\n    Macro mv;\n};\n\nstruct TempNode {\n    BeamNode node;\n    int eval;\n};\n\nstruct BeamPlanner {\n    vector<vector<int>> A;\n    vector<BeamNode> nodes;\n    chrono::steady_clock::time_point st;\n    int timeLimitMs;\n\n    BeamPlanner(const vector<vector<int>>& A_, int tl) : A(A_), timeLimitMs(tl) {}\n\n    int pos(int r, int c) const { return r * N + c; }\n\n    int dist(int r1, int c1, int r2, int c2) const {\n        return abs(r1 - r2) + abs(c1 - c2);\n    }\n\n    bool timeout() const {\n        auto now = chrono::steady_clock::now();\n        return chrono::duration_cast<chrono::milliseconds>(now - st).count() > timeLimitMs;\n    }\n\n    void fillGates(BeamNode& nd) {\n        for (int r = 0; r < N; r++) {\n            int p = pos(r, 0);\n            if (nd.cell[p] == -1 && nd.idx[r] < N) {\n                nd.cell[p] = A[r][nd.idx[r]];\n                nd.idx[r]++;\n            }\n        }\n    }\n\n    bool complete(const BeamNode& nd) const {\n        for (int g = 0; g < N; g++) {\n            if (nd.nxt[g] < (g + 1) * N) return false;\n        }\n        return true;\n    }\n\n    int heuristic(const BeamNode& nd) const {\n        int rem = 0;\n        for (int g = 0; g < N; g++) {\n            rem += (g + 1) * N - nd.nxt[g];\n        }\n\n        int h = rem * 6;\n\n        int best = 100;\n        for (int g = 0; g < N; g++) {\n            if (nd.nxt[g] >= (g + 1) * N) continue;\n            int target = nd.nxt[g];\n            for (int p = 0; p < V; p++) {\n                if (nd.cell[p] == target) {\n                    int rr = p / N, cc = p % N;\n                    best = min(best, dist(nd.r, nd.c, rr, cc));\n                }\n            }\n        }\n\n        if (best < 100) h += best;\n        return h;\n    }\n\n    string keyOf(const BeamNode& nd) const {\n        string s;\n        s.reserve(40);\n        for (int i = 0; i < V; i++) s.push_back(char(nd.cell[i] + 1));\n        for (int i = 0; i < N; i++) s.push_back(char(nd.idx[i]));\n        for (int i = 0; i < N; i++) s.push_back(char(nd.nxt[i]));\n        s.push_back(char(nd.r));\n        s.push_back(char(nd.c));\n        return s;\n    }\n\n    vector<pair<int,int>> freeStorageCells(const BeamNode& nd) const {\n        vector<pair<int,int>> res;\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 1; c <= 3; c++) {\n                if (nd.cell[pos(r, c)] == -1) res.push_back({r, c});\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (nd.idx[r] >= N && nd.cell[pos(r, 0)] == -1) {\n                res.push_back({r, 0});\n            }\n        }\n\n        return res;\n    }\n\n    void addCandidate(vector<TempNode>& temp, unordered_map<string, int>& mp, BeamNode&& nd) {\n        int ev = nd.cost + heuristic(nd);\n        string key = keyOf(nd);\n\n        auto it = mp.find(key);\n        if (it == mp.end()) {\n            int id = (int)temp.size();\n            mp.emplace(std::move(key), id);\n            temp.push_back({std::move(nd), ev});\n        } else {\n            int id = it->second;\n            if (nd.cost < temp[id].node.cost) {\n                temp[id] = {std::move(nd), ev};\n            }\n        }\n    }\n\n    vector<Macro> plan() {\n        st = chrono::steady_clock::now();\n\n        BeamNode init;\n        init.cell.fill(-1);\n        init.idx.fill(0);\n        init.nxt.fill(0);\n\n        for (int g = 0; g < N; g++) init.nxt[g] = g * N;\n\n        for (int r = 0; r < N; r++) {\n            init.cell[pos(r, 0)] = A[r][0];\n            init.idx[r] = 1;\n        }\n\n        init.r = 0;\n        init.c = 0;\n        init.cost = 0;\n        init.parent = -1;\n        init.mv = {-1, 0, 0, 0, 0};\n\n        nodes.clear();\n        nodes.reserve(80000);\n        nodes.push_back(init);\n\n        vector<int> cur = {0};\n\n        int bestComplete = -1;\n        int bestCost = INT_MAX;\n\n        const int WIDTH = 550;\n        const int MAX_LAYER = 55;\n        const int STORE_DEST_LIMIT = 5;\n\n        for (int layer = 0; layer < MAX_LAYER; layer++) {\n            if (timeout()) break;\n\n            vector<TempNode> temp;\n            temp.reserve(WIDTH * 20);\n\n            unordered_map<string, int> mp;\n            mp.reserve(WIDTH * 40);\n\n            for (int baseId : cur) {\n                if (timeout()) break;\n\n                const BeamNode& base = nodes[baseId];\n\n                for (int g = 0; g < N; g++) {\n                    if (base.nxt[g] >= (g + 1) * N) continue;\n\n                    int target = base.nxt[g];\n                    int found = -1;\n\n                    for (int p = 0; p < V; p++) {\n                        if (base.cell[p] == target) {\n                            found = p;\n                            break;\n                        }\n                    }\n\n                    if (found == -1) continue;\n\n                    int sr = found / N;\n                    int sc = found % N;\n                    int dr = g;\n                    int dc = N - 1;\n\n                    BeamNode nd = base;\n                    nd.parent = baseId;\n                    nd.mv = {0, sr, sc, dr, dc};\n\n                    nd.cell[found] = -1;\n                    nd.nxt[g]++;\n                    nd.r = dr;\n                    nd.c = dc;\n                    nd.cost += dist(base.r, base.c, sr, sc) + 1\n                             + dist(sr, sc, dr, dc) + 1;\n\n                    nd.cell[pos(dr, dc)] = -1;\n                    fillGates(nd);\n\n                    if (complete(nd)) {\n                        if (nd.cost < bestCost) {\n                            nodes.push_back(nd);\n                            bestComplete = (int)nodes.size() - 1;\n                            bestCost = nd.cost;\n                        }\n                    } else {\n                        addCandidate(temp, mp, std::move(nd));\n                    }\n                }\n\n                auto freeCells = freeStorageCells(base);\n                if (!freeCells.empty()) {\n                    for (int sr = 0; sr < N; sr++) {\n                        int sp = pos(sr, 0);\n                        int id = base.cell[sp];\n                        if (id == -1) continue;\n\n                        int group = id / N;\n                        if (base.nxt[group] == id) continue;\n\n                        vector<pair<int, pair<int,int>>> dsts;\n\n                        for (auto [dr, dc] : freeCells) {\n                            if (dr == sr && dc == 0) continue;\n\n                            int nowCost = dist(base.r, base.c, sr, 0) + 1\n                                        + dist(sr, 0, dr, dc) + 1;\n                            int futureCost = dist(dr, dc, group, N - 1);\n                            int score = nowCost + futureCost - dc;\n\n                            dsts.push_back({score, {dr, dc}});\n                        }\n\n                        sort(dsts.begin(), dsts.end());\n\n                        int lim = min((int)dsts.size(), STORE_DEST_LIMIT);\n                        for (int k = 0; k < lim; k++) {\n                            int dr = dsts[k].second.first;\n                            int dc = dsts[k].second.second;\n\n                            BeamNode nd = base;\n                            nd.parent = baseId;\n                            nd.mv = {1, sr, 0, dr, dc};\n\n                            nd.cell[sp] = -1;\n                            nd.cell[pos(dr, dc)] = id;\n                            nd.r = dr;\n                            nd.c = dc;\n                            nd.cost += dist(base.r, base.c, sr, 0) + 1\n                                     + dist(sr, 0, dr, dc) + 1;\n\n                            fillGates(nd);\n                            addCandidate(temp, mp, std::move(nd));\n                        }\n                    }\n                }\n            }\n\n            if (temp.empty()) break;\n\n            vector<int> ord(temp.size());\n            iota(ord.begin(), ord.end(), 0);\n\n            int take = min(WIDTH, (int)ord.size());\n\n            if (take < (int)ord.size()) {\n                nth_element(ord.begin(), ord.begin() + take, ord.end(), [&](int a, int b) {\n                    if (temp[a].eval != temp[b].eval) return temp[a].eval < temp[b].eval;\n                    return temp[a].node.cost < temp[b].node.cost;\n                });\n            }\n\n            ord.resize(take);\n\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (temp[a].eval != temp[b].eval) return temp[a].eval < temp[b].eval;\n                return temp[a].node.cost < temp[b].node.cost;\n            });\n\n            cur.clear();\n            cur.reserve(take);\n\n            for (int id : ord) {\n                nodes.push_back(std::move(temp[id].node));\n                cur.push_back((int)nodes.size() - 1);\n            }\n        }\n\n        vector<Macro> res;\n        if (bestComplete == -1) return res;\n\n        int v = bestComplete;\n        while (nodes[v].parent != -1) {\n            res.push_back(nodes[v].mv);\n            v = nodes[v].parent;\n        }\n\n        reverse(res.begin(), res.end());\n        return res;\n    }\n};\n\nstruct Executor {\n    vector<vector<int>> A;\n    int grid[N][N];\n    int idx[N];\n    int cr = 0, cc = 0;\n    int hold = -1;\n    bool first = true;\n    bool valid = true;\n    vector<string> S;\n\n    Executor(const vector<vector<int>>& A_) : A(A_) {\n        memset(grid, -1, sizeof(grid));\n        memset(idx, 0, sizeof(idx));\n        S.assign(N, \"\");\n    }\n\n    void step(char act) {\n        if (!valid) return;\n\n        for (int r = 0; r < N; r++) {\n            bool blockedByHolding = (hold != -1 && cr == r && cc == 0);\n            if (idx[r] < N && grid[r][0] == -1 && !blockedByHolding) {\n                grid[r][0] = A[r][idx[r]];\n                idx[r]++;\n            }\n        }\n\n        S[0].push_back(act);\n        for (int i = 1; i < N; i++) {\n            if (first) S[i].push_back('B');\n            else S[i].push_back('.');\n        }\n        first = false;\n\n        if (act == 'P') {\n            if (hold != -1 || grid[cr][cc] == -1) {\n                valid = false;\n                return;\n            }\n            hold = grid[cr][cc];\n            grid[cr][cc] = -1;\n        } else if (act == 'Q') {\n            if (hold == -1 || grid[cr][cc] != -1) {\n                valid = false;\n                return;\n            }\n            grid[cr][cc] = hold;\n            hold = -1;\n        } else if (act == 'U') {\n            if (cr == 0) valid = false;\n            else cr--;\n        } else if (act == 'D') {\n            if (cr == N - 1) valid = false;\n            else cr++;\n        } else if (act == 'L') {\n            if (cc == 0) valid = false;\n            else cc--;\n        } else if (act == 'R') {\n            if (cc == N - 1) valid = false;\n            else cc++;\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][N - 1] != -1) {\n                grid[r][N - 1] = -1;\n            }\n        }\n    }\n\n    void moveTo(int r, int c) {\n        while (valid && cr < r) step('D');\n        while (valid && cr > r) step('U');\n        while (valid && cc < c) step('R');\n        while (valid && cc > c) step('L');\n    }\n\n    bool executePlan(const vector<Macro>& plan) {\n        for (auto &m : plan) {\n            moveTo(m.sr, m.sc);\n            step('P');\n            moveTo(m.dr, m.dc);\n            step('Q');\n            if (!valid) return false;\n        }\n        if (S[0].empty()) step('.');\n        return valid;\n    }\n\n    vector<string> outputStrings() {\n        int T = 0;\n        for (auto &s : S) T = max(T, (int)s.size());\n        for (auto &s : S) {\n            while ((int)s.size() < T) s.push_back('.');\n        }\n        return S;\n    }\n};\n\nint outputLength(const vector<string>& s) {\n    int t = 0;\n    for (auto &x : s) t = max(t, (int)x.size());\n    return t;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto globalStart = chrono::steady_clock::now();\n\n    int inputN;\n    cin >> inputN;\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<string> best;\n    int bestLen = INT_MAX;\n\n    vector<Param> params;\n    for (int dm = 0; dm < 4; dm++) {\n        for (int dig = 0; dig < 5; dig++) {\n            for (int sm = 0; sm < 5; sm++) {\n                params.push_back({dm, dig, sm});\n            }\n        }\n    }\n\n    // Put the previously strong/default-like settings early.\n    params.insert(params.begin(), {0, 0, 0});\n    params.insert(params.begin(), {0, 0, 4});\n    params.insert(params.begin(), {2, 1, 4});\n\n    for (auto p : params) {\n        GreedySolver solver(A, p);\n        solver.solve();\n\n        if (solver.deliveredCnt != V) continue;\n\n        vector<string> cand = solver.outputStrings();\n        int len = outputLength(cand);\n\n        if (len < bestLen) {\n            bestLen = len;\n            best = cand;\n        }\n    }\n\n    // Safety fallback, though normally best is already set.\n    if (best.empty()) {\n        GreedySolver solver(A, {0, 0, 0});\n        solver.solve();\n        best = solver.outputStrings();\n        bestLen = outputLength(best);\n    }\n\n    auto afterGreedy = chrono::steady_clock::now();\n    int elapsedMs = chrono::duration_cast<chrono::milliseconds>(afterGreedy - globalStart).count();\n\n    // Optional beam search with conservative time budget.\n    if (elapsedMs < 500) {\n        int beamBudget = 1300;\n        BeamPlanner planner(A, beamBudget);\n        vector<Macro> plan = planner.plan();\n\n        if (!plan.empty()) {\n            Executor exec(A);\n            if (exec.executePlan(plan)) {\n                vector<string> cand = exec.outputStrings();\n                int len = outputLength(cand);\n                if (len < bestLen) {\n                    bestLen = len;\n                    best = cand;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int B = 10;\nstatic const int V = N * N;\nstatic const long long INF = (1LL << 60);\n\nint hval[V];\nlong long base_cost = 0;\n\nint dr[4] = {-1, 0, 1, 0};\nint dc[4] = {0, 1, 0, -1};\nchar mvchar[4] = {'U', 'R', 'D', 'L'};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n\n    DSU(int n = 0) { init(n); }\n\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n\n        if (a == b) return false;\n\n        if (sz[a] < sz[b]) swap(a, b);\n\n        p[b] = a;\n        sz[a] += sz[b];\n\n        return true;\n    }\n};\n\nstruct Edge {\n    int a, b;\n};\n\nstruct EvalResult {\n    long long cost = INF;\n    vector<int> order; // only nonzero cells, in visiting order\n};\n\nint id20(int r, int c) {\n    return r * N + c;\n}\n\nint manhattan20(int a, int b) {\n    return abs(a / N - b / N) + abs(a % N - b % N);\n}\n\nint dir_between(int a, int b) {\n    int ar = a / N;\n    int ac = a % N;\n    int br = b / N;\n    int bc = b % N;\n\n    for (int d = 0; d < 4; d++) {\n        if (ar + dr[d] == br && ac + dc[d] == bc) return d;\n    }\n\n    return -1;\n}\n\nvoid add_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n\n    if (d < 0 || e < 0) return;\n\n    mask[a] |= (1u << d);\n    mask[b] |= (1u << e);\n}\n\nvoid remove_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n\n    if (d < 0 || e < 0) return;\n\n    mask[a] &= ~(1u << d);\n    mask[b] &= ~(1u << e);\n}\n\nbool build_cycle_from_tree_edges(const vector<Edge>& tree_edges, vector<int>& cyc) {\n    array<unsigned char, V> mask;\n    mask.fill(0);\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int a = id20(2 * r, 2 * c);\n            int b = id20(2 * r, 2 * c + 1);\n            int e = id20(2 * r + 1, 2 * c + 1);\n            int d = id20(2 * r + 1, 2 * c);\n\n            add_edge_cell(mask, a, b);\n            add_edge_cell(mask, b, e);\n            add_edge_cell(mask, e, d);\n            add_edge_cell(mask, d, a);\n        }\n    }\n\n    for (auto ed : tree_edges) {\n        int ar = ed.a / B;\n        int ac = ed.a % B;\n        int br = ed.b / B;\n        int bc = ed.b % B;\n\n        if (ar == br) {\n            int r = ar;\n            int c = min(ac, bc);\n\n            int a1 = id20(2 * r, 2 * c + 1);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r, 2 * c + 2);\n            int b2 = id20(2 * r + 1, 2 * c + 2);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        } else {\n            int r = min(ar, br);\n            int c = ac;\n\n            int a1 = id20(2 * r + 1, 2 * c);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r + 2, 2 * c);\n            int b2 = id20(2 * r + 2, 2 * c + 1);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        }\n    }\n\n    for (int i = 0; i < V; i++) {\n        if (__builtin_popcount((int)mask[i]) != 2) return false;\n    }\n\n    cyc.clear();\n\n    int start = 0;\n    int cur = start;\n    int prev = -1;\n\n    while (true) {\n        cyc.push_back(cur);\n\n        int nxt = -1;\n\n        for (int d = 0; d < 4; d++) {\n            if (!(mask[cur] & (1u << d))) continue;\n\n            int r = cur / N + dr[d];\n            int c = cur % N + dc[d];\n            int nb = id20(r, c);\n\n            if (nb != prev) {\n                nxt = nb;\n                break;\n            }\n        }\n\n        if (nxt < 0) return false;\n\n        prev = cur;\n        cur = nxt;\n\n        if (cur == start) break;\n        if ((int)cyc.size() > V) return false;\n    }\n\n    return (int)cyc.size() == V;\n}\n\n// Evaluate a Hamiltonian cycle, but skip h=0 cells.\n// Movement between consecutive nonzero cells uses shortest Manhattan distance.\nvoid evaluate_cycle_order_skip_zero(const vector<int>& cyc, EvalResult& res, bool store_order) {\n    vector<int> seq;\n    seq.reserve(V);\n\n    for (int x : cyc) {\n        if (hval[x] != 0) seq.push_back(x);\n    }\n\n    int M = (int)seq.size();\n\n    if (M == 0) {\n        if (0 < res.cost) {\n            res.cost = 0;\n            if (store_order) res.order.clear();\n        }\n        return;\n    }\n\n    vector<int> pref(M + 1, 0);\n    for (int i = 0; i < M; i++) {\n        pref[i + 1] = pref[i] + hval[seq[i]];\n    }\n\n    int mn = pref[0];\n    for (int i = 0; i < M; i++) {\n        mn = min(mn, pref[i]);\n    }\n\n    for (int k = 0; k < M; k++) {\n        if (pref[k] != mn) continue;\n\n        long long load = 0;\n        long long move_cost = 0;\n        bool ok = true;\n\n        int start = seq[k];\n        move_cost += 100LL * (start / N + start % N);\n\n        for (int t = 0; t < M; t++) {\n            int id = seq[(k + t) % M];\n\n            load += hval[id];\n\n            if (load < 0) {\n                ok = false;\n                break;\n            }\n\n            if (t + 1 < M) {\n                int nxt = seq[(k + t + 1) % M];\n                int dist = manhattan20(id, nxt);\n                move_cost += (100LL + load) * dist;\n            }\n        }\n\n        if (!ok || load != 0) continue;\n\n        long long cost = base_cost + move_cost;\n\n        if (cost < res.cost) {\n            res.cost = cost;\n\n            if (store_order) {\n                res.order.clear();\n                res.order.reserve(M);\n\n                for (int t = 0; t < M; t++) {\n                    res.order.push_back(seq[(k + t) % M]);\n                }\n            }\n        }\n    }\n}\n\nEvalResult evaluate_cycle(const vector<int>& cyc, bool store_order) {\n    EvalResult res;\n\n    evaluate_cycle_order_skip_zero(cyc, res, store_order);\n\n    vector<int> rev = cyc;\n    reverse(rev.begin(), rev.end());\n\n    evaluate_cycle_order_skip_zero(rev, res, store_order);\n\n    return res;\n}\n\nvector<Edge> all_edges;\nint edge_id[100][100];\n\nvector<char> tree_to_mask(const vector<Edge>& tr) {\n    vector<char> in(all_edges.size(), 0);\n\n    for (auto e : tr) {\n        int id = edge_id[e.a][e.b];\n        if (id >= 0) in[id] = 1;\n    }\n\n    return in;\n}\n\nvector<Edge> mask_to_tree_edges(const vector<char>& in) {\n    vector<Edge> tr;\n    tr.reserve(B * B - 1);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        if (in[i]) tr.push_back(all_edges[i]);\n    }\n\n    return tr;\n}\n\nEvalResult evaluate_tree_mask(const vector<char>& in, bool store_order) {\n    vector<Edge> tr = mask_to_tree_edges(in);\n    vector<int> cyc;\n\n    if ((int)tr.size() != B * B - 1) return EvalResult();\n\n    if (!build_cycle_from_tree_edges(tr, cyc)) return EvalResult();\n\n    return evaluate_cycle(cyc, store_order);\n}\n\nvector<Edge> make_row_tree(int col) {\n    vector<Edge> res;\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c + 1 < B; c++) {\n            res.push_back({r * B + c, r * B + c + 1});\n        }\n    }\n\n    for (int r = 0; r + 1 < B; r++) {\n        res.push_back({r * B + col, (r + 1) * B + col});\n    }\n\n    return res;\n}\n\nvector<Edge> make_col_tree(int row) {\n    vector<Edge> res;\n\n    for (int c = 0; c < B; c++) {\n        for (int r = 0; r + 1 < B; r++) {\n            res.push_back({r * B + c, (r + 1) * B + c});\n        }\n    }\n\n    for (int c = 0; c + 1 < B; c++) {\n        res.push_back({row * B + c, row * B + c + 1});\n    }\n\n    return res;\n}\n\nvector<char> random_kruskal_tree(mt19937& rng) {\n    vector<int> perm(all_edges.size());\n    iota(perm.begin(), perm.end(), 0);\n\n    shuffle(perm.begin(), perm.end(), rng);\n\n    DSU dsu(B * B);\n    vector<char> in(all_edges.size(), 0);\n\n    int cnt = 0;\n\n    for (int id : perm) {\n        auto e = all_edges[id];\n\n        if (dsu.unite(e.a, e.b)) {\n            in[id] = 1;\n            cnt++;\n\n            if (cnt == B * B - 1) break;\n        }\n    }\n\n    return in;\n}\n\nvector<char> random_prim_tree(mt19937& rng) {\n    vector<vector<pair<int, int>>> g(B * B);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        auto e = all_edges[i];\n        g[e.a].push_back({e.b, i});\n        g[e.b].push_back({e.a, i});\n    }\n\n    vector<char> used(B * B, 0);\n    vector<char> in(all_edges.size(), 0);\n\n    int st = uniform_int_distribution<int>(0, B * B - 1)(rng);\n\n    used[st] = 1;\n\n    vector<pair<int, int>> frontier;\n\n    for (auto p : g[st]) {\n        frontier.push_back({p.first, p.second});\n    }\n\n    int cnt = 0;\n\n    while (cnt < B * B - 1 && !frontier.empty()) {\n        int k = uniform_int_distribution<int>(0, (int)frontier.size() - 1)(rng);\n\n        auto [to, eid] = frontier[k];\n\n        frontier[k] = frontier.back();\n        frontier.pop_back();\n\n        auto e = all_edges[eid];\n\n        int a = e.a;\n        int b = e.b;\n        int nxt = -1;\n\n        if (used[a] && !used[b]) nxt = b;\n        else if (used[b] && !used[a]) nxt = a;\n        else continue;\n\n        used[nxt] = 1;\n        in[eid] = 1;\n        cnt++;\n\n        for (auto p : g[nxt]) {\n            if (!used[p.first]) {\n                frontier.push_back({p.first, p.second});\n            }\n        }\n    }\n\n    return in;\n}\n\nvector<int> get_path_edges_in_tree(const vector<char>& in, int s, int t) {\n    vector<vector<pair<int, int>>> g(B * B);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        if (!in[i]) continue;\n\n        auto e = all_edges[i];\n\n        g[e.a].push_back({e.b, i});\n        g[e.b].push_back({e.a, i});\n    }\n\n    vector<int> par(B * B, -1);\n    vector<int> pedge(B * B, -1);\n\n    queue<int> q;\n\n    par[s] = s;\n    q.push(s);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        if (v == t) break;\n\n        for (auto [to, eid] : g[v]) {\n            if (par[to] != -1) continue;\n\n            par[to] = v;\n            pedge[to] = eid;\n            q.push(to);\n        }\n    }\n\n    vector<int> path;\n\n    if (par[t] == -1) return path;\n\n    int cur = t;\n\n    while (cur != s) {\n        path.push_back(pedge[cur]);\n        cur = par[cur];\n    }\n\n    return path;\n}\n\nvoid local_search(vector<char>& cur_tree, EvalResult& global_best, const Timer& timer) {\n    EvalResult cur_eval = evaluate_tree_mask(cur_tree, false);\n    long long cur_cost = cur_eval.cost;\n\n    if (cur_cost >= INF) return;\n\n    bool improved = true;\n\n    while (timer.elapsed() < 1.85 && improved) {\n        improved = false;\n\n        long long best_cost = cur_cost;\n        int best_add = -1;\n        int best_rem = -1;\n\n        vector<int> non_edges;\n\n        for (int i = 0; i < (int)all_edges.size(); i++) {\n            if (!cur_tree[i]) non_edges.push_back(i);\n        }\n\n        for (int eid : non_edges) {\n            if (timer.elapsed() > 1.85) break;\n\n            auto e = all_edges[eid];\n            vector<int> path = get_path_edges_in_tree(cur_tree, e.a, e.b);\n\n            for (int rem : path) {\n                cur_tree[eid] = 1;\n                cur_tree[rem] = 0;\n\n                EvalResult ev = evaluate_tree_mask(cur_tree, false);\n\n                cur_tree[eid] = 0;\n                cur_tree[rem] = 1;\n\n                if (ev.cost < best_cost) {\n                    best_cost = ev.cost;\n                    best_add = eid;\n                    best_rem = rem;\n                }\n            }\n        }\n\n        if (best_add != -1) {\n            cur_tree[best_add] = 1;\n            cur_tree[best_rem] = 0;\n\n            cur_cost = best_cost;\n            improved = true;\n\n            EvalResult stored = evaluate_tree_mask(cur_tree, true);\n\n            if (stored.cost < global_best.cost) {\n                global_best = stored;\n            }\n        }\n    }\n}\n\nvoid append_manhattan_moves(vector<string>& ans, int from, int to) {\n    int r = from / N;\n    int c = from % N;\n    int tr = to / N;\n    int tc = to % N;\n\n    while (r < tr) {\n        ans.push_back(\"D\");\n        r++;\n    }\n\n    while (r > tr) {\n        ans.push_back(\"U\");\n        r--;\n    }\n\n    while (c < tc) {\n        ans.push_back(\"R\");\n        c++;\n    }\n\n    while (c > tc) {\n        ans.push_back(\"L\");\n        c--;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int n;\n    cin >> n;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n\n            hval[id20(i, j)] = x;\n            base_cost += abs(x);\n        }\n    }\n\n    if (base_cost == 0) {\n        return 0;\n    }\n\n    memset(edge_id, -1, sizeof(edge_id));\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int v = r * B + c;\n\n            if (r + 1 < B) {\n                int u = (r + 1) * B + c;\n                int id = all_edges.size();\n\n                all_edges.push_back({v, u});\n\n                edge_id[v][u] = edge_id[u][v] = id;\n            }\n\n            if (c + 1 < B) {\n                int u = r * B + c + 1;\n                int id = all_edges.size();\n\n                all_edges.push_back({v, u});\n\n                edge_id[v][u] = edge_id[u][v] = id;\n            }\n        }\n    }\n\n    mt19937 rng(123456789);\n\n    EvalResult best;\n    vector<char> best_tree;\n\n    auto try_tree = [&](const vector<char>& in) {\n        EvalResult ev = evaluate_tree_mask(in, true);\n\n        if (ev.cost < best.cost) {\n            best = ev;\n            best_tree = in;\n        }\n    };\n\n    for (int c = 0; c < B; c++) {\n        try_tree(tree_to_mask(make_row_tree(c)));\n    }\n\n    for (int r = 0; r < B; r++) {\n        try_tree(tree_to_mask(make_col_tree(r)));\n    }\n\n    int iter = 0;\n\n    while (timer.elapsed() < 0.95) {\n        vector<char> tr;\n\n        if (iter & 1) tr = random_kruskal_tree(rng);\n        else tr = random_prim_tree(rng);\n\n        try_tree(tr);\n\n        iter++;\n    }\n\n    if (!best_tree.empty()) {\n        vector<char> cur = best_tree;\n\n        local_search(cur, best, timer);\n\n        best_tree = cur;\n    }\n\n    while (timer.elapsed() < 1.83) {\n        vector<char> tr;\n\n        if (iter & 1) tr = random_kruskal_tree(rng);\n        else tr = random_prim_tree(rng);\n\n        EvalResult ev = evaluate_tree_mask(tr, true);\n\n        if (ev.cost < best.cost) {\n            best = ev;\n            best_tree = tr;\n\n            vector<char> cur = best_tree;\n\n            local_search(cur, best, timer);\n\n            best_tree = cur;\n        }\n\n        iter++;\n    }\n\n    if (best.order.empty()) {\n        return 0;\n    }\n\n    vector<string> ans;\n\n    int cur = 0;\n\n    append_manhattan_moves(ans, cur, best.order[0]);\n    cur = best.order[0];\n\n    long long load = 0;\n\n    for (int idx = 0; idx < (int)best.order.size(); idx++) {\n        int id = best.order[idx];\n        int v = hval[id];\n\n        if (v > 0) {\n            ans.push_back(\"+\" + to_string(v));\n            load += v;\n        } else if (v < 0) {\n            ans.push_back(\"-\" + to_string(-v));\n            load += v;\n        }\n\n        if (idx + 1 < (int)best.order.size()) {\n            int nxt = best.order[idx + 1];\n\n            append_manhattan_moves(ans, id, nxt);\n\n            cur = nxt;\n        }\n    }\n\n    for (const string& s : ans) {\n        cout << s << '\\n';\n    }\n\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    int randint(int n) {\n        return (int)(next_u32() % n);\n    }\n\n    double uniform01() {\n        return (next_u32() >> 8) * (1.0 / 16777216.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int G = N * N;\n    const int K = 2 * N * (N - 1);\n    const int MAXS = 1500;\n    const int TOTAL = 1 << 15;\n\n    vector<vector<int>> X(K, vector<int>(M));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    XorShift rng;\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) {\n            rng.x ^= (uint64_t)(X[i][j] + 1009) * 11995408973635179863ULL;\n            rng.x ^= rng.x << 7;\n            rng.x ^= rng.x >> 9;\n        }\n    }\n\n    vector<int> initialMax(M, 0);\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) {\n            initialMax[j] = max(initialMax[j], X[i][j]);\n        }\n    }\n\n    vector<pair<int, int>> edges;\n    vector<vector<int>> incident(G);\n    vector<vector<int>> neigh(G);\n\n    auto gid = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j + 1 < N; j++) {\n            int a = gid(i, j);\n            int b = gid(i, j + 1);\n            int e = edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n            neigh[a].push_back(b);\n            neigh[b].push_back(a);\n        }\n    }\n\n    for (int i = 0; i + 1 < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = gid(i, j);\n            int b = gid(i + 1, j);\n            int e = edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n            neigh[a].push_back(b);\n            neigh[b].push_back(a);\n        }\n    }\n\n    vector<int> posOrder(G);\n    iota(posOrder.begin(), posOrder.end(), 0);\n\n    sort(posOrder.begin(), posOrder.end(), [&](int a, int b) {\n        int da = incident[a].size();\n        int db = incident[b].size();\n        if (da != db) return da > db;\n\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n        double ca = abs(ai - (N - 1) / 2.0) + abs(aj - (N - 1) / 2.0);\n        double cb = abs(bi - (N - 1) / 2.0) + abs(bj - (N - 1) / 2.0);\n        return ca < cb;\n    });\n\n    vector<double> logVal(TOTAL + 1, -1e100);\n    for (int i = 1; i <= TOTAL; i++) {\n        logVal[i] = log((double)i / TOTAL);\n    }\n\n    auto calc_delta_pair_score = [&](const vector<int>& slots,\n                                     const vector<vector<double>>& W,\n                                     int a,\n                                     int b) -> double {\n        if (a == b) return 0.0;\n        if (a >= G && b >= G) return 0.0;\n\n        double delta = 0.0;\n\n        for (auto [u, v] : edges) {\n            if (u != a && u != b && v != a && v != b) continue;\n\n            int su = slots[u];\n            int sv = slots[v];\n\n            int nsu = su;\n            int nsv = sv;\n\n            if (u == a) nsu = slots[b];\n            else if (u == b) nsu = slots[a];\n\n            if (v == a) nsv = slots[b];\n            else if (v == b) nsv = slots[a];\n\n            delta += W[nsu][nsv] - W[su][sv];\n        }\n\n        return delta;\n    };\n\n    auto total_pair_score = [&](const vector<int>& slots,\n                                const vector<vector<double>>& W) -> double {\n        double s = 0.0;\n        for (auto [u, v] : edges) {\n            s += W[slots[u]][slots[v]];\n        }\n        return s;\n    };\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> sumValue(K, 0);\n        for (int i = 0; i < K; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) s += X[i][j];\n            sumValue[i] = s;\n        }\n\n        double progress = (T == 1 ? 1.0 : (double)turn / (T - 1));\n\n        bool useExactQuantile = (turn >= 4);\n        bool finalTurn = (turn == T - 1);\n\n        vector<vector<int>> q950(K, vector<int>(K, 0));\n        vector<vector<int>> q985(K, vector<int>(K, 0));\n        vector<vector<int>> q995(K, vector<int>(K, 0));\n\n        vector<unsigned short> cdf;\n        if (finalTurn) {\n            cdf.assign(K * K * (MAXS + 1), 0);\n        }\n\n        if (useExactQuantile || finalTurn) {\n            vector<int> cnt(MAXS + 1, 0), nxt(MAXS + 1, 0);\n            vector<int> active, nactive;\n\n            int target950 = (950 * TOTAL + 999) / 1000;\n            int target985 = (985 * TOTAL + 999) / 1000;\n            int target995 = (995 * TOTAL + 999) / 1000;\n\n            for (int i = 0; i < K; i++) {\n                for (int j = i + 1; j < K; j++) {\n                    fill(cnt.begin(), cnt.end(), 0);\n                    fill(nxt.begin(), nxt.end(), 0);\n                    active.clear();\n                    active.push_back(0);\n                    cnt[0] = 1;\n\n                    for (int l = 0; l < M; l++) {\n                        nactive.clear();\n\n                        int a = X[i][l];\n                        int b = X[j][l];\n\n                        for (int s : active) {\n                            int c = cnt[s];\n\n                            int s1 = s + a;\n                            if (nxt[s1] == 0) nactive.push_back(s1);\n                            nxt[s1] += c;\n\n                            int s2 = s + b;\n                            if (nxt[s2] == 0) nactive.push_back(s2);\n                            nxt[s2] += c;\n                        }\n\n                        for (int s : active) cnt[s] = 0;\n\n                        for (int s : nactive) {\n                            cnt[s] = nxt[s];\n                            nxt[s] = 0;\n                        }\n\n                        active.swap(nactive);\n                    }\n\n                    int cum = 0;\n                    int qq950 = MAXS;\n                    int qq985 = MAXS;\n                    int qq995 = MAXS;\n                    bool f950 = false, f985 = false, f995 = false;\n\n                    int base1 = (i * K + j) * (MAXS + 1);\n                    int base2 = (j * K + i) * (MAXS + 1);\n\n                    for (int s = 0; s <= MAXS; s++) {\n                        cum += cnt[s];\n\n                        if (!f950 && cum >= target950) {\n                            qq950 = s;\n                            f950 = true;\n                        }\n\n                        if (!f985 && cum >= target985) {\n                            qq985 = s;\n                            f985 = true;\n                        }\n\n                        if (!f995 && cum >= target995) {\n                            qq995 = s;\n                            f995 = true;\n                        }\n\n                        if (finalTurn) {\n                            cdf[base1 + s] = (unsigned short)cum;\n                            cdf[base2 + s] = (unsigned short)cum;\n                        }\n                    }\n\n                    q950[i][j] = q950[j][i] = qq950;\n                    q985[i][j] = q985[j][i] = qq985;\n                    q995[i][j] = q995[j][i] = qq995;\n                }\n            }\n        }\n\n        double alpha = 0.45 * (1.0 - progress) + 0.08 * progress;\n        double tailCoef = 0.55 * (1.0 - progress) + 1.30 * progress;\n        double geneCoef = 0.08 * (1.0 - progress) + 0.02 * progress;\n\n        vector<vector<double>> W(K, vector<double>(K, 0.0));\n\n        for (int i = 0; i < K; i++) {\n            for (int j = i + 1; j < K; j++) {\n                double mu = 0.5 * (sumValue[i] + sumValue[j]);\n\n                double cmax = 0.0;\n                double diff2 = 0.0;\n                double gene = 0.0;\n\n                for (int l = 0; l < M; l++) {\n                    int a = X[i][l];\n                    int b = X[j][l];\n                    int mx = max(a, b);\n                    int d = a - b;\n\n                    cmax += mx;\n                    diff2 += (double)d * d;\n\n                    int den = max(1, initialMax[l]);\n                    gene += (double)mx * mx / den;\n                }\n\n                double sigma = 0.5 * sqrt(diff2);\n\n                double baseScore = mu;\n                baseScore += alpha * (cmax - mu);\n                baseScore += tailCoef * sigma;\n                baseScore += geneCoef * gene;\n\n                double score = baseScore;\n\n                if (useExactQuantile) {\n                    double exactScore =\n                        0.20 * q950[i][j] +\n                        0.55 * q985[i][j] +\n                        0.18 * q995[i][j] +\n                        0.07 * cmax;\n\n                    double blend = min(1.0, progress * progress * 1.15);\n                    score = (1.0 - blend) * baseScore + blend * exactScore;\n                }\n\n                W[i][j] = W[j][i] = score;\n            }\n        }\n\n        vector<double> potBySeed(K, 0.0);\n        vector<pair<double, int>> potential;\n        potential.reserve(K);\n\n        for (int i = 0; i < K; i++) {\n            vector<double> v;\n            v.reserve(K - 1);\n\n            for (int j = 0; j < K; j++) {\n                if (i != j) v.push_back(W[i][j]);\n            }\n\n            nth_element(v.begin(), v.begin() + 8, v.end(), greater<double>());\n\n            double p = 0.0;\n            for (int k = 0; k < 8; k++) p += v[k];\n\n            p += 0.16 * sumValue[i];\n\n            double soloGene = 0.0;\n            for (int l = 0; l < M; l++) {\n                int den = max(1, initialMax[l]);\n                double r = (double)X[i][l] / den;\n                soloGene += X[i][l] * r * r;\n            }\n\n            p += (0.85 * (1.0 - progress) + 0.25 * progress) * soloGene;\n\n            potBySeed[i] = p;\n            potential.push_back({p, i});\n        }\n\n        sort(potential.begin(), potential.end(), greater<pair<double, int>>());\n\n        vector<int> slots(K, -1);\n        vector<int> usedSeed(K, 0);\n        vector<int> selected;\n        selected.reserve(G);\n\n        for (int k = 0; k < G; k++) {\n            selected.push_back(potential[k].second);\n            usedSeed[potential[k].second] = 1;\n        }\n\n        // Greedy constructive initial layout.\n        vector<int> placedSeed(K, 0);\n        vector<int> filledPos(G, 0);\n\n        int firstPos = posOrder[0];\n        int firstSeed = selected[0];\n\n        slots[firstPos] = firstSeed;\n        filledPos[firstPos] = 1;\n        placedSeed[firstSeed] = 1;\n\n        for (int step = 1; step < G; step++) {\n            int bestPos = -1;\n            tuple<int, int, double> bestPosKey(-1, -1, 1e100);\n\n            for (int p = 0; p < G; p++) {\n                if (filledPos[p]) continue;\n\n                int cnt = 0;\n                for (int nb : neigh[p]) {\n                    if (filledPos[nb]) cnt++;\n                }\n\n                int deg = incident[p].size();\n                int pi = p / N, pj = p % N;\n                double centerDist = abs(pi - (N - 1) / 2.0) + abs(pj - (N - 1) / 2.0);\n\n                auto key = make_tuple(cnt, deg, -centerDist);\n                if (key > bestPosKey) {\n                    bestPosKey = key;\n                    bestPos = p;\n                }\n            }\n\n            int bestSeed = -1;\n            double bestScore = -1e100;\n\n            for (int s : selected) {\n                if (placedSeed[s]) continue;\n\n                double sc = 0.025 * potBySeed[s];\n\n                for (int nb : neigh[bestPos]) {\n                    if (filledPos[nb]) {\n                        sc += W[s][slots[nb]];\n                    }\n                }\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestSeed = s;\n                }\n            }\n\n            slots[bestPos] = bestSeed;\n            filledPos[bestPos] = 1;\n            placedSeed[bestSeed] = 1;\n        }\n\n        int ptr = G;\n        for (int i = 0; i < K; i++) {\n            if (!usedSeed[i]) {\n                slots[ptr++] = i;\n            }\n        }\n\n        double curScore = total_pair_score(slots, W);\n\n        int ITER = finalTurn ? 75000 : 92000;\n        double T0 = finalTurn ? 60.0 : 82.0;\n        double T1 = 0.05;\n\n        for (int it = 0; it < ITER; it++) {\n            int a, b;\n\n            if (rng.randint(100) < 67) {\n                a = rng.randint(G);\n                b = rng.randint(K);\n            } else {\n                a = rng.randint(K);\n                b = rng.randint(K);\n            }\n\n            if (a == b) continue;\n            if (a >= G && b >= G) continue;\n\n            double delta = calc_delta_pair_score(slots, W, a, b);\n\n            double ratio = (double)it / ITER;\n            double temp = T0 * (1.0 - ratio) + T1 * ratio;\n\n            bool accept = false;\n            if (delta >= 0.0) {\n                accept = true;\n            } else {\n                double prob = exp(delta / temp);\n                if (rng.uniform01() < prob) accept = true;\n            }\n\n            if (accept) {\n                swap(slots[a], slots[b]);\n                curScore += delta;\n            }\n        }\n\n        for (int pass = 0; pass < 3; pass++) {\n            bool improved = false;\n\n            for (int a = 0; a < K; a++) {\n                for (int b = a + 1; b < K; b++) {\n                    if (a >= G && b >= G) continue;\n\n                    double delta = calc_delta_pair_score(slots, W, a, b);\n                    if (delta > 1e-9) {\n                        swap(slots[a], slots[b]);\n                        curScore += delta;\n                        improved = true;\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n\n        if (finalTurn) {\n            vector<double> sumLog(MAXS + 1, 0.0), tmpLog(MAXS + 1);\n            vector<int> zeroCnt(MAXS + 1, 0), tmpZero(MAXS + 1);\n\n            auto addPair = [&](vector<double>& sl,\n                               vector<int>& zc,\n                               int a,\n                               int b,\n                               int coef) {\n                int base = (a * K + b) * (MAXS + 1);\n                for (int s = 0; s <= MAXS; s++) {\n                    int c = cdf[base + s];\n                    if (c == 0) {\n                        zc[s] += coef;\n                    } else {\n                        sl[s] += coef * logVal[c];\n                    }\n                }\n            };\n\n            auto exactScoreFromState = [&](const vector<double>& sl,\n                                           const vector<int>& zc) {\n                double res = 0.0;\n                for (int s = 0; s < MAXS; s++) {\n                    double prod = (zc[s] > 0 ? 0.0 : exp(sl[s]));\n                    res += 1.0 - prod;\n                }\n                return res;\n            };\n\n            for (auto [u, v] : edges) {\n                addPair(sumLog, zeroCnt, slots[u], slots[v], +1);\n            }\n\n            double exactCur = exactScoreFromState(sumLog, zeroCnt);\n\n            auto evalExactSwap = [&](int a, int b) -> double {\n                tmpLog = sumLog;\n                tmpZero = zeroCnt;\n\n                vector<int> aff;\n\n                if (a < G) {\n                    for (int e : incident[a]) aff.push_back(e);\n                }\n                if (b < G) {\n                    for (int e : incident[b]) aff.push_back(e);\n                }\n\n                sort(aff.begin(), aff.end());\n                aff.erase(unique(aff.begin(), aff.end()), aff.end());\n\n                for (int e : aff) {\n                    auto [u, v] = edges[e];\n\n                    int oldU = slots[u];\n                    int oldV = slots[v];\n\n                    int newU = oldU;\n                    int newV = oldV;\n\n                    if (u == a) newU = slots[b];\n                    else if (u == b) newU = slots[a];\n\n                    if (v == a) newV = slots[b];\n                    else if (v == b) newV = slots[a];\n\n                    addPair(tmpLog, tmpZero, oldU, oldV, -1);\n                    addPair(tmpLog, tmpZero, newU, newV, +1);\n                }\n\n                return exactScoreFromState(tmpLog, tmpZero);\n            };\n\n            const int EXACT_ITER = 13000;\n\n            for (int it = 0; it < EXACT_ITER; it++) {\n                int a, b;\n\n                if (rng.randint(100) < 72) {\n                    a = rng.randint(G);\n                    b = rng.randint(K);\n                } else {\n                    a = rng.randint(K);\n                    b = rng.randint(K);\n                }\n\n                if (a == b) continue;\n                if (a >= G && b >= G) continue;\n\n                double nxtScore = evalExactSwap(a, b);\n                double delta = nxtScore - exactCur;\n\n                double ratio = (double)it / EXACT_ITER;\n                double temp = 3.2 * (1.0 - ratio) + 0.01 * ratio;\n\n                bool accept = false;\n                if (delta >= 0.0) {\n                    accept = true;\n                } else {\n                    if (rng.uniform01() < exp(delta / temp)) accept = true;\n                }\n\n                if (accept) {\n                    swap(slots[a], slots[b]);\n                    sumLog.swap(tmpLog);\n                    zeroCnt.swap(tmpZero);\n                    exactCur = nxtScore;\n                }\n            }\n\n            for (int pass = 0; pass < 2; pass++) {\n                bool improved = false;\n\n                for (int a = 0; a < K; a++) {\n                    for (int b = a + 1; b < K; b++) {\n                        if (a >= G && b >= G) continue;\n\n                        double nxtScore = evalExactSwap(a, b);\n                        if (nxtScore > exactCur + 1e-9) {\n                            swap(slots[a], slots[b]);\n                            sumLog.swap(tmpLog);\n                            zeroCnt.swap(tmpZero);\n                            exactCur = nxtScore;\n                            improved = true;\n                        }\n                    }\n                }\n\n                if (!improved) break;\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << slots[gid(i, j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < M; j++) {\n                if (!(cin >> X[i][j])) return 0;\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nint DX[4] = {0, 1, 0, -1};\nint DY[4] = {1, 0, -1, 0};\n\nint manhattan(const Pos& a, const Pos& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nbool inside(int N, int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\nstruct Solution {\n    int Vp = 1;\n    vector<pair<int, int>> edges;\n    Pos init{0, 0};\n    vector<string> ops;\n};\n\n/* ---------------- single fingertip fallback ---------------- */\n\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    const int INF = 1e9;\n\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            int delta = INF;\n            int j1 = 0;\n\n            for (int j = 1; j <= n; j++) {\n                if (used[j]) continue;\n\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    vector<int> assignment(n, -1);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] != 0) assignment[p[j] - 1] = j - 1;\n    }\n\n    return assignment;\n}\n\nlong long eval_plan(\n    const vector<pair<int, int>>& plan,\n    const vector<Pos>& src,\n    const vector<Pos>& dst\n) {\n    long long cost = 0;\n\n    for (int i = 0; i < (int)plan.size(); i++) {\n        int s = plan[i].first;\n        int t = plan[i].second;\n\n        if (i > 0) {\n            int pt = plan[i - 1].second;\n            cost += manhattan(dst[pt], src[s]);\n        }\n\n        cost += manhattan(src[s], dst[t]);\n    }\n\n    return cost;\n}\n\nvector<pair<int, int>> plan_greedy_pair(\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    int alpha_num\n) {\n    int n = (int)src.size();\n\n    vector<int> remS(n), remT(n);\n    iota(remS.begin(), remS.end(), 0);\n    iota(remT.begin(), remT.end(), 0);\n\n    vector<pair<int, int>> plan;\n    bool has_cur = false;\n    Pos cur{0, 0};\n\n    while (!remS.empty()) {\n        long long best_score = (1LL << 60);\n        int best_si = -1;\n        int best_ti = -1;\n        int best_dcur = 0;\n        int best_dtr = 0;\n\n        for (int ai = 0; ai < (int)remS.size(); ai++) {\n            int s = remS[ai];\n            int dcur = has_cur ? manhattan(cur, src[s]) : 0;\n\n            for (int bi = 0; bi < (int)remT.size(); bi++) {\n                int t = remT[bi];\n                int dtr = manhattan(src[s], dst[t]);\n\n                long long score = 1LL * alpha_num * dcur + 2LL * dtr;\n\n                if (\n                    score < best_score ||\n                    (score == best_score && make_pair(dcur, dtr) < make_pair(best_dcur, best_dtr))\n                ) {\n                    best_score = score;\n                    best_si = ai;\n                    best_ti = bi;\n                    best_dcur = dcur;\n                    best_dtr = dtr;\n                }\n            }\n        }\n\n        int s = remS[best_si];\n        int t = remT[best_ti];\n\n        plan.push_back({s, t});\n        cur = dst[t];\n        has_cur = true;\n\n        remS[best_si] = remS.back();\n        remS.pop_back();\n\n        remT[best_ti] = remT.back();\n        remT.pop_back();\n    }\n\n    return plan;\n}\n\nvector<pair<int, int>> plan_hungarian_ordered(\n    const vector<Pos>& src,\n    const vector<Pos>& dst\n) {\n    int n = (int)src.size();\n\n    vector<vector<int>> cost(n, vector<int>(n));\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cost[i][j] = manhattan(src[i], dst[j]);\n        }\n    }\n\n    vector<int> assign = hungarian(cost);\n\n    vector<pair<int, int>> best_plan;\n    long long best_cost = (1LL << 60);\n\n    for (int st = 0; st < n; st++) {\n        vector<unsigned char> used(n, 0);\n        vector<pair<int, int>> plan;\n        plan.reserve(n);\n\n        used[st] = 1;\n        plan.push_back({st, assign[st]});\n\n        Pos cur = dst[assign[st]];\n\n        for (int step = 1; step < n; step++) {\n            int best = -1;\n            int best_d = 1e9;\n            int best_tr = 1e9;\n\n            for (int i = 0; i < n; i++) {\n                if (used[i]) continue;\n\n                int d = manhattan(cur, src[i]);\n                int tr = manhattan(src[i], dst[assign[i]]);\n\n                if (d < best_d || (d == best_d && tr < best_tr)) {\n                    best_d = d;\n                    best_tr = tr;\n                    best = i;\n                }\n            }\n\n            used[best] = 1;\n            plan.push_back({best, assign[best]});\n            cur = dst[assign[best]];\n        }\n\n        long long c = eval_plan(plan, src, dst);\n\n        if (c < best_cost) {\n            best_cost = c;\n            best_plan = move(plan);\n        }\n    }\n\n    return best_plan;\n}\n\nvoid append_single_move(\n    vector<string>& ops,\n    Pos& cur,\n    const Pos& to,\n    bool action_on_arrival\n) {\n    vector<char> moves;\n\n    while (cur.x < to.x) {\n        moves.push_back('D');\n        cur.x++;\n    }\n    while (cur.x > to.x) {\n        moves.push_back('U');\n        cur.x--;\n    }\n    while (cur.y < to.y) {\n        moves.push_back('R');\n        cur.y++;\n    }\n    while (cur.y > to.y) {\n        moves.push_back('L');\n        cur.y--;\n    }\n\n    if (moves.empty()) {\n        if (action_on_arrival) ops.push_back(\".P\");\n        return;\n    }\n\n    for (int i = 0; i < (int)moves.size(); i++) {\n        string op = \"..\";\n        op[0] = moves[i];\n\n        if (i == (int)moves.size() - 1 && action_on_arrival) {\n            op[1] = 'P';\n        }\n\n        ops.push_back(op);\n    }\n}\n\nSolution make_single_solution(const vector<Pos>& src, const vector<Pos>& dst) {\n    int D = (int)src.size();\n\n    Solution sol;\n    sol.Vp = 1;\n    sol.init = {0, 0};\n\n    if (D == 0) return sol;\n\n    vector<pair<int, int>> best_plan;\n    long long best_cost = (1LL << 60);\n\n    auto consider = [&](vector<pair<int, int>> plan) {\n        long long c = eval_plan(plan, src, dst);\n        if (c < best_cost) {\n            best_cost = c;\n            best_plan = move(plan);\n        }\n    };\n\n    consider(plan_greedy_pair(src, dst, 0));\n    consider(plan_greedy_pair(src, dst, 1));\n    consider(plan_greedy_pair(src, dst, 2));\n    consider(plan_greedy_pair(src, dst, 4));\n    consider(plan_hungarian_ordered(src, dst));\n\n    sol.init = src[best_plan[0].first];\n    Pos cur = sol.init;\n\n    sol.ops.push_back(\".P\");\n\n    for (int i = 0; i < D; i++) {\n        int si = best_plan[i].first;\n        int ti = best_plan[i].second;\n\n        if (i > 0) {\n            append_single_move(sol.ops, cur, src[si], true);\n        }\n\n        append_single_move(sol.ops, cur, dst[ti], true);\n    }\n\n    return sol;\n}\n\n/* ---------------- star arm solution ---------------- */\n\nstruct StarState {\n    int Vp;\n    Pos root;\n    vector<int> dir;\n    vector<int> holding;\n    vector<string> ops;\n};\n\nchar move_char(Pos& cur, const Pos& to) {\n    if (cur.x < to.x) {\n        cur.x++;\n        return 'D';\n    }\n    if (cur.x > to.x) {\n        cur.x--;\n        return 'U';\n    }\n    if (cur.y < to.y) {\n        cur.y++;\n        return 'R';\n    }\n    if (cur.y > to.y) {\n        cur.y--;\n        return 'L';\n    }\n    return '.';\n}\n\nvoid star_move_rotate_action(\n    StarState& st,\n    const Pos& to,\n    const vector<int>& desired,\n    const vector<int>& action_leaves\n) {\n    vector<int> do_action(st.Vp, 0);\n    for (int leaf : action_leaves) do_action[leaf] = 1;\n\n    auto ready = [&]() {\n        if (st.root.x != to.x || st.root.y != to.y) return false;\n        for (int i = 1; i < st.Vp; i++) {\n            if (desired[i] != -1 && st.dir[i] != desired[i]) return false;\n        }\n        return true;\n    };\n\n    while (true) {\n        if (ready()) {\n            string op(2 * st.Vp, '.');\n            bool any = false;\n\n            for (int i = 1; i < st.Vp; i++) {\n                if (do_action[i]) {\n                    op[st.Vp + i] = 'P';\n                    st.holding[i] ^= 1;\n                    any = true;\n                }\n            }\n\n            if (any) st.ops.push_back(op);\n            return;\n        }\n\n        string op(2 * st.Vp, '.');\n        op[0] = move_char(st.root, to);\n\n        for (int i = 1; i < st.Vp; i++) {\n            if (desired[i] == -1 || st.dir[i] == desired[i]) continue;\n\n            int diff = (desired[i] - st.dir[i] + 4) % 4;\n\n            if (diff == 1 || diff == 2) {\n                op[i] = 'R';\n                st.dir[i] = (st.dir[i] + 1) % 4;\n            } else {\n                op[i] = 'L';\n                st.dir[i] = (st.dir[i] + 3) % 4;\n            }\n        }\n\n        if (ready()) {\n            for (int i = 1; i < st.Vp; i++) {\n                if (do_action[i]) {\n                    op[st.Vp + i] = 'P';\n                    st.holding[i] ^= 1;\n                }\n            }\n            st.ops.push_back(op);\n            return;\n        }\n\n        st.ops.push_back(op);\n    }\n}\n\nSolution make_star_solution(\n    int N,\n    int V,\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    const vector<int>& input_lengths\n) {\n    int D = (int)src.size();\n\n    Solution sol;\n    sol.Vp = min(V, 1 + (int)input_lengths.size());\n    sol.init = {0, 0};\n\n    int F = sol.Vp - 1;\n    if (F <= 0 || D == 0) {\n        sol.Vp = 1;\n        return sol;\n    }\n\n    vector<int> leafLen(sol.Vp, 0);\n    vector<int> uniqueLens;\n\n    for (int i = 1; i < sol.Vp; i++) {\n        int L = input_lengths[i - 1];\n        L = max(1, min(L, N - 1));\n\n        leafLen[i] = L;\n        uniqueLens.push_back(L);\n        sol.edges.push_back({0, L});\n    }\n\n    sort(uniqueLens.begin(), uniqueLens.end());\n    uniqueLens.erase(unique(uniqueLens.begin(), uniqueLens.end()), uniqueLens.end());\n\n    int Lcnt = uniqueLens.size();\n    unordered_map<int, int> lenIndex;\n    for (int i = 0; i < Lcnt; i++) lenIndex[uniqueLens[i]] = i;\n\n    vector<vector<int>> leavesByLen(Lcnt);\n    for (int i = 1; i < sol.Vp; i++) {\n        leavesByLen[lenIndex[leafLen[i]]].push_back(i);\n    }\n\n    vector<vector<int>> sid(N, vector<int>(N, -1));\n    vector<vector<int>> tid(N, vector<int>(N, -1));\n\n    for (int i = 0; i < D; i++) {\n        sid[src[i].x][src[i].y] = i;\n        tid[dst[i].x][dst[i].y] = i;\n    }\n\n    vector<char> remS(D, 1), remT(D, 1);\n\n    auto count_center = [&](const Pos& c, const vector<vector<int>>& id, const vector<char>& rem) {\n        vector<int> cnt(Lcnt, 0);\n\n        for (int li = 0; li < Lcnt; li++) {\n            int L = uniqueLens[li];\n\n            for (int d = 0; d < 4; d++) {\n                int x = c.x + DX[d] * L;\n                int y = c.y + DY[d] * L;\n\n                if (!inside(N, x, y)) continue;\n\n                int idx = id[x][y];\n                if (idx != -1 && rem[idx]) cnt[li]++;\n            }\n\n            cnt[li] = min(cnt[li], (int)leavesByLen[li].size());\n        }\n\n        return cnt;\n    };\n\n    auto dirs_center = [&](const Pos& c, int li, const vector<vector<int>>& id, const vector<char>& rem) {\n        vector<int> dirs;\n        int L = uniqueLens[li];\n\n        for (int d = 0; d < 4; d++) {\n            int x = c.x + DX[d] * L;\n            int y = c.y + DY[d] * L;\n\n            if (!inside(N, x, y)) continue;\n\n            int idx = id[x][y];\n            if (idx != -1 && rem[idx]) dirs.push_back(d);\n        }\n\n        return dirs;\n    };\n\n    StarState st;\n    st.Vp = sol.Vp;\n    st.root = {0, 0};\n    st.dir.assign(sol.Vp, 0);\n    st.holding.assign(sol.Vp, 0);\n\n    bool initialized = false;\n    Pos curRoot{0, 0};\n    int remaining = D;\n\n    while (remaining > 0) {\n        vector<vector<int>> sCnt(N * N), tCnt(N * N);\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                int idc = x * N + y;\n                Pos c{x, y};\n\n                sCnt[idc] = count_center(c, sid, remS);\n                tCnt[idc] = count_center(c, tid, remT);\n            }\n        }\n\n        int bestK = -1;\n        int bestCost = 1e9;\n        Pos bestS{0, 0}, bestT{0, 0};\n\n        for (int sx = 0; sx < N; sx++) {\n            for (int sy = 0; sy < N; sy++) {\n                int si = sx * N + sy;\n\n                int sTotal = 0;\n                for (int v : sCnt[si]) sTotal += v;\n                if (sTotal == 0) continue;\n\n                Pos sc{sx, sy};\n\n                for (int tx = 0; tx < N; tx++) {\n                    for (int ty = 0; ty < N; ty++) {\n                        int ti = tx * N + ty;\n\n                        int k = 0;\n                        for (int li = 0; li < Lcnt; li++) {\n                            k += min(sCnt[si][li], tCnt[ti][li]);\n                        }\n\n                        if (k == 0) continue;\n\n                        Pos tc{tx, ty};\n\n                        int cost = (initialized ? manhattan(curRoot, sc) : 0) + manhattan(sc, tc);\n\n                        if (k > bestK || (k == bestK && cost < bestCost)) {\n                            bestK = k;\n                            bestCost = cost;\n                            bestS = sc;\n                            bestT = tc;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (bestK <= 0) break;\n\n        if (!initialized) {\n            sol.init = bestS;\n            st.root = bestS;\n            curRoot = bestS;\n            initialized = true;\n        }\n\n        vector<int> pickupDesired(sol.Vp, -1);\n        vector<int> releaseDesired(sol.Vp, -1);\n        vector<int> actionLeaves;\n\n        for (int li = 0; li < Lcnt; li++) {\n            vector<int> sd = dirs_center(bestS, li, sid, remS);\n            vector<int> td = dirs_center(bestT, li, tid, remT);\n\n            int q = min({(int)sd.size(), (int)td.size(), (int)leavesByLen[li].size()});\n\n            for (int z = 0; z < q; z++) {\n                int leaf = leavesByLen[li][z];\n                int sdir = sd[z];\n                int tdir = td[z];\n                int L = uniqueLens[li];\n\n                pickupDesired[leaf] = sdir;\n                releaseDesired[leaf] = tdir;\n                actionLeaves.push_back(leaf);\n\n                int sx = bestS.x + DX[sdir] * L;\n                int sy = bestS.y + DY[sdir] * L;\n                int tx = bestT.x + DX[tdir] * L;\n                int ty = bestT.y + DY[tdir] * L;\n\n                int si = sid[sx][sy];\n                int ti = tid[tx][ty];\n\n                if (si != -1 && remS[si]) {\n                    remS[si] = 0;\n                    remaining--;\n                }\n\n                if (ti != -1 && remT[ti]) {\n                    remT[ti] = 0;\n                }\n            }\n        }\n\n        if (actionLeaves.empty()) break;\n\n        star_move_rotate_action(st, bestS, pickupDesired, actionLeaves);\n        star_move_rotate_action(st, bestT, releaseDesired, actionLeaves);\n\n        curRoot = bestT;\n    }\n\n    if (remaining != 0 || !initialized) {\n        sol.Vp = 1;\n        sol.edges.clear();\n        sol.init = {0, 0};\n        sol.ops.clear();\n        return sol;\n    }\n\n    sol.ops = move(st.ops);\n    return sol;\n}\n\n/* ---------------- two-link arm solution ---------------- */\n\nstruct Option {\n    int dx, dy;\n    int d1, d2;\n};\n\nstruct TwoState {\n    int Vp;\n    int F;\n    Pos root;\n    vector<int> d1;\n    vector<int> d2;\n    vector<string> ops;\n};\n\nvoid two_move_rotate_action(\n    TwoState& st,\n    const Pos& to,\n    const vector<int>& desired1,\n    const vector<int>& desired2,\n    const vector<int>& actionLeaves\n) {\n    vector<int> do_action(st.Vp, 0);\n    for (int leaf : actionLeaves) do_action[leaf] = 1;\n\n    auto ready = [&]() {\n        if (st.root.x != to.x || st.root.y != to.y) return false;\n\n        for (int f = 0; f < st.F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            if (desired1[j] != -1 && st.d1[f] != desired1[j]) return false;\n            if (desired2[l] != -1 && st.d2[f] != desired2[l]) return false;\n        }\n\n        return true;\n    };\n\n    while (true) {\n        if (ready()) {\n            string op(2 * st.Vp, '.');\n            bool any = false;\n\n            for (int leaf : actionLeaves) {\n                op[st.Vp + leaf] = 'P';\n                any = true;\n            }\n\n            if (any) st.ops.push_back(op);\n            return;\n        }\n\n        string op(2 * st.Vp, '.');\n        op[0] = move_char(st.root, to);\n\n        for (int f = 0; f < st.F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            int rj = 0;\n\n            if (desired1[j] != -1 && st.d1[f] != desired1[j]) {\n                int diff = (desired1[j] - st.d1[f] + 4) % 4;\n\n                if (diff == 1 || diff == 2) {\n                    op[j] = 'R';\n                    rj = 1;\n                    st.d1[f] = (st.d1[f] + 1) % 4;\n                    st.d2[f] = (st.d2[f] + 1) % 4;\n                } else {\n                    op[j] = 'L';\n                    rj = -1;\n                    st.d1[f] = (st.d1[f] + 3) % 4;\n                    st.d2[f] = (st.d2[f] + 3) % 4;\n                }\n            }\n\n            (void)rj;\n\n            if (desired2[l] != -1 && st.d2[f] != desired2[l]) {\n                int diff = (desired2[l] - st.d2[f] + 4) % 4;\n\n                if (diff == 1 || diff == 2) {\n                    op[l] = 'R';\n                    st.d2[f] = (st.d2[f] + 1) % 4;\n                } else {\n                    op[l] = 'L';\n                    st.d2[f] = (st.d2[f] + 3) % 4;\n                }\n            }\n        }\n\n        if (ready()) {\n            for (int leaf : actionLeaves) {\n                op[st.Vp + leaf] = 'P';\n            }\n            st.ops.push_back(op);\n            return;\n        }\n\n        st.ops.push_back(op);\n    }\n}\n\nSolution make_two_link_solution(\n    int N,\n    int V,\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    const vector<pair<int, int>>& typeInput\n) {\n    int D = (int)src.size();\n\n    Solution sol;\n    int F = min((V - 1) / 2, (int)typeInput.size());\n\n    if (F <= 0 || D == 0) {\n        sol.Vp = 1;\n        return sol;\n    }\n\n    sol.Vp = 1 + 2 * F;\n\n    vector<int> A(F), B(F);\n\n    for (int f = 0; f < F; f++) {\n        A[f] = max(1, min(typeInput[f].first, N - 1));\n        B[f] = max(1, min(typeInput[f].second, N - 1));\n\n        int j = 1 + 2 * f;\n        sol.edges.push_back({0, A[f]});\n        sol.edges.push_back({j, B[f]});\n    }\n\n    vector<vector<Option>> opts(F);\n\n    for (int f = 0; f < F; f++) {\n        map<pair<int, int>, Option> mp;\n\n        for (int d1 = 0; d1 < 4; d1++) {\n            for (int d2 = 0; d2 < 4; d2++) {\n                int ox = DX[d1] * A[f] + DX[d2] * B[f];\n                int oy = DY[d1] * A[f] + DY[d2] * B[f];\n\n                pair<int, int> key{ox, oy};\n                if (!mp.count(key)) {\n                    mp[key] = {ox, oy, d1, d2};\n                }\n            }\n        }\n\n        for (auto& kv : mp) opts[f].push_back(kv.second);\n    }\n\n    vector<vector<int>> sid(N, vector<int>(N, -1));\n    vector<vector<int>> tid(N, vector<int>(N, -1));\n\n    for (int i = 0; i < D; i++) {\n        sid[src[i].x][src[i].y] = i;\n        tid[dst[i].x][dst[i].y] = i;\n    }\n\n    vector<char> remS(D, 1), remT(D, 1);\n\n    TwoState st;\n    st.Vp = sol.Vp;\n    st.F = F;\n    st.root = {0, 0};\n    st.d1.assign(F, 0);\n    st.d2.assign(F, 0);\n\n    bool initialized = false;\n    Pos curRoot{0, 0};\n    int remaining = D;\n\n    vector<int> stamp(N * N, 0);\n    int stamp_id = 1;\n\n    auto compute_data = [&](const vector<vector<int>>& id, const vector<char>& rem) {\n        vector<int> mask(N * N, 0), cnt(N * N, 0);\n\n        for (int cx = 0; cx < N; cx++) {\n            for (int cy = 0; cy < N; cy++) {\n                int cid = cx * N + cy;\n                stamp_id++;\n\n                for (int f = 0; f < F; f++) {\n                    bool okLeaf = false;\n\n                    for (const auto& op : opts[f]) {\n                        int x = cx + op.dx;\n                        int y = cy + op.dy;\n\n                        if (!inside(N, x, y)) continue;\n\n                        int idx = id[x][y];\n                        if (idx == -1 || !rem[idx]) continue;\n\n                        okLeaf = true;\n\n                        int cell = x * N + y;\n                        if (stamp[cell] != stamp_id) {\n                            stamp[cell] = stamp_id;\n                            cnt[cid]++;\n                        }\n                    }\n\n                    if (okLeaf) mask[cid] |= (1 << f);\n                }\n            }\n        }\n\n        return pair<vector<int>, vector<int>>(mask, cnt);\n    };\n\n    auto collect_options = [&](const Pos& c, int f, const vector<vector<int>>& id, const vector<char>& rem) {\n        vector<pair<int, Option>> res;\n\n        for (const auto& op : opts[f]) {\n            int x = c.x + op.dx;\n            int y = c.y + op.dy;\n\n            if (!inside(N, x, y)) continue;\n\n            int idx = id[x][y];\n            if (idx != -1 && rem[idx]) {\n                res.push_back({idx, op});\n            }\n        }\n\n        return res;\n    };\n\n    while (remaining > 0) {\n        auto [sMask, sCnt] = compute_data(sid, remS);\n        auto [tMask, tCnt] = compute_data(tid, remT);\n\n        int bestK = -1;\n        int bestCost = 1e9;\n        Pos bestS{0, 0}, bestT{0, 0};\n\n        for (int si = 0; si < N * N; si++) {\n            if (sCnt[si] == 0) continue;\n\n            Pos sc{si / N, si % N};\n\n            for (int ti = 0; ti < N * N; ti++) {\n                if (tCnt[ti] == 0) continue;\n\n                int common = __builtin_popcount((unsigned)(sMask[si] & tMask[ti]));\n                int k = min({common, sCnt[si], tCnt[ti]});\n\n                if (k <= 0) continue;\n\n                Pos tc{ti / N, ti % N};\n\n                int cost = (initialized ? manhattan(curRoot, sc) : 0) + manhattan(sc, tc);\n\n                if (k > bestK || (k == bestK && cost < bestCost)) {\n                    bestK = k;\n                    bestCost = cost;\n                    bestS = sc;\n                    bestT = tc;\n                }\n            }\n        }\n\n        if (bestK <= 0) break;\n\n        if (!initialized) {\n            sol.init = bestS;\n            st.root = bestS;\n            curRoot = bestS;\n            initialized = true;\n        }\n\n        vector<int> desired1(sol.Vp, -1);\n        vector<int> desired2(sol.Vp, -1);\n        vector<int> relDesired1(sol.Vp, -1);\n        vector<int> relDesired2(sol.Vp, -1);\n        vector<int> actionLeaves;\n\n        vector<char> usedS(D, 0), usedT(D, 0);\n\n        for (int f = 0; f < F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            auto so = collect_options(bestS, f, sid, remS);\n            auto to = collect_options(bestT, f, tid, remT);\n\n            bool assigned = false;\n\n            for (auto [si, sop] : so) {\n                if (usedS[si]) continue;\n\n                for (auto [ti, top] : to) {\n                    if (usedT[ti]) continue;\n\n                    usedS[si] = 1;\n                    usedT[ti] = 1;\n\n                    desired1[j] = sop.d1;\n                    desired2[l] = sop.d2;\n                    relDesired1[j] = top.d1;\n                    relDesired2[l] = top.d2;\n                    actionLeaves.push_back(l);\n\n                    remS[si] = 0;\n                    remT[ti] = 0;\n                    remaining--;\n\n                    assigned = true;\n                    break;\n                }\n\n                if (assigned) break;\n            }\n        }\n\n        if (actionLeaves.empty()) break;\n\n        two_move_rotate_action(st, bestS, desired1, desired2, actionLeaves);\n        two_move_rotate_action(st, bestT, relDesired1, relDesired2, actionLeaves);\n\n        curRoot = bestT;\n    }\n\n    if (remaining != 0 || !initialized) {\n        sol.Vp = 1;\n        sol.edges.clear();\n        sol.init = {0, 0};\n        sol.ops.clear();\n        return sol;\n    }\n\n    sol.ops = move(st.ops);\n    return sol;\n}\n\n/* ---------------- main ---------------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<Pos> src, dst;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                src.push_back({i, j});\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    vector<Solution> candidates;\n\n    candidates.push_back(make_single_solution(src, dst));\n\n    int Fstar = max(0, V - 1);\n\n    vector<int> len1, len2, len3;\n\n    for (int i = 0; i < Fstar; i++) {\n        len1.push_back(1 + i / 4);\n    }\n\n    for (int i = 0; i < Fstar; i++) {\n        len2.push_back(1 + i / 2);\n    }\n\n    for (int i = 0; i < Fstar; i++) {\n        int v = 1 + (i % 7);\n        len3.push_back(v);\n    }\n\n    candidates.push_back(make_star_solution(N, V, src, dst, len1));\n    candidates.push_back(make_star_solution(N, V, src, dst, len2));\n    candidates.push_back(make_star_solution(N, V, src, dst, len3));\n\n    vector<pair<int, int>> twoTypes1;\n    vector<pair<int, int>> twoTypes2;\n\n    int Ftwo = max(0, (V - 1) / 2);\n\n    for (int i = 0; i < Ftwo; i++) {\n        twoTypes1.push_back({1, 2});\n    }\n\n    for (int i = 0; i < Ftwo; i++) {\n        if (i % 3 == 0) twoTypes2.push_back({1, 1});\n        else if (i % 3 == 1) twoTypes2.push_back({1, 2});\n        else twoTypes2.push_back({2, 3});\n    }\n\n    candidates.push_back(make_two_link_solution(N, V, src, dst, twoTypes1));\n    candidates.push_back(make_two_link_solution(N, V, src, dst, twoTypes2));\n\n    int best = 0;\n\n    for (int i = 1; i < (int)candidates.size(); i++) {\n        if (candidates[i].ops.empty() && !src.empty()) continue;\n\n        if (candidates[i].ops.size() < candidates[best].ops.size()) {\n            best = i;\n        }\n    }\n\n    Solution ans = move(candidates[best]);\n\n    cout << ans.Vp << '\\n';\n\n    for (auto [p, L] : ans.edges) {\n        cout << p << ' ' << L << '\\n';\n    }\n\n    cout << ans.init.x << ' ' << ans.init.y << '\\n';\n\n    for (const string& op : ans.ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Fish {\n    int x, y, w;\n};\n\nstruct PolyCand {\n    int diff = -1000000000;\n    vector<pair<int,int>> poly;\n};\n\nstruct EvalResult {\n    bool ok = false;\n    int diff = -1000000000;\n    vector<char> mask;\n    vector<pair<int,int>> poly;\n};\n\nstatic const int LIM = 100000;\nstatic const int MAX_PERIM = 400000;\nstatic const int MAX_VERT = 1000;\n\nint N;\nvector<Fish> fishes;\nPolyCand bestAns;\n\nstatic inline int id(int x, int y, int G) {\n    return y * G + x;\n}\n\nint exactDiffRect(int x1, int y1, int x2, int y2) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) s += p.w;\n    }\n    return s;\n}\n\nvoid updateBest(const vector<pair<int,int>>& poly, int diff) {\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return;\n    if (diff > bestAns.diff) {\n        bestAns.diff = diff;\n        bestAns.poly = poly;\n    }\n}\n\nbool pointInsideMask(const vector<char>& mask, int G, int L, int px, int py) {\n    int xs[2], ys[2];\n    int nx = 0, ny = 0;\n\n    if (px == LIM) xs[nx++] = G - 1;\n    else xs[nx++] = px / L;\n    if (px > 0 && px % L == 0) xs[nx++] = px / L - 1;\n\n    if (py == LIM) ys[ny++] = G - 1;\n    else ys[ny++] = py / L;\n    if (py > 0 && py % L == 0) ys[ny++] = py / L - 1;\n\n    for (int i = 0; i < nx; i++) {\n        for (int j = 0; j < ny; j++) {\n            int x = xs[i], y = ys[j];\n            if (0 <= x && x < G && 0 <= y && y < G && mask[id(x,y,G)]) return true;\n        }\n    }\n    return false;\n}\n\nint exactDiffMask(const vector<char>& mask, int G, int L) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (pointInsideMask(mask, G, L, p.x, p.y)) s += p.w;\n    }\n    return s;\n}\n\nbool isConnected(const vector<char>& mask, int G) {\n    int st = -1, cnt = 0;\n    for (int i = 0; i < G * G; i++) {\n        if (mask[i]) {\n            cnt++;\n            if (st == -1) st = i;\n        }\n    }\n    if (cnt == 0) return false;\n\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    q.push(st);\n    vis[st] = 1;\n    int got = 0;\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        got++;\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n            int ni = id(nx,ny,G);\n            if (!mask[ni] || vis[ni]) continue;\n            vis[ni] = 1;\n            q.push(ni);\n        }\n    }\n    return got == cnt;\n}\n\nvoid fillHoles(vector<char>& mask, int G) {\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n\n    auto push_empty = [&](int x, int y) {\n        if (x < 0 || x >= G || y < 0 || y >= G) return;\n        int v = id(x,y,G);\n        if (!mask[v] && !vis[v]) {\n            vis[v] = 1;\n            q.push(v);\n        }\n    };\n\n    for (int i = 0; i < G; i++) {\n        push_empty(i, 0);\n        push_empty(i, G - 1);\n        push_empty(0, i);\n        push_empty(G - 1, i);\n    }\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            push_empty(x + dx[d], y + dy[d]);\n        }\n    }\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] && !vis[i]) mask[i] = 1;\n    }\n}\n\nvoid normalizeMask(vector<char>& mask, int G, const vector<int>& cellW) {\n    fillHoles(mask, G);\n\n    for (int iter = 0; iter < G * G; iter++) {\n        bool changed = false;\n        for (int y = 0; y + 1 < G; y++) {\n            for (int x = 0; x + 1 < G; x++) {\n                int a = id(x,y,G);\n                int b = id(x+1,y,G);\n                int c = id(x,y+1,G);\n                int d = id(x+1,y+1,G);\n\n                if (mask[a] && mask[d] && !mask[b] && !mask[c]) {\n                    if (cellW[b] >= cellW[c]) mask[b] = 1;\n                    else mask[c] = 1;\n                    changed = true;\n                }\n                if (mask[b] && mask[c] && !mask[a] && !mask[d]) {\n                    if (cellW[a] >= cellW[d]) mask[a] = 1;\n                    else mask[d] = 1;\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n        fillHoles(mask, G);\n    }\n}\n\nint calcPerimCells(const vector<char>& mask, int G) {\n    int per = 0;\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n            if (x == 0 || !mask[id(x-1,y,G)]) per++;\n            if (x == G-1 || !mask[id(x+1,y,G)]) per++;\n            if (y == 0 || !mask[id(x,y-1,G)]) per++;\n            if (y == G-1 || !mask[id(x,y+1,G)]) per++;\n        }\n    }\n    return per;\n}\n\nvector<pair<int,int>> extractPolygon(const vector<char>& mask, int G, int L) {\n    int V = (G + 1) * (G + 1);\n    vector<int> nxt(V, -1), indeg(V, 0);\n    bool bad = false;\n    int edgeCnt = 0;\n\n    auto vid = [&](int x, int y) {\n        return y * (G + 1) + x;\n    };\n\n    auto addEdge = [&](int x1, int y1, int x2, int y2) {\n        int u = vid(x1,y1), v = vid(x2,y2);\n        if (nxt[u] != -1) bad = true;\n        nxt[u] = v;\n        indeg[v]++;\n        if (indeg[v] > 1) bad = true;\n        edgeCnt++;\n    };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n\n            if (y == 0 || !mask[id(x,y-1,G)]) {\n                addEdge(x, y, x+1, y);\n            }\n            if (x == G-1 || !mask[id(x+1,y,G)]) {\n                addEdge(x+1, y, x+1, y+1);\n            }\n            if (y == G-1 || !mask[id(x,y+1,G)]) {\n                addEdge(x+1, y+1, x, y+1);\n            }\n            if (x == 0 || !mask[id(x-1,y,G)]) {\n                addEdge(x, y+1, x, y);\n            }\n        }\n    }\n\n    if (bad || edgeCnt == 0) return {};\n\n    int st = -1;\n    for (int i = 0; i < V; i++) {\n        if (nxt[i] != -1) {\n            st = i;\n            break;\n        }\n    }\n\n    vector<char> used(V, 0);\n    vector<pair<int,int>> poly;\n    int cur = st;\n\n    for (int step = 0; step <= edgeCnt; step++) {\n        if (cur == -1) return {};\n        if (cur == st && step > 0) break;\n        if (used[cur]) return {};\n        used[cur] = 1;\n\n        int gx = cur % (G + 1);\n        int gy = cur / (G + 1);\n        poly.push_back({gx * L, gy * L});\n\n        cur = nxt[cur];\n    }\n\n    if (cur != st) return {};\n\n    int usedEdges = 0;\n    for (int i = 0; i < V; i++) if (used[i]) usedEdges++;\n    if ((int)poly.size() != edgeCnt) {\n        // This usually means multiple cycles or invalid touching.\n        // Collinear vertices are counted here, so size should equal boundary edges.\n        return {};\n    }\n\n    auto collinear = [](pair<int,int> a, pair<int,int> b, pair<int,int> c) {\n        return (a.first == b.first && b.first == c.first) ||\n               (a.second == b.second && b.second == c.second);\n    };\n\n    bool changed = true;\n    while (changed && poly.size() >= 4) {\n        changed = false;\n        vector<pair<int,int>> np;\n        int m = (int)poly.size();\n        for (int i = 0; i < m; i++) {\n            auto a = poly[(i - 1 + m) % m];\n            auto b = poly[i];\n            auto c = poly[(i + 1) % m];\n            if (collinear(a,b,c)) {\n                changed = true;\n            } else {\n                np.push_back(b);\n            }\n        }\n        poly.swap(np);\n    }\n\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return {};\n\n    set<pair<int,int>> ss(poly.begin(), poly.end());\n    if (ss.size() != poly.size()) return {};\n\n    return poly;\n}\n\nEvalResult evalMask(vector<char> mask, int G, int L, const vector<int>& cellW) {\n    EvalResult res;\n    normalizeMask(mask, G, cellW);\n\n    if (!isConnected(mask, G)) return res;\n\n    int perCells = calcPerimCells(mask, G);\n    if (perCells * L > MAX_PERIM) return res;\n\n    auto poly = extractPolygon(mask, G, L);\n    if (poly.empty()) return res;\n\n    int diff = exactDiffMask(mask, G, L);\n\n    res.ok = true;\n    res.diff = diff;\n    res.mask = std::move(mask);\n    res.poly = std::move(poly);\n    return res;\n}\n\nvector<int> buildGridWeight(int G, int L) {\n    vector<int> w(G * G, 0);\n    for (auto &p : fishes) {\n        int x = min(G - 1, p.x / L);\n        int y = min(G - 1, p.y / L);\n        w[id(x,y,G)] += p.w;\n    }\n    return w;\n}\n\nvoid tryTinyBaseline() {\n    for (int i = 0; i < N; i++) {\n        int x = fishes[i].x;\n        int y = fishes[i].y;\n        int x1, x2, y1, y2;\n\n        if (x < LIM) x1 = x, x2 = x + 1;\n        else x1 = x - 1, x2 = x;\n\n        if (y < LIM) y1 = y, y2 = y + 1;\n        else y1 = y - 1, y2 = y;\n\n        int diff = exactDiffRect(x1,y1,x2,y2);\n        vector<pair<int,int>> poly = {\n            {x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}\n        };\n        updateBest(poly, diff);\n    }\n}\n\nvoid tryBestRectangle(int G, int L, const vector<int>& cellW) {\n    int maxSideSum = MAX_PERIM / (2 * L);\n\n    int bestVal = -1000000000;\n    int bx1 = 0, by1 = 0, bx2 = 1, by2 = 1;\n\n    vector<int> arr(G), pref(G + 1);\n\n    for (int xl = 0; xl < G; xl++) {\n        fill(arr.begin(), arr.end(), 0);\n\n        for (int xr = xl; xr < G; xr++) {\n            for (int y = 0; y < G; y++) {\n                arr[y] += cellW[id(xr,y,G)];\n            }\n\n            int width = xr - xl + 1;\n            int maxH = maxSideSum - width;\n            if (maxH <= 0) continue;\n            maxH = min(maxH, G);\n\n            pref[0] = 0;\n            for (int y = 0; y < G; y++) pref[y+1] = pref[y] + arr[y];\n\n            deque<int> dq;\n            for (int e = 1; e <= G; e++) {\n                int sNew = e - 1;\n                while (!dq.empty() && pref[dq.back()] >= pref[sNew]) dq.pop_back();\n                dq.push_back(sNew);\n\n                while (!dq.empty() && dq.front() < e - maxH) dq.pop_front();\n\n                int s = dq.front();\n                int val = pref[e] - pref[s];\n                if (val > bestVal) {\n                    bestVal = val;\n                    bx1 = xl;\n                    bx2 = xr + 1;\n                    by1 = s;\n                    by2 = e;\n                }\n            }\n        }\n    }\n\n    int x1 = bx1 * L;\n    int x2 = bx2 * L;\n    int y1 = by1 * L;\n    int y2 = by2 * L;\n\n    int diff = exactDiffRect(x1,y1,x2,y2);\n    vector<pair<int,int>> poly = {\n        {x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}\n    };\n    updateBest(poly, diff);\n}\n\nstruct Comp {\n    int score = 0;\n    int size = 0;\n    long long sx = 0, sy = 0;\n    vector<int> cells;\n};\n\nvector<Comp> getComponents(const vector<char>& mask, int G, const vector<int>& cellW) {\n    vector<Comp> comps;\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] || vis[i]) continue;\n\n        Comp c;\n        vis[i] = 1;\n        q.push(i);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            int x = v % G, y = v / G;\n\n            c.cells.push_back(v);\n            c.score += cellW[v];\n            c.size++;\n            c.sx += x;\n            c.sy += y;\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n                int ni = id(nx,ny,G);\n                if (!mask[ni] || vis[ni]) continue;\n                vis[ni] = 1;\n                q.push(ni);\n            }\n        }\n\n        if (c.size > 0) comps.push_back(std::move(c));\n    }\n\n    sort(comps.begin(), comps.end(), [](const Comp& a, const Comp& b) {\n        return a.score > b.score;\n    });\n\n    return comps;\n}\n\nvector<char> makeCompMask(const Comp& c, int G) {\n    vector<char> m(G * G, 0);\n    for (int v : c.cells) m[v] = 1;\n    return m;\n}\n\nvoid addPath(vector<char>& m, int G, int x1, int y1, int x2, int y2, bool hv) {\n    if (hv) {\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y1,G)] = 1;\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x2,y,G)] = 1;\n    } else {\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x1,y,G)] = 1;\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y2,G)] = 1;\n    }\n}\n\nvoid tryGreedyUnion(vector<Comp>& comps, int G, int L, const vector<int>& cellW) {\n    vector<Comp> pos;\n    for (auto &c : comps) {\n        if (c.score > 0) pos.push_back(c);\n        if ((int)pos.size() >= 20) break;\n    }\n    if (pos.empty()) return;\n\n    vector<char> cur = makeCompMask(pos[0], G);\n    auto er0 = evalMask(cur, G, L, cellW);\n    if (!er0.ok) return;\n\n    updateBest(er0.poly, er0.diff);\n    cur = er0.mask;\n    int curDiff = er0.diff;\n\n    for (int ci = 1; ci < (int)pos.size(); ci++) {\n        const Comp& c = pos[ci];\n\n        int cx = (int)(c.sx / max(1, c.size));\n        int cy = (int)(c.sy / max(1, c.size));\n\n        int ax = -1, ay = -1, bestD = INT_MAX;\n        for (int y = 0; y < G; y++) {\n            for (int x = 0; x < G; x++) {\n                if (!cur[id(x,y,G)]) continue;\n                int d = abs(x - cx) + abs(y - cy);\n                if (d < bestD) {\n                    bestD = d;\n                    ax = x;\n                    ay = y;\n                }\n            }\n        }\n\n        int bx = -1, by = -1;\n        bestD = INT_MAX;\n        for (int v : c.cells) {\n            int x = v % G, y = v / G;\n            int d = abs(x - ax) + abs(y - ay);\n            if (d < bestD) {\n                bestD = d;\n                bx = x;\n                by = y;\n            }\n        }\n\n        vector<char> base = cur;\n        for (int v : c.cells) base[v] = 1;\n\n        vector<char> m1 = base, m2 = base;\n        addPath(m1, G, ax, ay, bx, by, true);\n        addPath(m2, G, ax, ay, bx, by, false);\n\n        auto e1 = evalMask(m1, G, L, cellW);\n        auto e2 = evalMask(m2, G, L, cellW);\n\n        EvalResult bestE;\n        if (e1.ok) bestE = e1;\n        if (e2.ok && (!bestE.ok || e2.diff > bestE.diff)) bestE = e2;\n\n        if (bestE.ok) {\n            updateBest(bestE.poly, bestE.diff);\n            if (bestE.diff > curDiff) {\n                curDiff = bestE.diff;\n                cur = bestE.mask;\n            }\n        }\n    }\n}\n\nvector<int> boxSmooth(const vector<int>& w, int G, int r) {\n    vector<int> pref((G+1)*(G+1), 0);\n    auto pid = [&](int x, int y) { return y * (G + 1) + x; };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            pref[pid(x+1,y+1)] =\n                pref[pid(x+1,y)] + pref[pid(x,y+1)] - pref[pid(x,y)] + w[id(x,y,G)];\n        }\n    }\n\n    vector<int> sm(G * G, 0);\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            int x1 = max(0, x - r);\n            int y1 = max(0, y - r);\n            int x2 = min(G, x + r + 1);\n            int y2 = min(G, y + r + 1);\n            int val =\n                pref[pid(x2,y2)] - pref[pid(x1,y2)] -\n                pref[pid(x2,y1)] + pref[pid(x1,y1)];\n            sm[id(x,y,G)] = val;\n        }\n    }\n    return sm;\n}\n\nvoid processGrid(int L) {\n    int G = LIM / L;\n    vector<int> cellW = buildGridWeight(G, L);\n\n    tryBestRectangle(G, L, cellW);\n\n    vector<int> radii;\n    if (L == 500) radii = {0,1,2,3,5,8,12};\n    else if (L == 1000) radii = {0,1,2,3,5,8};\n    else if (L == 2000) radii = {0,1,2,3,4};\n    else radii = {0,1,2,3};\n\n    for (int r : radii) {\n        vector<int> sm = boxSmooth(cellW, G, r);\n\n        vector<int> thresholds;\n        if (r == 0) thresholds = {0};\n        else thresholds = {-1, 0, 1, 2, 4};\n\n        for (int th : thresholds) {\n            vector<char> mask(G * G, 0);\n            for (int i = 0; i < G * G; i++) {\n                if (sm[i] > th) mask[i] = 1;\n            }\n\n            auto comps = getComponents(mask, G, cellW);\n\n            int cnt = 0;\n            for (auto &c : comps) {\n                if (c.score <= 0) continue;\n                auto cm = makeCompMask(c, G);\n                auto er = evalMask(cm, G, L, cellW);\n                if (er.ok) updateBest(er.poly, er.diff);\n\n                cnt++;\n                if (cnt >= 30) break;\n            }\n\n            tryGreedyUnion(comps, G, L, cellW);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    fishes.reserve(2 * N);\n\n    for (int i = 0; i < 2 * N; i++) {\n        int x, y;\n        cin >> x >> y;\n        int w = (i < N ? 1 : -1);\n        fishes.push_back({x,y,w});\n    }\n\n    tryTinyBaseline();\n\n    vector<int> Ls = {500, 1000, 2000, 2500, 4000, 5000};\n    for (int L : Ls) {\n        processGrid(L);\n    }\n\n    if (bestAns.poly.empty()) {\n        // Absolute fallback.\n        cout << 4 << '\\n';\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << bestAns.poly.size() << '\\n';\n    for (auto [x,y] : bestAns.poly) {\n        x = max(0, min(LIM, x));\n        y = max(0, min(LIM, y));\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Op {\n    int p, r;\n    char d;\n    int b;\n};\n\nstruct Solution {\n    vector<Op> ops;\n    ll estScore;\n};\n\nstatic inline bool overlap(ll l1, ll r1, ll l2, ll r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstruct Solver {\n    int N, T;\n    ll sigma;\n    vector<ll> w, h;\n    vector<ll> obsW, obsH;\n    vector<ll> adjW, adjH;\n\n    vector<Solution> sols;\n    unordered_set<string> seen;\n    chrono::steady_clock::time_point st;\n    mt19937 rng;\n\n    Solver() : rng(1234567) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    pair<ll, ll> simulate(const vector<Op>& ops) const {\n        vector<ll> X(N), Y(N), W(N), H(N);\n        vector<char> used(N, 0);\n        ll BW = 0, BH = 0;\n\n        for (auto &op : ops) {\n            int p = op.p;\n            ll rw = op.r ? h[p] : w[p];\n            ll rh = op.r ? w[p] : h[p];\n            ll x = 0, y = 0;\n\n            if (op.d == 'U') {\n                x = (op.b == -1 ? 0 : X[op.b] + W[op.b]);\n                y = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap(x, x + rw, X[j], X[j] + W[j])) {\n                        y = max(y, Y[j] + H[j]);\n                    }\n                }\n            } else {\n                y = (op.b == -1 ? 0 : Y[op.b] + H[op.b]);\n                x = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap(y, y + rh, Y[j], Y[j] + H[j])) {\n                        x = max(x, X[j] + W[j]);\n                    }\n                }\n            }\n\n            X[p] = x;\n            Y[p] = y;\n            W[p] = rw;\n            H[p] = rh;\n            used[p] = 1;\n            BW = max(BW, x + rw);\n            BH = max(BH, y + rh);\n        }\n\n        return {BW, BH};\n    }\n\n    string makeKey(const vector<Op>& ops) const {\n        string s;\n        s.reserve(ops.size() * 3);\n        for (auto &op : ops) {\n            s.push_back(char(op.r));\n            s.push_back(op.d);\n            s.push_back(char(op.b + 1));\n        }\n        return s;\n    }\n\n    void addSolution(const vector<Op>& ops) {\n        if ((int)ops.size() != N) return;\n\n        string key = makeKey(ops);\n        if (seen.find(key) != seen.end()) return;\n        seen.insert(key);\n\n        auto [W0, H0] = simulate(ops);\n        sols.push_back({ops, W0 + H0});\n    }\n\n    struct SegInfo {\n        bool ok = false;\n        ll rowH = 0;\n        ll rowW = 0;\n        vector<int> rot;\n    };\n\n    SegInfo calcRowSegment(int l, int r, ll limitW, bool needRot) const {\n        vector<ll> cand;\n        cand.reserve((r - l) * 2);\n\n        for (int i = l; i < r; i++) {\n            cand.push_back(h[i]);\n            cand.push_back(w[i]);\n        }\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        for (ll HH : cand) {\n            ll sumW = 0;\n            bool ok = true;\n            vector<int> rots;\n            if (needRot) rots.reserve(r - l);\n\n            for (int i = l; i < r; i++) {\n                const ll INF = (1LL << 60);\n                ll bw = INF;\n                int br = -1;\n\n                if (h[i] <= HH) {\n                    bw = w[i];\n                    br = 0;\n                }\n                if (w[i] <= HH && h[i] < bw) {\n                    bw = h[i];\n                    br = 1;\n                }\n\n                if (br == -1) {\n                    ok = false;\n                    break;\n                }\n\n                sumW += bw;\n                if (sumW > limitW) {\n                    ok = false;\n                    break;\n                }\n\n                if (needRot) rots.push_back(br);\n            }\n\n            if (ok) {\n                SegInfo res;\n                res.ok = true;\n                res.rowH = HH;\n                res.rowW = sumW;\n                if (needRot) res.rot = move(rots);\n                return res;\n            }\n        }\n\n        return {};\n    }\n\n    SegInfo calcColSegment(int l, int r, ll limitH, bool needRot) const {\n        vector<ll> cand;\n        cand.reserve((r - l) * 2);\n\n        for (int i = l; i < r; i++) {\n            cand.push_back(w[i]);\n            cand.push_back(h[i]);\n        }\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        for (ll WW : cand) {\n            ll sumH = 0;\n            bool ok = true;\n            vector<int> rots;\n            if (needRot) rots.reserve(r - l);\n\n            for (int i = l; i < r; i++) {\n                const ll INF = (1LL << 60);\n                ll bh = INF;\n                int br = -1;\n\n                if (w[i] <= WW) {\n                    bh = h[i];\n                    br = 0;\n                }\n                if (h[i] <= WW && w[i] < bh) {\n                    bh = w[i];\n                    br = 1;\n                }\n\n                if (br == -1) {\n                    ok = false;\n                    break;\n                }\n\n                sumH += bh;\n                if (sumH > limitH) {\n                    ok = false;\n                    break;\n                }\n\n                if (needRot) rots.push_back(br);\n            }\n\n            if (ok) {\n                SegInfo res;\n                res.ok = true;\n                res.rowH = sumH;\n                res.rowW = WW;\n                if (needRot) res.rot = move(rots);\n                return res;\n            }\n        }\n\n        return {};\n    }\n\n    void generateShelfRows(ll limitW) {\n        const ll INF = (1LL << 60);\n\n        vector<vector<ll>> segH(N, vector<ll>(N + 1, INF));\n        vector<vector<ll>> segW(N, vector<ll>(N + 1, INF));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l + 1; r <= N; r++) {\n                SegInfo si = calcRowSegment(l, r, limitW, false);\n                if (si.ok) {\n                    segH[l][r] = si.rowH;\n                    segW[l][r] = si.rowW;\n                }\n            }\n        }\n\n        vector<ll> dpH(N + 1, INF), dpMaxW(N + 1, INF);\n        vector<int> prv(N + 1, -1);\n\n        dpH[0] = 0;\n        dpMaxW[0] = 0;\n\n        for (int i = 1; i <= N; i++) {\n            for (int l = 0; l < i; l++) {\n                if (dpH[l] == INF || segH[l][i] == INF) continue;\n\n                ll nh = dpH[l] + segH[l][i];\n                ll nw = max(dpMaxW[l], segW[l][i]);\n\n                if (nh < dpH[i] || (nh == dpH[i] && nw < dpMaxW[i])) {\n                    dpH[i] = nh;\n                    dpMaxW[i] = nw;\n                    prv[i] = l;\n                }\n            }\n        }\n\n        if (prv[N] == -1) return;\n\n        vector<pair<int,int>> rows;\n        for (int cur = N; cur > 0; cur = prv[cur]) {\n            rows.push_back({prv[cur], cur});\n        }\n        reverse(rows.begin(), rows.end());\n\n        vector<int> rot(N, 0);\n        for (auto [l, r] : rows) {\n            SegInfo si = calcRowSegment(l, r, limitW, true);\n            if (!si.ok) return;\n            for (int k = l; k < r; k++) rot[k] = si.rot[k - l];\n        }\n\n        vector<Op> ops;\n        ops.reserve(N);\n\n        int prevAnchor = -1;\n\n        for (int row = 0; row < (int)rows.size(); row++) {\n            auto [l, r] = rows[row];\n            int b = (row == 0 ? -1 : prevAnchor);\n\n            for (int i = l; i < r; i++) {\n                ops.push_back({i, rot[i], 'L', b});\n            }\n\n            ll bestH = -1;\n            int anchor = l;\n            for (int i = l; i < r; i++) {\n                ll hh = rot[i] ? w[i] : h[i];\n                if (hh > bestH) {\n                    bestH = hh;\n                    anchor = i;\n                }\n            }\n\n            prevAnchor = anchor;\n        }\n\n        addSolution(ops);\n    }\n\n    void generateShelfCols(ll limitH) {\n        const ll INF = (1LL << 60);\n\n        vector<vector<ll>> segW(N, vector<ll>(N + 1, INF));\n        vector<vector<ll>> segH(N, vector<ll>(N + 1, INF));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l + 1; r <= N; r++) {\n                SegInfo si = calcColSegment(l, r, limitH, false);\n                if (si.ok) {\n                    segW[l][r] = si.rowW;\n                    segH[l][r] = si.rowH;\n                }\n            }\n        }\n\n        vector<ll> dpW(N + 1, INF), dpMaxH(N + 1, INF);\n        vector<int> prv(N + 1, -1);\n\n        dpW[0] = 0;\n        dpMaxH[0] = 0;\n\n        for (int i = 1; i <= N; i++) {\n            for (int l = 0; l < i; l++) {\n                if (dpW[l] == INF || segW[l][i] == INF) continue;\n\n                ll nw = dpW[l] + segW[l][i];\n                ll nh = max(dpMaxH[l], segH[l][i]);\n\n                if (nw < dpW[i] || (nw == dpW[i] && nh < dpMaxH[i])) {\n                    dpW[i] = nw;\n                    dpMaxH[i] = nh;\n                    prv[i] = l;\n                }\n            }\n        }\n\n        if (prv[N] == -1) return;\n\n        vector<pair<int,int>> cols;\n        for (int cur = N; cur > 0; cur = prv[cur]) {\n            cols.push_back({prv[cur], cur});\n        }\n        reverse(cols.begin(), cols.end());\n\n        vector<int> rot(N, 0);\n        for (auto [l, r] : cols) {\n            SegInfo si = calcColSegment(l, r, limitH, true);\n            if (!si.ok) return;\n            for (int k = l; k < r; k++) rot[k] = si.rot[k - l];\n        }\n\n        vector<Op> ops;\n        ops.reserve(N);\n\n        int prevAnchor = -1;\n\n        for (int col = 0; col < (int)cols.size(); col++) {\n            auto [l, r] = cols[col];\n            int b = (col == 0 ? -1 : prevAnchor);\n\n            for (int i = l; i < r; i++) {\n                ops.push_back({i, rot[i], 'U', b});\n            }\n\n            ll bestW = -1;\n            int anchor = l;\n            for (int i = l; i < r; i++) {\n                ll ww = rot[i] ? h[i] : w[i];\n                if (ww > bestW) {\n                    bestW = ww;\n                    anchor = i;\n                }\n            }\n\n            prevAnchor = anchor;\n        }\n\n        addSolution(ops);\n    }\n\n    void generateSimpleRowsAndCols() {\n        for (int policy = 0; policy < 4; policy++) {\n            vector<Op> ops;\n            ops.reserve(N);\n\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (policy == 1) r = 1;\n                else if (policy == 2) r = (h[i] < w[i]);\n                else if (policy == 3) r = (w[i] < h[i]);\n\n                ops.push_back({i, r, 'L', -1});\n            }\n\n            addSolution(ops);\n        }\n\n        for (int policy = 0; policy < 4; policy++) {\n            vector<Op> ops;\n            ops.reserve(N);\n\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (policy == 1) r = 1;\n                else if (policy == 2) r = (h[i] < w[i]);\n                else if (policy == 3) r = (w[i] < h[i]);\n\n                ops.push_back({i, r, 'U', -1});\n            }\n\n            addSolution(ops);\n        }\n    }\n\n    void generateGreedy(double wp, double wa, double wb, double noiseCoef) {\n        vector<Op> ops;\n        ops.reserve(N);\n\n        vector<ll> X(N), Y(N), RW(N), RH(N);\n        vector<char> used(N, 0);\n        ll curW = 0, curH = 0;\n\n        long double area = 0;\n        for (int i = 0; i < N; i++) area += (long double)w[i] * h[i];\n\n        double scale = max(1.0, sqrt((double)area));\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        for (int i = 0; i < N; i++) {\n            double bestCost = 1e100;\n            Op bestOp{i, 0, 'L', -1};\n            ll bestX = 0, bestY = 0, bestRW = w[i], bestRH = h[i];\n            ll bestBW = 0, bestBH = 0;\n\n            for (int r = 0; r < 2; r++) {\n                ll rw = r ? h[i] : w[i];\n                ll rh = r ? w[i] : h[i];\n\n                for (int d0 = 0; d0 < 2; d0++) {\n                    char d = d0 ? 'L' : 'U';\n\n                    for (int b = -1; b < i; b++) {\n                        ll x = 0, y = 0;\n\n                        if (d == 'U') {\n                            x = (b == -1 ? 0 : X[b] + RW[b]);\n                            y = 0;\n\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (overlap(x, x + rw, X[j], X[j] + RW[j])) {\n                                    y = max(y, Y[j] + RH[j]);\n                                }\n                            }\n                        } else {\n                            y = (b == -1 ? 0 : Y[b] + RH[b]);\n                            x = 0;\n\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (overlap(y, y + rh, Y[j], Y[j] + RH[j])) {\n                                    x = max(x, X[j] + RW[j]);\n                                }\n                            }\n                        }\n\n                        ll BW = max(curW, x + rw);\n                        ll BH = max(curH, y + rh);\n\n                        double cost = 0.0;\n                        cost += wp * (double)(BW + BH);\n                        cost += wa * ((double)BW * (double)BH / scale);\n                        cost += wb * (double)llabs(BW - BH);\n                        cost += noiseCoef * scale * ud(rng);\n                        cost += 0.0001 * (double)(x + y);\n\n                        if (cost < bestCost) {\n                            bestCost = cost;\n                            bestOp = {i, r, d, b};\n                            bestX = x;\n                            bestY = y;\n                            bestRW = rw;\n                            bestRH = rh;\n                            bestBW = BW;\n                            bestBH = BH;\n                        }\n                    }\n                }\n            }\n\n            ops.push_back(bestOp);\n            X[i] = bestX;\n            Y[i] = bestY;\n            RW[i] = bestRW;\n            RH[i] = bestRH;\n            used[i] = 1;\n            curW = bestBW;\n            curH = bestBH;\n        }\n\n        addSolution(ops);\n    }\n\n    void makeAdjustedDimensions() {\n        vector<ll> vals;\n        vals.reserve(2 * N);\n        for (int i = 0; i < N; i++) {\n            vals.push_back(obsW[i]);\n            vals.push_back(obsH[i]);\n        }\n\n        sort(vals.begin(), vals.end());\n\n        int m = vals.size();\n        double q10 = vals[max(0, min(m - 1, m / 10))];\n\n        // Prior: true side lengths are approximately uniform on [L, 100000].\n        double Lhat = (q10 - 10000.0) / 0.9;\n        Lhat = min(50000.0, max(10000.0, Lhat));\n\n        double mean = (Lhat + 100000.0) * 0.5;\n        double var = (100000.0 - Lhat) * (100000.0 - Lhat) / 12.0;\n        double a = var / (var + (double)sigma * (double)sigma);\n\n        // Slightly conservative shrink. For small sigma this is nearly identity.\n        a = 1.0 - 1.15 * (1.0 - a);\n        a = min(1.0, max(0.55, a));\n\n        adjW.resize(N);\n        adjH.resize(N);\n\n        for (int i = 0; i < N; i++) {\n            adjW[i] = max(1LL, (ll)llround(a * obsW[i] + (1.0 - a) * mean));\n            adjH[i] = max(1LL, (ll)llround(a * obsH[i] + (1.0 - a) * mean));\n        }\n    }\n\n    vector<ll> makeLimits(int cnt, double lo, double hi) const {\n        long double area = 0;\n        ll minSingleSide = 1;\n\n        for (int i = 0; i < N; i++) {\n            area += (long double)w[i] * h[i];\n            minSingleSide = max(minSingleSide, min(w[i], h[i]));\n        }\n\n        double sqrtA = sqrt((double)area);\n        vector<ll> limits;\n\n        for (int k = 0; k < cnt; k++) {\n            double f = lo + (hi - lo) * k / max(1, cnt - 1);\n            limits.push_back(max<ll>(minSingleSide, (ll)llround(sqrtA * f)));\n        }\n\n        sort(limits.begin(), limits.end());\n        limits.erase(unique(limits.begin(), limits.end()), limits.end());\n        return limits;\n    }\n\n    void recomputeScoresWithObserved() {\n        w = obsW;\n        h = obsH;\n\n        for (auto &s : sols) {\n            auto [BW, BH] = simulate(s.ops);\n            s.estScore = BW + BH;\n        }\n    }\n\n    void generateAll() {\n        st = chrono::steady_clock::now();\n\n        obsW = w;\n        obsH = h;\n        makeAdjustedDimensions();\n\n        // Main search using observed sizes.\n        w = obsW;\n        h = obsH;\n\n        generateSimpleRowsAndCols();\n\n        {\n            vector<ll> limits = makeLimits(55, 0.50, 2.65);\n            for (ll L : limits) {\n                if (elapsed() > 1.55) break;\n                generateShelfRows(L);\n                generateShelfCols(L);\n            }\n        }\n\n        int greedyTrials = 0;\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        while (elapsed() < 2.48 && greedyTrials < 750) {\n            greedyTrials++;\n\n            double wp = 1.0;\n            double wa = pow(10.0, -0.45 + 1.35 * ud(rng));\n            double wb = 0.03 + 1.50 * ud(rng);\n            double nz = 0.0;\n\n            if (greedyTrials % 3 == 0) nz = 0.01 * ud(rng);\n            if (greedyTrials % 7 == 0) nz = 0.05 * ud(rng);\n            if (greedyTrials % 19 == 0) nz = 0.10 * ud(rng);\n\n            generateGreedy(wp, wa, wb, nz);\n        }\n\n        // Additional diversification using shrunk dimensions.\n        // These candidates are finally ranked by observed-size simulation.\n        if (elapsed() < 2.62) {\n            w = adjW;\n            h = adjH;\n\n            vector<ll> limits = makeLimits(18, 0.55, 2.45);\n            for (ll L : limits) {\n                if (elapsed() > 2.60) break;\n                generateShelfRows(L);\n                generateShelfCols(L);\n            }\n\n            int adjTrials = 0;\n            while (elapsed() < 2.66 && adjTrials < 80) {\n                adjTrials++;\n\n                double wp = 1.0;\n                double wa = pow(10.0, -0.35 + 1.20 * ud(rng));\n                double wb = 0.05 + 1.20 * ud(rng);\n                double nz = 0.02 * ud(rng);\n\n                generateGreedy(wp, wa, wb, nz);\n            }\n        }\n\n        if (sols.empty()) {\n            w = obsW;\n            h = obsH;\n            vector<Op> ops;\n            for (int i = 0; i < N; i++) ops.push_back({i, 0, 'L', -1});\n            addSolution(ops);\n        }\n\n        recomputeScoresWithObserved();\n\n        sort(sols.begin(), sols.end(), [](const Solution& a, const Solution& b) {\n            return a.estScore < b.estScore;\n        });\n    }\n\n    void run() {\n        cin >> N >> T >> sigma;\n\n        w.resize(N);\n        h.resize(N);\n\n        for (int i = 0; i < N; i++) {\n            cin >> w[i] >> h[i];\n        }\n\n        generateAll();\n\n        for (int t = 0; t < T; t++) {\n            const vector<Op>& ops = sols[t % sols.size()].ops;\n\n            cout << ops.size() << '\\n';\n            for (auto &op : ops) {\n                cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n            }\n            cout.flush();\n\n            ll Wobs, Hobs;\n            if (!(cin >> Wobs >> Hobs)) return;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.run();\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 10;\nstatic constexpr int MAXN = 1000;\nstatic constexpr long long NEG = -(1LL << 60);\n\nstruct Edge {\n    int u, v;\n    long long len2;\n};\n\nstruct Solver {\n    int N, M, HH;\n    vector<int> A;\n    vector<Edge> edges;\n    vector<vector<int>> adj;\n    vector<int> xs, ys;\n    vector<bitset<MAXN>> con;\n\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n\n    vector<array<long long, 11>> dp_no, dp_need;\n    vector<vector<int>> children;\n\n    vector<int> orderHigh, orderLow;\n\n    Solver() : rng(1234567) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    long long scoreLabels(const vector<int>& d) const {\n        long long s = 0;\n        for (int i = 0; i < N; i++) s += 1LL * (d[i] + 1) * A[i];\n        return s;\n    }\n\n    long long keyPrim(int mode, int from, int to) {\n        long long noise = (long long)(rng() % 100000);\n        long long dx = xs[from] - xs[to];\n        long long dy = ys[from] - ys[to];\n        long long len2 = dx * dx + dy * dy;\n\n        if (mode == 0) return 1LL * A[to] * 100000 + noise;\n        if (mode == 1) return 1LL * (101 - A[to]) * 100000 + noise;\n        if (mode == 2) return (long long)(rng() & 0x7fffffff);\n        if (mode == 3) return len2 * 1000 + noise;\n        if (mode == 4) return (2000000LL - min(len2, 2000000LL)) * 1000 + noise;\n        return 1LL * A[to] * 50000 + len2 + noise;\n    }\n\n    vector<int> makePrimTree(int mode) {\n        vector<int> par(N, -2), used(N, 0);\n\n        int start = 0;\n        if (mode == 0 || mode == 5) start = min_element(A.begin(), A.end()) - A.begin();\n        else if (mode == 1) start = max_element(A.begin(), A.end()) - A.begin();\n        else start = rng() % N;\n\n        using T = tuple<long long, int, int>;\n        priority_queue<T, vector<T>, greater<T>> pq;\n\n        used[start] = 1;\n        par[start] = -1;\n        int cnt = 1;\n\n        for (int to : adj[start]) pq.emplace(keyPrim(mode, start, to), start, to);\n\n        while (cnt < N && !pq.empty()) {\n            auto [key, from, v] = pq.top();\n            pq.pop();\n\n            if (used[v]) continue;\n\n            used[v] = 1;\n            par[v] = from;\n            cnt++;\n\n            for (int to : adj[v]) {\n                if (!used[to]) pq.emplace(keyPrim(mode, v, to), v, to);\n            }\n        }\n\n        return par;\n    }\n\n    vector<int> makeDFSTree(int mode) {\n        vector<vector<pair<long long, int>>> ord(N);\n\n        for (int v = 0; v < N; v++) {\n            for (int to : adj[v]) {\n                long long noise = (long long)(rng() % 100000);\n                long long key;\n\n                if (mode == 0) key = 1LL * A[to] * 100000 + noise;\n                else if (mode == 1) key = 1LL * (101 - A[to]) * 100000 + noise;\n                else key = (long long)(rng() & 0x7fffffff);\n\n                ord[v].push_back({key, to});\n            }\n            sort(ord[v].begin(), ord[v].end());\n        }\n\n        int start;\n        if (mode == 0) start = min_element(A.begin(), A.end()) - A.begin();\n        else if (mode == 1) start = max_element(A.begin(), A.end()) - A.begin();\n        else start = rng() % N;\n\n        vector<int> par(N, -2), used(N, 0), idx(N, 0), stk;\n        stk.push_back(start);\n        used[start] = 1;\n        par[start] = -1;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n\n            while (idx[v] < (int)ord[v].size() && used[ord[v][idx[v]].second]) idx[v]++;\n\n            if (idx[v] == (int)ord[v].size()) {\n                stk.pop_back();\n                continue;\n            }\n\n            int to = ord[v][idx[v]++].second;\n            used[to] = 1;\n            par[to] = v;\n            stk.push_back(to);\n        }\n\n        return par;\n    }\n\n    long long childVal(int c, int childLabel, int parentLabel) const {\n        if (childLabel == 0 || parentLabel == childLabel - 1) return dp_no[c][childLabel];\n        return dp_need[c][childLabel];\n    }\n\n    vector<int> solveOnTree(const vector<int>& treePar) {\n        vector<vector<int>> tadj(N);\n\n        for (int v = 0; v < N; v++) {\n            if (treePar[v] >= 0) {\n                tadj[v].push_back(treePar[v]);\n                tadj[treePar[v]].push_back(v);\n            }\n        }\n\n        children.assign(N, {});\n        vector<int> parent(N, -1), order;\n        order.reserve(N);\n\n        vector<int> stk = {0};\n        parent[0] = -2;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n            stk.pop_back();\n            order.push_back(v);\n\n            for (int to : tadj[v]) {\n                if (to == parent[v]) continue;\n                parent[to] = v;\n                children[v].push_back(to);\n                stk.push_back(to);\n            }\n        }\n\n        dp_no.assign(N, {});\n        dp_need.assign(N, {});\n\n        for (int ii = N - 1; ii >= 0; ii--) {\n            int v = order[ii];\n\n            for (int l = 0; l <= H; l++) {\n                long long base = 1LL * (l + 1) * A[v];\n                vector<long long> bestChild;\n                bestChild.reserve(children[v].size());\n\n                bool ok = true;\n                long long sum = base;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n\n                    for (int lc = 0; lc <= H; lc++) {\n                        best = max(best, childVal(c, lc, l));\n                    }\n\n                    if (best <= NEG / 2) ok = false;\n\n                    sum += best;\n                    bestChild.push_back(best);\n                }\n\n                dp_no[v][l] = ok ? sum : NEG;\n\n                if (l == 0 || !ok) {\n                    dp_need[v][l] = NEG;\n                } else {\n                    int forcedLabel = l - 1;\n                    long long bestDelta = NEG;\n\n                    for (int idx = 0; idx < (int)children[v].size(); idx++) {\n                        int c = children[v][idx];\n                        long long fv = childVal(c, forcedLabel, l);\n\n                        if (fv <= NEG / 2) continue;\n\n                        bestDelta = max(bestDelta, fv - bestChild[idx]);\n                    }\n\n                    if (bestDelta <= NEG / 2) dp_need[v][l] = NEG;\n                    else dp_need[v][l] = sum + bestDelta;\n                }\n            }\n        }\n\n        int rootLabel = 0;\n        bool rootNeed = false;\n        long long bestRoot = dp_no[0][0];\n\n        for (int l = 1; l <= H; l++) {\n            if (dp_need[0][l] > bestRoot) {\n                bestRoot = dp_need[0][l];\n                rootLabel = l;\n                rootNeed = true;\n            }\n        }\n\n        vector<int> label(N, 0);\n\n        function<void(int, int, bool)> rec = [&](int v, int l, bool needSupportChild) {\n            label[v] = l;\n\n            int forcedChild = -1;\n\n            if (needSupportChild) {\n                int forcedLabel = l - 1;\n                long long bestDelta = NEG;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n\n                    for (int lc = 0; lc <= H; lc++) best = max(best, childVal(c, lc, l));\n\n                    long long fv = childVal(c, forcedLabel, l);\n\n                    if (fv <= NEG / 2) continue;\n\n                    long long delta = fv - best;\n\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        forcedChild = c;\n                    }\n                }\n            }\n\n            for (int c : children[v]) {\n                int lcBest = 0;\n                long long valBest = NEG;\n\n                if (c == forcedChild) {\n                    lcBest = l - 1;\n                } else {\n                    for (int lc = 0; lc <= H; lc++) {\n                        long long val = childVal(c, lc, l);\n\n                        if (val > valBest) {\n                            valBest = val;\n                            lcBest = lc;\n                        }\n                    }\n                }\n\n                bool childNeed = !(lcBest == 0 || l == lcBest - 1);\n                rec(c, lcBest, childNeed);\n            }\n        };\n\n        rec(0, rootLabel, rootNeed);\n        return label;\n    }\n\n    vector<int> calcCnt(const vector<int>& d) const {\n        vector<int> cnt(N, 0);\n\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) continue;\n\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) cnt[v]++;\n            }\n        }\n\n        return cnt;\n    }\n\n    bool canMove(const vector<int>& d, const vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n\n        if (old == nl) return false;\n\n        if (nl > 0) {\n            bool has = false;\n\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) {\n                    has = true;\n                    break;\n                }\n            }\n\n            if (!has) return false;\n        }\n\n        for (int to : adj[v]) {\n            if (d[to] > 0 && d[to] - 1 == old && cnt[to] == 1) return false;\n        }\n\n        return true;\n    }\n\n    bool canMoveExcept(\n        const vector<int>& d,\n        const vector<int>& cnt,\n        int v,\n        int nl,\n        int exceptVertex,\n        int exceptFinalDepth\n    ) const {\n        int old = d[v];\n\n        if (old == nl) return false;\n\n        if (nl > 0) {\n            bool has = false;\n\n            for (int to : adj[v]) {\n                int td = (to == exceptVertex ? exceptFinalDepth : d[to]);\n\n                if (td == nl - 1) {\n                    has = true;\n                    break;\n                }\n            }\n\n            if (!has) return false;\n        }\n\n        for (int to : adj[v]) {\n            if (to == exceptVertex) continue;\n\n            if (d[to] > 0 && d[to] - 1 == old && cnt[to] == 1) return false;\n        }\n\n        return true;\n    }\n\n    void applyMove(vector<int>& d, vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n\n        for (int to : adj[v]) {\n            if (d[to] > 0) {\n                if (old == d[to] - 1) cnt[to]--;\n                if (nl == d[to] - 1) cnt[to]++;\n            }\n        }\n\n        d[v] = nl;\n\n        if (nl == 0) {\n            cnt[v] = 0;\n        } else {\n            int c = 0;\n\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) c++;\n            }\n\n            cnt[v] = c;\n        }\n    }\n\n    void greedyImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 20; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int old = d[v];\n\n                for (int nl = H; nl > old; nl--) {\n                    if (canMove(d, cnt, v, nl)) {\n                        applyMove(d, cnt, v, nl);\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void supportPairImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 5; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int dv = d[v];\n\n                if (dv == H) continue;\n\n                for (int t = H; t > dv; t--) {\n                    if (canMove(d, cnt, v, t)) {\n                        applyMove(d, cnt, v, t);\n                        changed = true;\n                        dv = t;\n                        break;\n                    }\n\n                    int need = t - 1;\n                    int bestU = -1;\n                    long long bestNet = 0;\n\n                    for (int u : adj[v]) {\n                        if (d[u] == need) continue;\n                        if (!canMoveExcept(d, cnt, u, need, v, t)) continue;\n\n                        long long net = 1LL * (t - dv) * A[v] + 1LL * (need - d[u]) * A[u];\n\n                        if (net > bestNet) {\n                            bestNet = net;\n                            bestU = u;\n                        }\n                    }\n\n                    if (bestU != -1) {\n                        int oldU = d[bestU];\n\n                        applyMove(d, cnt, bestU, need);\n\n                        if (canMove(d, cnt, v, t)) {\n                            applyMove(d, cnt, v, t);\n                            changed = true;\n                            dv = t;\n                            break;\n                        } else {\n                            applyMove(d, cnt, bestU, oldU);\n                        }\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    bool checkFeasible(const vector<int>& d) const {\n        for (int v = 0; v < N; v++) {\n            if (d[v] < 0 || d[v] > H) return false;\n\n            if (d[v] == 0) continue;\n\n            bool ok = false;\n\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return false;\n        }\n\n        return true;\n    }\n\n    void supportRoleSwapImprove(vector<int>& d, double timeLimit) {\n        for (int pass = 0; pass < 4 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n            vector<int> cnt = calcCnt(d);\n\n            int checked = 0;\n\n            for (int v : orderHigh) {\n                if (elapsed() >= timeLimit) break;\n                if (++checked > 750) break;\n\n                int k = d[v];\n                if (k >= H) continue;\n\n                vector<int> critical;\n\n                for (int to : adj[v]) {\n                    if (d[to] == k + 1 && cnt[to] == 1) critical.push_back(to);\n                }\n\n                if (critical.empty()) continue;\n                if ((int)critical.size() > 10) continue;\n\n                vector<int> cand;\n                vector<char> mark(N, 0);\n\n                auto addCand = [&](int x) {\n                    if (x == v) return;\n                    if (!mark[x]) {\n                        mark[x] = 1;\n                        cand.push_back(x);\n                    }\n                };\n\n                for (int c : critical) {\n                    addCand(c);\n                    for (int u : adj[c]) addCand(u);\n                }\n\n                long long bestGain = 0;\n                int bestU = -1;\n                int bestT = -1;\n\n                for (int u : cand) {\n                    if (d[u] == k) continue;\n\n                    bool covers = true;\n\n                    for (int c : critical) {\n                        if (u == c) continue;\n                        if (!con[u][c]) {\n                            covers = false;\n                            break;\n                        }\n                    }\n\n                    if (!covers) continue;\n\n                    for (int t = H; t > k; t--) {\n                        long long gain = 1LL * (t - k) * A[v] + 1LL * (k - d[u]) * A[u];\n\n                        if (gain <= bestGain) continue;\n\n                        if (!canMoveExcept(d, cnt, u, k, v, t)) continue;\n\n                        vector<int> td = d;\n                        vector<int> tc = cnt;\n\n                        applyMove(td, tc, u, k);\n\n                        if (!canMove(td, tc, v, t)) continue;\n\n                        applyMove(td, tc, v, t);\n\n                        bool localOk = true;\n\n                        for (int x : critical) {\n                            if (td[x] == 0) continue;\n\n                            bool ok = false;\n                            for (int nb : adj[x]) {\n                                if (td[nb] == td[x] - 1) {\n                                    ok = true;\n                                    break;\n                                }\n                            }\n\n                            if (!ok) {\n                                localOk = false;\n                                break;\n                            }\n                        }\n\n                        if (!localOk) continue;\n\n                        bestGain = gain;\n                        bestU = u;\n                        bestT = t;\n                    }\n                }\n\n                if (bestU != -1) {\n                    applyMove(d, cnt, bestU, k);\n                    applyMove(d, cnt, v, bestT);\n\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n\n            greedyImprove(d);\n            supportPairImprove(d);\n        }\n    }\n\n    struct PathState {\n        array<int, 11> node;\n        int len;\n        long long delta;\n    };\n\n    bool validatePathMove(const vector<int>& d, const PathState& s, int targetDepth) const {\n        vector<int> affected;\n        vector<int> mark(N, 0);\n\n        auto addAffected = [&](int x) {\n            if (!mark[x]) {\n                mark[x] = 1;\n                affected.push_back(x);\n            }\n        };\n\n        for (int i = 0; i < s.len; i++) {\n            int x = s.node[i];\n            addAffected(x);\n\n            for (int to : adj[x]) addAffected(to);\n        }\n\n        auto getDepth = [&](int x) {\n            for (int i = 0; i < s.len; i++) {\n                if (s.node[i] == x) return targetDepth - i;\n            }\n            return d[x];\n        };\n\n        for (int x : affected) {\n            int dx = getDepth(x);\n\n            if (dx == 0) continue;\n\n            bool ok = false;\n\n            for (int to : adj[x]) {\n                if (getDepth(to) == dx - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return false;\n        }\n\n        return true;\n    }\n\n    pair<long long, PathState> findBestPathMove(const vector<int>& d, int v, int targetDepth) const {\n        constexpr int BEAM = 36;\n\n        PathState init;\n        init.node.fill(-1);\n        init.node[0] = v;\n        init.len = 1;\n        init.delta = 1LL * (targetDepth - d[v]) * A[v];\n\n        vector<PathState> beam;\n        beam.push_back(init);\n\n        for (int dep = targetDepth - 1; dep >= 0; dep--) {\n            vector<PathState> nxt;\n            nxt.reserve(BEAM * 8);\n\n            for (const auto& s : beam) {\n                int cur = s.node[s.len - 1];\n\n                for (int nb : adj[cur]) {\n                    bool used = false;\n\n                    for (int i = 0; i < s.len; i++) {\n                        if (s.node[i] == nb) {\n                            used = true;\n                            break;\n                        }\n                    }\n\n                    if (used) continue;\n\n                    PathState ns = s;\n                    ns.node[ns.len++] = nb;\n                    ns.delta += 1LL * (dep - d[nb]) * A[nb];\n                    nxt.push_back(ns);\n                }\n            }\n\n            if (nxt.empty()) {\n                PathState dummy;\n                dummy.len = 0;\n                dummy.delta = NEG;\n                return {NEG, dummy};\n            }\n\n            sort(nxt.begin(), nxt.end(), [](const PathState& a, const PathState& b) {\n                return a.delta > b.delta;\n            });\n\n            if ((int)nxt.size() > BEAM) nxt.resize(BEAM);\n            beam.swap(nxt);\n        }\n\n        long long bestGain = NEG;\n        PathState best;\n        best.len = 0;\n        best.delta = NEG;\n\n        for (const auto& s : beam) {\n            if (s.delta <= 0) continue;\n            if (!validatePathMove(d, s, targetDepth)) continue;\n\n            if (s.delta > bestGain) {\n                bestGain = s.delta;\n                best = s;\n            }\n        }\n\n        return {bestGain, best};\n    }\n\n    void pathChainImprove(vector<int>& d, double timeLimit) {\n        for (int pass = 0; pass < 3 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n\n            for (int idx = 0; idx < N && elapsed() < timeLimit; idx++) {\n                int v = orderHigh[idx];\n\n                if (d[v] == H) continue;\n\n                long long bestGain = 0;\n                PathState bestState;\n                int bestTarget = -1;\n\n                for (int t = H; t > d[v]; t--) {\n                    auto [gain, state] = findBestPathMove(d, v, t);\n\n                    if (gain > bestGain) {\n                        bestGain = gain;\n                        bestState = state;\n                        bestTarget = t;\n                    }\n                }\n\n                if (bestGain > 0 && bestTarget >= 0) {\n                    for (int i = 0; i < bestState.len; i++) {\n                        d[bestState.node[i]] = bestTarget - i;\n                    }\n\n                    changed = true;\n                }\n            }\n\n            greedyImprove(d);\n            supportPairImprove(d);\n\n            if (!changed) break;\n        }\n    }\n\n    void lowPerturbAndImprove(vector<int>& d) const {\n        vector<int> best = d;\n        long long bestScore = scoreLabels(d);\n\n        vector<int> cur = d;\n        vector<int> cnt = calcCnt(cur);\n\n        int tried = 0;\n\n        for (int v : orderLow) {\n            if (++tried > 350) break;\n\n            int old = cur[v];\n\n            if (old == 0) continue;\n\n            int chosen = -1;\n\n            for (int nl = 0; nl < old; nl++) {\n                if (!canMove(cur, cnt, v, nl)) continue;\n\n                long long loss = 1LL * A[v] * (old - nl);\n                long long pot = 0;\n\n                for (int to : adj[v]) {\n                    if (cur[to] == nl + 1) pot += A[to];\n                    pot += A[to] / 10;\n                }\n\n                if (loss <= 120 + pot) {\n                    chosen = nl;\n                    break;\n                }\n            }\n\n            if (chosen != -1) applyMove(cur, cnt, v, chosen);\n        }\n\n        greedyImprove(cur);\n        supportPairImprove(cur);\n\n        long long sc = scoreLabels(cur);\n\n        if (sc > bestScore) d = cur;\n    }\n\n    void annealImprove(vector<int>& bestLabel, double timeLimit) {\n        vector<int> cur = bestLabel;\n        vector<int> cnt = calcCnt(cur);\n\n        long long curScore = scoreLabels(cur);\n        long long bestScore = curScore;\n\n        double startTime = elapsed();\n        int iter = 0;\n\n        uniform_real_distribution<double> real01(0.0, 1.0);\n\n        while (elapsed() < timeLimit) {\n            iter++;\n\n            double now = elapsed();\n            double progress = (now - startTime) / max(1e-9, timeLimit - startTime);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 55.0 * (1.0 - progress) + 1.0 * progress;\n\n            int v;\n\n            if ((rng() % 100) < 70) v = orderHigh[rng() % min(N, 550)];\n            else v = rng() % N;\n\n            int old = cur[v];\n            int nl;\n\n            if ((rng() % 100) < 72 && old < H) nl = old + 1 + (rng() % (H - old));\n            else nl = rng() % (H + 1);\n\n            if (nl == old) continue;\n            if (!canMove(cur, cnt, v, nl)) continue;\n\n            long long delta = 1LL * (nl - old) * A[v];\n\n            bool accept = false;\n\n            if (delta >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / temp);\n                if (real01(rng) < prob) accept = true;\n            }\n\n            if (accept) {\n                applyMove(cur, cnt, v, nl);\n                curScore += delta;\n\n                if (curScore > bestScore && checkFeasible(cur)) {\n                    bestScore = curScore;\n                    bestLabel = cur;\n                }\n            }\n\n            if (iter % 2500 == 0) {\n                greedyImprove(cur);\n                supportPairImprove(cur);\n\n                cnt = calcCnt(cur);\n                curScore = scoreLabels(cur);\n\n                if (curScore > bestScore && checkFeasible(cur)) {\n                    bestScore = curScore;\n                    bestLabel = cur;\n                }\n\n                if (curScore + 3000 < bestScore || (rng() % 100) < 12) {\n                    cur = bestLabel;\n                    cnt = calcCnt(cur);\n                    curScore = bestScore;\n                }\n            }\n        }\n\n        greedyImprove(bestLabel);\n        supportPairImprove(bestLabel);\n    }\n\n    vector<int> buildParents(const vector<int>& d) const {\n        vector<int> p(N, -1);\n\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) {\n                p[v] = -1;\n            } else {\n                int best = -1;\n                int bestA = 1e9;\n\n                for (int to : adj[v]) {\n                    if (d[to] == d[v] - 1) {\n                        if (A[to] < bestA) {\n                            bestA = A[to];\n                            best = to;\n                        }\n                    }\n                }\n\n                p[v] = best;\n            }\n        }\n\n        return p;\n    }\n\n    void safeKeepBest(vector<int>& bestLabel, const vector<int>& cand) const {\n        if (!checkFeasible(cand)) return;\n        if (scoreLabels(cand) > scoreLabels(bestLabel)) bestLabel = cand;\n    }\n\n    void run() {\n        cin >> N >> M >> HH;\n\n        A.resize(N);\n        for (int i = 0; i < N; i++) cin >> A[i];\n\n        edges.resize(M);\n        adj.assign(N, {});\n        con.assign(N, bitset<MAXN>());\n\n        for (int i = 0; i < M; i++) {\n            int u, v;\n            cin >> u >> v;\n\n            edges[i] = {u, v, 0};\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n            con[u][v] = 1;\n            con[v][u] = 1;\n        }\n\n        xs.resize(N);\n        ys.resize(N);\n\n        for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n        for (auto& e : edges) {\n            long long dx = xs[e.u] - xs[e.v];\n            long long dy = ys[e.u] - ys[e.v];\n            e.len2 = dx * dx + dy * dy;\n        }\n\n        orderHigh.resize(N);\n        orderLow.resize(N);\n\n        iota(orderHigh.begin(), orderHigh.end(), 0);\n        iota(orderLow.begin(), orderLow.end(), 0);\n\n        sort(orderHigh.begin(), orderHigh.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] > A[b];\n            return adj[a].size() > adj[b].size();\n        });\n\n        sort(orderLow.begin(), orderLow.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] < A[b];\n            return adj[a].size() < adj[b].size();\n        });\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestLabel(N, 0);\n        long long bestScore = scoreLabels(bestLabel);\n\n        int iter = 0;\n\n        while (elapsed() < 1.08) {\n            vector<int> treePar;\n\n            if (iter % 5 == 0) treePar = makeDFSTree((iter / 5) % 3);\n            else treePar = makePrimTree(iter % 6);\n\n            vector<int> label = solveOnTree(treePar);\n\n            greedyImprove(label);\n            supportPairImprove(label);\n\n            if (iter % 2 == 0) lowPerturbAndImprove(label);\n\n            long long sc = scoreLabels(label);\n\n            if (sc > bestScore && checkFeasible(label)) {\n                bestScore = sc;\n                bestLabel = label;\n            }\n\n            iter++;\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            supportRoleSwapImprove(cand, 1.32);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            pathChainImprove(cand, 1.58);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            supportRoleSwapImprove(cand, 1.68);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        annealImprove(bestLabel, 1.88);\n\n        {\n            vector<int> cand = bestLabel;\n            supportRoleSwapImprove(cand, 1.93);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        if (!checkFeasible(bestLabel)) fill(bestLabel.begin(), bestLabel.end(), 0);\n\n        vector<int> parent = buildParents(bestLabel);\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << parent[i];\n        }\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.run();\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nchar opposite_dir(char d) {\n    if (d == 'L') return 'R';\n    if (d == 'R') return 'L';\n    if (d == 'U') return 'D';\n    return 'U';\n}\n\nbool apply_shift(vector<string>& b, char d, int p) {\n    if (d == 'L') {\n        if (b[p][0] == 'o') return false;\n        for (int j = 0; j + 1 < N; j++) b[p][j] = b[p][j + 1];\n        b[p][N - 1] = '.';\n    } else if (d == 'R') {\n        if (b[p][N - 1] == 'o') return false;\n        for (int j = N - 1; j >= 1; j--) b[p][j] = b[p][j - 1];\n        b[p][0] = '.';\n    } else if (d == 'U') {\n        if (b[0][p] == 'o') return false;\n        for (int i = 0; i + 1 < N; i++) b[i][p] = b[i + 1][p];\n        b[N - 1][p] = '.';\n    } else {\n        if (b[N - 1][p] == 'o') return false;\n        for (int i = N - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n    return true;\n}\n\nint count_oni(const vector<string>& b) {\n    int c = 0;\n    for (auto& s : b) {\n        for (char ch : s) if (ch == 'x') c++;\n    }\n    return c;\n}\n\nbool validate_solution(const vector<string>& init, const vector<Op>& ops) {\n    if ((int)ops.size() > 4 * N * N) return false;\n    vector<string> b = init;\n    for (auto [d, p] : ops) {\n        if (p < 0 || p >= N) return false;\n        if (!apply_shift(b, d, p)) return false;\n    }\n    return count_oni(b) == 0;\n}\n\n/* -------------------- Restoring set-cover solver -------------------- */\n\nstruct Cand {\n    char d;\n    int p;\n    int s;\n    uint64_t mask;\n};\n\nint eval_cover(const vector<int>& sel, const vector<Cand>& cand, uint64_t allmask) {\n    uint64_t u = 0;\n    int sum = 0, mx = 0;\n    for (int id : sel) {\n        u |= cand[id].mask;\n        sum += cand[id].s;\n        mx = max(mx, cand[id].s);\n    }\n    if (u != allmask) return 1e9;\n    return 2 * sum - mx;\n}\n\nvoid prune_cover(vector<int>& sel, const vector<Cand>& cand, uint64_t allmask, mt19937& rng) {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        shuffle(sel.begin(), sel.end(), rng);\n        for (int k = 0; k < (int)sel.size(); k++) {\n            uint64_t u = 0;\n            for (int t = 0; t < (int)sel.size(); t++) {\n                if (t != k) u |= cand[sel[t]].mask;\n            }\n            if (u == allmask) {\n                sel.erase(sel.begin() + k);\n                changed = true;\n                break;\n            }\n        }\n    }\n}\n\nvector<Op> build_ops_from_cover(const vector<int>& sel, const vector<Cand>& cand) {\n    vector<Op> ops;\n    if (sel.empty()) return ops;\n\n    int last_pos = 0;\n    for (int i = 1; i < (int)sel.size(); i++) {\n        if (cand[sel[i]].s > cand[sel[last_pos]].s) last_pos = i;\n    }\n\n    for (int k = 0; k < (int)sel.size(); k++) {\n        const Cand& c = cand[sel[k]];\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        if (k != last_pos) {\n            char od = opposite_dir(c.d);\n            for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n        }\n    }\n    return ops;\n}\n\nvector<Op> solve_set_cover(const vector<string>& init, mt19937& rng) {\n    int id[N][N];\n    memset(id, -1, sizeof(id));\n    vector<pair<int,int>> oni;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (init[i][j] == 'x') {\n                id[i][j] = (int)oni.size();\n                oni.push_back({i, j});\n            }\n        }\n    }\n\n    int Mx = oni.size();\n    uint64_t allmask = (Mx == 64 ? ~0ULL : ((1ULL << Mx) - 1));\n    vector<Cand> cand;\n\n    auto add_cand = [&](char d, int p, int s, uint64_t mask) {\n        if (mask) cand.push_back({d, p, s, mask});\n    };\n\n    for (int i = 0; i < N; i++) {\n        int first_o = N;\n        for (int j = 0; j < N; j++) if (init[i][j] == 'o') { first_o = j; break; }\n\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int j = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('L', i, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int j = N - 1; j >= 0; j--) if (init[i][j] == 'o') { last_o = j; break; }\n\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int j = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('R', i, s, mask);\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int first_o = N;\n        for (int i = 0; i < N; i++) if (init[i][j] == 'o') { first_o = i; break; }\n\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int i = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('U', j, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int i = N - 1; i >= 0; i--) if (init[i][j] == 'o') { last_o = i; break; }\n\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int i = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('D', j, s, mask);\n            }\n        }\n    }\n\n    int C = cand.size();\n    vector<int> alive(C, 1);\n    for (int i = 0; i < C; i++) {\n        for (int j = 0; j < C; j++) if (i != j) {\n            bool subset = (cand[i].mask & ~cand[j].mask) == 0;\n            if (subset && (cand[j].s < cand[i].s || (cand[j].s == cand[i].s && j < i))) {\n                alive[i] = 0;\n                break;\n            }\n        }\n    }\n\n    vector<Cand> nc;\n    for (int i = 0; i < C; i++) if (alive[i]) nc.push_back(cand[i]);\n    cand.swap(nc);\n\n    vector<int> best_sel;\n\n    {\n        vector<int> sel;\n        for (int k = 0; k < Mx; k++) {\n            int best = -1;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                if ((cand[i].mask >> k) & 1ULL) {\n                    if (best == -1 || cand[i].s < cand[best].s) best = i;\n                }\n            }\n            if (best != -1) sel.push_back(best);\n        }\n\n        sort(sel.begin(), sel.end());\n        sel.erase(unique(sel.begin(), sel.end()), sel.end());\n        prune_cover(sel, cand, allmask, rng);\n        best_sel = sel;\n    }\n\n    int best_score = eval_cover(best_sel, cand, allmask);\n\n    for (int iter = 0; iter < 5000; iter++) {\n        uint64_t covered = 0;\n        vector<int> sel;\n        double alpha = 1.0 + (rng() % 1200) / 1000.0;\n\n        while (covered != allmask) {\n            vector<pair<double,int>> v;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                uint64_t nw = cand[i].mask & ~covered;\n                if (!nw) continue;\n                int cnt = __builtin_popcountll(nw);\n                double noise = 0.85 + (rng() % 3000) / 10000.0;\n                double sc = cand[i].s / pow((double)cnt, alpha) * noise;\n                v.push_back({sc, i});\n            }\n\n            if (v.empty()) break;\n            sort(v.begin(), v.end());\n\n            int K = min<int>((int)v.size(), 3 + (rng() % 8));\n            int chosen = v[rng() % K].second;\n            sel.push_back(chosen);\n            covered |= cand[chosen].mask;\n        }\n\n        if (covered != allmask) continue;\n\n        prune_cover(sel, cand, allmask, rng);\n        int sc = eval_cover(sel, cand, allmask);\n\n        if (sc < best_score) {\n            best_score = sc;\n            best_sel = sel;\n        }\n    }\n\n    return build_ops_from_cover(best_sel, cand);\n}\n\n/* -------------------- Dynamic macro solvers -------------------- */\n\nstruct DynCand {\n    char d;\n    int p;\n    int s;\n    int rem;\n    bool bounce;\n};\n\nvoid add_dyn_cands_for_line(vector<DynCand>& res, const vector<string>& b, bool bounce_allowed) {\n    for (int i = 0; i < N; i++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[i][s - 1] != 'o'; s++) {\n            if (b[i][s - 1] == 'x') {\n                rem++;\n                res.push_back({'L', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'L', i, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[i][N - s] != 'o'; s++) {\n            if (b[i][N - s] == 'x') {\n                rem++;\n                res.push_back({'R', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'R', i, s, rem, true});\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[s - 1][j] != 'o'; s++) {\n            if (b[s - 1][j] == 'x') {\n                rem++;\n                res.push_back({'U', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'U', j, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[N - s][j] != 'o'; s++) {\n            if (b[N - s][j] == 'x') {\n                rem++;\n                res.push_back({'D', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'D', j, s, rem, true});\n            }\n        }\n    }\n}\n\nbool apply_dyn(vector<string>& b, vector<Op>& ops, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n        ops.push_back({c.d, c.p});\n    }\n\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n            ops.push_back({od, c.p});\n        }\n    }\n\n    return true;\n}\n\nbool apply_dyn_board_only(vector<string>& b, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n    }\n\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n        }\n    }\n\n    return true;\n}\n\nint dyn_cost(const DynCand& c) {\n    return c.s * (c.bounce ? 2 : 1);\n}\n\nvector<Op> dynamic_trial(const vector<string>& init, mt19937& rng, int mode) {\n    vector<string> b = init;\n    vector<Op> ops;\n\n    double alpha = 1.0 + (rng() % 1400) / 1000.0;\n    bool bounce_allowed = (mode != 0);\n\n    for (int step = 0; step < 45; step++) {\n        int oni = count_oni(b);\n        if (oni == 0) return ops;\n        if ((int)ops.size() > 4 * N * N) return {};\n\n        vector<DynCand> cs;\n        add_dyn_cands_for_line(cs, b, bounce_allowed);\n        if (cs.empty()) return {};\n\n        vector<pair<double,int>> rank;\n        for (int i = 0; i < (int)cs.size(); i++) {\n            int cost = dyn_cost(cs[i]);\n            double sc = cost / pow((double)cs[i].rem, alpha);\n\n            if (mode == 0 && cs[i].bounce) continue;\n            if (mode == 1 && cs[i].bounce) sc *= 1.15;\n            if (mode == 2 && !cs[i].bounce) sc *= 0.85;\n            if (mode == 3 && cs[i].bounce) sc *= 0.85;\n\n            double noise = 0.80 + (rng() % 4000) / 10000.0;\n            sc *= noise;\n\n            rank.push_back({sc, i});\n        }\n\n        if (rank.empty()) return {};\n        sort(rank.begin(), rank.end());\n\n        int K;\n        if (mode == 4) K = 1;\n        else K = min<int>((int)rank.size(), 3 + (rng() % 8));\n\n        DynCand chosen = cs[rank[(K == 1 ? 0 : (int)(rng() % K))].second];\n\n        if (!apply_dyn(b, ops, chosen)) return {};\n    }\n\n    if (count_oni(b) == 0) return ops;\n    return {};\n}\n\n/* -------------------- Beam macro solver -------------------- */\n\nuint64_t hash_board(const vector<string>& b) {\n    uint64_t h = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        for (char c : b[i]) {\n            h ^= (unsigned char)c;\n            h *= 1099511628211ULL;\n        }\n    }\n    return h;\n}\n\nint sum_visible_min_dist(const vector<string>& b) {\n    int sum = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) if (b[i][j] == 'x') {\n            int best = 25;\n\n            bool ok = true;\n            for (int k = 0; k < j; k++) if (b[i][k] == 'o') ok = false;\n            if (ok) best = min(best, j + 1);\n\n            ok = true;\n            for (int k = j + 1; k < N; k++) if (b[i][k] == 'o') ok = false;\n            if (ok) best = min(best, N - j);\n\n            ok = true;\n            for (int k = 0; k < i; k++) if (b[k][j] == 'o') ok = false;\n            if (ok) best = min(best, i + 1);\n\n            ok = true;\n            for (int k = i + 1; k < N; k++) if (b[k][j] == 'o') ok = false;\n            if (ok) best = min(best, N - i);\n\n            if (best == 25) best = 12;\n            sum += best;\n        }\n    }\n\n    return sum;\n}\n\nstruct BeamNode {\n    vector<string> b;\n    vector<DynCand> path;\n    int cost;\n    int rem;\n    double eval;\n};\n\nvector<Op> build_ops_from_dyn_path(const vector<DynCand>& path) {\n    vector<Op> ops;\n    for (auto& c : path) {\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        if (c.bounce) {\n            char od = opposite_dir(c.d);\n            for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n        }\n    }\n    return ops;\n}\n\nvector<Op> beam_search_solver(\n    const vector<string>& init,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline,\n    int incumbent_cost\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    vector<Op> best_ops;\n\n    BeamNode root;\n    root.b = init;\n    root.cost = 0;\n    root.rem = count_oni(init);\n    root.eval = root.rem;\n    vector<BeamNode> beam;\n    beam.push_back(root);\n\n    const int BEAM_WIDTH = 120;\n    const int MAX_CAND = 45;\n\n    for (int depth = 0; depth < 45 && elapsed() < deadline; depth++) {\n        vector<BeamNode> nxt;\n        unordered_map<uint64_t, int> seen;\n        seen.reserve(BEAM_WIDTH * MAX_CAND * 2);\n\n        for (auto& node : beam) {\n            if (elapsed() >= deadline) break;\n\n            vector<DynCand> cs;\n            add_dyn_cands_for_line(cs, node.b, true);\n            if (cs.empty()) continue;\n\n            vector<pair<double,int>> ord;\n            ord.reserve(cs.size());\n\n            for (int i = 0; i < (int)cs.size(); i++) {\n                double sc = dyn_cost(cs[i]) / pow((double)cs[i].rem, 1.35);\n                if (cs[i].bounce) sc *= 1.08;\n                sc *= 0.98 + (rng() % 400) / 10000.0;\n                ord.push_back({sc, i});\n            }\n\n            sort(ord.begin(), ord.end());\n            int lim = min<int>(MAX_CAND, ord.size());\n\n            for (int z = 0; z < lim; z++) {\n                const DynCand& c = cs[ord[z].second];\n                int ncst = node.cost + dyn_cost(c);\n                if (ncst >= incumbent_cost) continue;\n\n                BeamNode nb;\n                nb.b = node.b;\n                if (!apply_dyn_board_only(nb.b, c)) continue;\n\n                nb.rem = count_oni(nb.b);\n                if (nb.rem >= node.rem) continue;\n\n                nb.cost = ncst;\n                nb.path = node.path;\n                nb.path.push_back(c);\n\n                if (nb.rem == 0) {\n                    vector<Op> ops = build_ops_from_dyn_path(nb.path);\n                    if ((int)ops.size() < incumbent_cost) {\n                        incumbent_cost = ops.size();\n                        best_ops = ops;\n                    }\n                    continue;\n                }\n\n                uint64_t h = hash_board(nb.b);\n                auto it = seen.find(h);\n                if (it != seen.end() && it->second <= nb.cost) continue;\n                seen[h] = nb.cost;\n\n                nb.eval = nb.cost + 1.6 * nb.rem + 0.10 * sum_visible_min_dist(nb.b);\n                nxt.push_back(std::move(nb));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        sort(nxt.begin(), nxt.end(), [](const BeamNode& a, const BeamNode& b) {\n            if (a.eval != b.eval) return a.eval < b.eval;\n            return a.cost < b.cost;\n        });\n\n        if ((int)nxt.size() > BEAM_WIDTH) nxt.resize(BEAM_WIDTH);\n        beam.swap(nxt);\n    }\n\n    return best_ops;\n}\n\n/* -------------------- Sequence simplification -------------------- */\n\nvoid postprocess_remove_blocks(\n    const vector<string>& init,\n    vector<Op>& ops,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    if (!validate_solution(init, ops)) return;\n\n    bool improved = true;\n\n    while (improved && elapsed() < deadline) {\n        improved = false;\n\n        for (int len = 8; len >= 1 && elapsed() < deadline; len--) {\n            if ((int)ops.size() < len) continue;\n\n            vector<int> idx;\n            for (int i = 0; i + len <= (int)ops.size(); i++) idx.push_back(i);\n\n            // Mostly deterministic, partly randomized.\n            if (len <= 3) shuffle(idx.begin(), idx.end(), rng);\n\n            for (int st : idx) {\n                if (elapsed() >= deadline) break;\n                if (st + len > (int)ops.size()) continue;\n\n                vector<Op> cand;\n                cand.reserve(ops.size() - len);\n                for (int i = 0; i < (int)ops.size(); i++) {\n                    if (i < st || i >= st + len) cand.push_back(ops[i]);\n                }\n\n                if (validate_solution(init, cand)) {\n                    ops.swap(cand);\n                    improved = true;\n                    break;\n                }\n            }\n\n            if (improved) break;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n\n    vector<string> init(N);\n    for (int i = 0; i < N; i++) cin >> init[i];\n\n    mt19937 rng(1234567);\n    auto start = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    vector<Op> best = solve_set_cover(init, rng);\n    if (!validate_solution(init, best)) best.clear();\n\n    {\n        vector<Op> beam_ops = beam_search_solver(\n            init,\n            rng,\n            start,\n            0.55,\n            best.empty() ? 4 * N * N + 1 : (int)best.size()\n        );\n\n        if (!beam_ops.empty() && (best.empty() || beam_ops.size() < best.size())) {\n            if (validate_solution(init, beam_ops)) best = beam_ops;\n        }\n    }\n\n    int trial = 0;\n    while (elapsed() < 1.75) {\n        int mode;\n        if (trial == 0) mode = 4;\n        else if (trial == 1) mode = 0;\n        else mode = rng() % 5;\n\n        vector<Op> ops = dynamic_trial(init, rng, mode);\n\n        if (!ops.empty() && (best.empty() || ops.size() < best.size())) {\n            if (validate_solution(init, ops)) best = ops;\n        }\n\n        trial++;\n    }\n\n    if (!best.empty()) {\n        postprocess_remove_blocks(init, best, rng, start, 1.94);\n    }\n\n    if (best.empty() || !validate_solution(init, best) || (int)best.size() > 4 * N * N) {\n        rng.seed(42);\n        best = solve_set_cover(init, rng);\n        if (!validate_solution(init, best)) best.clear();\n    }\n\n    for (auto [d, p] : best) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T;\nmt19937 rng(123456789);\n\ndouble elapsed_sec() {\n    static auto st = chrono::steady_clock::now();\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - st).count();\n}\n\nstruct Graph {\n    array<int, MAXN> a{}, b{}, cnt{};\n    int err = INT_MAX;\n};\n\nGraph evaluate(const array<int, MAXN>& a, const array<int, MAXN>& b) {\n    Graph g;\n    g.a = a;\n    g.b = b;\n    g.cnt.fill(0);\n\n    int cur = 0;\n    g.cnt[cur] = 1;\n\n    for (int step = 1; step < L; step++) {\n        int c = g.cnt[cur];\n        cur = (c & 1) ? a[cur] : b[cur];\n        g.cnt[cur]++;\n    }\n\n    long long e = 0;\n    for (int i = 0; i < N; i++) {\n        e += llabs((long long)g.cnt[i] - T[i]);\n    }\n    g.err = (int)e;\n    return g;\n}\n\nint weighted_pick(const vector<int>& v, const vector<int>& w) {\n    long long sum = 0;\n    for (int x : w) sum += x;\n    if (sum <= 0) return v[rng() % v.size()];\n\n    long long r = rng() % sum;\n    for (int i = 0; i < (int)v.size(); i++) {\n        if (r < w[i]) return v[i];\n        r -= w[i];\n    }\n    return v.back();\n}\n\nGraph make_cycle_candidate(int id) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    sort(active.begin(), active.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    if (id == 1) {\n        reverse(active.begin(), active.end());\n    } else if (id >= 2) {\n        int m = (int)active.size();\n        int swaps = (id % 9 + 1) * m / 16;\n        for (int k = 0; k < swaps; k++) {\n            int p = rng() % m;\n            int q = rng() % m;\n            swap(active[p], active[q]);\n        }\n    }\n\n    int m = (int)active.size();\n\n    vector<int> succ(N, root);\n    array<long long, MAXN> in{};\n    in.fill(0);\n\n    for (int k = 0; k < m; k++) {\n        int v = active[k];\n        int to = active[(k + 1) % m];\n        succ[v] = to;\n        in[to] += T[v];\n    }\n\n    vector<int> sources = active;\n    sort(sources.begin(), sources.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    vector<int> assigned(N, root);\n\n    for (int s : sources) {\n        long long w = T[s];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(m);\n\n        for (int d : active) {\n            long long before = llabs(in[d] - 2LL * T[d]);\n            long long after = llabs(in[d] + w - 2LL * T[d]);\n            cand.push_back({after - before, d});\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int choose = 0;\n        if (id >= 2) {\n            int lim = min(5, (int)cand.size());\n            choose = rng() % lim;\n        }\n\n        int d = cand[choose].second;\n        assigned[s] = d;\n        in[d] += w;\n    }\n\n    for (int it = 0; it < 45; it++) {\n        long long best_delta = 0;\n        int best_s = -1, best_d = -1;\n\n        for (int s : sources) {\n            int old = assigned[s];\n            long long w = T[s];\n\n            for (int d : active) {\n                if (d == old) continue;\n\n                long long cur =\n                    llabs(in[old] - 2LL * T[old]) +\n                    llabs(in[d] - 2LL * T[d]);\n\n                long long nxt =\n                    llabs(in[old] - w - 2LL * T[old]) +\n                    llabs(in[d] + w - 2LL * T[d]);\n\n                long long delta = nxt - cur;\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_s = s;\n                    best_d = d;\n                }\n            }\n        }\n\n        if (best_s == -1) break;\n\n        int old = assigned[best_s];\n        long long w = T[best_s];\n        in[old] -= w;\n        in[best_d] += w;\n        assigned[best_s] = best_d;\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            a[i] = succ[i];\n            b[i] = assigned[i];\n            if (id >= 2 && (rng() & 1)) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nstruct Token {\n    int src;\n    int slot;\n    int w;\n};\n\nGraph make_balanced_candidate(int id) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    vector<Token> tok;\n    tok.reserve(active.size() * 2);\n    for (int s : active) {\n        tok.push_back({s, 0, T[s]});\n        tok.push_back({s, 1, T[s]});\n    }\n\n    int M = (int)tok.size();\n\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    vector<int> noise(M);\n    for (int i = 0; i < M; i++) noise[i] = (int)(rng() & 1023);\n\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        long long kx = 1000000LL * tok[x].w + noise[x] * (id % 7);\n        long long ky = 1000000LL * tok[y].w + noise[y] * (id % 7);\n        if (kx != ky) return kx > ky;\n        return x < y;\n    });\n\n    if (id % 11 == 0) {\n        shuffle(ord.begin(), ord.end(), rng);\n    } else if (id % 5 == 0) {\n        int block = 8 + (id % 7);\n        for (int l = 0; l < M; l += block) {\n            int r = min(M, l + block);\n            shuffle(ord.begin() + l, ord.begin() + r, rng);\n        }\n    }\n\n    array<long long, MAXN> rem{};\n    for (int i = 0; i < N; i++) rem[i] = 2LL * T[i];\n\n    array<array<int, 2>, MAXN> dest;\n    for (int i = 0; i < N; i++) dest[i][0] = dest[i][1] = -1;\n\n    vector<int> token_dest(M, -1);\n\n    bool hard_no_self = (id % 6 == 0 || id % 6 == 3);\n    bool avoid_same = (id % 6 != 1);\n\n    for (int idx : ord) {\n        int s = tok[idx].src;\n        int sl = tok[idx].slot;\n        int w = tok[idx].w;\n        int other = dest[s][1 - sl];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(active.size());\n\n        for (int d : active) {\n            if (hard_no_self && d == s && active.size() > 1) continue;\n\n            long long delta = llabs(rem[d] - w) - llabs(rem[d]);\n            long long penalty = 0;\n\n            if (d == s) penalty += 2LL * w + 500;\n            if (avoid_same && other == d) penalty += w / 2 + 300;\n\n            long long score = delta * 100000LL + penalty * 100LL + (int)(rng() & 2047);\n            cand.push_back({score, d});\n        }\n\n        if (cand.empty()) {\n            for (int d : active) {\n                long long delta = llabs(rem[d] - w) - llabs(rem[d]);\n                cand.push_back({delta * 100000LL + (int)(rng() & 2047), d});\n            }\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int lim = min((int)cand.size(), 1 + (id % 5));\n        if (id % 13 == 0) lim = min((int)cand.size(), 8);\n\n        int d = cand[rng() % lim].second;\n        dest[s][sl] = d;\n        token_dest[idx] = d;\n        rem[d] -= w;\n    }\n\n    auto violates = [&](int idx, int d) -> bool {\n        int s = tok[idx].src;\n        int sl = tok[idx].slot;\n        if (hard_no_self && d == s && active.size() > 1) return true;\n        if (avoid_same && dest[s][1 - sl] == d && active.size() > 2) return true;\n        return false;\n    };\n\n    int improve_trials = 3500;\n    for (int it = 0; it < improve_trials; it++) {\n        if (rng() & 1) {\n            int idx = rng() % M;\n            int old = token_dest[idx];\n            int d = active[rng() % active.size()];\n            if (d == old) continue;\n            if (violates(idx, d)) continue;\n\n            long long w = tok[idx].w;\n            long long delta =\n                llabs(rem[old] + w) - llabs(rem[old]) +\n                llabs(rem[d] - w) - llabs(rem[d]);\n\n            if (delta < 0 || (delta == 0 && (rng() & 7) == 0)) {\n                rem[old] += w;\n                rem[d] -= w;\n                token_dest[idx] = d;\n                dest[tok[idx].src][tok[idx].slot] = d;\n            }\n        } else {\n            int x = rng() % M;\n            int y = rng() % M;\n            if (x == y) continue;\n\n            int dx = token_dest[x];\n            int dy = token_dest[y];\n            if (dx == dy) continue;\n            if (violates(x, dy) || violates(y, dx)) continue;\n\n            long long wx = tok[x].w;\n            long long wy = tok[y].w;\n\n            long long before = llabs(rem[dx]) + llabs(rem[dy]);\n\n            long long ndx = rem[dx] + wx - wy;\n            long long ndy = rem[dy] + wy - wx;\n\n            long long after = llabs(ndx) + llabs(ndy);\n            long long delta = after - before;\n\n            if (delta < 0 || (delta == 0 && (rng() & 15) == 0)) {\n                rem[dx] = ndx;\n                rem[dy] = ndy;\n\n                token_dest[x] = dy;\n                token_dest[y] = dx;\n\n                dest[tok[x].src][tok[x].slot] = dy;\n                dest[tok[y].src][tok[y].slot] = dx;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            int x = dest[i][0];\n            int y = dest[i][1];\n            if (x < 0) x = root;\n            if (y < 0) y = root;\n            a[i] = x;\n            b[i] = y;\n\n            if (rng() & 1) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n\n    uint64_t seed = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n        seed ^= (uint64_t)(T[i] + 1000003) * (i + 1009);\n        seed *= 1099511628211ULL;\n    }\n    rng.seed((uint32_t)(seed ^ (seed >> 32)));\n\n    Graph best;\n    best.err = INT_MAX;\n\n    for (int id = 0; id < 35; id++) {\n        if (elapsed_sec() > 0.45) break;\n        Graph g = make_cycle_candidate(id);\n        if (g.err < best.err) best = g;\n    }\n\n    for (int id = 0; id < 220; id++) {\n        if (elapsed_sec() > 1.05) break;\n        Graph g = make_balanced_candidate(id);\n        if (g.err < best.err) best = g;\n    }\n\n    Graph cur = best;\n\n    for (int pass = 0; pass < 4; pass++) {\n        bool improved = false;\n\n        for (int i = 0; i < N; i++) {\n            if (elapsed_sec() > 1.25) break;\n            if (cur.a[i] == cur.b[i]) continue;\n\n            swap(cur.a[i], cur.b[i]);\n            Graph ng = evaluate(cur.a, cur.b);\n\n            if (ng.err <= cur.err) {\n                cur = ng;\n                improved = true;\n                if (cur.err < best.err) best = cur;\n            } else {\n                swap(cur.a[i], cur.b[i]);\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    cur = best;\n\n    while (elapsed_sec() < 1.88) {\n        vector<int> over, under, wover, wunder;\n\n        for (int i = 0; i < N; i++) {\n            int d = cur.cnt[i] - T[i];\n            if (d > 0) {\n                over.push_back(i);\n                wover.push_back(d);\n            } else if (d < 0) {\n                under.push_back(i);\n                wunder.push_back(-d);\n            }\n        }\n\n        if (over.empty() || under.empty()) break;\n\n        array<int, MAXN> na = cur.a;\n        array<int, MAXN> nb = cur.b;\n\n        int typ = rng() % 100;\n\n        if (typ < 18) {\n            int i = rng() % N;\n            if (na[i] == nb[i]) continue;\n            swap(na[i], nb[i]);\n        } else if (typ < 72) {\n            int v = weighted_pick(over, wover);\n            int u = weighted_pick(under, wunder);\n\n            vector<pair<int, int>> edges;\n            for (int i = 0; i < N; i++) {\n                if (na[i] == v) edges.push_back({i, 0});\n                if (nb[i] == v) edges.push_back({i, 1});\n            }\n\n            if (edges.empty()) continue;\n\n            auto [s, slot] = edges[rng() % edges.size()];\n            if (slot == 0) na[s] = u;\n            else nb[s] = u;\n        } else if (typ < 88) {\n            int s = weighted_pick(over, wover);\n            int u = weighted_pick(under, wunder);\n\n            if (rng() & 1) na[s] = u;\n            else nb[s] = u;\n        } else {\n            int s = rng() % N;\n            int u = weighted_pick(under, wunder);\n\n            if (rng() & 1) na[s] = u;\n            else nb[s] = u;\n        }\n\n        Graph ng = evaluate(na, nb);\n\n        bool accept = false;\n\n        if (ng.err <= cur.err) {\n            accept = true;\n        } else {\n            double e = elapsed_sec();\n            double remain = max(0.0, 1.88 - e);\n            int temp = max(1, (int)(900.0 * remain / 1.88));\n            int diff = ng.err - cur.err;\n\n            if (diff < temp && (int)(rng() % temp) < temp - diff) {\n                accept = true;\n            }\n        }\n\n        if (accept) {\n            cur = ng;\n            if (cur.err < best.err) best = cur;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), 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\nint N, M, Q, L, W;\nvector<int> G;\nvector<double> cx, cy;\n\ninline double dist2p(double x1, double y1, double x2, double y2) {\n    double dx = x1 - x2;\n    double dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\ninline double edist(int a, int b) {\n    return sqrt(dist2p(cx[a], cy[a], cx[b], cy[b]));\n}\n\ninline unsigned long long ekey(int a, int b) {\n    if (a > b) swap(a, b);\n    return (unsigned long long)a << 32 | (unsigned int)b;\n}\n\ninline pair<int,int> decode_key(unsigned long long k) {\n    int a = (int)(k >> 32);\n    int b = (int)(k & 0xffffffffu);\n    return {a, b};\n}\n\nlong long hilbert_index(int x, int y, int bits = 14) {\n    long long d = 0;\n    int n = 1 << bits;\n    for (int s = n >> 1; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += 1LL * s * s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = n - 1 - x;\n                y = n - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\ndouble mst_cost(const vector<int>& verts) {\n    int n = (int)verts.size();\n    if (n <= 1) return 0.0;\n    if (n == 2) return edist(verts[0], verts[1]);\n\n    vector<double> minv(n, 1e100);\n    vector<char> used(n, 0);\n    minv[0] = 0.0;\n    double res = 0.0;\n\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n\n        used[v] = 1;\n        res += best;\n\n        int cv = verts[v];\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(cv, verts[u]);\n                if (d < minv[u]) minv[u] = d;\n            }\n        }\n    }\n\n    return res;\n}\n\nvector<pair<int,int>> prim_edges(const vector<int>& verts) {\n    int n = (int)verts.size();\n    vector<pair<int,int>> ret;\n\n    if (n <= 1) return ret;\n    if (n == 2) {\n        ret.push_back({verts[0], verts[1]});\n        return ret;\n    }\n\n    vector<double> minv(n, 1e100);\n    vector<int> par(n, -1);\n    vector<char> used(n, 0);\n    minv[0] = 0.0;\n\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n\n        used[v] = 1;\n        if (par[v] != -1) ret.push_back({verts[v], verts[par[v]]});\n\n        int cv = verts[v];\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(cv, verts[u]);\n                if (d < minv[u]) {\n                    minv[u] = d;\n                    par[u] = v;\n                }\n            }\n        }\n    }\n\n    return ret;\n}\n\ndouble total_mst_cost(const vector<vector<int>>& groups) {\n    double s = 0.0;\n    for (auto& g : groups) s += mst_cost(g);\n    return s;\n}\n\nvector<vector<int>> build_from_order(const vector<int>& ord, const vector<int>& perm) {\n    vector<vector<int>> groups(M);\n    int pos = 0;\n\n    for (int id : perm) {\n        groups[id].assign(ord.begin() + pos, ord.begin() + pos + G[id]);\n        pos += G[id];\n    }\n\n    return groups;\n}\n\nstruct OrderEvaluator {\n    const vector<int>* ord;\n    unordered_map<int, double> cache;\n\n    OrderEvaluator(const vector<int>& o) {\n        ord = &o;\n        cache.reserve(5000);\n    }\n\n    double interval_cost(int s, int len) {\n        if (len <= 1) return 0.0;\n        if (len == 2) return edist((*ord)[s], (*ord)[s + 1]);\n\n        int key = s * 1000 + len;\n        auto it = cache.find(key);\n        if (it != cache.end()) return it->second;\n\n        vector<int> verts;\n        verts.reserve(len);\n        for (int i = 0; i < len; i++) verts.push_back((*ord)[s + i]);\n\n        double c = mst_cost(verts);\n        cache[key] = c;\n        return c;\n    }\n\n    double seq_cost(const vector<int>& perm) {\n        int pos = 0;\n        double res = 0.0;\n\n        for (int id : perm) {\n            res += interval_cost(pos, G[id]);\n            pos += G[id];\n        }\n\n        return res;\n    }\n\n    vector<int> improve_perm(vector<int> perm, int maxPass = 20) {\n        if (M <= 1) return perm;\n\n        double cur = seq_cost(perm);\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            bool changed = false;\n\n            vector<int> pref(M + 1, 0);\n            for (int i = 0; i < M; i++) pref[i + 1] = pref[i] + G[perm[i]];\n\n            for (int i = 0; i + 1 < M; i++) {\n                int s = pref[i];\n                int a = perm[i], b = perm[i + 1];\n\n                double oldc = interval_cost(s, G[a]) + interval_cost(s + G[a], G[b]);\n                double newc = interval_cost(s, G[b]) + interval_cost(s + G[b], G[a]);\n\n                if (newc + 1e-9 < oldc) {\n                    swap(perm[i], perm[i + 1]);\n                    cur += newc - oldc;\n                    changed = true;\n\n                    pref[i + 1] = pref[i] + G[perm[i]];\n                    for (int j = i + 1; j < M; j++) {\n                        pref[j + 1] = pref[j] + G[perm[j]];\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        return perm;\n    }\n};\n\nvector<vector<int>> make_size_perms() {\n    vector<vector<int>> vars;\n\n    vector<int> p(M);\n    iota(p.begin(), p.end(), 0);\n    vars.push_back(p);\n\n    vector<int> r = p;\n    reverse(r.begin(), r.end());\n    vars.push_back(r);\n\n    vector<int> asc = p;\n    sort(asc.begin(), asc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n    vars.push_back(asc);\n\n    vector<int> desc = p;\n    sort(desc.begin(), desc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n    vars.push_back(desc);\n\n    return vars;\n}\n\npair<vector<int>, int> split_group_ids_subset_sum(const vector<int>& gids, int total) {\n    int target = total / 2;\n\n    vector<char> dp(total + 1, 0);\n    vector<int> preSum(total + 1, -1), preId(total + 1, -1);\n    dp[0] = 1;\n\n    for (int id : gids) {\n        int w = G[id];\n        for (int s = total - w; s >= 0; s--) {\n            if (dp[s] && !dp[s + w]) {\n                dp[s + w] = 1;\n                preSum[s + w] = s;\n                preId[s + w] = id;\n            }\n        }\n    }\n\n    int best = -1;\n    for (int d = 0; d <= total; d++) {\n        int s1 = target - d;\n        int s2 = target + d;\n\n        if (s1 > 0 && s1 < total && dp[s1]) {\n            best = s1;\n            break;\n        }\n        if (s2 > 0 && s2 < total && dp[s2]) {\n            best = s2;\n            break;\n        }\n    }\n\n    if (best == -1) {\n        vector<int> left = {gids[0]};\n        return {left, G[gids[0]]};\n    }\n\n    vector<int> left;\n    int cur = best;\n\n    while (cur > 0) {\n        int id = preId[cur];\n        left.push_back(id);\n        cur = preSum[cur];\n    }\n\n    return {left, best};\n}\n\nvoid recursive_partition(\n    const vector<int>& cities,\n    const vector<int>& gids,\n    int depth,\n    int variant,\n    vector<vector<int>>& groups\n) {\n    if (gids.size() == 1) {\n        groups[gids[0]] = cities;\n        return;\n    }\n\n    int total = cities.size();\n    auto [leftIds, leftCount] = split_group_ids_subset_sum(gids, total);\n\n    vector<char> inLeft(M, 0);\n    for (int id : leftIds) inLeft[id] = 1;\n\n    vector<int> rightIds;\n    for (int id : gids) {\n        if (!inLeft[id]) rightIds.push_back(id);\n    }\n\n    vector<int> sorted = cities;\n\n    if (variant == 0) {\n        double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n\n        for (int v : cities) {\n            minx = min(minx, cx[v]);\n            maxx = max(maxx, cx[v]);\n            miny = min(miny, cy[v]);\n            maxy = max(maxy, cy[v]);\n        }\n\n        bool useX = (maxx - minx >= maxy - miny);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            if (useX) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            } else {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            }\n        });\n    } else if (variant == 1) {\n        bool useX = (depth % 2 == 0);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            if (useX) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            } else {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            }\n        });\n    } else if (variant == 2) {\n        double mx = 0.0, my = 0.0;\n\n        for (int v : cities) {\n            mx += cx[v];\n            my += cy[v];\n        }\n\n        mx /= cities.size();\n        my /= cities.size();\n\n        double sxx = 0.0, syy = 0.0, sxy = 0.0;\n\n        for (int v : cities) {\n            double x = cx[v] - mx;\n            double y = cy[v] - my;\n            sxx += x * x;\n            syy += y * y;\n            sxy += x * y;\n        }\n\n        double theta = 0.5 * atan2(2.0 * sxy, sxx - syy);\n        double vx = cos(theta), vy = sin(theta);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            double pa = cx[a] * vx + cy[a] * vy;\n            double pb = cx[b] * vx + cy[b] * vy;\n            if (pa != pb) return pa < pb;\n            return a < b;\n        });\n    } else {\n        bool diag = (depth % 2 == 0);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            double pa = diag ? (cx[a] + cy[a]) : (cx[a] - cy[a]);\n            double pb = diag ? (cx[b] + cy[b]) : (cx[b] - cy[b]);\n            if (pa != pb) return pa < pb;\n            return a < b;\n        });\n    }\n\n    vector<int> leftCities(sorted.begin(), sorted.begin() + leftCount);\n    vector<int> rightCities(sorted.begin() + leftCount, sorted.end());\n\n    recursive_partition(leftCities, leftIds, depth + 1, variant, groups);\n    recursive_partition(rightCities, rightIds, depth + 1, variant, groups);\n}\n\nvector<vector<int>> make_recursive_candidate(int variant) {\n    vector<int> cities(N), gids(M);\n    iota(cities.begin(), cities.end(), 0);\n    iota(gids.begin(), gids.end(), 0);\n\n    vector<vector<int>> groups(M);\n    recursive_partition(cities, gids, 0, variant, groups);\n    return groups;\n}\n\nvector<vector<int>> make_greedy_candidate(int variant) {\n    vector<vector<int>> groups(M);\n    vector<char> used(N, 0);\n\n    vector<int> gids(M);\n    iota(gids.begin(), gids.end(), 0);\n\n    if (variant <= 4 || variant == 7) {\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] > G[b];\n            return a < b;\n        });\n    } else if (variant == 6) {\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] < G[b];\n            return a < b;\n        });\n    }\n\n    vector<long long> hval(N);\n    for (int i = 0; i < N; i++) {\n        int xi = min(16383, max(0, (int)llround(cx[i] * 16383.0 / 10000.0)));\n        int yi = min(16383, max(0, (int)llround(cy[i] * 16383.0 / 10000.0)));\n        hval[i] = hilbert_index(xi, yi);\n    }\n\n    for (int gid : gids) {\n        vector<int> rem;\n        rem.reserve(N);\n\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) rem.push_back(i);\n        }\n\n        if ((int)rem.size() == G[gid]) {\n            groups[gid] = rem;\n            for (int v : rem) used[v] = 1;\n            continue;\n        }\n\n        int seed = rem[0];\n\n        if (variant == 0) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cx[a] < cx[b];\n            });\n        } else if (variant == 1) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cx[a] < cx[b];\n            });\n        } else if (variant == 2) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cy[a] < cy[b];\n            });\n        } else if (variant == 3) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cy[a] < cy[b];\n            });\n        } else if (variant == 7) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return hval[a] < hval[b];\n            });\n        } else {\n            double mx = 0.0, my = 0.0;\n\n            for (int v : rem) {\n                mx += cx[v];\n                my += cy[v];\n            }\n\n            mx /= rem.size();\n            my /= rem.size();\n\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return dist2p(cx[a], cy[a], mx, my) < dist2p(cx[b], cy[b], mx, my);\n            });\n        }\n\n        vector<pair<double,int>> cand;\n        cand.reserve(rem.size());\n\n        for (int v : rem) {\n            cand.push_back({dist2p(cx[v], cy[v], cx[seed], cy[seed]), v});\n        }\n\n        sort(cand.begin(), cand.end());\n\n        vector<int> sel;\n        for (int i = 0; i < G[gid]; i++) sel.push_back(cand[i].second);\n\n        if ((int)sel.size() >= 4) {\n            double mx = 0.0, my = 0.0;\n            for (int v : sel) {\n                mx += cx[v];\n                my += cy[v];\n            }\n            mx /= sel.size();\n            my /= sel.size();\n\n            cand.clear();\n            for (int v : rem) {\n                cand.push_back({dist2p(cx[v], cy[v], mx, my), v});\n            }\n\n            sort(cand.begin(), cand.end());\n            sel.clear();\n            for (int i = 0; i < G[gid]; i++) sel.push_back(cand[i].second);\n        }\n\n        groups[gid] = sel;\n        for (int v : sel) used[v] = 1;\n    }\n\n    return groups;\n}\n\nvector<vector<int>> capacitated_lloyd(vector<vector<int>> init, int iterations) {\n    vector<vector<int>> cur = init;\n    vector<vector<int>> best = cur;\n    double bestCost = total_mst_cost(best);\n\n    if (M == 1) return cur;\n\n    for (int it = 0; it < iterations; it++) {\n        vector<double> gx(M, 0.0), gy(M, 0.0);\n\n        for (int gid = 0; gid < M; gid++) {\n            for (int v : cur[gid]) {\n                gx[gid] += cx[v];\n                gy[gid] += cy[v];\n            }\n            gx[gid] /= max(1, (int)cur[gid].size());\n            gy[gid] /= max(1, (int)cur[gid].size());\n        }\n\n        struct Item {\n            double margin;\n            int city;\n            vector<pair<double,int>> ord;\n        };\n\n        vector<Item> items;\n        items.reserve(N);\n\n        for (int v = 0; v < N; v++) {\n            vector<pair<double,int>> ds;\n            ds.reserve(M);\n\n            for (int gid = 0; gid < M; gid++) {\n                double d = dist2p(cx[v], cy[v], gx[gid], gy[gid]);\n                ds.push_back({d, gid});\n            }\n\n            int keep = min(M, max(12, min(32, M)));\n            nth_element(ds.begin(), ds.begin() + keep - 1, ds.end());\n            ds.resize(keep);\n            sort(ds.begin(), ds.end());\n\n            double margin = 1e18;\n            if ((int)ds.size() >= 2) margin = ds[1].first - ds[0].first;\n\n            items.push_back({margin, v, move(ds)});\n        }\n\n        sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n            return a.margin > b.margin;\n        });\n\n        vector<int> rem = G;\n        vector<vector<int>> nxt(M);\n\n        for (auto& item : items) {\n            int chosen = -1;\n\n            for (auto [d, gid] : item.ord) {\n                if (rem[gid] > 0) {\n                    chosen = gid;\n                    break;\n                }\n            }\n\n            if (chosen == -1) {\n                double bd = 1e100;\n                for (int gid = 0; gid < M; gid++) {\n                    if (rem[gid] <= 0) continue;\n                    double d = dist2p(cx[item.city], cy[item.city], gx[gid], gy[gid]);\n                    if (d < bd) {\n                        bd = d;\n                        chosen = gid;\n                    }\n                }\n            }\n\n            nxt[chosen].push_back(item.city);\n            rem[chosen]--;\n        }\n\n        cur.swap(nxt);\n\n        double c = total_mst_cost(cur);\n        if (c < bestCost) {\n            bestCost = c;\n            best = cur;\n        }\n    }\n\n    return best;\n}\n\nstring subset_key(vector<int> v) {\n    sort(v.begin(), v.end());\n    string s;\n    s.reserve(v.size() * 5);\n\n    for (int x : v) {\n        s += to_string(x);\n        s += ',';\n    }\n\n    return s;\n}\n\nvector<pair<int,int>> do_query(const vector<int>& c) {\n    cout << \"? \" << c.size();\n    for (int v : c) cout << ' ' << v;\n    cout << endl;\n    cout.flush();\n\n    vector<pair<int,int>> ret;\n\n    for (int i = 0; i < (int)c.size() - 1; i++) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        ret.push_back({a, b});\n    }\n\n    return ret;\n}\n\nvector<int> nearest_subset_to_seed(const vector<int>& group, int seed) {\n    vector<pair<double,int>> v;\n    v.reserve(group.size());\n\n    for (int x : group) {\n        v.push_back({edist(seed, x), x});\n    }\n\n    sort(v.begin(), v.end());\n\n    vector<int> sub;\n    int lim = min(L, (int)v.size());\n\n    for (int i = 0; i < lim; i++) sub.push_back(v[i].second);\n\n    return sub;\n}\n\nvector<int> nearest_subset_to_edge(const vector<int>& group, int a, int b) {\n    double mx = (cx[a] + cx[b]) * 0.5;\n    double my = (cy[a] + cy[b]) * 0.5;\n\n    vector<pair<double,int>> v;\n    v.reserve(group.size());\n\n    for (int x : group) {\n        double d = dist2p(cx[x], cy[x], mx, my);\n        if (x == a || x == b) d -= 1e18;\n        v.push_back({d, x});\n    }\n\n    sort(v.begin(), v.end());\n\n    vector<int> sub;\n    int lim = min(L, (int)v.size());\n\n    for (int i = 0; i < lim; i++) sub.push_back(v[i].second);\n\n    bool hasA = false, hasB = false;\n    for (int x : sub) {\n        if (x == a) hasA = true;\n        if (x == b) hasB = true;\n    }\n\n    if (!hasA && !sub.empty()) sub.back() = a;\n\n    hasB = false;\n    for (int x : sub) {\n        if (x == b) hasB = true;\n    }\n\n    if (!hasB && sub.size() >= 2) sub[sub.size() - 2] = b;\n\n    sort(sub.begin(), sub.end());\n    sub.erase(unique(sub.begin(), sub.end()), sub.end());\n\n    for (int x : group) {\n        if ((int)sub.size() >= min(L, (int)group.size())) break;\n        if (find(sub.begin(), sub.end(), x) == sub.end()) sub.push_back(x);\n    }\n\n    return sub;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    cx.resize(N);\n    cy.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cx[i] = (lx + rx) * 0.5;\n        cy[i] = (ly + ry) * 0.5;\n    }\n\n    vector<vector<vector<int>>> candidates;\n    auto perms = make_size_perms();\n\n    auto add_order_candidates = [&](const vector<int>& ord) {\n        OrderEvaluator ev(ord);\n\n        for (auto p : perms) {\n            candidates.push_back(build_from_order(ord, p));\n\n            if (timer.sec() < 0.75) {\n                vector<int> imp = ev.improve_perm(p, 18);\n                candidates.push_back(build_from_order(ord, imp));\n            }\n        }\n    };\n\n    // Hilbert variants.\n    for (int t = 0; t < 8; t++) {\n        vector<pair<long long,int>> v;\n\n        for (int i = 0; i < N; i++) {\n            double x = cx[i], y = cy[i];\n            double X = x, Y = y;\n\n            if (t == 0) { X = x; Y = y; }\n            if (t == 1) { X = y; Y = x; }\n            if (t == 2) { X = 10000 - x; Y = y; }\n            if (t == 3) { X = x; Y = 10000 - y; }\n            if (t == 4) { X = 10000 - x; Y = 10000 - y; }\n            if (t == 5) { X = y; Y = 10000 - x; }\n            if (t == 6) { X = 10000 - y; Y = x; }\n            if (t == 7) { X = 10000 - y; Y = 10000 - x; }\n\n            int xi = min(16383, max(0, (int)llround(X * 16383.0 / 10000.0)));\n            int yi = min(16383, max(0, (int)llround(Y * 16383.0 / 10000.0)));\n            v.push_back({hilbert_index(xi, yi), i});\n        }\n\n        sort(v.begin(), v.end());\n\n        vector<int> ord;\n        ord.reserve(N);\n\n        for (auto [d, i] : v) ord.push_back(i);\n\n        add_order_candidates(ord);\n    }\n\n    // Linear / diagonal / angular orders.\n    const double PI = acos(-1.0);\n\n    for (int t = 0; t < 12; t++) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        double ang = (t >= 6 ? (t - 6) * PI / 12.0 : 0.0);\n        double vx = cos(ang), vy = sin(ang);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            double ka, kb;\n\n            if (t == 0) ka = cx[a], kb = cx[b];\n            else if (t == 1) ka = cy[a], kb = cy[b];\n            else if (t == 2) ka = cx[a] + cy[a], kb = cx[b] + cy[b];\n            else if (t == 3) ka = cx[a] - cy[a], kb = cx[b] - cy[b];\n            else if (t == 4) ka = -cx[a] + cy[a], kb = -cx[b] + cy[b];\n            else if (t == 5) ka = -cx[a] - cy[a], kb = -cx[b] - cy[b];\n            else ka = cx[a] * vx + cy[a] * vy, kb = cx[b] * vx + cy[b] * vy;\n\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n\n        add_order_candidates(ord);\n    }\n\n    // Recursive geometric bisection candidates.\n    for (int v = 0; v < 4; v++) {\n        candidates.push_back(make_recursive_candidate(v));\n    }\n\n    // Greedy disk-like candidates.\n    for (int v = 0; v < 8; v++) {\n        candidates.push_back(make_greedy_candidate(v));\n    }\n\n    double bestScore = 1e100;\n    vector<vector<int>> groups;\n\n    for (auto& cand : candidates) {\n        double sc = total_mst_cost(cand);\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = cand;\n        }\n    }\n\n    // Capacity-aware Lloyd refinement.\n    if (timer.sec() < 0.95) {\n        auto km = capacitated_lloyd(groups, 5);\n        double sc = total_mst_cost(km);\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = km;\n        }\n    }\n\n    // Local city-swap improvement.\n    vector<int> cityGroup(N), cityPos(N);\n    vector<double> groupCost(M);\n\n    for (int gid = 0; gid < M; gid++) {\n        for (int p = 0; p < (int)groups[gid].size(); p++) {\n            cityGroup[groups[gid][p]] = gid;\n            cityPos[groups[gid][p]] = p;\n        }\n        groupCost[gid] = mst_cost(groups[gid]);\n    }\n\n    const int KNN = 24;\n    vector<vector<int>> knn(N);\n\n    for (int i = 0; i < N; i++) {\n        vector<pair<double,int>> v;\n        v.reserve(N - 1);\n\n        for (int j = 0; j < N; j++) {\n            if (i == j) continue;\n            v.push_back({edist(i, j), j});\n        }\n\n        nth_element(v.begin(), v.begin() + KNN, v.end());\n        v.resize(KNN);\n        sort(v.begin(), v.end());\n\n        for (auto [d, j] : v) knn[i].push_back(j);\n    }\n\n    auto mst_cost_with_swap = [&](int gid, int outCity, int inCity) {\n        vector<int> tmp = groups[gid];\n        int p = cityPos[outCity];\n        tmp[p] = inCity;\n        return mst_cost(tmp);\n    };\n\n    for (int pass = 0; pass < 6; pass++) {\n        if (timer.sec() > 1.30) break;\n\n        vector<double> gx(M, 0.0), gy(M, 0.0);\n\n        for (int gid = 0; gid < M; gid++) {\n            for (int v : groups[gid]) {\n                gx[gid] += cx[v];\n                gy[gid] += cy[v];\n            }\n            gx[gid] /= groups[gid].size();\n            gy[gid] /= groups[gid].size();\n        }\n\n        struct Cand {\n            double approx;\n            int a, b;\n        };\n\n        vector<Cand> sw;\n        unordered_set<unsigned long long> seen;\n        seen.reserve(N * KNN * 2);\n\n        for (int a = 0; a < N; a++) {\n            int ga = cityGroup[a];\n\n            for (int b : knn[a]) {\n                int gb = cityGroup[b];\n                if (ga == gb) continue;\n\n                unsigned long long key = ekey(a, b);\n                if (seen.count(key)) continue;\n                seen.insert(key);\n\n                double da1 = sqrt(dist2p(cx[a], cy[a], gx[ga], gy[ga]));\n                double db1 = sqrt(dist2p(cx[b], cy[b], gx[gb], gy[gb]));\n                double da2 = sqrt(dist2p(cx[a], cy[a], gx[gb], gy[gb]));\n                double db2 = sqrt(dist2p(cx[b], cy[b], gx[ga], gy[ga]));\n                double approx = da2 + db2 - da1 - db1;\n\n                if (approx < 450.0) {\n                    sw.push_back({approx, a, b});\n                }\n            }\n        }\n\n        sort(sw.begin(), sw.end(), [](const Cand& x, const Cand& y) {\n            return x.approx < y.approx;\n        });\n\n        if ((int)sw.size() > 9000) sw.resize(9000);\n\n        bool changed = false;\n\n        for (auto c : sw) {\n            if (timer.sec() > 1.48) break;\n\n            int a = c.a, b = c.b;\n            int ga = cityGroup[a], gb = cityGroup[b];\n            if (ga == gb) continue;\n\n            double oldCost = groupCost[ga] + groupCost[gb];\n            double na = mst_cost_with_swap(ga, a, b);\n            double nb = mst_cost_with_swap(gb, b, a);\n            double newCost = na + nb;\n\n            if (newCost + 1e-7 < oldCost) {\n                int pa = cityPos[a], pb = cityPos[b];\n\n                groups[ga][pa] = b;\n                groups[gb][pb] = a;\n\n                cityGroup[a] = gb;\n                cityGroup[b] = ga;\n                cityPos[a] = pb;\n                cityPos[b] = pa;\n\n                groupCost[ga] = na;\n                groupCost[gb] = nb;\n\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    vector<vector<pair<int,int>>> backupEdges(M);\n\n    for (int gid = 0; gid < M; gid++) {\n        backupEdges[gid] = prim_edges(groups[gid]);\n    }\n\n    vector<vector<pair<int,int>>> finalEdges(M);\n    vector<unordered_map<unsigned long long,int>> oracleEdges(M);\n\n    struct PlannedQuery {\n        int gid;\n        vector<int> cities;\n        bool exactSmall;\n    };\n\n    vector<PlannedQuery> queries;\n    unordered_set<string> usedSubset;\n    usedSubset.reserve(2000);\n\n    auto add_query = [&](int gid, const vector<int>& c, bool exactSmall) -> bool {\n        if ((int)queries.size() >= Q) return false;\n        if ((int)c.size() < 2 || (int)c.size() > L) return false;\n\n        string key = subset_key(c);\n        if (usedSubset.count(key)) return false;\n        usedSubset.insert(key);\n\n        queries.push_back({gid, c, exactSmall});\n        return true;\n    };\n\n    // Exact whole-group queries for small groups.\n    vector<int> smallIds;\n\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n        if (3 <= g && g <= L) smallIds.push_back(gid);\n    }\n\n    sort(smallIds.begin(), smallIds.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    for (int gid : smallIds) {\n        add_query(gid, groups[gid], true);\n    }\n\n    // Large groups: query local neighborhoods, especially near long estimated MST edges.\n    vector<int> largeIds;\n\n    for (int gid = 0; gid < M; gid++) {\n        if ((int)groups[gid].size() > L) largeIds.push_back(gid);\n    }\n\n    sort(largeIds.begin(), largeIds.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    vector<vector<pair<double,pair<int,int>>>> longEdges(M);\n\n    for (int gid : largeIds) {\n        for (auto [a, b] : backupEdges[gid]) {\n            longEdges[gid].push_back({edist(a, b), {a, b}});\n        }\n\n        sort(longEdges[gid].begin(), longEdges[gid].end(), [](auto& x, auto& y) {\n            return x.first > y.first;\n        });\n    }\n\n    int round = 0;\n\n    while ((int)queries.size() < Q && !largeIds.empty()) {\n        bool any = false;\n\n        for (int gid : largeIds) {\n            if ((int)queries.size() >= Q) break;\n\n            int g = groups[gid].size();\n            vector<int> sub;\n\n            if (round % 2 == 0) {\n                int idx = (round / 2) % g;\n                int seed = groups[gid][idx];\n                sub = nearest_subset_to_seed(groups[gid], seed);\n            } else {\n                int idx = (round / 2);\n\n                if (idx < (int)longEdges[gid].size()) {\n                    auto [a, b] = longEdges[gid][idx].second;\n                    sub = nearest_subset_to_edge(groups[gid], a, b);\n                } else {\n                    int seed = groups[gid][idx % g];\n                    sub = nearest_subset_to_seed(groups[gid], seed);\n                }\n            }\n\n            if (add_query(gid, sub, false)) any = true;\n        }\n\n        round++;\n        if (!any && round > 2 * N + 20) break;\n    }\n\n    // Execute queries.\n    for (auto& qu : queries) {\n        auto ret = do_query(qu.cities);\n        int gid = qu.gid;\n\n        for (auto [a, b] : ret) {\n            oracleEdges[gid][ekey(a, b)]++;\n        }\n\n        if (qu.exactSmall) {\n            finalEdges[gid] = ret;\n        }\n    }\n\n    // Construct final road sets.\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n\n        if (g <= 1) {\n            finalEdges[gid].clear();\n        } else if (g == 2) {\n            finalEdges[gid] = {{groups[gid][0], groups[gid][1]}};\n        } else if (g <= L && !finalEdges[gid].empty()) {\n            // Exact MST already obtained.\n        } else {\n            struct EdgeCand {\n                double w;\n                int a, b;\n            };\n\n            vector<EdgeCand> cand;\n\n            for (auto& kv : oracleEdges[gid]) {\n                auto [a, b] = decode_key(kv.first);\n                int cnt = kv.second;\n                double factor = 0.60 - 0.04 * min(4, cnt - 1);\n                cand.push_back({edist(a, b) * factor, a, b});\n            }\n\n            for (auto [a, b] : backupEdges[gid]) {\n                cand.push_back({edist(a, b), a, b});\n            }\n\n            // Extra estimated nearest-neighbor candidates.\n            for (int a : groups[gid]) {\n                vector<pair<double,int>> near;\n\n                for (int b : groups[gid]) {\n                    if (a == b) continue;\n                    near.push_back({edist(a, b), b});\n                }\n\n                sort(near.begin(), near.end());\n\n                int lim = min(4, (int)near.size());\n                for (int i = 0; i < lim; i++) {\n                    int b = near[i].second;\n                    cand.push_back({near[i].first * 1.035, a, b});\n                }\n            }\n\n            sort(cand.begin(), cand.end(), [](const EdgeCand& x, const EdgeCand& y) {\n                if (x.w != y.w) return x.w < y.w;\n                if (x.a != y.a) return x.a < y.a;\n                return x.b < y.b;\n            });\n\n            DSU dsu(N);\n            vector<pair<int,int>> tree;\n            tree.reserve(g - 1);\n\n            for (auto& e : cand) {\n                if (dsu.unite(e.a, e.b)) {\n                    tree.push_back({e.a, e.b});\n                    if ((int)tree.size() == g - 1) break;\n                }\n            }\n\n            if ((int)tree.size() != g - 1) {\n                tree = backupEdges[gid];\n            }\n\n            finalEdges[gid] = tree;\n        }\n    }\n\n    cout << \"!\" << '\\n';\n\n    for (int gid = 0; gid < M; gid++) {\n        for (int i = 0; i < (int)groups[gid].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[gid][i];\n        }\n        cout << '\\n';\n\n        for (auto [a, b] : finalEdges[gid]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Act {\n    char a, d;\n};\n\nconst int MAXC = 400;\nconst int INF = 1e9;\n\nint N, M;\nvector<int> pos_id;\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\nauto START_TIME = chrono::steady_clock::now();\n\ndouble elapsed_sec() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - START_TIME).count();\n}\n\ninline int id(int r, int c) { return r * N + c; }\ninline int rr(int x) { return x / N; }\ninline int cc(int x) { return x % N; }\ninline bool inside(int r, int c) { return 0 <= r && r < N && 0 <= c && c < N; }\n\ninline bool blocked(const bitset<MAXC>& g, int r, int c) {\n    if (!inside(r, c)) return true;\n    return g[id(r, c)];\n}\n\nint slide_stop(const bitset<MAXC>& g, int s, int dir) {\n    int r = rr(s), c = cc(s);\n    while (true) {\n        int nr = r + dr[dir], nc = c + dc[dir];\n        if (blocked(g, nr, nc)) break;\n        r = nr;\n        c = nc;\n    }\n    return id(r, c);\n}\n\nstruct BFSRes {\n    array<int, MAXC> dist;\n    array<int, MAXC> par;\n    array<char, MAXC> pact;\n    array<char, MAXC> pdir;\n};\n\nBFSRes forward_bfs(const bitset<MAXC>& g, int start, int forbid_stop = -1) {\n    BFSRes res;\n    res.dist.fill(INF);\n    res.par.fill(-1);\n    res.pact.fill(0);\n    res.pdir.fill(0);\n\n    if (g[start]) return res;\n\n    int q[MAXC];\n    int head = 0, tail = 0;\n\n    res.dist[start] = 0;\n    q[tail++] = start;\n\n    while (head < tail) {\n        int v = q[head++];\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            // Move\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (to != forbid_stop && res.dist[to] == INF) {\n                    res.dist[to] = res.dist[v] + 1;\n                    res.par[to] = v;\n                    res.pact[to] = 'M';\n                    res.pdir[to] = dch[d];\n                    q[tail++] = to;\n                }\n            }\n\n            // Slide\n            int to = slide_stop(g, v, d);\n            if (to != v && to != forbid_stop && res.dist[to] == INF) {\n                res.dist[to] = res.dist[v] + 1;\n                res.par[to] = v;\n                res.pact[to] = 'S';\n                res.pdir[to] = dch[d];\n                q[tail++] = to;\n            }\n        }\n    }\n\n    return res;\n}\n\narray<int, MAXC> reverse_bfs_dist(const bitset<MAXC>& g, int target) {\n    array<int, MAXC> dist;\n    dist.fill(INF);\n\n    if (g[target]) return dist;\n\n    int q[MAXC];\n    int head = 0, tail = 0;\n\n    dist[target] = 0;\n    q[tail++] = target;\n\n    while (head < tail) {\n        int v = q[head++];\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            // Reverse of Move d.\n            int pr = r - dr[d], pc = c - dc[d];\n            if (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q[tail++] = u;\n                }\n            }\n\n            // Reverse of Slide d.\n            int br = r + dr[d], bc = c + dc[d];\n            if (!blocked(g, br, bc)) continue;\n\n            pr = r - dr[d];\n            pc = c - dc[d];\n            while (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q[tail++] = u;\n                }\n                pr -= dr[d];\n                pc -= dc[d];\n            }\n        }\n    }\n\n    return dist;\n}\n\nvector<Act> restore_forward(const BFSRes& bfs, int start, int goal) {\n    vector<Act> rev;\n    int cur = goal;\n\n    while (cur != start) {\n        if (cur < 0 || bfs.par[cur] < 0) return {};\n        rev.push_back({bfs.pact[cur], bfs.pdir[cur]});\n        cur = bfs.par[cur];\n    }\n\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nvector<Act> restore_by_reverse_dist(\n    const bitset<MAXC>& g,\n    const array<int, MAXC>& dist,\n    int start,\n    int target\n) {\n    vector<Act> ret;\n    int cur = start;\n\n    while (cur != target) {\n        int cd = dist[cur];\n        bool found = false;\n\n        for (int d = 0; d < 4 && !found; d++) {\n            int r = rr(cur), c = cc(cur);\n\n            // Move\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (dist[to] == cd - 1) {\n                    ret.push_back({'M', dch[d]});\n                    cur = to;\n                    found = true;\n                    break;\n                }\n            }\n\n            // Slide\n            int to = slide_stop(g, cur, d);\n            if (to != cur && dist[to] == cd - 1) {\n                ret.push_back({'S', dch[d]});\n                cur = to;\n                found = true;\n                break;\n            }\n        }\n\n        if (!found) {\n            ret.clear();\n            return ret;\n        }\n    }\n\n    return ret;\n}\n\nint dir_from_to(int p, int b) {\n    int pr = rr(p), pc = cc(p);\n    int br = rr(b), bc = cc(b);\n\n    for (int d = 0; d < 4; d++) {\n        if (pr + dr[d] == br && pc + dc[d] == bc) return d;\n    }\n    return -1;\n}\n\nstruct State {\n    bitset<MAXC> grid;\n    int cost = 0;\n    vector<Act> acts;\n};\n\nstruct Option {\n    int cost;\n    int b;\n    int p;\n};\n\nint manhattan_id(int a, int b) {\n    return abs(rr(a) - rr(b)) + abs(cc(a) - cc(b));\n}\n\nint blocked_future_count(const bitset<MAXC>& g, int from_index) {\n    int cnt = 0;\n    for (int k = from_index; k < M; k++) {\n        if (g[pos_id[k]]) cnt++;\n    }\n    return cnt;\n}\n\nint one_step_heuristic(const State& st, int leg) {\n    if (leg + 1 >= M) return 0;\n    if (elapsed_sec() > 1.68) return 0;\n\n    int s = pos_id[leg];\n    int t = pos_id[leg + 1];\n\n    BFSRes bfs = forward_bfs(st.grid, s, -1);\n    int d = bfs.dist[t];\n\n    if (d >= INF) return manhattan_id(s, t) + 20;\n    return d;\n}\n\nvector<State> expand_state(\n    const State& st,\n    int leg\n) {\n    constexpr int TOP_K = 5;\n    constexpr int ALLOW_EXTRA = 4;\n\n    vector<State> res;\n\n    int start = pos_id[leg - 1];\n    int target = pos_id[leg];\n\n    BFSRes bfs_normal = forward_bfs(st.grid, start, -1);\n    BFSRes bfs_avoid = forward_bfs(st.grid, start, target);\n\n    int base_cost = bfs_normal.dist[target];\n    vector<Act> base_path;\n\n    if (base_cost < INF) {\n        base_path = restore_forward(bfs_normal, start, target);\n\n        // Baseline: no alteration.\n        State ns;\n        ns.grid = st.grid;\n        ns.acts = st.acts;\n        ns.acts.insert(ns.acts.end(), base_path.begin(), base_path.end());\n        ns.cost = (int)ns.acts.size();\n        res.push_back(std::move(ns));\n\n        // Cheap future-preparation:\n        // after reaching target, toggle an adjacent block.\n        // Unlike the previous version, this may also place a block on a future target.\n        for (int d = 0; d < 4; d++) {\n            int br = rr(target) + dr[d];\n            int bc = cc(target) + dc[d];\n            if (!inside(br, bc)) continue;\n\n            int b = id(br, bc);\n\n            bitset<MAXC> g2 = st.grid;\n            g2.flip(b);\n\n            if (g2[target]) continue;\n\n            State ps;\n            ps.grid = g2;\n            ps.acts = st.acts;\n            ps.acts.insert(ps.acts.end(), base_path.begin(), base_path.end());\n            ps.acts.push_back({'A', dch[d]});\n            ps.cost = (int)ps.acts.size();\n            res.push_back(std::move(ps));\n        }\n    }\n\n    // If close to the time limit, skip expensive alteration search.\n    if (elapsed_sec() > 1.70) return res;\n\n    vector<Option> opts;\n\n    for (int b = 0; b < N * N; b++) {\n        if ((b & 31) == 0 && elapsed_sec() > 1.80) break;\n\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(b);\n\n        // The current target must be unblocked after the alteration.\n        // If b == target and it was blocked, this is a useful removal candidate.\n        // If b == target and it was not blocked, this candidate is invalid.\n        if (g2[target]) continue;\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n\n        int best_cost = INF;\n        int best_p = -1;\n\n        int br = rr(b), bc = cc(b);\n\n        for (int d = 0; d < 4; d++) {\n            int pr = br - dr[d], pc = bc - dc[d];\n            if (!inside(pr, pc)) continue;\n\n            int p = id(pr, pc);\n\n            if (st.grid[p]) continue;\n            if (g2[p]) continue;\n            if (bfs_avoid.dist[p] >= INF) continue;\n            if (dist_to_target[p] >= INF) continue;\n\n            int cand = bfs_avoid.dist[p] + 1 + dist_to_target[p];\n\n            if (cand < best_cost) {\n                best_cost = cand;\n                best_p = p;\n            }\n        }\n\n        if (best_p < 0) continue;\n\n        if (base_cost < INF && best_cost > base_cost + ALLOW_EXTRA) continue;\n\n        opts.push_back({best_cost, b, best_p});\n    }\n\n    sort(opts.begin(), opts.end(), [](const Option& x, const Option& y) {\n        return x.cost < y.cost;\n    });\n\n    if ((int)opts.size() > TOP_K) opts.resize(TOP_K);\n\n    for (const auto& op : opts) {\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(op.b);\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n\n        if (dist_to_target[op.p] >= INF) continue;\n\n        auto path1 = restore_forward(bfs_avoid, start, op.p);\n        if (path1.empty() && op.p != start) continue;\n\n        int ad = dir_from_to(op.p, op.b);\n        if (ad < 0) continue;\n\n        auto path2 = restore_by_reverse_dist(g2, dist_to_target, op.p, target);\n        if (path2.empty() && op.p != target) continue;\n\n        State ns;\n        ns.grid = g2;\n        ns.acts = st.acts;\n        ns.acts.insert(ns.acts.end(), path1.begin(), path1.end());\n        ns.acts.push_back({'A', dch[ad]});\n        ns.acts.insert(ns.acts.end(), path2.begin(), path2.end());\n        ns.cost = (int)ns.acts.size();\n\n        res.push_back(std::move(ns));\n    }\n\n    return res;\n}\n\nvector<Act> simple_fallback_empty_board() {\n    vector<Act> ret;\n    int cur = pos_id[0];\n\n    for (int k = 1; k < M; k++) {\n        int t = pos_id[k];\n\n        int r = rr(cur), c = cc(cur);\n        int tr = rr(t), tc = cc(t);\n\n        while (r < tr) {\n            ret.push_back({'M', 'D'});\n            r++;\n        }\n        while (r > tr) {\n            ret.push_back({'M', 'U'});\n            r--;\n        }\n        while (c < tc) {\n            ret.push_back({'M', 'R'});\n            c++;\n        }\n        while (c > tc) {\n            ret.push_back({'M', 'L'});\n            c--;\n        }\n\n        cur = t;\n    }\n\n    return ret;\n}\n\nint dir_index(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\nbool simulate(const vector<Act>& acts) {\n    if ((int)acts.size() > 2 * N * M) return false;\n\n    bitset<MAXC> g;\n    int cur = pos_id[0];\n    int nxt = 1;\n\n    for (auto [a, ch] : acts) {\n        int d = dir_index(ch);\n        int r = rr(cur), c = cc(cur);\n\n        if (a == 'M') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n\n            int to = id(nr, nc);\n            if (g[to]) return false;\n\n            cur = to;\n\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'S') {\n            while (true) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (!inside(nr, nc) || g[id(nr, nc)]) break;\n                r = nr;\n                c = nc;\n            }\n\n            cur = id(r, c);\n\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'A') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n\n            int b = id(nr, nc);\n            g.flip(b);\n        } else {\n            return false;\n        }\n    }\n\n    return nxt == M;\n}\n\nvoid greedy_delete_limited(vector<Act>& ans) {\n    int i = 0;\n\n    while (i < (int)ans.size()) {\n        if (elapsed_sec() > 1.88) break;\n\n        vector<Act> cand;\n        cand.reserve(ans.size() - 1);\n\n        for (int j = 0; j < (int)ans.size(); j++) {\n            if (j != i) cand.push_back(ans[j]);\n        }\n\n        if (simulate(cand)) {\n            ans.swap(cand);\n        } else {\n            i++;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    pos_id.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        int r, c;\n        cin >> r >> c;\n        pos_id[k] = id(r, c);\n    }\n\n    constexpr int BEAM_W = 6;\n    constexpr int COST_FIRST_KEEP = 4;\n\n    vector<State> beam;\n    State init;\n    init.grid.reset();\n    init.cost = 0;\n    beam.push_back(init);\n\n    for (int leg = 1; leg < M; leg++) {\n        vector<State> candidates;\n\n        for (const auto& st : beam) {\n            auto ex = expand_state(st, leg);\n            for (auto& ns : ex) candidates.push_back(std::move(ns));\n        }\n\n        if (candidates.empty()) {\n            auto fb = simple_fallback_empty_board();\n            for (auto [a, d] : fb) cout << a << ' ' << d << '\\n';\n            return 0;\n        }\n\n        sort(candidates.begin(), candidates.end(), [](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        vector<State> unique_candidates;\n        for (auto& st : candidates) {\n            bool dup = false;\n            for (const auto& u : unique_candidates) {\n                if (u.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) unique_candidates.push_back(std::move(st));\n        }\n\n        candidates.swap(unique_candidates);\n\n        vector<State> nb;\n\n        // Keep several pure-low-cost states to reduce regressions.\n        sort(candidates.begin(), candidates.end(), [](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        for (auto& st : candidates) {\n            bool dup = false;\n            for (const auto& kept : nb) {\n                if (kept.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (dup) continue;\n\n            nb.push_back(st);\n            if ((int)nb.size() >= COST_FIRST_KEEP) break;\n        }\n\n        struct Ranked {\n            long long score;\n            int cost;\n            int idx;\n        };\n\n        vector<Ranked> rank;\n        rank.reserve(candidates.size());\n\n        for (int i = 0; i < (int)candidates.size(); i++) {\n            int h = one_step_heuristic(candidates[i], leg);\n\n            // Small penalty for blocked unvisited targets.\n            // Temporary target blocking can be useful, so keep this penalty mild.\n            int bf = blocked_future_count(candidates[i].grid, leg + 1);\n\n            long long sc = 100LL * candidates[i].cost + 12LL * h + 10LL * bf;\n            rank.push_back({sc, candidates[i].cost, i});\n        }\n\n        sort(rank.begin(), rank.end(), [](const Ranked& a, const Ranked& b) {\n            if (a.score != b.score) return a.score < b.score;\n            return a.cost < b.cost;\n        });\n\n        for (const auto& rnk : rank) {\n            const State& st = candidates[rnk.idx];\n\n            bool dup = false;\n            for (const auto& kept : nb) {\n                if (kept.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (dup) continue;\n\n            nb.push_back(st);\n            if ((int)nb.size() >= BEAM_W) break;\n        }\n\n        if (nb.empty()) {\n            auto fb = simple_fallback_empty_board();\n            for (auto [a, d] : fb) cout << a << ' ' << d << '\\n';\n            return 0;\n        }\n\n        beam = std::move(nb);\n    }\n\n    int best = -1;\n    for (int i = 0; i < (int)beam.size(); i++) {\n        if (best == -1 || beam[i].cost < beam[best].cost) {\n            best = i;\n        }\n    }\n\n    vector<Act> ans = beam[best].acts;\n\n    if (!simulate(ans)) {\n        ans = simple_fallback_empty_board();\n    } else {\n        greedy_delete_limited(ans);\n    }\n\n    if (!simulate(ans)) {\n        ans = simple_fallback_empty_board();\n    }\n\n    for (auto [a, d] : ans) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#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 Rect {\n    int a, b, c, d;\n};\n\nstruct Blocker {\n    int id;\n    int gap;\n    int limit;\n};\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\nvector<long double> wt;\nmt19937 rng(1234567);\nTimer timer_;\n\nlong long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\ndouble score_area(long long s, long long r) {\n    if (s <= 0) return 0.0;\n    double q = (double)min(s, r) / (double)max(s, r);\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble evaluate(const vector<Rect>& rects) {\n    double sum = 0.0;\n    for (int i = 0; i < n; i++) {\n        const Rect& e = rects[i];\n        if (e.a <= xs[i] && xs[i] + 1 <= e.c && e.b <= ys[i] && ys[i] + 1 <= e.d) {\n            sum += score_area(area(e), rs[i]);\n        }\n    }\n    return sum;\n}\n\nbool overlap1d(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\n/* ---------- slicing construction ---------- */\n\nstruct SplitCand {\n    int axis;\n    int k;\n    int cut;\n    double cost;\n};\n\nvoid build_rec(const vector<int>& ids, int L, int B, int R, int T, vector<Rect>& out, int topK) {\n    int m = (int)ids.size();\n\n    if (m == 1) {\n        out[ids[0]] = {L, B, R, T};\n        return;\n    }\n\n    long double totalTarget = 0;\n    for (int id : ids) totalTarget += wt[id];\n\n    long long regionArea = 1LL * (R - L) * (T - B);\n    vector<SplitCand> cands;\n\n    for (int axis = 0; axis < 2; axis++) {\n        vector<int> v = ids;\n\n        if (axis == 0) {\n            sort(v.begin(), v.end(), [&](int p, int q) {\n                if (xs[p] != xs[q]) return xs[p] < xs[q];\n                return ys[p] < ys[q];\n            });\n        } else {\n            sort(v.begin(), v.end(), [&](int p, int q) {\n                if (ys[p] != ys[q]) return ys[p] < ys[q];\n                return xs[p] < xs[q];\n            });\n        }\n\n        vector<long double> pref(m + 1, 0);\n        for (int i = 0; i < m; i++) pref[i + 1] = pref[i] + wt[v[i]];\n\n        for (int k = 1; k < m; k++) {\n            int coordL = (axis == 0 ? xs[v[k - 1]] : ys[v[k - 1]]);\n            int coordR = (axis == 0 ? xs[v[k]] : ys[v[k]]);\n            if (coordL >= coordR) continue;\n\n            int start = (axis == 0 ? L : B);\n            int end = (axis == 0 ? R : T);\n            int otherLen = (axis == 0 ? T - B : R - L);\n            int len = end - start;\n\n            int lo = max(coordL + 1, start + 1);\n            int hi = min(coordR, end - 1);\n            if (lo > hi) continue;\n\n            long double ratio = pref[k] / totalTarget;\n            int desired = (int)llround((long double)start + ratio * len);\n            int cut = min(max(desired, lo), hi);\n\n            long long leftArea = 1LL * (cut - start) * otherLen;\n            long long rightArea = regionArea - leftArea;\n\n            long double leftTarget = pref[k];\n            long double rightTarget = totalTarget - leftTarget;\n            long double scale = (long double)regionArea / totalTarget;\n\n            double er1 = fabs((double)((long double)leftArea / leftTarget - scale));\n            double er2 = fabs((double)((long double)rightArea / rightTarget - scale));\n            double cost = er1 * (double)(leftTarget / totalTarget)\n                        + er2 * (double)(rightTarget / totalTarget);\n\n            if (k == 1) {\n                int id = v[0];\n                cost += 0.08 * (1.0 - score_area(leftArea, rs[id]));\n            }\n            if (m - k == 1) {\n                int id = v[m - 1];\n                cost += 0.08 * (1.0 - score_area(rightArea, rs[id]));\n            }\n\n            cands.push_back({axis, k, cut, cost});\n        }\n    }\n\n    if (cands.empty()) {\n        vector<int> v = ids;\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (xs[p] != xs[q]) return xs[p] < xs[q];\n            return ys[p] < ys[q];\n        });\n\n        int k = m / 2;\n        int cut = (L + R) / 2;\n        cut = min(max(cut, L + 1), R - 1);\n\n        vector<int> A(v.begin(), v.begin() + k), C(v.begin() + k, v.end());\n        build_rec(A, L, B, cut, T, out, topK);\n        build_rec(C, cut, B, R, T, out, topK);\n        return;\n    }\n\n    sort(cands.begin(), cands.end(), [](const SplitCand& x, const SplitCand& y) {\n        return x.cost < y.cost;\n    });\n\n    int pick = 0;\n    if (topK > 1) {\n        int lim = min<int>(topK, cands.size());\n        double u = uniform_real_distribution<double>(0.0, 1.0)(rng);\n        pick = min(lim - 1, (int)(u * u * lim));\n    }\n\n    SplitCand ch = cands[pick];\n\n    vector<int> v = ids;\n    if (ch.axis == 0) {\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (xs[p] != xs[q]) return xs[p] < xs[q];\n            return ys[p] < ys[q];\n        });\n    } else {\n        sort(v.begin(), v.end(), [&](int p, int q) {\n            if (ys[p] != ys[q]) return ys[p] < ys[q];\n            return xs[p] < xs[q];\n        });\n    }\n\n    vector<int> left(v.begin(), v.begin() + ch.k);\n    vector<int> right(v.begin() + ch.k, v.end());\n\n    if (ch.axis == 0) {\n        build_rec(left, L, B, ch.cut, T, out, topK);\n        build_rec(right, ch.cut, B, R, T, out, topK);\n    } else {\n        build_rec(left, L, B, R, ch.cut, out, topK);\n        build_rec(right, L, ch.cut, R, T, out, topK);\n    }\n}\n\nvector<Rect> build_slicing(int topK, double noise) {\n    wt.assign(n, 0);\n\n    if (noise <= 0) {\n        for (int i = 0; i < n; i++) wt[i] = rs[i];\n    } else {\n        normal_distribution<double> nd(0.0, noise);\n        for (int i = 0; i < n; i++) {\n            double mul = exp(nd(rng));\n            mul = min(1.45, max(0.70, mul));\n            wt[i] = (long double)rs[i] * mul;\n        }\n    }\n\n    vector<Rect> res(n);\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n    build_rec(ids, 0, 0, 10000, 10000, res, topK);\n    return res;\n}\n\n/* ---------- local improvement ---------- */\n\nbool shrink_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect cur = rects[id];\n        long long A = area(cur);\n        double curScore = score_area(A, rs[id]);\n\n        Rect best = cur;\n        double bestGain = 1e-15;\n\n        auto try_delta = [&](int dir, int maxd) {\n            if (maxd <= 0) return;\n\n            int len = (dir < 2 ? cur.d - cur.b : cur.c - cur.a);\n            vector<int> ds;\n\n            long long excess = A - rs[id];\n            if (excess > 0) {\n                long long q = excess / len;\n                for (long long z : {q - 2, q - 1, q, q + 1, q + 2}) {\n                    if (1 <= z && z <= maxd) ds.push_back((int)z);\n                }\n            }\n\n            ds.push_back(1);\n            ds.push_back(maxd);\n            sort(ds.begin(), ds.end());\n            ds.erase(unique(ds.begin(), ds.end()), ds.end());\n\n            for (int dlt : ds) {\n                Rect nr = cur;\n                if (dir == 0) nr.a += dlt;\n                if (dir == 1) nr.c -= dlt;\n                if (dir == 2) nr.b += dlt;\n                if (dir == 3) nr.d -= dlt;\n\n                if (!(nr.a < nr.c && nr.b < nr.d)) continue;\n                if (!(nr.a <= xs[id] && xs[id] + 1 <= nr.c && nr.b <= ys[id] && ys[id] + 1 <= nr.d)) continue;\n\n                double gain = score_area(area(nr), rs[id]) - curScore;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = nr;\n                }\n            }\n        };\n\n        try_delta(0, xs[id] - cur.a);\n        try_delta(1, cur.c - (xs[id] + 1));\n        try_delta(2, ys[id] - cur.b);\n        try_delta(3, cur.d - (ys[id] + 1));\n\n        if (bestGain > 1e-14) {\n            rects[id] = best;\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nint max_expand_delta(const vector<Rect>& rects, int id, int dir) {\n    const Rect& r = rects[id];\n    int lim;\n\n    if (dir == 0) {\n        lim = r.a;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.b, r.d, o.b, o.d) && o.c <= r.a) {\n                lim = min(lim, r.a - o.c);\n            }\n        }\n    } else if (dir == 1) {\n        lim = 10000 - r.c;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.b, r.d, o.b, o.d) && o.a >= r.c) {\n                lim = min(lim, o.a - r.c);\n            }\n        }\n    } else if (dir == 2) {\n        lim = r.b;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.a, r.c, o.a, o.c) && o.d <= r.b) {\n                lim = min(lim, r.b - o.d);\n            }\n        }\n    } else {\n        lim = 10000 - r.d;\n        for (int j = 0; j < n; j++) if (j != id) {\n            const Rect& o = rects[j];\n            if (overlap1d(r.a, r.c, o.a, o.c) && o.b >= r.d) {\n                lim = min(lim, o.b - r.d);\n            }\n        }\n    }\n\n    return lim;\n}\n\nbool expand_pass(vector<Rect>& rects, bool randomOrder, double deadline) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect cur = rects[id];\n        long long A = area(cur);\n        double curScore = score_area(A, rs[id]);\n\n        Rect best = cur;\n        double bestGain = 1e-15;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int maxd = max_expand_delta(rects, id, dir);\n            if (maxd <= 0) continue;\n\n            int len = (dir < 2 ? cur.d - cur.b : cur.c - cur.a);\n            vector<int> ds;\n\n            long long need = rs[id] - A;\n            if (need > 0) {\n                long long q = need / len;\n                for (long long z : {q - 2, q - 1, q, q + 1, q + 2}) {\n                    if (1 <= z && z <= maxd) ds.push_back((int)z);\n                }\n            }\n\n            ds.push_back(1);\n            ds.push_back(maxd);\n            sort(ds.begin(), ds.end());\n            ds.erase(unique(ds.begin(), ds.end()), ds.end());\n\n            for (int dlt : ds) {\n                Rect nr = cur;\n                if (dir == 0) nr.a -= dlt;\n                if (dir == 1) nr.c += dlt;\n                if (dir == 2) nr.b -= dlt;\n                if (dir == 3) nr.d += dlt;\n\n                double gain = score_area(area(nr), rs[id]) - curScore;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = nr;\n                }\n            }\n        }\n\n        if (bestGain > 1e-14) {\n            rects[id] = best;\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nbool steal_pass(vector<Rect>& rects, bool randomOrder, double deadline, bool extended = false) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (randomOrder) shuffle(ord.begin(), ord.end(), rng);\n\n    bool moved = false;\n\n    for (int id : ord) {\n        if (timer_.elapsed() > deadline) break;\n\n        Rect r = rects[id];\n        long long Ai = area(r);\n        double oldSi = score_area(Ai, rs[id]);\n\n        int bestDir = -1;\n        int bestD = 0;\n        double bestGain = 1e-13;\n\n        for (int dir = 0; dir < 4; dir++) {\n            vector<Blocker> bs;\n            int maxD;\n            int lenI = (dir < 2 ? r.d - r.b : r.c - r.a);\n\n            auto add_blocker = [&](int j, int gap, int lim) {\n                int cap = (lim >= gap ? lim : gap);\n                bs.push_back({j, gap, lim});\n                maxD = min(maxD, cap);\n            };\n\n            if (dir == 0) {\n                maxD = r.a;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.b, r.d, o.b, o.d) && o.c <= r.a) {\n                        add_blocker(j, r.a - o.c, r.a - (xs[j] + 1));\n                    }\n                }\n            } else if (dir == 1) {\n                maxD = 10000 - r.c;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.b, r.d, o.b, o.d) && o.a >= r.c) {\n                        add_blocker(j, o.a - r.c, xs[j] - r.c);\n                    }\n                }\n            } else if (dir == 2) {\n                maxD = r.b;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.a, r.c, o.a, o.c) && o.d <= r.b) {\n                        add_blocker(j, r.b - o.d, r.b - (ys[j] + 1));\n                    }\n                }\n            } else {\n                maxD = 10000 - r.d;\n                for (int j = 0; j < n; j++) if (j != id) {\n                    const Rect& o = rects[j];\n                    if (overlap1d(r.a, r.c, o.a, o.c) && o.b >= r.d) {\n                        add_blocker(j, o.b - r.d, ys[j] - r.d);\n                    }\n                }\n            }\n\n            if (maxD <= 0) continue;\n\n            vector<int> cand;\n\n            auto add_one = [&](long long x) {\n                if (1 <= x && x <= maxD) cand.push_back((int)x);\n            };\n\n            auto add_near = [&](long long x) {\n                for (long long y : {x - 3, x - 2, x - 1, x, x + 1, x + 2, x + 3}) {\n                    add_one(y);\n                }\n            };\n\n            add_one(1);\n            add_one(maxD);\n            add_one(maxD / 2);\n            add_one(maxD / 3);\n            add_one(2LL * maxD / 3);\n\n            if (extended) {\n                for (int k = 1; k < 8; k++) add_one(1LL * maxD * k / 8);\n                for (int t = 0; t < 8; t++) {\n                    add_one(uniform_int_distribution<int>(1, maxD)(rng));\n                }\n            }\n\n            long long needI = rs[id] - Ai;\n            if (needI > 0) add_near(needI / lenI);\n\n            for (auto bl : bs) {\n                add_one(bl.gap);\n                add_one(bl.gap + 1);\n                add_one(bl.limit);\n\n                if (extended) {\n                    for (int z = -8; z <= 8; z++) {\n                        add_one(bl.gap + z);\n                        add_one(bl.limit + z);\n                    }\n                }\n\n                int j = bl.id;\n                const Rect& o = rects[j];\n                int lenJ = (dir < 2 ? o.d - o.b : o.c - o.a);\n                long long Aj = area(o);\n\n                if (Aj > rs[j]) {\n                    long long red = Aj - rs[j];\n                    add_near(bl.gap + red / lenJ);\n                    if (extended) {\n                        add_near(bl.gap + red / lenJ - 8);\n                        add_near(bl.gap + red / lenJ + 8);\n                    }\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n            for (int delta : cand) {\n                if (delta <= 0 || delta > maxD) continue;\n\n                bool feasible = true;\n                double gain = score_area(Ai + 1LL * delta * lenI, rs[id]) - oldSi;\n\n                for (auto bl : bs) {\n                    if (delta <= bl.gap) continue;\n\n                    if (delta > bl.limit) {\n                        feasible = false;\n                        break;\n                    }\n\n                    int j = bl.id;\n                    const Rect& o = rects[j];\n                    long long Aj = area(o);\n                    int lenJ = (dir < 2 ? o.d - o.b : o.c - o.a);\n                    long long nAj = Aj - 1LL * (delta - bl.gap) * lenJ;\n\n                    gain += score_area(nAj, rs[j]) - score_area(Aj, rs[j]);\n                }\n\n                if (!feasible) continue;\n\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestDir = dir;\n                    bestD = delta;\n                }\n            }\n        }\n\n        if (bestDir != -1) {\n            Rect old = rects[id];\n\n            if (bestDir == 0) rects[id].a -= bestD;\n            if (bestDir == 1) rects[id].c += bestD;\n            if (bestDir == 2) rects[id].b -= bestD;\n            if (bestDir == 3) rects[id].d += bestD;\n\n            for (int j = 0; j < n; j++) if (j != id) {\n                Rect& o = rects[j];\n\n                if (bestDir == 0) {\n                    if (overlap1d(old.b, old.d, o.b, o.d) && o.c <= old.a) {\n                        int gap = old.a - o.c;\n                        if (bestD > gap) o.c = old.a - bestD;\n                    }\n                } else if (bestDir == 1) {\n                    if (overlap1d(old.b, old.d, o.b, o.d) && o.a >= old.c) {\n                        int gap = o.a - old.c;\n                        if (bestD > gap) o.a = old.c + bestD;\n                    }\n                } else if (bestDir == 2) {\n                    if (overlap1d(old.a, old.c, o.a, o.c) && o.d <= old.b) {\n                        int gap = old.b - o.d;\n                        if (bestD > gap) o.d = old.b - bestD;\n                    }\n                } else {\n                    if (overlap1d(old.a, old.c, o.a, o.c) && o.b >= old.d) {\n                        int gap = o.b - old.d;\n                        if (bestD > gap) o.b = old.d + bestD;\n                    }\n                }\n            }\n\n            moved = true;\n        }\n    }\n\n    return moved;\n}\n\nvoid shrink_only(vector<Rect>& rects, double deadline) {\n    for (int it = 0; it < 20 && timer_.elapsed() < deadline; it++) {\n        if (!shrink_pass(rects, false, deadline)) break;\n    }\n}\n\nvoid improve_solution(vector<Rect>& rects, double deadline) {\n    for (int it = 0; timer_.elapsed() < deadline; it++) {\n        bool moved = false;\n        moved |= shrink_pass(rects, true, deadline);\n        moved |= steal_pass(rects, true, deadline, false);\n        moved |= expand_pass(rects, true, deadline);\n        if (!moved) break;\n    }\n}\n\nvoid improve_solution_extended(vector<Rect>& rects, double deadline) {\n    for (int it = 0; timer_.elapsed() < deadline; it++) {\n        bool moved = false;\n        moved |= shrink_pass(rects, true, deadline);\n        moved |= steal_pass(rects, true, deadline, false);\n        moved |= expand_pass(rects, true, deadline);\n\n        if (!moved && timer_.elapsed() < deadline) {\n            moved |= steal_pass(rects, true, deadline, true);\n            if (moved) {\n                expand_pass(rects, true, deadline);\n                shrink_pass(rects, true, deadline);\n            }\n        }\n\n        if (!moved) break;\n    }\n}\n\nvector<Rect> unit_solution() {\n    vector<Rect> sol(n);\n    for (int i = 0; i < n; i++) {\n        sol[i] = {xs[i], ys[i], xs[i] + 1, ys[i] + 1};\n    }\n    return sol;\n}\n\n/* ---------- main ---------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n;\n    xs.resize(n);\n    ys.resize(n);\n    rs.resize(n);\n\n    for (int i = 0; i < n; i++) {\n        cin >> xs[i] >> ys[i] >> rs[i];\n    }\n\n    vector<Rect> best = unit_solution();\n    double bestScore = evaluate(best);\n\n    auto consider_best = [&](const vector<Rect>& sol) {\n        double sc = evaluate(sol);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = sol;\n        }\n    };\n\n    vector<pair<double, vector<Rect>>> tops;\n\n    auto insert_top = [&](vector<Rect> sol) {\n        double sc = evaluate(sol);\n        tops.push_back({sc, sol});\n        sort(tops.begin(), tops.end(), [](const auto& p, const auto& q) {\n            return p.first > q.first;\n        });\n        if ((int)tops.size() > 8) tops.pop_back();\n        consider_best(sol);\n    };\n\n    int cnt = 0;\n\n    while (timer_.elapsed() < 2.85) {\n        int topK;\n        if (cnt == 0) topK = 1;\n        else if (cnt % 5 == 0) topK = 3;\n        else if (cnt % 5 == 1) topK = 5;\n        else topK = 10;\n\n        double noise = 0.0;\n        if (cnt > 0) {\n            if (cnt % 3 == 0) noise = 0.06;\n            else if (cnt % 3 == 1) noise = 0.10;\n            else noise = 0.14;\n        }\n\n        vector<Rect> sol = build_slicing(topK, noise);\n        shrink_only(sol, 2.85);\n        insert_top(sol);\n\n        cnt++;\n    }\n\n    sort(tops.begin(), tops.end(), [](const auto& p, const auto& q) {\n        return p.first > q.first;\n    });\n\n    int m = (int)tops.size();\n    for (int i = 0; i < m && timer_.elapsed() < 4.76; i++) {\n        vector<Rect> sol = tops[i].second;\n        double remain = 4.76 - timer_.elapsed();\n        double deadline = timer_.elapsed() + remain / max(1, m - i);\n        improve_solution(sol, deadline);\n        consider_best(sol);\n    }\n\n    if (timer_.elapsed() < 4.90) {\n        vector<Rect> sol = unit_solution();\n        improve_solution(sol, 4.90);\n        consider_best(sol);\n    }\n\n    // Safe final polishing: work on copies and accept only if full score improves.\n    if (timer_.elapsed() < 4.96) {\n        vector<Rect> sol = best;\n        improve_solution(sol, 4.96);\n        consider_best(sol);\n    }\n\n    if (timer_.elapsed() < 4.975) {\n        vector<Rect> sol = best;\n        improve_solution_extended(sol, 4.975);\n        consider_best(sol);\n    }\n\n    for (int i = 0; i < n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' ' << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int V = N * N;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\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\nstruct Path {\n    int score = 0;\n    vector<int> cells;\n    string moves;\n};\n\nstruct Params {\n    double wp;\n    double wd;\n    double w1;\n    double w2;\n    double noise;\n    double randomMoveProb;\n};\n\nint si, sj;\nint tile_id[V];\nint point_val[V];\nint nb[V][4];\nchar nb_dir[V][4];\n\nPath best_path;\nvector<Path> pool;\n\nParams make_params(XorShift &rng) {\n    Params p;\n    int mode = rng.nextInt(10);\n\n    if (mode == 0) {\n        p = {1.8, 4.0, 0.22, 0.08, 30.0, 0.02};\n    } else if (mode == 1) {\n        p = {1.0, -24.0, 0.12, 0.05, 45.0, 0.03};\n    } else if (mode == 2) {\n        p = {1.2, 8.0, 0.36, 0.11, 55.0, 0.04};\n    } else if (mode == 3) {\n        p = {1.0, 0.0, 0.16, 0.05, 120.0, 0.12};\n    } else if (mode == 4) {\n        p = {0.85, -34.0, 0.07, 0.03, 60.0, 0.04};\n    } else if (mode == 5) {\n        p = {1.0, 18.0, 0.46, 0.15, 45.0, 0.02};\n    } else if (mode == 6) {\n        p = {2.4, -8.0, 0.26, 0.08, 40.0, 0.02};\n    } else if (mode == 7) {\n        p = {0.9, 2.0, 0.12, 0.04, 160.0, 0.15};\n    } else if (mode == 8) {\n        p = {1.5, -16.0, 0.28, 0.12, 35.0, 0.02};\n    } else {\n        p = {1.1, 26.0, 0.35, 0.20, 65.0, 0.05};\n    }\n\n    p.wp *= 0.75 + rng.nextDouble() * 0.70;\n    p.wd *= 0.75 + rng.nextDouble() * 0.70;\n    p.w1 *= 0.70 + rng.nextDouble() * 0.80;\n    p.w2 *= 0.70 + rng.nextDouble() * 0.80;\n    p.noise *= 0.70 + rng.nextDouble() * 0.80;\n\n    return p;\n}\n\ndouble eval_move(\n    int to,\n    const vector<int> &seen,\n    int mark,\n    const Params &par,\n    XorShift &rng\n) {\n    int tid_to = tile_id[to];\n\n    int degree1 = 0;\n    int best_next_point = 0;\n    double best_look2 = 0.0;\n\n    for (int k = 0; k < 4; k++) {\n        int v1 = nb[to][k];\n        if (v1 < 0) continue;\n\n        int tid1 = tile_id[v1];\n        if (tid1 == tid_to) continue;\n        if (seen[tid1] == mark) continue;\n\n        degree1++;\n        best_next_point = max(best_next_point, point_val[v1]);\n\n        int degree2 = 0;\n        int best_p2 = 0;\n\n        for (int l = 0; l < 4; l++) {\n            int v2 = nb[v1][l];\n            if (v2 < 0) continue;\n\n            int tid2 = tile_id[v2];\n            if (tid2 == tid_to || tid2 == tid1) continue;\n            if (seen[tid2] == mark) continue;\n\n            degree2++;\n            best_p2 = max(best_p2, point_val[v2]);\n        }\n\n        double look2 = point_val[v1] + 8.0 * degree2 + 0.25 * best_p2;\n        best_look2 = max(best_look2, look2);\n    }\n\n    double e = 0.0;\n    e += par.wp * point_val[to];\n    e += par.wd * degree1;\n    e += par.w1 * best_next_point;\n    e += par.w2 * best_look2;\n    e += par.noise * (rng.nextDouble() - 0.5);\n    return e;\n}\n\nint choose_next(\n    int pos,\n    const vector<int> &seen,\n    int mark,\n    const Params &par,\n    XorShift &rng,\n    char &out_dir\n) {\n    int cand[4];\n    char cdir[4];\n    int cnt = 0;\n\n    for (int k = 0; k < 4; k++) {\n        int to = nb[pos][k];\n        if (to < 0) continue;\n\n        int tid = tile_id[to];\n        if (seen[tid] == mark) continue;\n\n        cand[cnt] = to;\n        cdir[cnt] = nb_dir[pos][k];\n        cnt++;\n    }\n\n    if (cnt == 0) return -1;\n\n    if (cnt == 1) {\n        out_dir = cdir[0];\n        return cand[0];\n    }\n\n    if (rng.nextDouble() < par.randomMoveProb) {\n        int id = rng.nextInt(cnt);\n        out_dir = cdir[id];\n        return cand[id];\n    }\n\n    double best_eval = -1e100;\n    int best_id = 0;\n\n    for (int i = 0; i < cnt; i++) {\n        double e = eval_move(cand[i], seen, mark, par, rng);\n        if (e > best_eval) {\n            best_eval = e;\n            best_id = i;\n        }\n    }\n\n    out_dir = cdir[best_id];\n    return cand[best_id];\n}\n\nvoid consider_path(const Path &p) {\n    if (p.score > best_path.score) {\n        best_path = p;\n    }\n\n    constexpr int POOL_SIZE = 24;\n\n    if ((int)pool.size() < POOL_SIZE) {\n        pool.push_back(p);\n    } else {\n        int worst = 0;\n        for (int i = 1; i < (int)pool.size(); i++) {\n            if (pool[i].score < pool[worst].score) worst = i;\n        }\n        if (p.score > pool[worst].score) {\n            pool[worst] = p;\n        }\n    }\n}\n\nPath build_greedy_from_prefix(\n    const Path *base,\n    int prefix_len,\n    vector<int> &seen,\n    int mark,\n    XorShift &rng\n) {\n    Path cur;\n    cur.cells.reserve(V);\n    cur.moves.reserve(V);\n\n    if (base == nullptr) {\n        int st = si * N + sj;\n        cur.cells.push_back(st);\n        cur.score = point_val[st];\n        seen[tile_id[st]] = mark;\n    } else {\n        prefix_len = max(prefix_len, 1);\n        prefix_len = min(prefix_len, (int)base->cells.size());\n\n        cur.cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n        cur.moves.assign(base->moves.begin(), base->moves.begin() + prefix_len - 1);\n\n        cur.score = 0;\n        for (int c : cur.cells) {\n            cur.score += point_val[c];\n            seen[tile_id[c]] = mark;\n        }\n    }\n\n    Params par = make_params(rng);\n\n    while (true) {\n        int pos = cur.cells.back();\n        char d = '?';\n        int nxt = choose_next(pos, seen, mark, par, rng, d);\n\n        if (nxt < 0) break;\n\n        seen[tile_id[nxt]] = mark;\n        cur.cells.push_back(nxt);\n        cur.moves.push_back(d);\n        cur.score += point_val[nxt];\n    }\n\n    return cur;\n}\n\nint select_prefix_len(const Path &p, XorShift &rng) {\n    int L = (int)p.cells.size();\n    if (L <= 1) return 1;\n\n    double u = rng.nextDouble();\n    double x;\n    int typ = rng.nextInt(100);\n\n    if (typ < 45) {\n        x = sqrt(u);\n    } else if (typ < 75) {\n        x = u;\n    } else if (typ < 92) {\n        x = u * u;\n    } else {\n        x = 0.82 + 0.18 * u;\n    }\n\n    int prefix_len = 1 + (int)(x * (L - 1));\n    prefix_len = min(prefix_len, L - 1);\n    prefix_len = max(prefix_len, 1);\n    return prefix_len;\n}\n\nstruct DFSSearcher {\n    vector<int> &seen;\n    int mark;\n    XorShift &rng;\n    Timer &timer;\n    double time_limit;\n    Params par;\n\n    vector<int> cur_cells;\n    string cur_moves;\n\n    int nodes = 0;\n    int node_limit = 50000;\n\n    DFSSearcher(\n        vector<int> &seen_,\n        int mark_,\n        XorShift &rng_,\n        Timer &timer_,\n        double time_limit_\n    )\n        : seen(seen_),\n          mark(mark_),\n          rng(rng_),\n          timer(timer_),\n          time_limit(time_limit_) {\n        par = make_params(rng);\n        par.noise *= 0.45;\n        par.randomMoveProb = 0.0;\n    }\n\n    bool time_or_budget_over() {\n        if ((nodes & 2047) == 0) {\n            if (timer.elapsed() > time_limit) return true;\n        }\n        return nodes >= node_limit;\n    }\n\n    bool dfs(int pos, int score) {\n        nodes++;\n\n        if (score > best_path.score) {\n            best_path.score = score;\n            best_path.cells = cur_cells;\n            best_path.moves = cur_moves;\n        }\n\n        if (time_or_budget_over()) return true;\n\n        struct Cand {\n            int to;\n            char dir;\n            double e;\n        };\n\n        Cand cand[4];\n        int cnt = 0;\n\n        for (int k = 0; k < 4; k++) {\n            int to = nb[pos][k];\n            if (to < 0) continue;\n\n            int tid = tile_id[to];\n            if (seen[tid] == mark) continue;\n\n            cand[cnt++] = {to, nb_dir[pos][k], eval_move(to, seen, mark, par, rng)};\n        }\n\n        if (cnt == 0) return false;\n\n        sort(cand, cand + cnt, [](const Cand &a, const Cand &b) {\n            return a.e > b.e;\n        });\n\n        if (cnt >= 2 && rng.nextInt(100) < 18) {\n            swap(cand[0], cand[rng.nextInt(cnt)]);\n        }\n\n        for (int i = 0; i < cnt; i++) {\n            int to = cand[i].to;\n            int tid = tile_id[to];\n\n            seen[tid] = mark;\n            cur_cells.push_back(to);\n            cur_moves.push_back(cand[i].dir);\n\n            bool stop = dfs(to, score + point_val[to]);\n\n            cur_moves.pop_back();\n            cur_cells.pop_back();\n            seen[tid] = 0;\n\n            if (stop) return true;\n        }\n\n        return false;\n    }\n\n    void run_from_prefix(const Path *base, int prefix_len) {\n        cur_cells.clear();\n        cur_moves.clear();\n        cur_cells.reserve(V);\n        cur_moves.reserve(V);\n\n        int score = 0;\n\n        if (base == nullptr) {\n            int st = si * N + sj;\n            cur_cells.push_back(st);\n            score = point_val[st];\n            seen[tile_id[st]] = mark;\n        } else {\n            prefix_len = max(prefix_len, 1);\n            prefix_len = min(prefix_len, (int)base->cells.size());\n\n            cur_cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n            cur_moves.assign(base->moves.begin(), base->moves.begin() + prefix_len - 1);\n\n            for (int c : cur_cells) {\n                score += point_val[c];\n                seen[tile_id[c]] = mark;\n            }\n        }\n\n        if (score > best_path.score) {\n            best_path.score = score;\n            best_path.cells = cur_cells;\n            best_path.moves = cur_moves;\n        }\n\n        dfs(cur_cells.back(), score);\n    }\n};\n\nchar dir_between(int a, int b) {\n    int ai = a / N, aj = a % N;\n    int bi = b / N, bj = b % N;\n    if (bi == ai - 1 && bj == aj) return 'U';\n    if (bi == ai + 1 && bj == aj) return 'D';\n    if (bi == ai && bj == aj - 1) return 'L';\n    return 'R';\n}\n\nvoid rebuild_moves(Path &p) {\n    p.moves.clear();\n    p.moves.reserve(p.cells.size());\n    for (int i = 0; i + 1 < (int)p.cells.size(); i++) {\n        p.moves.push_back(dir_between(p.cells[i], p.cells[i + 1]));\n    }\n}\n\nbool find_best_detour_for_edge(\n    int start,\n    int target,\n    vector<unsigned char> &used_tile,\n    int max_intermediate,\n    Timer &timer,\n    double limit,\n    vector<int> &best_nodes,\n    int &best_score\n) {\n    vector<int> cur_nodes;\n    cur_nodes.reserve(max_intermediate);\n\n    bool stopped_by_time = false;\n\n    function<void(int, int, int)> dfs = [&](int pos, int depth, int score) {\n        if (stopped_by_time) return;\n        if (timer.elapsed() > limit) {\n            stopped_by_time = true;\n            return;\n        }\n\n        for (int k = 0; k < 4; k++) {\n            int to = nb[pos][k];\n            if (to < 0) continue;\n\n            if (to == target) {\n                if (depth >= 1 && score > best_score) {\n                    best_score = score;\n                    best_nodes = cur_nodes;\n                }\n                continue;\n            }\n\n            if (depth >= max_intermediate) continue;\n\n            int tid = tile_id[to];\n            if (used_tile[tid]) continue;\n\n            used_tile[tid] = 1;\n            cur_nodes.push_back(to);\n\n            dfs(to, depth + 1, score + point_val[to]);\n\n            cur_nodes.pop_back();\n            used_tile[tid] = 0;\n        }\n    };\n\n    dfs(start, 0, 0);\n    return best_score > 0;\n}\n\nvoid improve_by_detour_insertion(Path &p, int max_tid, Timer &timer, double limit) {\n    vector<unsigned char> used_tile(max_tid + 1, 0);\n\n    for (int c : p.cells) {\n        used_tile[tile_id[c]] = 1;\n    }\n\n    const int MAX_INTERMEDIATE = 5;\n\n    while (timer.elapsed() < limit) {\n        int best_edge = -1;\n        int best_add_score = 0;\n        vector<int> best_insert_nodes;\n\n        int L = (int)p.cells.size();\n\n        for (int i = 0; i + 1 < L; i++) {\n            if ((i & 31) == 0 && timer.elapsed() > limit) break;\n\n            vector<int> cand_nodes;\n            int cand_score = 0;\n\n            find_best_detour_for_edge(\n                p.cells[i],\n                p.cells[i + 1],\n                used_tile,\n                MAX_INTERMEDIATE,\n                timer,\n                limit,\n                cand_nodes,\n                cand_score\n            );\n\n            if (cand_score > best_add_score) {\n                best_add_score = cand_score;\n                best_edge = i;\n                best_insert_nodes = std::move(cand_nodes);\n            }\n        }\n\n        if (best_edge < 0 || best_insert_nodes.empty()) break;\n\n        p.cells.insert(\n            p.cells.begin() + best_edge + 1,\n            best_insert_nodes.begin(),\n            best_insert_nodes.end()\n        );\n\n        for (int c : best_insert_nodes) {\n            used_tile[tile_id[c]] = 1;\n            p.score += point_val[c];\n        }\n    }\n\n    rebuild_moves(p);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tid = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            int id = i * N + j;\n            tile_id[id] = x;\n            max_tid = max(max_tid, x);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> point_val[i * N + j];\n        }\n    }\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    for (int i = 0; i < V; i++) {\n        for (int k = 0; k < 4; k++) {\n            nb[i][k] = -1;\n            nb_dir[i][k] = '?';\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            for (int k = 0; k < 4; k++) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    nb[id][k] = ni * N + nj;\n                    nb_dir[id][k] = dc[k];\n                }\n            }\n        }\n    }\n\n    uint64_t seed = 123456789;\n    seed ^= (uint64_t)(si * 51 + sj + 1) * 1000003ULL;\n\n    for (int i = 0; i < V; i++) {\n        seed ^= (uint64_t)(tile_id[i] + 1) * 11995408973635179863ULL;\n        seed ^= (uint64_t)(point_val[i] + 7) * 10150724397891781847ULL;\n        seed = seed * 6364136223846793005ULL + 1442695040888963407ULL;\n    }\n\n    XorShift rng(seed);\n    Timer timer;\n\n    vector<int> seen(max_tid + 1, 0);\n    int mark = 1;\n\n    {\n        int st = si * N + sj;\n        best_path.score = point_val[st];\n        best_path.cells = {st};\n        best_path.moves = \"\";\n    }\n\n    const double SEARCH_LIMIT = 1.92;\n    const double GREEDY_PHASE = 0.62;\n    const double FINAL_LIMIT = 1.965;\n\n    // Phase 1: randomized greedy rollouts.\n    while (timer.elapsed() < GREEDY_PHASE) {\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        Path cur;\n\n        bool fresh = pool.empty() || rng.nextInt(100) < 24;\n\n        if (fresh) {\n            cur = build_greedy_from_prefix(nullptr, 0, seen, mark, rng);\n        } else {\n            const Path *base;\n\n            if (rng.nextInt(100) < 68) {\n                base = &best_path;\n            } else {\n                base = &pool[rng.nextInt((int)pool.size())];\n            }\n\n            int prefix_len = select_prefix_len(*base, rng);\n            cur = build_greedy_from_prefix(base, prefix_len, seen, mark, rng);\n        }\n\n        consider_path(cur);\n    }\n\n    // Phase 2: DFS/local tail search from promising prefixes.\n    while (timer.elapsed() < SEARCH_LIMIT) {\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        const Path *base = nullptr;\n        int prefix_len = 1;\n\n        int mode = rng.nextInt(100);\n\n        if (mode < 15 || pool.empty()) {\n            base = nullptr;\n            prefix_len = 1;\n        } else if (mode < 78) {\n            base = &best_path;\n            prefix_len = select_prefix_len(*base, rng);\n        } else {\n            base = &pool[rng.nextInt((int)pool.size())];\n            prefix_len = select_prefix_len(*base, rng);\n        }\n\n        DFSSearcher dfs(seen, mark, rng, timer, SEARCH_LIMIT);\n\n        int L = (base == nullptr ? 1 : (int)base->cells.size());\n\n        if (base != nullptr && prefix_len > L * 3 / 4) {\n            dfs.node_limit = 35000 + rng.nextInt(50000);\n        } else {\n            dfs.node_limit = 18000 + rng.nextInt(45000);\n        }\n\n        dfs.run_from_prefix(base, prefix_len);\n\n        if (rng.nextInt(100) < 25) {\n            consider_path(best_path);\n        }\n    }\n\n    // Final safe improvement: insert short unused-tile detours into the best path.\n    improve_by_detour_insertion(best_path, max_tid, timer, FINAL_LIMIT);\n\n    cout << best_path.moves << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HEDGE = 30 * 29;\nstatic constexpr int VEDGE = 29 * 30;\nstatic constexpr int E = HEDGE + VEDGE;\nstatic constexpr int RCVAR = 60;\nstatic constexpr int SEGVAR = 120;\n\nstruct Obs {\n    array<int, RCVAR> x;\n    vector<int> edges;\n    long long y;\n};\n\nvector<Obs> observations;\n\ndouble hcost[N], vcost[N];\ndouble edge_est[E];\nint edge_freq[E];\n\nint splitH[N], splitV[N];\ndouble segH[N][2], segV[N][2];\n\nbool edge_ready = false;\nbool seg_ready = false;\n\nuint64_t rng_state = 88172645463325252ull;\n\nuint64_t xorshift() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\ndouble clamp_double(double x, double lo, double hi) {\n    return max(lo, min(hi, x));\n}\n\ndouble observation_weight(int len, long long y) {\n    if (len <= 0) return 0.0;\n\n    double w_len = 400.0 / ((double)len * len);\n\n    double w_y = w_len;\n    if (y > 0) {\n        w_y = 10000000000.0 / ((double)y * (double)y);\n    }\n\n    double w = 0.35 * w_len + 0.65 * w_y;\n    return clamp_double(w, 0.04, 6.0);\n}\n\nint hid(int i, int j) {\n    return i * 29 + j;\n}\n\nint vid(int i, int j) {\n    return HEDGE + i * 30 + j;\n}\n\ndouble base_weight(int id) {\n    if (id < HEDGE) {\n        return hcost[id / 29];\n    } else {\n        int x = id - HEDGE;\n        return vcost[x % 30];\n    }\n}\n\ndouble segment_weight(int id) {\n    if (!seg_ready) return base_weight(id);\n\n    if (id < HEDGE) {\n        int i = id / 29;\n        int j = id % 29;\n        int p = (j < splitH[i] ? 0 : 1);\n        return segH[i][p];\n    } else {\n        int x = id - HEDGE;\n        int i = x / 30;\n        int j = x % 30;\n        int p = (i < splitV[j] ? 0 : 1);\n        return segV[j][p];\n    }\n}\n\ndouble structural_weight(int id) {\n    return segment_weight(id);\n}\n\nvoid solve_row_col_model() {\n    static double a[RCVAR][RCVAR + 1];\n\n    for (int i = 0; i < RCVAR; i++) {\n        for (int j = 0; j <= RCVAR; j++) {\n            a[i][j] = 0.0;\n        }\n    }\n\n    const double lambda = 80.0;\n\n    for (int i = 0; i < RCVAR; i++) {\n        a[i][i] += lambda;\n    }\n\n    for (const auto& ob : observations) {\n        vector<pair<int, int>> nz;\n        int len = 0;\n\n        for (int i = 0; i < RCVAR; i++) {\n            if (ob.x[i]) {\n                nz.push_back({i, ob.x[i]});\n                len += ob.x[i];\n            }\n        }\n\n        if (len == 0) continue;\n\n        double w = observation_weight(len, ob.y);\n        double r = (double)ob.y - 5000.0 * len;\n\n        for (auto [i, xi] : nz) {\n            a[i][RCVAR] += w * xi * r;\n            for (auto [j, xj] : nz) {\n                a[i][j] += w * (double)xi * xj;\n            }\n        }\n    }\n\n    for (int col = 0; col < RCVAR; col++) {\n        int piv = col;\n\n        for (int row = col + 1; row < RCVAR; row++) {\n            if (fabs(a[row][col]) > fabs(a[piv][col])) {\n                piv = row;\n            }\n        }\n\n        if (piv != col) {\n            for (int j = col; j <= RCVAR; j++) {\n                swap(a[piv][j], a[col][j]);\n            }\n        }\n\n        double div = a[col][col];\n        if (fabs(div) < 1e-12) continue;\n\n        for (int j = col; j <= RCVAR; j++) {\n            a[col][j] /= div;\n        }\n\n        for (int row = 0; row < RCVAR; row++) {\n            if (row == col) continue;\n\n            double factor = a[row][col];\n            if (fabs(factor) < 1e-12) continue;\n\n            for (int j = col; j <= RCVAR; j++) {\n                a[row][j] -= factor * a[col][j];\n            }\n        }\n    }\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = clamp_double(5000.0 + a[i][RCVAR], 1000.0, 9000.0);\n    }\n\n    for (int j = 0; j < 30; j++) {\n        vcost[j] = clamp_double(5000.0 + a[30 + j][RCVAR], 1000.0, 9000.0);\n    }\n}\n\nvoid smooth_edge_est(double strength) {\n    static double nxt[E];\n\n    for (int id = 0; id < E; id++) {\n        nxt[id] = edge_est[id];\n    }\n\n    for (int i = 0; i < 30; i++) {\n        for (int j = 0; j < 29; j++) {\n            int id = hid(i, j);\n\n            double sum = edge_est[id] * 2.0;\n            double den = 2.0;\n\n            if (j > 0) {\n                int nid = hid(i, j - 1);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            if (j + 1 < 29) {\n                int nid = hid(i, j + 1);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            nxt[id] = edge_est[id] * (1.0 - strength) + (sum / den) * strength;\n        }\n    }\n\n    for (int i = 0; i < 29; i++) {\n        for (int j = 0; j < 30; j++) {\n            int id = vid(i, j);\n\n            double sum = edge_est[id] * 2.0;\n            double den = 2.0;\n\n            if (i > 0) {\n                int nid = vid(i - 1, j);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            if (i + 1 < 29) {\n                int nid = vid(i + 1, j);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            nxt[id] = edge_est[id] * (1.0 - strength) + (sum / den) * strength;\n        }\n    }\n\n    for (int id = 0; id < E; id++) {\n        edge_est[id] = clamp_double(nxt[id], 800.0, 9500.0);\n    }\n}\n\nvoid rebuild_edge_model(int turn) {\n    static double prior[E];\n    static double b[E], x[E], r[E], p[E], Ap[E];\n\n    for (int id = 0; id < E; id++) {\n        prior[id] = structural_weight(id);\n        b[id] = 0.0;\n        x[id] = 0.0;\n    }\n\n    vector<double> ws;\n    ws.reserve(observations.size());\n\n    for (const auto& ob : observations) {\n        int len = (int)ob.edges.size();\n\n        if (len == 0) {\n            ws.push_back(0.0);\n            continue;\n        }\n\n        double pred = 0.0;\n        for (int id : ob.edges) {\n            pred += prior[id];\n        }\n\n        double rr = (double)ob.y - pred;\n        double clip = max(4500.0, 0.16 * pred);\n        rr = clamp_double(rr, -clip, clip);\n\n        double w = observation_weight(len, ob.y);\n\n        ws.push_back(w);\n\n        for (int id : ob.edges) {\n            b[id] += w * rr;\n        }\n    }\n\n    double lambda;\n    if (turn < 250) lambda = 8.0;\n    else if (turn < 700) lambda = 6.0;\n    else lambda = 5.0;\n\n    auto matvec = [&](const double in[E], double out[E]) {\n        for (int id = 0; id < E; id++) {\n            out[id] = lambda * in[id];\n        }\n\n        int m = (int)observations.size();\n\n        for (int oi = 0; oi < m; oi++) {\n            const auto& ob = observations[oi];\n            if (ws[oi] == 0.0) continue;\n\n            double s = 0.0;\n            for (int id : ob.edges) {\n                s += in[id];\n            }\n\n            double c = ws[oi] * s;\n\n            for (int id : ob.edges) {\n                out[id] += c;\n            }\n        }\n    };\n\n    for (int id = 0; id < E; id++) {\n        r[id] = b[id];\n        p[id] = r[id];\n    }\n\n    double rsold = 0.0;\n    for (int id = 0; id < E; id++) {\n        rsold += r[id] * r[id];\n    }\n\n    int iters;\n    if (turn < 250) iters = 22;\n    else if (turn < 700) iters = 28;\n    else iters = 34;\n\n    for (int it = 0; it < iters; it++) {\n        if (rsold < 1e-7) break;\n\n        matvec(p, Ap);\n\n        double denom = 0.0;\n        for (int id = 0; id < E; id++) {\n            denom += p[id] * Ap[id];\n        }\n\n        if (fabs(denom) < 1e-12) break;\n\n        double alpha = rsold / denom;\n\n        for (int id = 0; id < E; id++) {\n            x[id] += alpha * p[id];\n            r[id] -= alpha * Ap[id];\n        }\n\n        double rsnew = 0.0;\n        for (int id = 0; id < E; id++) {\n            rsnew += r[id] * r[id];\n        }\n\n        if (rsnew < 1e-7) break;\n\n        double beta = rsnew / rsold;\n\n        for (int id = 0; id < E; id++) {\n            p[id] = r[id] + beta * p[id];\n        }\n\n        rsold = rsnew;\n    }\n\n    for (int id = 0; id < E; id++) {\n        double conf = (double)edge_freq[id] / (double)(edge_freq[id] + 7);\n        double z = x[id] * conf;\n        edge_est[id] = clamp_double(prior[id] + z, 800.0, 9500.0);\n    }\n\n    smooth_edge_est(turn < 300 ? 0.035 : 0.020);\n\n    edge_ready = true;\n}\n\nvoid update_splits_from_edge() {\n    for (int i = 0; i < 30; i++) {\n        double best = 1e100;\n        int bestx = 14;\n\n        for (int x = 1; x <= 28; x++) {\n            double sl = 0.0, wl = 0.0;\n            double sr = 0.0, wr = 0.0;\n\n            for (int j = 0; j < 29; j++) {\n                int id = hid(i, j);\n                double w = 0.4 + edge_freq[id];\n\n                if (j < x) {\n                    sl += edge_est[id] * w;\n                    wl += w;\n                } else {\n                    sr += edge_est[id] * w;\n                    wr += w;\n                }\n            }\n\n            double ml = sl / max(1e-9, wl);\n            double mr = sr / max(1e-9, wr);\n\n            double sse = 0.0;\n\n            for (int j = 0; j < 29; j++) {\n                int id = hid(i, j);\n                double w = 0.4 + edge_freq[id];\n                double m = (j < x ? ml : mr);\n                double d = edge_est[id] - m;\n                sse += w * d * d;\n            }\n\n            if (sse < best) {\n                best = sse;\n                bestx = x;\n            }\n        }\n\n        splitH[i] = bestx;\n    }\n\n    for (int j = 0; j < 30; j++) {\n        double best = 1e100;\n        int besty = 14;\n\n        for (int y = 1; y <= 28; y++) {\n            double su = 0.0, wu = 0.0;\n            double sd = 0.0, wd = 0.0;\n\n            for (int i = 0; i < 29; i++) {\n                int id = vid(i, j);\n                double w = 0.4 + edge_freq[id];\n\n                if (i < y) {\n                    su += edge_est[id] * w;\n                    wu += w;\n                } else {\n                    sd += edge_est[id] * w;\n                    wd += w;\n                }\n            }\n\n            double mu = su / max(1e-9, wu);\n            double md = sd / max(1e-9, wd);\n\n            double sse = 0.0;\n\n            for (int i = 0; i < 29; i++) {\n                int id = vid(i, j);\n                double w = 0.4 + edge_freq[id];\n                double m = (i < y ? mu : md);\n                double d = edge_est[id] - m;\n                sse += w * d * d;\n            }\n\n            if (sse < best) {\n                best = sse;\n                besty = y;\n            }\n        }\n\n        splitV[j] = besty;\n    }\n}\n\nint seg_index_from_edge(int id) {\n    if (id < HEDGE) {\n        int i = id / 29;\n        int j = id % 29;\n        int p = (j < splitH[i] ? 0 : 1);\n        return i * 2 + p;\n    } else {\n        int x = id - HEDGE;\n        int i = x / 30;\n        int j = x % 30;\n        int p = (i < splitV[j] ? 0 : 1);\n        return 60 + j * 2 + p;\n    }\n}\n\nvoid solve_segment_model(int turn) {\n    static double a[SEGVAR][SEGVAR + 1];\n\n    for (int i = 0; i < SEGVAR; i++) {\n        for (int j = 0; j <= SEGVAR; j++) {\n            a[i][j] = 0.0;\n        }\n    }\n\n    double lambda = (turn < 300 ? 65.0 : 45.0);\n    double tie = (turn < 300 ? 25.0 : 16.0);\n\n    for (int i = 0; i < 30; i++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = i * 2 + p;\n            double prior = hcost[i] - 5000.0;\n            a[idx][idx] += lambda;\n            a[idx][SEGVAR] += lambda * prior;\n        }\n\n        int a0 = i * 2;\n        int a1 = i * 2 + 1;\n        a[a0][a0] += tie;\n        a[a1][a1] += tie;\n        a[a0][a1] -= tie;\n        a[a1][a0] -= tie;\n    }\n\n    for (int j = 0; j < 30; j++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = 60 + j * 2 + p;\n            double prior = vcost[j] - 5000.0;\n            a[idx][idx] += lambda;\n            a[idx][SEGVAR] += lambda * prior;\n        }\n\n        int a0 = 60 + j * 2;\n        int a1 = 60 + j * 2 + 1;\n        a[a0][a0] += tie;\n        a[a1][a1] += tie;\n        a[a0][a1] -= tie;\n        a[a1][a0] -= tie;\n    }\n\n    static int cnt[SEGVAR];\n\n    for (const auto& ob : observations) {\n        fill(cnt, cnt + SEGVAR, 0);\n\n        int len = (int)ob.edges.size();\n        if (len == 0) continue;\n\n        for (int id : ob.edges) {\n            cnt[seg_index_from_edge(id)]++;\n        }\n\n        vector<pair<int, int>> nz;\n\n        for (int i = 0; i < SEGVAR; i++) {\n            if (cnt[i]) {\n                nz.push_back({i, cnt[i]});\n            }\n        }\n\n        double w = observation_weight(len, ob.y);\n        double r = (double)ob.y - 5000.0 * len;\n\n        for (auto [i, xi] : nz) {\n            a[i][SEGVAR] += w * xi * r;\n            for (auto [j, xj] : nz) {\n                a[i][j] += w * (double)xi * xj;\n            }\n        }\n    }\n\n    for (int col = 0; col < SEGVAR; col++) {\n        int piv = col;\n\n        for (int row = col + 1; row < SEGVAR; row++) {\n            if (fabs(a[row][col]) > fabs(a[piv][col])) {\n                piv = row;\n            }\n        }\n\n        if (piv != col) {\n            for (int j = col; j <= SEGVAR; j++) {\n                swap(a[piv][j], a[col][j]);\n            }\n        }\n\n        double div = a[col][col];\n        if (fabs(div) < 1e-12) continue;\n\n        for (int j = col; j <= SEGVAR; j++) {\n            a[col][j] /= div;\n        }\n\n        for (int row = 0; row < SEGVAR; row++) {\n            if (row == col) continue;\n\n            double factor = a[row][col];\n            if (fabs(factor) < 1e-12) continue;\n\n            for (int j = col; j <= SEGVAR; j++) {\n                a[row][j] -= factor * a[col][j];\n            }\n        }\n    }\n\n    for (int i = 0; i < 30; i++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = i * 2 + p;\n            segH[i][p] = clamp_double(5000.0 + a[idx][SEGVAR], 900.0, 9500.0);\n        }\n    }\n\n    for (int j = 0; j < 30; j++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = 60 + j * 2 + p;\n            segV[j][p] = clamp_double(5000.0 + a[idx][SEGVAR], 900.0, 9500.0);\n        }\n    }\n\n    seg_ready = true;\n}\n\nvoid online_edge_update(long long y, const vector<int>& edges) {\n    if (!edge_ready || edges.empty()) return;\n\n    double pred = 0.0;\n\n    for (int id : edges) {\n        pred += edge_est[id];\n    }\n\n    double err = (double)y - pred;\n    double clip = max(4000.0, 0.12 * pred);\n    err = clamp_double(err, -clip, clip);\n\n    double delta = 0.006 * err / (double)edges.size();\n\n    for (int id : edges) {\n        edge_est[id] += delta;\n        edge_est[id] = clamp_double(edge_est[id], 800.0, 9500.0);\n    }\n}\n\ndouble learned_weight_raw(int id, int turn) {\n    double b = base_weight(id);\n    double s = segment_weight(id);\n\n    double seg_mix = ((double)turn - 80.0) / 420.0;\n    seg_mix = clamp_double(seg_mix, 0.0, 0.84);\n\n    double w = b * (1.0 - seg_mix) + s * seg_mix;\n\n    if (edge_ready) {\n        double edge_mix = ((double)turn - 260.0) / 760.0;\n        edge_mix = clamp_double(edge_mix, 0.0, 0.24);\n        w = w * (1.0 - edge_mix) + edge_est[id] * edge_mix;\n    }\n\n    return clamp_double(w, 800.0, 9500.0);\n}\n\ndouble model_weight_for_search(int id, int turn) {\n    double learned = learned_weight_raw(id, turn);\n\n    double rel = ((double)turn - 25.0) / 520.0;\n    rel = clamp_double(rel, 0.0, 1.0);\n\n    double w = 5000.0 * (1.0 - rel) + learned * rel;\n    return clamp_double(w, 800.0, 9500.0);\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool horizontal_first) {\n    string res;\n\n    auto add_vertical = [&]() {\n        if (si < ti) {\n            while (si < ti) {\n                res.push_back('D');\n                si++;\n            }\n        } else {\n            while (si > ti) {\n                res.push_back('U');\n                si--;\n            }\n        }\n    };\n\n    auto add_horizontal = [&]() {\n        if (sj < tj) {\n            while (sj < tj) {\n                res.push_back('R');\n                sj++;\n            }\n        } else {\n            while (sj > tj) {\n                res.push_back('L');\n                sj--;\n            }\n        }\n    };\n\n    if (horizontal_first) {\n        add_horizontal();\n        add_vertical();\n    } else {\n        add_vertical();\n        add_horizontal();\n    }\n\n    return res;\n}\n\nvoid extract_features(\n    int si,\n    int sj,\n    const string& path,\n    array<int, RCVAR>& feat,\n    vector<int>& edges\n) {\n    feat.fill(0);\n    edges.clear();\n\n    int i = si;\n    int j = sj;\n\n    for (char c : path) {\n        if (c == 'R') {\n            int id = hid(i, j);\n            edges.push_back(id);\n            feat[i]++;\n            j++;\n        } else if (c == 'L') {\n            int id = hid(i, j - 1);\n            edges.push_back(id);\n            feat[i]++;\n            j--;\n        } else if (c == 'D') {\n            int id = vid(i, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i++;\n        } else {\n            int id = vid(i - 1, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i--;\n        }\n    }\n}\n\ndouble estimated_path_cost(int si, int sj, const string& path, int turn) {\n    int i = si;\n    int j = sj;\n    double cost = 0.0;\n\n    for (char c : path) {\n        if (c == 'R') {\n            cost += model_weight_for_search(hid(i, j), turn);\n            j++;\n        } else if (c == 'L') {\n            cost += model_weight_for_search(hid(i, j - 1), turn);\n            j--;\n        } else if (c == 'D') {\n            cost += model_weight_for_search(vid(i, j), turn);\n            i++;\n        } else {\n            cost += model_weight_for_search(vid(i - 1, j), turn);\n            i--;\n        }\n    }\n\n    return cost;\n}\n\nstring choose_early_path(int si, int sj, int ti, int tj, int turn) {\n    string p1 = manhattan_path(si, sj, ti, tj, true);\n    string p2 = manhattan_path(si, sj, ti, tj, false);\n\n    if (p1 == p2) return p1;\n\n    if (turn < 45) {\n        return (xorshift() & 1) ? p1 : p2;\n    }\n\n    double c1 = estimated_path_cost(si, sj, p1, turn);\n    double c2 = estimated_path_cost(si, sj, p2, turn);\n\n    int eps = (turn < 100 ? 18 : 7);\n\n    if ((int)(xorshift() % 100) < eps) {\n        return (c1 < c2) ? p2 : p1;\n    }\n\n    return (c1 < c2) ? p1 : p2;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    const double INF = 1e100;\n\n    vector<double> dist(900, INF);\n    vector<int> parent(900, -1);\n    vector<char> pchar(900, '?');\n\n    auto node = [](int i, int j) {\n        return i * 30 + j;\n    };\n\n    priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n\n    int s = node(si, sj);\n    int t = node(ti, tj);\n\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\n        if (d != dist[u]) continue;\n        if (u == t) break;\n\n        int i = u / 30;\n        int j = u % 30;\n\n        auto relax = [&](int ni, int nj, char c, int eid) {\n            int v = node(ni, nj);\n            double nd = d + model_weight_for_search(eid, turn);\n\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                pchar[v] = c;\n                pq.push({nd, v});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, 'U', vid(i - 1, j));\n        if (i + 1 < 30) relax(i + 1, j, 'D', vid(i, j));\n        if (j > 0) relax(i, j - 1, 'L', hid(i, j - 1));\n        if (j + 1 < 30) relax(i, j + 1, 'R', hid(i, j));\n    }\n\n    string res;\n    int cur = t;\n\n    while (cur != s) {\n        res.push_back(pchar[cur]);\n        cur = parent[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = 5000.0;\n        vcost[i] = 5000.0;\n        splitH[i] = 14;\n        splitV[i] = 14;\n\n        segH[i][0] = segH[i][1] = 5000.0;\n        segV[i][0] = segV[i][1] = 5000.0;\n    }\n\n    for (int id = 0; id < E; id++) {\n        edge_est[id] = 5000.0;\n        edge_freq[id] = 0;\n    }\n\n    for (int turn = 0; turn < 1000; turn++) {\n        int si, sj, ti, tj;\n\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0;\n        }\n\n        string path;\n\n        if (turn < 100) {\n            path = choose_early_path(si, sj, ti, tj, turn);\n        } else {\n            path = dijkstra_path(si, sj, ti, tj, turn);\n        }\n\n        array<int, RCVAR> feat;\n        vector<int> edges;\n        extract_features(si, sj, path, feat, edges);\n\n        cout << path << endl;\n        cout.flush();\n\n        long long result;\n\n        if (!(cin >> result)) {\n            return 0;\n        }\n\n        Obs ob;\n        ob.x = feat;\n        ob.edges = edges;\n        ob.y = result;\n        observations.push_back(ob);\n\n        for (int id : edges) {\n            edge_freq[id]++;\n        }\n\n        if (turn < 260 || turn % 5 == 4 || turn >= 850) {\n            solve_row_col_model();\n        }\n\n        bool trigger = false;\n\n        if (turn >= 60) {\n            if (turn < 300) {\n                trigger = (turn % 12 == 11);\n            } else if (turn < 800) {\n                trigger = (turn % 24 == 23);\n            } else {\n                trigger = (turn % 14 == 13);\n            }\n        }\n\n        if (trigger) {\n            if (turn >= 75 && edge_ready) {\n                update_splits_from_edge();\n                solve_segment_model(turn);\n            }\n\n            rebuild_edge_model(turn);\n        }\n\n        online_edge_update(result, edges);\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int C = 400;\nstatic constexpr int ALPHA = 8;\nstatic constexpr long long BIG = 2000000000LL;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstruct Precomp {\n    int M;\n    const vector<string>* ps;\n    vector<array<vector<int>, ALPHA>> inc; // inc[cell][required_char] -> pid\n\n    inline int placementCell(int sid, int idx, int p) const {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    }\n\n    void build(const vector<string>& s) {\n        ps = &s;\n        M = (int)s.size();\n\n        inc.clear();\n        inc.resize(C);\n\n        int reservePerBucket = max(16, M * 2 * 12 / 8 + 20);\n        for (int c = 0; c < C; c++) {\n            for (int ch = 0; ch < ALPHA; ch++) {\n                inc[c][ch].reserve(reservePerBucket);\n            }\n        }\n\n        for (int sid = 0; sid < M; sid++) {\n            int len = (int)s[sid].size();\n\n            for (int idx = 0; idx < 800; idx++) {\n                int pid = sid * 800 + idx;\n\n                for (int p = 0; p < len; p++) {\n                    int cell = placementCell(sid, idx, p);\n                    int req = s[sid][p] - 'A';\n                    inc[cell][req].push_back(pid);\n                }\n            }\n        }\n    }\n};\n\nstruct KmerScorer {\n    int maxQ = 2;\n    vector<vector<int>> dense;\n    vector<unordered_map<unsigned long long, int>> sparse;\n\n    int mult[13] = {\n        0, 0,\n        1, 2, 5, 12, 30, 80, 200, 500, 1200, 2500, 5000\n    };\n\n    KmerScorer() {\n        dense.resize(13);\n        sparse.resize(13);\n    }\n\n    void build(const vector<string>& s) {\n        maxQ = 2;\n\n        for (auto& t : s) {\n            maxQ = max(maxQ, min(12, (int)t.size()));\n        }\n\n        for (int q = 2; q <= min(8, maxQ); q++) {\n            dense[q].assign(1 << (3 * q), 0);\n        }\n\n        for (auto& t : s) {\n            int L = (int)t.size();\n            vector<int> a(L);\n\n            for (int i = 0; i < L; i++) {\n                a[i] = t[i] - 'A';\n            }\n\n            for (int q = 2; q <= min(12, L); q++) {\n                for (int l = 0; l + q <= L; l++) {\n                    unsigned long long code = 0;\n\n                    for (int p = 0; p < q; p++) {\n                        code = (code << 3) | a[l + p];\n                    }\n\n                    int w = mult[q];\n\n                    if (q <= 8) dense[q][(int)code] += w;\n                    else sparse[q][code] += w;\n                }\n            }\n        }\n    }\n\n    inline int getWeight(int q, unsigned long long code) const {\n        if (q <= 8) return dense[q][(int)code];\n\n        auto it = sparse[q].find(code);\n        if (it == sparse[q].end()) return 0;\n        return it->second;\n    }\n\n    unsigned long long codeWindow(\n        const vector<unsigned char>& board,\n        int i,\n        int j,\n        int dir,\n        int q,\n        int overrideCell = -1,\n        int overrideVal = 0\n    ) const {\n        unsigned long long code = 0;\n\n        for (int p = 0; p < q; p++) {\n            int ni = i;\n            int nj = j;\n\n            if (dir == 0) nj = (j + p) % N;\n            else ni = (i + p) % N;\n\n            int cell = ni * N + nj;\n            int v = (cell == overrideCell ? overrideVal : board[cell]);\n\n            if (v < 0 || v >= 8) return ULLONG_MAX;\n\n            code = (code << 3) | (unsigned)v;\n        }\n\n        return code;\n    }\n\n    long long score(const vector<unsigned char>& board) const {\n        long long res = 0;\n\n        for (int q = 2; q <= maxQ; q++) {\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    auto c1 = codeWindow(board, i, j, 0, q);\n                    if (c1 != ULLONG_MAX) res += getWeight(q, c1);\n\n                    auto c2 = codeWindow(board, i, j, 1, q);\n                    if (c2 != ULLONG_MAX) res += getWeight(q, c2);\n                }\n            }\n        }\n\n        return res;\n    }\n\n    long long delta(const vector<unsigned char>& board, int cell, int nc) const {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        int i = cell / N;\n        int j = cell % N;\n        long long d = 0;\n\n        for (int q = 2; q <= maxQ; q++) {\n            for (int off = 0; off < q; off++) {\n                int sj = (j - off + N) % N;\n\n                auto oldCode = codeWindow(board, i, sj, 0, q);\n                auto newCode = codeWindow(board, i, sj, 0, q, cell, nc);\n\n                if (oldCode != ULLONG_MAX) d -= getWeight(q, oldCode);\n                if (newCode != ULLONG_MAX) d += getWeight(q, newCode);\n\n                int si = (i - off + N) % N;\n\n                oldCode = codeWindow(board, si, j, 1, q);\n                newCode = codeWindow(board, si, j, 1, q, cell, nc);\n\n                if (oldCode != ULLONG_MAX) d -= getWeight(q, oldCode);\n                if (newCode != ULLONG_MAX) d += getWeight(q, newCode);\n            }\n        }\n\n        return d;\n    }\n};\n\nstruct Evaluator {\n    int M;\n    const vector<string>* ps;\n    const Precomp* pc;\n\n    vector<unsigned char> board;\n\n    vector<unsigned char> mis;\n    vector<array<unsigned short, 13>> hist;\n    vector<long long> val;\n\n    long long obj = 0;\n    int covered = 0;\n\n    long long nearTable[13] = {\n        0,\n        1000000,\n        300000,\n        100000,\n        30000,\n        10000,\n        3000,\n        1000,\n        300,\n        100,\n        30,\n        10,\n        0\n    };\n\n    Evaluator() {}\n\n    Evaluator(const vector<string>& s, const Precomp& pre, const vector<unsigned char>& _board) {\n        ps = &s;\n        pc = &pre;\n        M = (int)s.size();\n        board = _board;\n        build();\n    }\n\n    inline const string& str(int sid) const {\n        return (*ps)[sid];\n    }\n\n    inline int placementCell(int sid, int idx, int p) const {\n        return pc->placementCell(sid, idx, p);\n    }\n\n    inline long long calcVal(int sid) const {\n        if (hist[sid][0] > 0) {\n            return BIG + min<int>(hist[sid][0], 1000);\n        }\n\n        for (int d = 1; d <= 12; d++) {\n            if (hist[sid][d] > 0) {\n                return nearTable[d] + min<int>(hist[sid][d], 1000);\n            }\n        }\n\n        return 0;\n    }\n\n    void build() {\n        int P = M * 800;\n\n        mis.assign(P, 0);\n        hist.assign(M, {});\n        val.assign(M, 0);\n\n        for (int sid = 0; sid < M; sid++) {\n            int len = (int)str(sid).size();\n\n            for (int idx = 0; idx < 800; idx++) {\n                int pid = sid * 800 + idx;\n                int mm = 0;\n\n                for (int p = 0; p < len; p++) {\n                    int cell = placementCell(sid, idx, p);\n                    int req = str(sid)[p] - 'A';\n\n                    if (board[cell] != req) mm++;\n                }\n\n                mis[pid] = (unsigned char)mm;\n                hist[sid][mm]++;\n            }\n        }\n\n        obj = 0;\n        covered = 0;\n\n        for (int sid = 0; sid < M; sid++) {\n            val[sid] = calcVal(sid);\n            obj += val[sid];\n\n            if (hist[sid][0] > 0) covered++;\n        }\n    }\n\n    inline void processPlacementChange(int pid, int deltaMis, long long& deltaObj) {\n        int sid = pid / 800;\n\n        long long oldVal = val[sid];\n        bool oldCov = hist[sid][0] > 0;\n\n        int oldMis = mis[pid];\n        hist[sid][oldMis]--;\n\n        int nm = oldMis + deltaMis;\n\n        mis[pid] = (unsigned char)nm;\n        hist[sid][nm]++;\n\n        bool newCov = hist[sid][0] > 0;\n\n        if (oldCov && !newCov) covered--;\n        if (!oldCov && newCov) covered++;\n\n        long long newVal = calcVal(sid);\n        val[sid] = newVal;\n        deltaObj += newVal - oldVal;\n    }\n\n    long long applyChange(int cell, int nc) {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        long long deltaObj = 0;\n\n        if (0 <= oc && oc < ALPHA) {\n            for (int pid : pc->inc[cell][oc]) {\n                processPlacementChange(pid, +1, deltaObj);\n            }\n        }\n\n        if (0 <= nc && nc < ALPHA) {\n            for (int pid : pc->inc[cell][nc]) {\n                processPlacementChange(pid, -1, deltaObj);\n            }\n        }\n\n        board[cell] = (unsigned char)nc;\n        obj += deltaObj;\n\n        return deltaObj;\n    }\n\n    int minMismatchOfString(int sid) const {\n        for (int d = 0; d <= 12; d++) {\n            if (hist[sid][d] > 0) return d;\n        }\n\n        return 13;\n    }\n\n    int bestPlacementIndex(int sid, XorShift& rng) const {\n        int best = 100;\n        int cnt = 0;\n        int bestIdx = 0;\n        int base = sid * 800;\n\n        for (int idx = 0; idx < 800; idx++) {\n            int mm = mis[base + idx];\n\n            if (mm < best) {\n                best = mm;\n                cnt = 1;\n                bestIdx = idx;\n            } else if (mm == best) {\n                cnt++;\n                if (rng.nextInt(cnt) == 0) bestIdx = idx;\n            }\n        }\n\n        return bestIdx;\n    }\n};\n\nstruct BestState {\n    int covered = -1;\n    long long obj = LLONG_MIN;\n    vector<unsigned char> board;\n\n    void update(const Evaluator& ev) {\n        if (ev.covered > covered || (ev.covered == covered && ev.obj > obj)) {\n            covered = ev.covered;\n            obj = ev.obj;\n            board = ev.board;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    int inputN, M;\n    cin >> inputN >> M;\n\n    vector<string> s(M);\n    for (int i = 0; i < M; i++) cin >> s[i];\n\n    XorShift rng(123456789);\n\n    auto elapsedSec = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    Precomp pre;\n    pre.build(s);\n\n    KmerScorer ksc;\n    ksc.build(s);\n\n    vector<int> freq(ALPHA, 1);\n\n    for (auto& t : s) {\n        for (char ch : t) {\n            freq[ch - 'A']++;\n        }\n    }\n\n    vector<int> pref(ALPHA);\n    pref[0] = freq[0];\n\n    for (int i = 1; i < ALPHA; i++) {\n        pref[i] = pref[i - 1] + freq[i];\n    }\n\n    int fsum = pref.back();\n\n    auto randomChar = [&]() {\n        int r = rng.nextInt(fsum);\n        return (unsigned char)(lower_bound(pref.begin(), pref.end(), r + 1) - pref.begin());\n    };\n\n    auto placementCellRaw = [&](int idx, int p) {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    };\n\n    auto conflictOfPlacement = [&](const vector<unsigned char>& b, const string& t, int idx) {\n        int conf = 0;\n        int len = (int)t.size();\n\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            int req = t[p] - 'A';\n\n            if (b[cell] != req) conf++;\n        }\n\n        return conf;\n    };\n\n    auto stampRaw = [&](vector<unsigned char>& b, const string& t, int idx) {\n        int len = (int)t.size();\n\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            b[cell] = (unsigned char)(t[p] - 'A');\n        }\n    };\n\n    vector<unsigned char> boardStamp(C);\n\n    for (int i = 0; i < C; i++) {\n        boardStamp[i] = randomChar();\n    }\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n\n    for (int pass = 0; pass < 6; pass++) {\n        if (pass == 5) {\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return s[a].size() < s[b].size();\n            });\n        } else {\n            shuffle(order.begin(), order.end(), mt19937((unsigned)rng.next()));\n        }\n\n        for (int sid : order) {\n            int bestConf = 100;\n            int bestIdx = 0;\n            int cnt = 0;\n\n            for (int idx = 0; idx < 800; idx++) {\n                int conf = conflictOfPlacement(boardStamp, s[sid], idx);\n\n                if (conf < bestConf) {\n                    bestConf = conf;\n                    bestIdx = idx;\n                    cnt = 1;\n                } else if (conf == bestConf) {\n                    cnt++;\n\n                    if (rng.nextInt(cnt) == 0) {\n                        bestIdx = idx;\n                    }\n                }\n            }\n\n            stampRaw(boardStamp, s[sid], bestIdx);\n        }\n    }\n\n    BestState best;\n\n    auto doSearch = [&](Evaluator& ev, bool useKmer, double endTime) {\n        long long curK = 0;\n        if (useKmer) curK = ksc.score(ev.board);\n\n        vector<pair<int, int>> changed;\n        int iter = 0;\n\n        best.update(ev);\n\n        while (true) {\n            if ((iter & 7) == 0 && elapsedSec() > endTime) break;\n\n            double progress = min(1.0, elapsedSec() / endTime);\n\n            double temp = useKmer\n                ? (1500000.0 * (1.0 - progress) + 20000.0 * progress)\n                : (200000.0 * (1.0 - progress) + 2000.0 * progress);\n\n            long long kScale = 0;\n            if (useKmer) kScale = (ev.covered < M ? 220 : 30);\n\n            if (ev.covered < M && iter % 5 == 0) {\n                int bestSid = -1;\n                int bestMM = 100;\n                int cnt = 0;\n\n                for (int sid = 0; sid < M; sid++) {\n                    if (ev.hist[sid][0] == 0) {\n                        int mm = ev.minMismatchOfString(sid);\n\n                        if (mm < bestMM) {\n                            bestMM = mm;\n                            bestSid = sid;\n                            cnt = 1;\n                        } else if (mm == bestMM) {\n                            cnt++;\n                            if (rng.nextInt(cnt) == 0) bestSid = sid;\n                        }\n                    }\n                }\n\n                if (bestSid != -1) {\n                    int idx = ev.bestPlacementIndex(bestSid, rng);\n\n                    changed.clear();\n\n                    long long oldObj = ev.obj;\n                    long long oldK = curK;\n\n                    int len = (int)s[bestSid].size();\n\n                    for (int p = 0; p < len; p++) {\n                        int cell = ev.placementCell(bestSid, idx, p);\n                        int req = s[bestSid][p] - 'A';\n\n                        if (ev.board[cell] != req) {\n                            int old = ev.board[cell];\n                            changed.push_back({cell, old});\n\n                            if (useKmer) {\n                                curK += ksc.delta(ev.board, cell, req);\n                            }\n\n                            ev.applyChange(cell, req);\n                        }\n                    }\n\n                    long long exactD = ev.obj - oldObj;\n                    long long kD = curK - oldK;\n                    long long combD = exactD + kScale * kD;\n\n                    bool accept = false;\n\n                    if (combD >= 0) {\n                        accept = true;\n                    } else if (exactD > -BIG / 2) {\n                        if (rng.nextDouble() < exp((double)combD / temp)) {\n                            accept = true;\n                        }\n                    }\n\n                    if (!accept) {\n                        for (int i = (int)changed.size() - 1; i >= 0; i--) {\n                            int cell = changed[i].first;\n                            int old = changed[i].second;\n\n                            if (useKmer) {\n                                curK += ksc.delta(ev.board, cell, old);\n                            }\n\n                            ev.applyChange(cell, old);\n                        }\n                    } else {\n                        best.update(ev);\n                    }\n                }\n            } else {\n                int cell = rng.nextInt(C);\n                int old = ev.board[cell];\n\n                long long bestComb = 0;\n                long long bestK = 0;\n                int bestChar = old;\n\n                for (int nc = 0; nc < ALPHA; nc++) {\n                    if (nc == old) continue;\n\n                    long long kd = 0;\n                    if (useKmer) kd = ksc.delta(ev.board, cell, nc);\n\n                    long long ed = ev.applyChange(cell, nc);\n                    ev.applyChange(cell, old);\n\n                    long long cd = ed + kScale * kd;\n\n                    if (cd > bestComb) {\n                        bestComb = cd;\n                        bestK = kd;\n                        bestChar = nc;\n                    }\n                }\n\n                if (bestChar != old) {\n                    if (useKmer) curK += bestK;\n\n                    ev.applyChange(cell, bestChar);\n                    best.update(ev);\n                } else {\n                    int nc = rng.nextInt(ALPHA);\n                    if (nc == old) nc = (nc + 1) % ALPHA;\n\n                    long long kd = 0;\n                    if (useKmer) kd = ksc.delta(ev.board, cell, nc);\n\n                    long long ed = ev.applyChange(cell, nc);\n                    long long cd = ed + kScale * kd;\n\n                    bool accept = false;\n\n                    if (cd >= 0) {\n                        accept = true;\n                    } else if (ed > -BIG / 2) {\n                        if (rng.nextDouble() < exp((double)cd / temp)) {\n                            accept = true;\n                        }\n                    }\n\n                    if (accept) {\n                        if (useKmer) curK += kd;\n                        best.update(ev);\n                    } else {\n                        ev.applyChange(cell, old);\n                    }\n                }\n            }\n\n            iter++;\n        }\n    };\n\n    // Exact-cover search from greedy board.\n    Evaluator evExact(s, pre, boardStamp);\n    doSearch(evExact, false, 1.10);\n\n    // Independent k-mer optimized candidate.\n    vector<unsigned char> boardKmer(C);\n\n    for (int i = 0; i < C; i++) {\n        boardKmer[i] = randomChar();\n    }\n\n    long long kScore = ksc.score(boardKmer);\n\n    while (elapsedSec() < 1.55) {\n        int cell = rng.nextInt(C);\n        int old = boardKmer[cell];\n\n        long long bestD = 0;\n        int bestC = old;\n\n        for (int nc = 0; nc < ALPHA; nc++) {\n            if (nc == old) continue;\n\n            long long d = ksc.delta(boardKmer, cell, nc);\n\n            if (d > bestD) {\n                bestD = d;\n                bestC = nc;\n            }\n        }\n\n        if (bestC != old) {\n            boardKmer[cell] = (unsigned char)bestC;\n            kScore += bestD;\n        } else {\n            int nc = rng.nextInt(ALPHA);\n            if (nc == old) nc = (nc + 1) % ALPHA;\n\n            long long d = ksc.delta(boardKmer, cell, nc);\n\n            if (d >= 0 || rng.nextDouble() < exp((double)d / 30.0)) {\n                boardKmer[cell] = (unsigned char)nc;\n                kScore += d;\n            }\n        }\n    }\n\n    Evaluator evKmer(s, pre, boardKmer);\n    best.update(evKmer);\n\n    vector<unsigned char> startCombined;\n\n    if (evKmer.covered > best.covered ||\n        (evKmer.covered == best.covered && ksc.score(evKmer.board) > ksc.score(best.board))) {\n        startCombined = evKmer.board;\n    } else {\n        startCombined = best.board;\n    }\n\n    // K-mer-assisted exact search.\n    Evaluator evCombined(s, pre, startCombined);\n    doSearch(evCombined, true, 2.84);\n\n    // Final safe exact-cover intensification from the best known board.\n    if (elapsedSec() < 2.94) {\n        Evaluator evPolish(s, pre, best.board);\n        doSearch(evPolish, false, 2.94);\n    }\n\n    vector<unsigned char> answer = best.board;\n\n    // If perfect coverage was achieved, greedily erase unnecessary cells.\n    if (best.covered == M) {\n        Evaluator evFinal(s, pre, answer);\n\n        vector<int> cells(C);\n        iota(cells.begin(), cells.end(), 0);\n        shuffle(cells.begin(), cells.end(), mt19937((unsigned)rng.next()));\n\n        for (int cell : cells) {\n            int old = evFinal.board[cell];\n\n            if (old == 8) continue;\n\n            evFinal.applyChange(cell, 8);\n\n            if (evFinal.covered < M) {\n                evFinal.applyChange(cell, old);\n            }\n        }\n\n        answer = evFinal.board;\n    }\n\n    for (int i = 0; i < N; i++) {\n        string out;\n\n        for (int j = 0; j < N; j++) {\n            int v = answer[i * N + j];\n\n            if (v == 8) out.push_back('.');\n            else out.push_back(char('A' + v));\n        }\n\n        cout << out << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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 HopcroftKarp {\n    int nL, nR;\n    vector<vector<int>> adj;\n    vector<int> pairU, pairV, dist;\n\n    HopcroftKarp(int nL_=0, int nR_=0) : nL(nL_), nR(nR_) {\n        adj.assign(nL, {});\n        pairU.assign(nL, -1);\n        pairV.assign(nR, -1);\n        dist.assign(nL, 0);\n    }\n\n    bool bfs() {\n        queue<int> q;\n        bool found = false;\n\n        for (int u = 0; u < nL; u++) {\n            if (pairU[u] == -1) {\n                dist[u] = 0;\n                q.push(u);\n            } else {\n                dist[u] = -1;\n            }\n        }\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (int v : adj[u]) {\n                int u2 = pairV[v];\n                if (u2 == -1) {\n                    found = true;\n                } else if (dist[u2] == -1) {\n                    dist[u2] = dist[u] + 1;\n                    q.push(u2);\n                }\n            }\n        }\n\n        return found;\n    }\n\n    bool dfs(int u) {\n        for (int v : adj[u]) {\n            int u2 = pairV[v];\n            if (u2 == -1 || (dist[u2] == dist[u] + 1 && dfs(u2))) {\n                pairU[u] = v;\n                pairV[v] = u;\n                return true;\n            }\n        }\n        dist[u] = -1;\n        return false;\n    }\n\n    int max_matching() {\n        int matching = 0;\n        while (bfs()) {\n            for (int u = 0; u < nL; u++) {\n                if (pairU[u] == -1 && dfs(u)) matching++;\n            }\n        }\n        return matching;\n    }\n\n    pair<vector<char>, vector<char>> min_vertex_cover() {\n        vector<char> visL(nL, 0), visR(nR, 0);\n        queue<int> q;\n\n        for (int u = 0; u < nL; u++) {\n            if (pairU[u] == -1) {\n                visL[u] = 1;\n                q.push(u);\n            }\n        }\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (int v : adj[u]) {\n                if (pairU[u] == v) continue;\n                if (visR[v]) continue;\n\n                visR[v] = 1;\n                int u2 = pairV[v];\n                if (u2 != -1 && !visL[u2]) {\n                    visL[u2] = 1;\n                    q.push(u2);\n                }\n            }\n        }\n\n        vector<char> coverL(nL, 0), coverR(nR, 0);\n        for (int u = 0; u < nL; u++) coverL[u] = !visL[u];\n        for (int v = 0; v < nR; v++) coverR[v] = visR[v];\n        return {coverL, coverR};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<int> ri, rj, cost;\n\n    int R = 0;\n    int startRid = -1;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R++;\n                ri.push_back(i);\n                rj.push_back(j);\n                cost.push_back(grid[i][j] - '0');\n\n                if (i == si && j == sj) startRid = id[i][j];\n            }\n        }\n    }\n\n    int W = (R + 63) >> 6;\n\n    vector<int> hid(R), vid(R);\n    vector<vector<int>> hCells, vCells;\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n\n            vector<int> cells;\n            while (j < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                j++;\n            }\n\n            int h = (int)hCells.size();\n            for (int x : cells) hid[x] = h;\n            hCells.push_back(cells);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n\n            vector<int> cells;\n            while (i < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                i++;\n            }\n\n            int v = (int)vCells.size();\n            for (int x : cells) vid[x] = v;\n            vCells.push_back(cells);\n        }\n    }\n\n    int H = (int)hCells.size();\n    int V = (int)vCells.size();\n\n    vector<uint64_t> coverBits((ll)R * W, 0);\n\n    for (int x = 0; x < R; x++) {\n        uint64_t* bs = &coverBits[(ll)x * W];\n\n        for (int y : hCells[hid[x]]) {\n            bs[y >> 6] |= 1ULL << (y & 63);\n        }\n        for (int y : vCells[vid[x]]) {\n            bs[y >> 6] |= 1ULL << (y & 63);\n        }\n    }\n\n    vector<int> coverWeight(R, 0);\n    for (int x = 0; x < R; x++) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        int s = 0;\n        for (int w = 0; w < W; w++) s += __builtin_popcountll(bs[w]);\n        coverWeight[x] = s;\n    }\n\n    vector<uint64_t> fullMask(W, 0);\n    for (int x = 0; x < R; x++) {\n        fullMask[x >> 6] |= 1ULL << (x & 63);\n    }\n\n    auto is_full_bits = [&](const vector<uint64_t>& bs) -> bool {\n        for (int w = 0; w < W; w++) {\n            if ((bs[w] & fullMask[w]) != fullMask[w]) return false;\n        }\n        return true;\n    };\n\n    auto pop_and = [&](const uint64_t* a, const vector<uint64_t>& b) -> int {\n        int res = 0;\n        for (int w = 0; w < W; w++) {\n            res += __builtin_popcountll(a[w] & b[w]);\n        }\n        return res;\n    };\n\n    auto erase_cover_from_uncovered = [&](vector<uint64_t>& uncovered, int x) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W; w++) {\n            uncovered[w] &= ~bs[w];\n        }\n    };\n\n    auto reduce_selected = [&](vector<int> selected, bool sortFirst) {\n        if (sortFirst) {\n            sort(selected.begin(), selected.end());\n            selected.erase(unique(selected.begin(), selected.end()), selected.end());\n        } else {\n            vector<char> seen(R, 0);\n            vector<int> tmp;\n            for (int x : selected) {\n                if (!seen[x]) {\n                    seen[x] = 1;\n                    tmp.push_back(x);\n                }\n            }\n            selected.swap(tmp);\n        }\n\n        selected.erase(remove(selected.begin(), selected.end(), startRid), selected.end());\n\n        vector<int> cnt(R, 0);\n\n        auto addCoverCount = [&](int x, int delta) {\n            const uint64_t* bs = &coverBits[(ll)x * W];\n\n            for (int w = 0; w < W; w++) {\n                uint64_t v = bs[w];\n\n                while (v) {\n                    int b = __builtin_ctzll(v);\n                    int y = (w << 6) + b;\n                    if (y < R) cnt[y] += delta;\n                    v &= v - 1;\n                }\n            }\n        };\n\n        addCoverCount(startRid, 1);\n        for (int x : selected) addCoverCount(x, 1);\n\n        vector<int> kept;\n\n        for (int idx = (int)selected.size() - 1; idx >= 0; idx--) {\n            int x = selected[idx];\n            bool removable = true;\n\n            const uint64_t* bs = &coverBits[(ll)x * W];\n\n            for (int w = 0; w < W && removable; w++) {\n                uint64_t v = bs[w];\n\n                while (v) {\n                    int b = __builtin_ctzll(v);\n                    int y = (w << 6) + b;\n\n                    if (y < R && cnt[y] <= 1) {\n                        removable = false;\n                        break;\n                    }\n\n                    v &= v - 1;\n                }\n            }\n\n            if (removable) {\n                addCoverCount(x, -1);\n            } else {\n                kept.push_back(x);\n            }\n        }\n\n        reverse(kept.begin(), kept.end());\n        return kept;\n    };\n\n    auto selected_covers_all = [&](const vector<int>& selected) {\n        vector<uint64_t> bs(W, 0);\n\n        const uint64_t* sbs = &coverBits[(ll)startRid * W];\n        for (int w = 0; w < W; w++) bs[w] |= sbs[w];\n\n        for (int x : selected) {\n            const uint64_t* cbs = &coverBits[(ll)x * W];\n            for (int w = 0; w < W; w++) bs[w] |= cbs[w];\n        }\n\n        return is_full_bits(bs);\n    };\n\n    auto make_greedy_raw = [&](int mode) {\n        vector<int> selected;\n        vector<uint64_t> uncovered = fullMask;\n        erase_cover_from_uncovered(uncovered, startRid);\n\n        vector<char> selectedFlag(R, 0);\n        vector<int> nearDist(R);\n\n        for (int x = 0; x < R; x++) {\n            nearDist[x] = abs(ri[x] - si) + abs(rj[x] - sj);\n        }\n\n        auto anyUncovered = [&]() -> bool {\n            for (uint64_t x : uncovered) {\n                if (x) return true;\n            }\n            return false;\n        };\n\n        while (anyUncovered()) {\n            int best = -1;\n            int bestGain = -1;\n            int bestTie = INT_MIN;\n            ll bestScore = LLONG_MIN;\n\n            for (int x = 0; x < R; x++) {\n                if (selectedFlag[x]) continue;\n\n                const uint64_t* bs = &coverBits[(ll)x * W];\n                int gain = pop_and(bs, uncovered);\n                if (gain <= 0) continue;\n\n                int hLen = (int)hCells[hid[x]].size();\n                int vLen = (int)vCells[vid[x]].size();\n                int segLen = hLen + vLen;\n                int startD = abs(ri[x] - si) + abs(rj[x] - sj);\n                int nd = nearDist[x];\n\n                if (mode == 0) {\n                    int tie =\n                        10 * segLen\n                        - abs(ri[x] - si)\n                        - abs(rj[x] - sj);\n\n                    if (gain > bestGain || (gain == bestGain && tie > bestTie)) {\n                        bestGain = gain;\n                        bestTie = tie;\n                        best = x;\n                    }\n                } else {\n                    ll score;\n                    if (mode == 1) {\n                        score = (ll)gain * 10000 - 70LL * nd + 90LL * segLen - 5LL * startD;\n                    } else if (mode == 2) {\n                        score = (ll)gain * 7500 - 105LL * nd + 120LL * segLen - 8LL * cost[x];\n                    } else if (mode == 3) {\n                        score = (ll)gain * 7000 - 110LL * startD + 100LL * segLen - 35LL * nd;\n                    } else if (mode == 4) {\n                        score = (ll)gain * 8800 - 130LL * nd + 60LL * segLen + 8LL * hLen * vLen;\n                    } else {\n                        score = (ll)gain * 6400 - 65LL * nd - 95LL * startD + 180LL * segLen - 18LL * cost[x];\n                    }\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        best = x;\n                    }\n                }\n            }\n\n            if (best == -1) break;\n\n            selectedFlag[best] = 1;\n            selected.push_back(best);\n            erase_cover_from_uncovered(uncovered, best);\n\n            if (mode != 0) {\n                for (int y = 0; y < R; y++) {\n                    int d = abs(ri[y] - ri[best]) + abs(rj[y] - rj[best]);\n                    if (d < nearDist[y]) nearDist[y] = d;\n                }\n            }\n        }\n\n        return selected;\n    };\n\n    auto make_greedy = [&](int mode, bool sortReduce) {\n        return reduce_selected(make_greedy_raw(mode), sortReduce);\n    };\n\n    vector<int> greedySelected = make_greedy(0, true);\n\n    vector<int> mvcSelected;\n    bool mvcValid = false;\n\n    {\n        int hs = hid[startRid];\n        int vs = vid[startRid];\n\n        HopcroftKarp hk(H, V);\n\n        unordered_map<ll, int> edgeCell;\n        edgeCell.reserve(R * 2 + 10);\n\n        for (int x = 0; x < R; x++) {\n            int h = hid[x], v = vid[x];\n            edgeCell[(ll)h * V + v] = x;\n\n            if (h == hs || v == vs) continue;\n            hk.adj[h].push_back(v);\n        }\n\n        for (int h = 0; h < H; h++) {\n            sort(hk.adj[h].begin(), hk.adj[h].end());\n            hk.adj[h].erase(unique(hk.adj[h].begin(), hk.adj[h].end()), hk.adj[h].end());\n        }\n\n        hk.max_matching();\n        auto [coverH, coverV] = hk.min_vertex_cover();\n\n        HopcroftKarp hk2(H, V);\n        for (int x = 0; x < R; x++) {\n            int h = hid[x], v = vid[x];\n            if (coverH[h] && coverV[v]) {\n                hk2.adj[h].push_back(v);\n            }\n        }\n\n        for (int h = 0; h < H; h++) {\n            sort(hk2.adj[h].begin(), hk2.adj[h].end());\n            hk2.adj[h].erase(unique(hk2.adj[h].begin(), hk2.adj[h].end()), hk2.adj[h].end());\n        }\n\n        hk2.max_matching();\n\n        vector<char> doneH(H, 0), doneV(V, 0);\n\n        for (int h = 0; h < H; h++) {\n            int v = hk2.pairU[h];\n            if (v != -1 && coverH[h] && coverV[v]) {\n                auto it = edgeCell.find((ll)h * V + v);\n                if (it != edgeCell.end()) {\n                    mvcSelected.push_back(it->second);\n                    doneH[h] = 1;\n                    doneV[v] = 1;\n                }\n            }\n        }\n\n        auto best_cell_in_list = [&](const vector<int>& cells) {\n            int best = cells[0];\n            int bestScore = INT_MAX;\n\n            for (int x : cells) {\n                int score =\n                    10 * (abs(ri[x] - si) + abs(rj[x] - sj))\n                    - (int)hCells[hid[x]].size()\n                    - (int)vCells[vid[x]].size();\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = x;\n                }\n            }\n\n            return best;\n        };\n\n        for (int h = 0; h < H; h++) {\n            if (coverH[h] && !doneH[h]) {\n                mvcSelected.push_back(best_cell_in_list(hCells[h]));\n                doneH[h] = 1;\n            }\n        }\n\n        for (int v = 0; v < V; v++) {\n            if (coverV[v] && !doneV[v]) {\n                mvcSelected.push_back(best_cell_in_list(vCells[v]));\n                doneV[v] = 1;\n            }\n        }\n\n        mvcSelected = reduce_selected(mvcSelected, true);\n        mvcValid = selected_covers_all(mvcSelected);\n    }\n\n    vector<vector<int>> candidates;\n    candidates.push_back(greedySelected);\n\n    vector<char> inUnion(R, 0);\n    inUnion[startRid] = 1;\n    int unionCount = 1;\n\n    auto mark_union = [&](const vector<int>& sel) {\n        for (int x : sel) {\n            if (!inUnion[x]) {\n                inUnion[x] = 1;\n                unionCount++;\n            }\n        }\n    };\n\n    mark_union(greedySelected);\n\n    auto same_set = [&](vector<int> a, vector<int> b) {\n        sort(a.begin(), a.end());\n        sort(b.begin(), b.end());\n        return a == b;\n    };\n\n    auto try_add_candidate = [&](const vector<int>& sel, int capUnion, bool sizeGuard) {\n        if (sel.empty()) return;\n        if (!selected_covers_all(sel)) return;\n\n        if (sizeGuard && sel.size() > greedySelected.size() * 3 / 2 + 25) return;\n\n        for (auto& c : candidates) {\n            if (same_set(c, sel)) return;\n        }\n\n        int add = 0;\n        for (int x : sel) {\n            if (!inUnion[x]) add++;\n        }\n\n        if (unionCount + add > capUnion) return;\n\n        candidates.push_back(sel);\n        mark_union(sel);\n    };\n\n    if (mvcValid) {\n        try_add_candidate(mvcSelected, 660, false);\n    }\n\n    for (int mode = 1; mode <= 5 && timer.elapsed() < 0.58; mode++) {\n        vector<int> cand = make_greedy(mode, true);\n        try_add_candidate(cand, 660, true);\n    }\n\n    for (int mode = 0; mode <= 2 && timer.elapsed() < 0.70; mode++) {\n        vector<int> cand = make_greedy(mode, false);\n        try_add_candidate(cand, 660, true);\n    }\n\n    vector<int> nodeRid;\n    nodeRid.push_back(startRid);\n\n    vector<int> ridToNode(R, -1);\n    ridToNode[startRid] = 0;\n\n    for (const auto& selected : candidates) {\n        for (int x : selected) {\n            if (ridToNode[x] == -1) {\n                ridToNode[x] = (int)nodeRid.size();\n                nodeRid.push_back(x);\n            }\n        }\n    }\n\n    int G = (int)nodeRid.size();\n\n    vector<vector<pair<int,int>>> adj(R);\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n\n    for (int x = 0; x < R; x++) {\n        int i = ri[x], j = rj[x];\n\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d];\n            int nj = j + dj[d];\n\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && id[ni][nj] != -1) {\n                int y = id[ni][nj];\n                adj[x].push_back({y, cost[y]});\n            }\n        }\n    }\n\n    const int INF = 1e9;\n\n    vector<vector<int>> distMat(G, vector<int>(G, INF));\n    vector<vector<short>> prevNode(G, vector<short>(R, -1));\n\n    for (int s = 0; s < G; s++) {\n        int src = nodeRid[s];\n\n        vector<int> dist(R, INF);\n        vector<int> pathScore(R, -1);\n        vector<short> pre(R, -1);\n\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n\n        dist[src] = 0;\n        pathScore[src] = coverWeight[src];\n        pq.push({0, src});\n\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top();\n            pq.pop();\n\n            if (cd != dist[v]) continue;\n\n            for (auto [to, w] : adj[v]) {\n                int nd = cd + w;\n                int ns = pathScore[v] + coverWeight[to];\n\n                if (nd < dist[to] || (nd == dist[to] && ns > pathScore[to])) {\n                    dist[to] = nd;\n                    pathScore[to] = ns;\n                    pre[to] = (short)v;\n                    pq.push({nd, to});\n                }\n            }\n        }\n\n        prevNode[s].swap(pre);\n\n        for (int t = 0; t < G; t++) {\n            distMat[s][t] = dist[nodeRid[t]];\n        }\n    }\n\n    vector<int> nodeCost(G);\n    for (int i = 0; i < G; i++) nodeCost[i] = cost[nodeRid[i]];\n\n    auto cycleCost = [&](const vector<int>& cyc) -> ll {\n        ll res = 0;\n        int m = (int)cyc.size();\n\n        for (int i = 0; i < m; i++) {\n            res += distMat[cyc[i]][cyc[(i + 1) % m]];\n        }\n\n        return res;\n    };\n\n    auto symDist = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        return distMat[a][b] + nodeCost[a];\n    };\n\n    auto improve_cycle = [&](vector<int>& cycle, double endTime) {\n        if ((int)cycle.size() > 780) return;\n\n        while (timer.elapsed() < endTime) {\n            int m = (int)cycle.size();\n\n            ll bestDelta = 0;\n            int bestType = 0;\n            int bestL = -1, bestR = -1;\n            int bestI = -1, bestJ = -1, bestPos = -1;\n\n            // 2-opt reversal.\n            for (int l = 1; l < m - 1; l++) {\n                if ((l & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                for (int r = l + 1; r < m; r++) {\n                    int a = cycle[l - 1];\n                    int b = cycle[l];\n                    int c = cycle[r];\n                    int d = cycle[(r + 1) % m];\n\n                    ll delta =\n                        (ll)symDist(a, c) + symDist(b, d)\n                        - symDist(a, b) - symDist(c, d);\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 1;\n                        bestL = l;\n                        bestR = r;\n                    }\n                }\n            }\n\n            // 1-node relocation.\n            for (int i = 1; i < m; i++) {\n                if ((i & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                int x = cycle[i];\n                int a = cycle[i - 1];\n                int b = cycle[(i + 1) % m];\n\n                ll removeDelta =\n                    (ll)distMat[a][b]\n                    - distMat[a][x]\n                    - distMat[x][b];\n\n                for (int pos = 0; pos < m; pos++) {\n                    if (pos == i || pos == i - 1) continue;\n\n                    int c = cycle[pos];\n                    int d = cycle[(pos + 1) % m];\n\n                    ll delta =\n                        removeDelta\n                        + (ll)distMat[c][x]\n                        + distMat[x][d]\n                        - distMat[c][d];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 2;\n                        bestI = i;\n                        bestPos = pos;\n                    }\n                }\n            }\n\n            // Or-opt-2: relocate two consecutive non-start nodes.\n            for (int i = 1; i + 1 < m; i++) {\n                if ((i & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                int x = cycle[i];\n                int y = cycle[i + 1];\n                int a = cycle[i - 1];\n                int b = cycle[(i + 2) % m];\n\n                ll removeDelta =\n                    (ll)distMat[a][b]\n                    - distMat[a][x]\n                    - distMat[x][y]\n                    - distMat[y][b];\n\n                for (int pos = 0; pos < m; pos++) {\n                    if (i - 1 <= pos && pos <= i + 1) continue;\n\n                    int c = cycle[pos];\n                    int d = cycle[(pos + 1) % m];\n\n                    ll delta =\n                        removeDelta\n                        + (ll)distMat[c][x]\n                        + distMat[x][y]\n                        + distMat[y][d]\n                        - distMat[c][d];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 3;\n                        bestI = i;\n                        bestPos = pos;\n                    }\n                }\n            }\n\n            // Directed swap of two non-start nodes.\n            for (int i = 1; i < m; i++) {\n                if ((i & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                for (int j = i + 1; j < m; j++) {\n                    ll delta;\n\n                    if (j == i + 1) {\n                        int a = cycle[i - 1];\n                        int x = cycle[i];\n                        int y = cycle[j];\n                        int b = cycle[(j + 1) % m];\n\n                        delta =\n                            (ll)distMat[a][y]\n                            + distMat[y][x]\n                            + distMat[x][b]\n                            - distMat[a][x]\n                            - distMat[x][y]\n                            - distMat[y][b];\n                    } else {\n                        int a = cycle[i - 1];\n                        int x = cycle[i];\n                        int b = cycle[i + 1];\n\n                        int c = cycle[j - 1];\n                        int y = cycle[j];\n                        int d = cycle[(j + 1) % m];\n\n                        delta =\n                            (ll)distMat[a][y]\n                            + distMat[y][b]\n                            + distMat[c][x]\n                            + distMat[x][d]\n                            - distMat[a][x]\n                            - distMat[x][b]\n                            - distMat[c][y]\n                            - distMat[y][d];\n                    }\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 4;\n                        bestI = i;\n                        bestJ = j;\n                    }\n                }\n            }\n\n            if (bestType == 0) break;\n\n            if (bestType == 1) {\n                reverse(cycle.begin() + bestL, cycle.begin() + bestR + 1);\n            } else if (bestType == 2) {\n                int x = cycle[bestI];\n                cycle.erase(cycle.begin() + bestI);\n\n                int insertIdx;\n                if (bestPos < bestI) insertIdx = bestPos + 1;\n                else insertIdx = bestPos;\n\n                cycle.insert(cycle.begin() + insertIdx, x);\n            } else if (bestType == 3) {\n                int x = cycle[bestI];\n                int y = cycle[bestI + 1];\n\n                cycle.erase(cycle.begin() + bestI, cycle.begin() + bestI + 2);\n\n                int insertIdx;\n                if (bestPos < bestI) insertIdx = bestPos + 1;\n                else insertIdx = bestPos - 1;\n\n                cycle.insert(cycle.begin() + insertIdx, y);\n                cycle.insert(cycle.begin() + insertIdx, x);\n            } else {\n                swap(cycle[bestI], cycle[bestJ]);\n            }\n        }\n    };\n\n    auto construct_cycle = [&](const vector<int>& selected) {\n        vector<int> localNodes;\n        localNodes.push_back(0);\n\n        for (int x : selected) {\n            int g = ridToNode[x];\n            if (g > 0) localNodes.push_back(g);\n        }\n\n        sort(localNodes.begin() + 1, localNodes.end());\n        localNodes.erase(unique(localNodes.begin(), localNodes.end()), localNodes.end());\n\n        int M = (int)localNodes.size();\n        vector<int> cycle;\n\n        if (M == 1) {\n            cycle = {0};\n        } else if (M <= 440) {\n            cycle = {0};\n\n            vector<int> unused;\n            for (int i = 1; i < M; i++) unused.push_back(localNodes[i]);\n\n            while (!unused.empty()) {\n                int bestUIdx = -1;\n                int bestPos = -1;\n                int bestDelta = INF;\n\n                for (int ui = 0; ui < (int)unused.size(); ui++) {\n                    int x = unused[ui];\n                    int m = (int)cycle.size();\n\n                    for (int p = 0; p < m; p++) {\n                        int a = cycle[p];\n                        int b = cycle[(p + 1) % m];\n\n                        int delta =\n                            distMat[a][x]\n                            + distMat[x][b]\n                            - distMat[a][b];\n\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestUIdx = ui;\n                            bestPos = p;\n                        }\n                    }\n                }\n\n                int x = unused[bestUIdx];\n                cycle.insert(cycle.begin() + bestPos + 1, x);\n                unused.erase(unused.begin() + bestUIdx);\n            }\n        } else {\n            vector<char> used(G, 0);\n            cycle = {0};\n            used[0] = 1;\n\n            int cur = 0;\n\n            for (int step = 1; step < M; step++) {\n                int best = -1;\n                int bd = INF;\n\n                for (int x : localNodes) {\n                    if (!used[x] && distMat[cur][x] < bd) {\n                        bd = distMat[cur][x];\n                        best = x;\n                    }\n                }\n\n                used[best] = 1;\n                cycle.push_back(best);\n                cur = best;\n            }\n        }\n\n        return cycle;\n    };\n\n    vector<vector<int>> cycles;\n    cycles.reserve(candidates.size());\n\n    for (const auto& cand : candidates) {\n        cycles.push_back(construct_cycle(cand));\n    }\n\n    if (!cycles.empty()) {\n        improve_cycle(cycles[0], min(1.45, timer.elapsed() + 0.34));\n    }\n    if (cycles.size() >= 2) {\n        improve_cycle(cycles[1], min(1.82, timer.elapsed() + 0.32));\n    }\n    for (int k = 2; k < (int)cycles.size() && timer.elapsed() < 2.02; k++) {\n        improve_cycle(cycles[k], min(2.02, timer.elapsed() + 0.10));\n    }\n\n    int bestIdx = 0;\n    ll bestCost = cycleCost(cycles[0]);\n\n    for (int k = 1; k < (int)cycles.size(); k++) {\n        ll c = cycleCost(cycles[k]);\n        if (c < bestCost) {\n            bestCost = c;\n            bestIdx = k;\n        }\n    }\n\n    vector<int> cycle = cycles[bestIdx];\n\n    improve_cycle(cycle, 2.12);\n\n    auto reconstructPath = [&](int srcNode, int dstNode) {\n        vector<int> path;\n\n        int src = nodeRid[srcNode];\n        int dst = nodeRid[dstNode];\n\n        int cur = dst;\n\n        while (cur != src) {\n            path.push_back(cur);\n            cur = prevNode[srcNode][cur];\n\n            if (cur < 0) break;\n        }\n\n        path.push_back(src);\n        reverse(path.begin(), path.end());\n\n        return path;\n    };\n\n    struct EdgeCache {\n        int G, W, R;\n        const vector<int>& nodeRid;\n        const vector<vector<short>>& prevNode;\n        const vector<uint64_t>& coverBits;\n        vector<uint64_t> data;\n        vector<unsigned char> done;\n\n        EdgeCache(\n            int G_,\n            int W_,\n            int R_,\n            const vector<int>& nodeRid_,\n            const vector<vector<short>>& prevNode_,\n            const vector<uint64_t>& coverBits_\n        )\n            : G(G_), W(W_), R(R_), nodeRid(nodeRid_),\n              prevNode(prevNode_), coverBits(coverBits_) {\n            data.assign((ll)G * G * W, 0);\n            done.assign((ll)G * G, 0);\n        }\n\n        uint64_t* get(int a, int b) {\n            ll idx = (ll)a * G + b;\n            uint64_t* ret = &data[idx * W];\n\n            if (done[idx]) return ret;\n            done[idx] = 1;\n\n            int src = nodeRid[a];\n            int dst = nodeRid[b];\n\n            vector<int> path;\n            int cur = dst;\n\n            while (cur != src) {\n                path.push_back(cur);\n                cur = prevNode[a][cur];\n\n                if (cur < 0) break;\n            }\n\n            path.push_back(src);\n\n            for (int x : path) {\n                const uint64_t* bs = &coverBits[(ll)x * W];\n\n                for (int w = 0; w < W; w++) {\n                    ret[w] |= bs[w];\n                }\n            }\n\n            return ret;\n        }\n    };\n\n    if (G <= 680 && timer.elapsed() < 2.23) {\n        EdgeCache cache(G, W, R, nodeRid, prevNode, coverBits);\n\n        while ((int)cycle.size() > 1 && timer.elapsed() < 2.76) {\n            int m = (int)cycle.size();\n\n            vector<uint64_t> pref((ll)(m + 1) * W, 0);\n            vector<uint64_t> suff((ll)(m + 1) * W, 0);\n            vector<ll> edgePref(m + 1, 0);\n\n            for (int e = 0; e < m; e++) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n\n                for (int w = 0; w < W; w++) {\n                    pref[(ll)(e + 1) * W + w] =\n                        pref[(ll)e * W + w] | ec[w];\n                }\n\n                edgePref[e + 1] =\n                    edgePref[e] + distMat[cycle[e]][cycle[(e + 1) % m]];\n            }\n\n            for (int e = m - 1; e >= 0; e--) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n\n                for (int w = 0; w < W; w++) {\n                    suff[(ll)e * W + w] =\n                        suff[(ll)(e + 1) * W + w] | ec[w];\n                }\n            }\n\n            int bestP = -1;\n            int bestQ = -1;\n            ll bestSave = 0;\n            vector<uint64_t> tmp(W);\n\n            int maxBlock = 10;\n\n            for (int p = 1; p < m; p++) {\n                if ((p & 15) == 0 && timer.elapsed() >= 2.76) break;\n\n                for (int len = 1; len <= maxBlock && p + len - 1 < m; len++) {\n                    int q = p + len - 1;\n\n                    int prv = cycle[p - 1];\n                    int nxt = cycle[(q + 1) % m];\n\n                    ll removedCost = edgePref[q + 1] - edgePref[p - 1];\n                    ll save = removedCost - distMat[prv][nxt];\n\n                    if (save <= bestSave) continue;\n\n                    uint64_t* ec = cache.get(prv, nxt);\n\n                    for (int w = 0; w < W; w++) {\n                        tmp[w] =\n                            pref[(ll)(p - 1) * W + w]\n                            | suff[(ll)(q + 1) * W + w]\n                            | ec[w];\n                    }\n\n                    bool ok = true;\n\n                    for (int w = 0; w < W; w++) {\n                        if ((tmp[w] & fullMask[w]) != fullMask[w]) {\n                            ok = false;\n                            break;\n                        }\n                    }\n\n                    if (ok) {\n                        bestSave = save;\n                        bestP = p;\n                        bestQ = q;\n                    }\n                }\n            }\n\n            if (bestP == -1) break;\n\n            cycle.erase(cycle.begin() + bestP, cycle.begin() + bestQ + 1);\n        }\n    }\n\n    auto cycle_nodes_cover_all = [&]() {\n        vector<uint64_t> bs(W, 0);\n\n        for (int g : cycle) {\n            int rid = nodeRid[g];\n            const uint64_t* cbs = &coverBits[(ll)rid * W];\n\n            for (int w = 0; w < W; w++) {\n                bs[w] |= cbs[w];\n            }\n        }\n\n        return is_full_bits(bs);\n    };\n\n    if (timer.elapsed() < 2.86 && cycle_nodes_cover_all()) {\n        improve_cycle(cycle, 2.92);\n    }\n\n    string ans;\n\n    auto moveChar = [&](int a, int b) -> char {\n        int da = ri[b] - ri[a];\n        int db = rj[b] - rj[a];\n\n        if (da == -1) return 'U';\n        if (da == 1) return 'D';\n        if (db == -1) return 'L';\n        return 'R';\n    };\n\n    int m = (int)cycle.size();\n\n    for (int e = 0; e < m; e++) {\n        int a = cycle[e];\n        int b = cycle[(e + 1) % m];\n\n        vector<int> path = reconstructPath(a, b);\n\n        for (int k = 1; k < (int)path.size(); k++) {\n            ans.push_back(moveChar(path[k - 1], path[k]));\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Record {\n    int task;\n    int dur;\n};\n\nint N, M, K, R;\nvector<vector<int>> D;\nvector<vector<int>> children_;\nvector<int> remdep;\nvector<int> status_; // -1:not started, 0:running, 1:done\n\nvector<vector<int>> skill_est;\nvector<vector<Record>> records_;\nvector<int> member_task;\nvector<int> member_start;\n\nvector<double> bottom_priority;\nvector<double> min_cost, avg_cost;\nvector<double> reach_score;\n\nconst int MAX_SKILL = 70;\n\ndouble base_skill;\nconst double PRIOR_COMP = 0.008;\nconst double PRIOR_NORM = 0.003;\nconst double NORM_TARGET = 40.0;\n\ninline double obsPenalty(int w, int t) {\n    static const double p1[5] = {\n        0.0,\n        -log(4.0 / 7.0),\n        -log(3.0 / 7.0),\n        -log(2.0 / 7.0),\n        -log(1.0 / 7.0)\n    };\n\n    if (t == 1) {\n        if (w <= 4) return p1[w];\n        double x = w - 4;\n        return 3.0 + 2.0 * x * x;\n    } else {\n        if (w == 0) {\n            return 5.0 + 1.0 * t * t;\n        }\n        int lo = max(1, t - 3);\n        int hi = t + 3;\n        if (w < lo) {\n            double x = lo - w;\n            return 2.0 * x * x;\n        }\n        if (w > hi) {\n            double x = w - hi;\n            return 2.0 * x * x;\n        }\n        return 1.0 + 0.04 * abs(w - t);\n    }\n}\n\ninline int calcWTaskSkill(int task, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; k++) {\n        if (D[task][k] > s[k]) w += D[task][k] - s[k];\n    }\n    return w;\n}\n\ninline double expectedDurationFromWInt(int w) {\n    if (w == 0) return 1.0;\n    if (w == 1) return 13.0 / 7.0;\n    if (w == 2) return 17.0 / 7.0;\n    if (w == 3) return 22.0 / 7.0;\n    return (double)w;\n}\n\ninline double expectedDurationFromWDouble(double w) {\n    if (w <= 0.0) return 1.0;\n\n    static const double table[5] = {\n        1.0,\n        13.0 / 7.0,\n        17.0 / 7.0,\n        22.0 / 7.0,\n        4.0\n    };\n\n    if (w < 4.0) {\n        int a = (int)floor(w);\n        double f = w - a;\n        return table[a] * (1.0 - f) + table[a + 1] * f;\n    }\n\n    return w;\n}\n\ninline double memberConfidence(int mem) {\n    int c = (int)records_[mem].size();\n\n    // Conservative early, almost fully trusted after sufficient observations.\n    return (double)c / ((double)c + 3.5);\n}\n\ninline double expectedDuration(int task, int mem) {\n    const auto& s = skill_est[mem];\n\n    double conf = memberConfidence(mem);\n    double w = 0.0;\n\n    for (int k = 0; k < K; k++) {\n        double eff_skill = base_skill + conf * ((double)s[k] - base_skill);\n        if ((double)D[task][k] > eff_skill) {\n            w += (double)D[task][k] - eff_skill;\n        }\n    }\n\n    return expectedDurationFromWDouble(w);\n}\n\nvoid optimizeMember(int mem) {\n    auto& recs = records_[mem];\n    if (recs.empty()) return;\n\n    vector<int>& s = skill_est[mem];\n    int Rm = (int)recs.size();\n\n    vector<int> curW(Rm, 0);\n    for (int r = 0; r < Rm; r++) {\n        curW[r] = calcWTaskSkill(recs[r].task, s);\n    }\n\n    double sumsq = 0.0;\n    for (int k = 0; k < K; k++) sumsq += 1.0 * s[k] * s[k];\n\n    int passes = 3;\n    if (Rm >= 12) passes = 4;\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool changed_any = false;\n\n        for (int k = 0; k < K; k++) {\n            int old = s[k];\n\n            double bestObj = 1e100;\n            int bestVal = old;\n\n            for (int val = 0; val <= MAX_SKILL; val++) {\n                double obj = 0.0;\n\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    int oldContrib = max(0, D[task][k] - old);\n                    int newContrib = max(0, D[task][k] - val);\n                    int nw = curW[r] - oldContrib + newContrib;\n                    obj += obsPenalty(nw, recs[r].dur);\n                }\n\n                double compPrior = PRIOR_COMP * (val - base_skill) * (val - base_skill);\n\n                double nsumsq = sumsq - 1.0 * old * old + 1.0 * val * val;\n                double norm = sqrt(nsumsq);\n                double normPrior = PRIOR_NORM * (norm - NORM_TARGET) * (norm - NORM_TARGET);\n\n                obj += compPrior + normPrior;\n\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestVal = val;\n                }\n            }\n\n            if (bestVal != old) {\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    curW[r] -= max(0, D[task][k] - old);\n                    curW[r] += max(0, D[task][k] - bestVal);\n                }\n\n                sumsq = sumsq - 1.0 * old * old + 1.0 * bestVal * bestVal;\n                s[k] = bestVal;\n                changed_any = true;\n            }\n        }\n\n        if (!changed_any) break;\n    }\n}\n\nvoid precomputeReachScore() {\n    vector<double> dp(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        double v = 0.0;\n\n        for (int c : children_[i]) {\n            v += 1.0 + dp[c];\n            if (v > 1e6) {\n                v = 1e6;\n                break;\n            }\n        }\n\n        dp[i] = v;\n    }\n\n    reach_score.assign(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        reach_score[i] = log1p(dp[i]);\n    }\n}\n\nvoid recomputePriorities() {\n    min_cost.assign(N, 0.0);\n    avg_cost.assign(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        if (status_[i] == 1) {\n            min_cost[i] = avg_cost[i] = 0.0;\n            continue;\n        }\n\n        double mn = 1e100;\n        double sum = 0.0;\n\n        for (int j = 0; j < M; j++) {\n            double e = expectedDuration(i, j);\n            mn = min(mn, e);\n            sum += e;\n        }\n\n        min_cost[i] = mn;\n        avg_cost[i] = sum / M;\n    }\n\n    bottom_priority.assign(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        if (status_[i] == 1) {\n            bottom_priority[i] = 0.0;\n            continue;\n        }\n\n        double nodeCost = 0.7 * min_cost[i] + 0.3 * avg_cost[i];\n\n        double mx = 0.0;\n        for (int c : children_[i]) {\n            mx = max(mx, bottom_priority[c]);\n        }\n\n        bottom_priority[i] = nodeCost + mx;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K >> R;\n\n    D.assign(N, vector<int>(K));\n\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) cin >> D[i][k];\n    }\n\n    children_.assign(N, {});\n    remdep.assign(N, 0);\n\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u;\n        --v;\n\n        children_[u].push_back(v);\n        remdep[v]++;\n    }\n\n    base_skill = 35.0 / sqrt((double)K);\n    int init_skill = max(0, (int)round(base_skill));\n\n    skill_est.assign(M, vector<int>(K, init_skill));\n    records_.assign(M, {});\n\n    status_.assign(N, -1);\n    member_task.assign(M, -1);\n    member_start.assign(M, -1);\n\n    precomputeReachScore();\n\n    for (int day = 1; day <= 2000; day++) {\n        recomputePriorities();\n\n        vector<int> free_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready;\n        for (int i = 0; i < N; i++) {\n            if (status_[i] == -1 && remdep[i] == 0) ready.push_back(i);\n        }\n\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (bottom_priority[a] != bottom_priority[b]) {\n                return bottom_priority[a] > bottom_priority[b];\n            }\n            if (reach_score[a] != reach_score[b]) {\n                return reach_score[a] > reach_score[b];\n            }\n            return a < b;\n        });\n\n        vector<pair<int, int>> assignments;\n\n        while (!free_members.empty()) {\n            int bestFi = -1;\n            int bestTask = -1;\n            double bestScore = -1e100;\n\n            int limit = min((int)ready.size(), 300);\n\n            for (int fi = 0; fi < (int)free_members.size(); fi++) {\n                int mem = free_members[fi];\n\n                for (int idx = 0; idx < limit; idx++) {\n                    int task = ready[idx];\n\n                    if (status_[task] != -1) continue;\n\n                    double pred = expectedDuration(task, mem);\n\n                    double score =\n                        bottom_priority[task]\n                        + 0.15 * reach_score[task]\n                        - 0.70 * pred\n                        + 0.20 * (avg_cost[task] - pred);\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestFi = fi;\n                        bestTask = task;\n                    }\n                }\n            }\n\n            if (bestFi == -1) break;\n\n            int mem = free_members[bestFi];\n\n            status_[bestTask] = 0;\n            member_task[mem] = bestTask;\n            member_start[mem] = day;\n\n            assignments.push_back({mem, bestTask});\n\n            free_members.erase(free_members.begin() + bestFi);\n        }\n\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << mem + 1 << ' ' << task + 1;\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        for (int i = 0; i < cnt; i++) {\n            int f;\n            cin >> f;\n            --f;\n\n            int task = member_task[f];\n            if (task < 0) continue;\n\n            int dur = day - member_start[f] + 1;\n\n            status_[task] = 1;\n            member_task[f] = -1;\n            member_start[f] = -1;\n\n            records_[f].push_back({task, dur});\n            optimizeMember(f);\n\n            for (int c : children_[task]) {\n                remdep[c]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int ax, ay, cx, cy;\n    int score;\n};\n\nstruct Node {\n    int x, y;\n    int id;   // -1 depot\n    int type; // 0 pickup, 1 delivery\n};\n\nstruct InsertInfo {\n    int cost;\n    int pgap;\n    int dgap;\n};\n\nstruct State {\n    vector<Node> route;\n    vector<int> selected;\n    vector<char> used;\n    int cost;\n};\n\nstatic const int N = 1000;\nstatic const int K = 50;\nstatic const int DEP = 400;\nstatic const int INF = 1e9;\n\nvector<Order> ords;\nchrono::steady_clock::time_point start_time;\n\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\ninline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline int ndist(const Node& a, const Node& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\ninline Node pickupNode(int id) {\n    return Node{ords[id].ax, ords[id].ay, id, 0};\n}\n\ninline Node deliveryNode(int id) {\n    return Node{ords[id].cx, ords[id].cy, id, 1};\n}\n\nint routeCost(const vector<Node>& route) {\n    int res = 0;\n    for (int i = 0; i + 1 < (int)route.size(); i++) {\n        res += ndist(route[i], route[i + 1]);\n    }\n    return res;\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    double nextDouble() {\n        return (next() + 0.5) / 4294967296.0;\n    }\n\n    int randint(int l, int r) {\n        return l + (int)(next() % (uint32_t)(r - l + 1));\n    }\n};\n\nXorShift rng;\n\nInsertInfo bestInsert(const vector<Node>& route, int oid) {\n    const int L = (int)route.size();\n\n    const int px = ords[oid].ax;\n    const int py = ords[oid].ay;\n    const int dx = ords[oid].cx;\n    const int dy = ords[oid].cy;\n\n    int best = INF;\n    int bestP = -1;\n    int bestD = -1;\n\n    for (int i = 0; i <= L - 2; i++) {\n        const Node& A = route[i];\n        const Node& B = route[i + 1];\n\n        int directAB = ndist(A, B);\n\n        int val = mdist(A.x, A.y, px, py)\n                + mdist(px, py, dx, dy)\n                + mdist(dx, dy, B.x, B.y)\n                - directAB;\n\n        if (val < best) {\n            best = val;\n            bestP = i;\n            bestD = i;\n        }\n\n        int addPickup = mdist(A.x, A.y, px, py)\n                      + mdist(px, py, B.x, B.y)\n                      - directAB;\n\n        for (int j = i + 1; j <= L - 2; j++) {\n            const Node& C = route[j];\n            const Node& D = route[j + 1];\n\n            int addDelivery = mdist(C.x, C.y, dx, dy)\n                            + mdist(dx, dy, D.x, D.y)\n                            - ndist(C, D);\n\n            val = addPickup + addDelivery;\n\n            if (val < best) {\n                best = val;\n                bestP = i;\n                bestD = j;\n            }\n        }\n    }\n\n    return InsertInfo{best, bestP, bestD};\n}\n\nvoid applyInsert(vector<Node>& route, int oid, const InsertInfo& ins) {\n    vector<Node> nr;\n    nr.reserve(route.size() + 2);\n\n    Node P = pickupNode(oid);\n    Node D = deliveryNode(oid);\n\n    for (int i = 0; i < (int)route.size(); i++) {\n        nr.push_back(route[i]);\n\n        if (i == ins.pgap) {\n            nr.push_back(P);\n            if (ins.dgap == ins.pgap) {\n                nr.push_back(D);\n            }\n        }\n\n        if (ins.dgap > ins.pgap && i == ins.dgap) {\n            nr.push_back(D);\n        }\n    }\n\n    route.swap(nr);\n}\n\nvector<Node> removeOrder(const vector<Node>& route, int oid) {\n    vector<Node> nr;\n    nr.reserve(route.size() - 2);\n    for (const auto& v : route) {\n        if (v.id != oid) nr.push_back(v);\n    }\n    return nr;\n}\n\nbool feasibleReverse(const vector<Node>& route, int l, int r) {\n    static int p[N], d[N];\n    fill(p, p + N, -1);\n    fill(d, d + N, -1);\n\n    int n = (int)route.size();\n\n    for (int i = 1; i <= n - 2; i++) {\n        int ni = i;\n        if (l <= i && i <= r) ni = l + r - i;\n\n        const Node& v = route[i];\n        if (v.type == 0) p[v.id] = ni;\n        else d[v.id] = ni;\n    }\n\n    for (int i = 1; i <= n - 2; i++) {\n        int id = route[i].id;\n        if (p[id] != -1 && d[id] != -1 && p[id] > d[id]) {\n            return false;\n        }\n    }\n\n    return true;\n}\n\nbool feasibleSwap(const vector<Node>& route, int a, int b) {\n    static int p[N], d[N];\n    fill(p, p + N, -1);\n    fill(d, d + N, -1);\n\n    int n = (int)route.size();\n\n    for (int i = 1; i <= n - 2; i++) {\n        int ni = i;\n        if (i == a) ni = b;\n        else if (i == b) ni = a;\n\n        const Node& v = route[i];\n        if (v.type == 0) p[v.id] = ni;\n        else d[v.id] = ni;\n    }\n\n    for (int i = 1; i <= n - 2; i++) {\n        int id = route[i].id;\n        if (p[id] != -1 && d[id] != -1 && p[id] > d[id]) {\n            return false;\n        }\n    }\n\n    return true;\n}\n\nbool pairReinsertOptimize(State& st, double limitTime, int maxPass = 4) {\n    bool any = false;\n\n    for (int pass = 0; pass < maxPass && elapsed() < limitTime; pass++) {\n        bool improved = false;\n\n        for (int oid : st.selected) {\n            if (elapsed() >= limitTime) break;\n\n            vector<Node> rem = removeOrder(st.route, oid);\n            int remCost = routeCost(rem);\n\n            InsertInfo ins = bestInsert(rem, oid);\n            int newCost = remCost + ins.cost;\n\n            if (newCost < st.cost) {\n                st.route.swap(rem);\n                applyInsert(st.route, oid, ins);\n                st.cost = newCost;\n                improved = true;\n                any = true;\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nbool twoOptOptimize(State& st, double limitTime) {\n    bool any = false;\n    int n = (int)st.route.size();\n\n    while (elapsed() < limitTime) {\n        int bestDelta = 0;\n        int bestL = -1;\n        int bestR = -1;\n\n        for (int l = 1; l <= n - 3; l++) {\n            for (int r = l + 1; r <= n - 2; r++) {\n                int delta = ndist(st.route[l - 1], st.route[r])\n                          + ndist(st.route[l], st.route[r + 1])\n                          - ndist(st.route[l - 1], st.route[l])\n                          - ndist(st.route[r], st.route[r + 1]);\n\n                if (delta < bestDelta && feasibleReverse(st.route, l, r)) {\n                    bestDelta = delta;\n                    bestL = l;\n                    bestR = r;\n                }\n            }\n        }\n\n        if (bestDelta >= 0) break;\n\n        reverse(st.route.begin() + bestL, st.route.begin() + bestR + 1);\n        st.cost += bestDelta;\n        any = true;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nbool swapOptimize(State& st, double limitTime) {\n    bool any = false;\n    int n = (int)st.route.size();\n\n    while (elapsed() < limitTime) {\n        int bestDelta = 0;\n        int bestI = -1;\n        int bestJ = -1;\n\n        for (int i = 1; i <= n - 3; i++) {\n            for (int j = i + 1; j <= n - 2; j++) {\n                int delta;\n\n                if (i + 1 == j) {\n                    delta = ndist(st.route[i - 1], st.route[j])\n                          + ndist(st.route[j], st.route[i])\n                          + ndist(st.route[i], st.route[j + 1])\n                          - ndist(st.route[i - 1], st.route[i])\n                          - ndist(st.route[i], st.route[j])\n                          - ndist(st.route[j], st.route[j + 1]);\n                } else {\n                    delta = ndist(st.route[i - 1], st.route[j])\n                          + ndist(st.route[j], st.route[i + 1])\n                          + ndist(st.route[j - 1], st.route[i])\n                          + ndist(st.route[i], st.route[j + 1])\n                          - ndist(st.route[i - 1], st.route[i])\n                          - ndist(st.route[i], st.route[i + 1])\n                          - ndist(st.route[j - 1], st.route[j])\n                          - ndist(st.route[j], st.route[j + 1]);\n                }\n\n                if (delta < bestDelta && feasibleSwap(st.route, i, j)) {\n                    bestDelta = delta;\n                    bestI = i;\n                    bestJ = j;\n                }\n            }\n        }\n\n        if (bestDelta >= 0) break;\n\n        swap(st.route[bestI], st.route[bestJ]);\n        st.cost += bestDelta;\n        any = true;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nvoid routeLocalOptimize(State& st, double limitTime, bool heavy) {\n    while (elapsed() < limitTime) {\n        int before = st.cost;\n\n        pairReinsertOptimize(st, limitTime, 3);\n        twoOptOptimize(st, limitTime);\n\n        if (heavy) {\n            swapOptimize(st, limitTime);\n            twoOptOptimize(st, limitTime);\n            pairReinsertOptimize(st, limitTime, 2);\n        }\n\n        st.cost = routeCost(st.route);\n\n        if (st.cost >= before) break;\n    }\n}\n\nState constructGreedy(const vector<int>& pool, int randomTop) {\n    Node depot{DEP, DEP, -1, -1};\n\n    State st;\n    st.route = {depot, depot};\n    st.used.assign(N, 0);\n    st.selected.clear();\n    st.cost = 0;\n\n    struct Choice {\n        int cost;\n        int oid;\n        InsertInfo ins;\n    };\n\n    for (int step = 0; step < K; step++) {\n        vector<Choice> top;\n        top.reserve(randomTop);\n\n        for (int oid : pool) {\n            if (st.used[oid]) continue;\n\n            InsertInfo ins = bestInsert(st.route, oid);\n            Choice ch{ins.cost, oid, ins};\n\n            if ((int)top.size() < randomTop) {\n                top.push_back(ch);\n            } else {\n                int worst = 0;\n                for (int i = 1; i < (int)top.size(); i++) {\n                    if (top[i].cost > top[worst].cost) worst = i;\n                }\n                if (ch.cost < top[worst].cost) top[worst] = ch;\n            }\n        }\n\n        sort(top.begin(), top.end(), [](const Choice& a, const Choice& b) {\n            return a.cost < b.cost;\n        });\n\n        int idx = 0;\n        if (randomTop > 1 && (int)top.size() > 1) {\n            int lim = (int)top.size();\n            double u = rng.nextDouble();\n            idx = min(lim - 1, (int)(u * u * lim));\n        }\n\n        Choice ch = top[idx];\n\n        applyInsert(st.route, ch.oid, ch.ins);\n        st.used[ch.oid] = 1;\n        st.selected.push_back(ch.oid);\n        st.cost += ch.ins.cost;\n    }\n\n    st.cost = routeCost(st.route);\n    return st;\n}\n\nvector<int> makeClusterPool(int cx, int cy, int M) {\n    vector<pair<int, int>> v;\n    v.reserve(N);\n\n    for (int i = 0; i < N; i++) {\n        int cluster = mdist(ords[i].ax, ords[i].ay, cx, cy)\n                    + mdist(ords[i].cx, ords[i].cy, cx, cy);\n\n        int center = mdist(ords[i].ax, ords[i].ay, DEP, DEP)\n                   + mdist(ords[i].cx, ords[i].cy, DEP, DEP);\n\n        int paird = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        int sc = cluster * 10 + center * 3 + paird;\n        v.push_back({sc, i});\n    }\n\n    if (M < N) {\n        nth_element(v.begin(), v.begin() + M, v.end());\n        v.resize(M);\n    }\n\n    sort(v.begin(), v.end());\n\n    vector<int> pool;\n    pool.reserve(v.size());\n    for (auto [_, id] : v) pool.push_back(id);\n\n    return pool;\n}\n\nvoid replaceOptimize(State& st, const vector<int>& candList, double limitTime) {\n    while (elapsed() < limitTime) {\n        int bestNewCost = st.cost;\n        int bestRemove = -1;\n        int bestAdd = -1;\n\n        int checks = 0;\n        bool timeout = false;\n\n        for (int remOid : st.selected) {\n            vector<Node> remRoute = removeOrder(st.route, remOid);\n            int remCost = routeCost(remRoute);\n\n            for (int addOid : candList) {\n                if (st.used[addOid]) continue;\n\n                InsertInfo ins = bestInsert(remRoute, addOid);\n                int newCost = remCost + ins.cost;\n\n                if (newCost < bestNewCost) {\n                    bestNewCost = newCost;\n                    bestRemove = remOid;\n                    bestAdd = addOid;\n                }\n\n                if ((++checks & 255) == 0 && elapsed() > limitTime) {\n                    timeout = true;\n                    break;\n                }\n            }\n\n            if (timeout) break;\n        }\n\n        if (bestRemove == -1) break;\n\n        vector<Node> remRoute = removeOrder(st.route, bestRemove);\n        InsertInfo ins = bestInsert(remRoute, bestAdd);\n\n        st.route.swap(remRoute);\n        applyInsert(st.route, bestAdd, ins);\n\n        st.used[bestRemove] = 0;\n        st.used[bestAdd] = 1;\n\n        for (int& x : st.selected) {\n            if (x == bestRemove) {\n                x = bestAdd;\n                break;\n            }\n        }\n\n        st.cost = routeCost(st.route);\n        routeLocalOptimize(st, min(limitTime, elapsed() + 0.08), false);\n\n        if (timeout) break;\n    }\n\n    st.cost = routeCost(st.route);\n}\n\nvoid destroyRepairOptimize(State& best, const vector<int>& candList, double limitTime) {\n    vector<int> cand;\n    int lim = min((int)candList.size(), 650);\n    cand.reserve(lim);\n    for (int i = 0; i < lim; i++) cand.push_back(candList[i]);\n\n    while (elapsed() < limitTime) {\n        State cur = best;\n\n        int q = rng.randint(2, 5);\n\n        vector<pair<int, int>> saving;\n        saving.reserve(K);\n\n        for (int oid : cur.selected) {\n            vector<Node> rem = removeOrder(cur.route, oid);\n            int rc = routeCost(rem);\n            saving.push_back({cur.cost - rc, oid});\n        }\n\n        sort(saving.begin(), saving.end(), greater<pair<int, int>>());\n\n        vector<int> removed;\n        vector<char> remFlag(N, 0);\n\n        int topRange = min((int)saving.size(), 18);\n\n        for (int t = 0; t < q; t++) {\n            int idx;\n            if (rng.nextDouble() < 0.70) {\n                idx = rng.randint(0, topRange - 1);\n            } else {\n                idx = rng.randint(0, (int)saving.size() - 1);\n            }\n\n            int oid = saving[idx].second;\n            if (remFlag[oid]) {\n                t--;\n                continue;\n            }\n\n            remFlag[oid] = 1;\n            removed.push_back(oid);\n        }\n\n        vector<Node> nr;\n        nr.reserve(cur.route.size() - 2 * removed.size());\n\n        for (const Node& v : cur.route) {\n            if (v.id != -1 && remFlag[v.id]) continue;\n            nr.push_back(v);\n        }\n\n        cur.route.swap(nr);\n\n        vector<int> ns;\n        ns.reserve(K);\n        for (int oid : cur.selected) {\n            if (!remFlag[oid]) ns.push_back(oid);\n            else cur.used[oid] = 0;\n        }\n        cur.selected.swap(ns);\n        cur.cost = routeCost(cur.route);\n\n        while ((int)cur.selected.size() < K && elapsed() < limitTime) {\n            int bestAdd = -1;\n            InsertInfo bestIns{INF, -1, -1};\n\n            for (int oid : cand) {\n                if (cur.used[oid]) continue;\n\n                InsertInfo ins = bestInsert(cur.route, oid);\n\n                if (ins.cost < bestIns.cost) {\n                    bestIns = ins;\n                    bestAdd = oid;\n                }\n            }\n\n            if (bestAdd == -1) break;\n\n            applyInsert(cur.route, bestAdd, bestIns);\n            cur.used[bestAdd] = 1;\n            cur.selected.push_back(bestAdd);\n            cur.cost += bestIns.cost;\n        }\n\n        if ((int)cur.selected.size() != K) continue;\n\n        cur.cost = routeCost(cur.route);\n        routeLocalOptimize(cur, min(limitTime, elapsed() + 0.05), false);\n\n        if (cur.cost < best.cost) {\n            best = cur;\n        }\n    }\n\n    best.cost = routeCost(best.route);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    ords.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> ords[i].ax >> ords[i].ay >> ords[i].cx >> ords[i].cy;\n\n        int centerSum = mdist(DEP, DEP, ords[i].ax, ords[i].ay)\n                      + mdist(DEP, DEP, ords[i].cx, ords[i].cy);\n\n        int pairDist = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        ords[i].score = centerSum + pairDist / 2;\n    }\n\n    vector<int> allIds(N);\n    iota(allIds.begin(), allIds.end(), 0);\n\n    vector<int> sortedIds = allIds;\n    sort(sortedIds.begin(), sortedIds.end(), [](int a, int b) {\n        return ords[a].score < ords[b].score;\n    });\n\n    State best = constructGreedy(allIds, 1);\n    routeLocalOptimize(best, 0.35, true);\n\n    vector<int> centerPool;\n    for (int i = 0; i < 700; i++) centerPool.push_back(sortedIds[i]);\n\n    int iter = 0;\n\n    while (elapsed() < 1.05) {\n        vector<int> pool;\n\n        if (iter % 4 == 0) {\n            int base = sortedIds[rng.randint(0, 499)];\n            int cx = (ords[base].ax + ords[base].cx) / 2 + rng.randint(-80, 80);\n            int cy = (ords[base].ay + ords[base].cy) / 2 + rng.randint(-80, 80);\n\n            cx = max(150, min(650, cx));\n            cy = max(150, min(650, cy));\n\n            pool = makeClusterPool(cx, cy, 420);\n        } else if (iter % 4 == 1) {\n            pool = makeClusterPool(\n                400 + rng.randint(-160, 160),\n                400 + rng.randint(-160, 160),\n                420\n            );\n        } else {\n            pool = centerPool;\n        }\n\n        State cur = constructGreedy(pool, 7);\n        routeLocalOptimize(cur, min(1.20, elapsed() + 0.05), false);\n\n        if (cur.cost < best.cost) {\n            best = cur;\n        }\n\n        iter++;\n    }\n\n    routeLocalOptimize(best, 1.35, true);\n\n    vector<int> replaceCand;\n    for (int i = 0; i < 850; i++) replaceCand.push_back(sortedIds[i]);\n\n    replaceOptimize(best, replaceCand, 1.80);\n\n    destroyRepairOptimize(best, replaceCand, 1.92);\n\n    routeLocalOptimize(best, 1.97, true);\n\n    cout << K;\n    for (int oid : best.selected) {\n        cout << ' ' << oid + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (const Node& v : best.route) {\n        cout << ' ' << v.x << ' ' << v.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 400;\nstatic constexpr int M = 1995;\nstatic constexpr int SAMPLES = 96;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n};\n\nstruct DSU {\n    int16_t p[N];\n    int16_t sz[N];\n\n    inline void init() {\n        for (int i = 0; i < N; i++) {\n            p[i] = i;\n            sz[i] = 1;\n        }\n    }\n\n    inline int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    inline bool same(int a, int b) {\n        return find(a) == find(b);\n    }\n\n    inline bool unite(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n        if (ra == rb) return false;\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        return true;\n    }\n};\n\nstruct SmallDSU {\n    int16_t p[N];\n    int16_t sz[N];\n\n    inline void init(int n) {\n        for (int i = 0; i < n; i++) {\n            p[i] = i;\n            sz[i] = 1;\n        }\n    }\n\n    inline int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    inline bool same(int a, int b) {\n        return find(a) == find(b);\n    }\n\n    inline bool unite(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n        if (ra == rb) return false;\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        return true;\n    }\n};\n\nstatic uint16_t sampled_w[SAMPLES][M];\nstatic int16_t nxt_edge[SAMPLES][M];\nstatic int16_t prv_edge[SAMPLES][M];\nstatic int16_t head_edge[SAMPLES];\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<int16_t> u(M), v(M);\n    vector<int> d(M);\n\n    for (int i = 0; i < M; i++) {\n        int a, b;\n        cin >> a >> b;\n\n        u[i] = int16_t(a);\n        v[i] = int16_t(b);\n\n        long long dx = x[a] - x[b];\n        long long dy = y[a] - y[b];\n        d[i] = int(floor(sqrt(double(dx * dx + dy * dy)) + 0.5));\n    }\n\n    XorShift rng;\n\n    for (int s = 0; s < SAMPLES; s++) {\n        for (int i = 0; i < M; i++) {\n            sampled_w[s][i] = uint16_t(rng.randint(d[i], 3 * d[i]));\n        }\n    }\n\n    for (int s = 0; s < SAMPLES; s++) {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (sampled_w[s][a] != sampled_w[s][b]) {\n                return sampled_w[s][a] < sampled_w[s][b];\n            }\n            return a < b;\n        });\n\n        head_edge[s] = int16_t(ord[0]);\n\n        for (int i = 0; i < M; i++) {\n            int e = ord[i];\n            prv_edge[s][e] = int16_t(i == 0 ? -1 : ord[i - 1]);\n            nxt_edge[s][e] = int16_t(i + 1 == M ? -1 : ord[i + 1]);\n        }\n    }\n\n    DSU accepted;\n    accepted.init();\n\n    static int16_t root_to_cid[N];\n    static int16_t vertex_cid[N];\n\n    int accepted_edges = 0;\n\n    for (int cur = 0; cur < M; cur++) {\n        int len;\n        cin >> len;\n\n        // Remove current edge from all future-edge sorted lists.\n        for (int s = 0; s < SAMPLES; s++) {\n            int p = prv_edge[s][cur];\n            int n = nxt_edge[s][cur];\n\n            if (p == -1) head_edge[s] = int16_t(n);\n            else nxt_edge[s][p] = int16_t(n);\n\n            if (n != -1) prv_edge[s][n] = int16_t(p);\n        }\n\n        int answer = 0;\n\n        if (!accepted.same(u[cur], v[cur])) {\n            fill(root_to_cid, root_to_cid + N, int16_t(-1));\n\n            int comp_count = 0;\n            for (int i = 0; i < N; i++) {\n                int r = accepted.find(i);\n                if (root_to_cid[r] == -1) {\n                    root_to_cid[r] = int16_t(comp_count++);\n                }\n                vertex_cid[i] = root_to_cid[r];\n            }\n\n            int start_comp = vertex_cid[u[cur]];\n            int goal_comp = vertex_cid[v[cur]];\n\n            /*\n                Safety check:\n                If accepted edges + all future edges excluding current cannot\n                connect the graph, current edge is mandatory.\n            */\n            bool reject_possible = true;\n            {\n                SmallDSU reach;\n                reach.init(comp_count);\n\n                int c = comp_count;\n\n                for (int e = cur + 1; e < M; e++) {\n                    int a = vertex_cid[u[e]];\n                    int b = vertex_cid[v[e]];\n\n                    if (a == b) continue;\n\n                    if (reach.unite(a, b)) {\n                        c--;\n                        if (c == 1) break;\n                    }\n                }\n\n                if (c > 1) {\n                    reject_possible = false;\n                }\n            }\n\n            if (!reject_possible) {\n                answer = 1;\n            } else {\n                long long sum_delta = 0;\n\n                /*\n                    For each sampled future world:\n                    Run Kruskal after rejecting current edge only until the\n                    current endpoint components first become connected.\n\n                    In Kruskal's MST, this connection weight equals the maximum\n                    edge weight on the MST path between the endpoints.\n\n                    Forcing current edge changes the cost by:\n                        len - connection_weight\n                */\n                for (int s = 0; s < SAMPLES; s++) {\n                    SmallDSU dsu;\n                    dsu.init(comp_count);\n\n                    int connect_weight = 0;\n\n                    for (int e = head_edge[s]; e != -1; e = nxt_edge[s][e]) {\n                        int a = vertex_cid[u[e]];\n                        int b = vertex_cid[v[e]];\n\n                        if (a == b) continue;\n\n                        if (dsu.unite(a, b)) {\n                            if (dsu.same(start_comp, goal_comp)) {\n                                connect_weight = sampled_w[s][e];\n                                break;\n                            }\n                        }\n                    }\n\n                    sum_delta += (long long)len - connect_weight;\n                }\n\n                if (sum_delta < 0) {\n                    answer = 1;\n                }\n            }\n\n            if (answer) {\n                accepted.unite(u[cur], v[cur]);\n                accepted_edges++;\n            }\n        }\n\n        cout << answer << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct Task {\n    int sx, sy;\n    int wx, wy;\n};\n\nstruct Plan {\n    // kind: 0 = corner rectangle, 1 = strip\n    // corner ori: 0 TL, 1 TR, 2 BL, 3 BR\n    // strip  ori: 0 top, 1 bottom, 2 left, 3 right\n    int kind = 0;\n    int ori = 0;\n    int H = 10;\n    int W = 10;\n    int plannedPets = 0;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\n\nbool wall_[31][31];\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char mvChar[4] = {'U', 'D', 'L', 'R'};\nconst char buildChar[4] = {'u', 'd', 'l', 'r'};\n\nPlan plan_;\nint x1_, x2_, y1_, y2_;\nvector<Task> tasks;\n\nbool inBoard(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nbool passable(int x, int y) {\n    return inBoard(x, y) && !wall_[x][y];\n}\n\nvoid getBoundsParam(const Plan &p, int &x1, int &x2, int &y1, int &y2) {\n    if (p.kind == 0) {\n        int H = p.H;\n        int W = p.W;\n\n        if (p.ori == 0) {\n            x1 = 1; x2 = H; y1 = 1; y2 = W;\n        } else if (p.ori == 1) {\n            x1 = 1; x2 = H; y1 = 31 - W; y2 = 30;\n        } else if (p.ori == 2) {\n            x1 = 31 - H; x2 = 30; y1 = 1; y2 = W;\n        } else {\n            x1 = 31 - H; x2 = 30; y1 = 31 - W; y2 = 30;\n        }\n    } else {\n        int S = p.H;\n\n        if (p.ori == 0) {\n            x1 = 1; x2 = S; y1 = 1; y2 = 30;\n        } else if (p.ori == 1) {\n            x1 = 31 - S; x2 = 30; y1 = 1; y2 = 30;\n        } else if (p.ori == 2) {\n            x1 = 1; x2 = 30; y1 = 1; y2 = S;\n        } else {\n            x1 = 1; x2 = 30; y1 = 31 - S; y2 = 30;\n        }\n    }\n}\n\nvoid setRegionBounds() {\n    getBoundsParam(plan_, x1_, x2_, y1_, y2_);\n}\n\nbool insideRegion(int x, int y) {\n    return x1_ <= x && x <= x2_ && y1_ <= y && y <= y2_;\n}\n\nbool insideParam(int x, int y, const Plan &p) {\n    int a, b, c, d;\n    getBoundsParam(p, a, b, c, d);\n    return a <= x && x <= b && c <= y && y <= d;\n}\n\nint areaOfPlan(const Plan &p) {\n    if (p.kind == 0) return p.H * p.W;\n    return p.H * 30;\n}\n\nint taskCountOfPlan(const Plan &p) {\n    if (p.kind == 0) return p.H + p.W;\n    return 30;\n}\n\nint distToRegion(int x, int y, const Plan &p) {\n    int a, b, c, d;\n    getBoundsParam(p, a, b, c, d);\n\n    int res = 0;\n    if (x < a) res += a - x;\n    if (x > b) res += x - b;\n    if (y < c) res += c - y;\n    if (y > d) res += y - d;\n    return res;\n}\n\nint petsInsidePlan(const Plan &p) {\n    int cnt = 0;\n    for (auto &pet : pets) {\n        if (insideParam(pet.x, pet.y, p)) cnt++;\n    }\n    return cnt;\n}\n\nint petsInsideCurrent() {\n    int cnt = 0;\n    for (auto &pet : pets) {\n        if (insideRegion(pet.x, pet.y)) cnt++;\n    }\n    return cnt;\n}\n\nint humansInsideCurrent() {\n    int cnt = 0;\n    for (auto &h : humans) {\n        if (insideRegion(h.x, h.y)) cnt++;\n    }\n    return cnt;\n}\n\nvoid makeTasks() {\n    tasks.clear();\n    setRegionBounds();\n\n    if (plan_.kind == 0) {\n        int H = plan_.H;\n        int W = plan_.W;\n\n        if (plan_.ori == 0) {\n            for (int c = 1; c <= W; c++) tasks.push_back({H, c, H + 1, c});\n            for (int r = 1; r <= H; r++) tasks.push_back({r, W, r, W + 1});\n        } else if (plan_.ori == 1) {\n            int L = 31 - W;\n            for (int c = L; c <= 30; c++) tasks.push_back({H, c, H + 1, c});\n            for (int r = 1; r <= H; r++) tasks.push_back({r, L, r, L - 1});\n        } else if (plan_.ori == 2) {\n            int U = 31 - H;\n            for (int c = 1; c <= W; c++) tasks.push_back({U, c, U - 1, c});\n            for (int r = U; r <= 30; r++) tasks.push_back({r, W, r, W + 1});\n        } else {\n            int U = 31 - H;\n            int L = 31 - W;\n            for (int c = L; c <= 30; c++) tasks.push_back({U, c, U - 1, c});\n            for (int r = U; r <= 30; r++) tasks.push_back({r, L, r, L - 1});\n        }\n    } else {\n        int S = plan_.H;\n\n        if (plan_.ori == 0) {\n            for (int c = 1; c <= 30; c++) tasks.push_back({S, c, S + 1, c});\n        } else if (plan_.ori == 1) {\n            int U = 31 - S;\n            for (int c = 1; c <= 30; c++) tasks.push_back({U, c, U - 1, c});\n        } else if (plan_.ori == 2) {\n            for (int r = 1; r <= 30; r++) tasks.push_back({r, S, r, S + 1});\n        } else {\n            int L = 31 - S;\n            for (int r = 1; r <= 30; r++) tasks.push_back({r, L, r, L - 1});\n        }\n    }\n}\n\ndouble evaluatePlan(const Plan &p, bool conservativeStripPenalty) {\n    int pcnt = petsInsidePlan(p);\n\n    double avgDist = 0;\n    for (auto &h : humans) {\n        avgDist += distToRegion(h.x, h.y, p);\n    }\n    avgDist /= M;\n\n    int area = areaOfPlan(p);\n    int taskCnt = taskCountOfPlan(p);\n\n    double val = area * pow(0.5, pcnt)\n               - 1.8 * avgDist\n               - 0.35 * taskCnt;\n\n    if (p.kind == 1 && conservativeStripPenalty) {\n        val -= 25.0;\n        if (pcnt >= 3) val -= 100.0;\n    }\n\n    return val;\n}\n\nvoid selectPlan(bool allowAdvanced) {\n    Plan bestSquare;\n    double bestSquareVal = -1e100;\n\n    for (int ori = 0; ori < 4; ori++) {\n        for (int S = 8; S <= 18; S++) {\n            Plan p;\n            p.kind = 0;\n            p.ori = ori;\n            p.H = S;\n            p.W = S;\n            p.plannedPets = petsInsidePlan(p);\n\n            double val = evaluatePlan(p, false);\n\n            if (val > bestSquareVal) {\n                bestSquareVal = val;\n                bestSquare = p;\n            }\n        }\n    }\n\n    Plan best = bestSquare;\n    double bestVal = bestSquareVal;\n\n    if (allowAdvanced) {\n        for (int ori = 0; ori < 4; ori++) {\n            for (int H = 6; H <= 18; H++) {\n                for (int W = 6; W <= 18; W++) {\n                    int mn = min(H, W);\n                    int mx = max(H, W);\n                    if (mn * 2 < mx) continue;\n\n                    Plan p;\n                    p.kind = 0;\n                    p.ori = ori;\n                    p.H = H;\n                    p.W = W;\n                    p.plannedPets = petsInsidePlan(p);\n\n                    double val = evaluatePlan(p, false);\n\n                    if (val > bestVal + 18.0) {\n                        bestVal = val;\n                        best = p;\n                    }\n                }\n            }\n        }\n\n        for (int ori = 0; ori < 4; ori++) {\n            for (int S = 8; S <= 22; S++) {\n                Plan p;\n                p.kind = 1;\n                p.ori = ori;\n                p.H = S;\n                p.W = 30;\n                p.plannedPets = petsInsidePlan(p);\n\n                if (p.plannedPets > 2) continue;\n\n                double val = evaluatePlan(p, true);\n\n                if (val > bestVal + 40.0) {\n                    bestVal = val;\n                    best = p;\n                }\n            }\n        }\n    }\n\n    best.plannedPets = petsInsidePlan(best);\n    plan_ = best;\n    makeTasks();\n}\n\nbool allHumansInside() {\n    return humansInsideCurrent() == M;\n}\n\nbool allTasksDone() {\n    for (auto &t : tasks) {\n        if (!wall_[t.wx][t.wy]) return false;\n    }\n    return true;\n}\n\nchar dirFromTo(int x1, int y1, int x2, int y2, bool build) {\n    for (int d = 0; d < 4; d++) {\n        if (x1 + dx[d] == x2 && y1 + dy[d] == y2) {\n            return build ? buildChar[d] : mvChar[d];\n        }\n    }\n    return '.';\n}\n\nbool validBuildTarget(\n    int x,\n    int y,\n    const bool occH[31][31],\n    const bool occP[31][31]\n) {\n    if (!inBoard(x, y)) return false;\n    if (occH[x][y]) return false;\n    if (occP[x][y]) return false;\n\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n\n        if (inBoard(nx, ny) && occP[nx][ny]) return false;\n    }\n\n    return true;\n}\n\nvoid bfsAll(\n    int sx,\n    int sy,\n    const bool avoid[31][31],\n    bool restrictInside,\n    int dist[31][31],\n    char first[31][31]\n) {\n    for (int i = 1; i <= 30; i++) {\n        for (int j = 1; j <= 30; j++) {\n            dist[i][j] = -1;\n            first[i][j] = '.';\n        }\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();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n\n            if (!inBoard(nx, ny)) continue;\n            if (!passable(nx, ny)) continue;\n            if (avoid[nx][ny]) continue;\n            if (restrictInside && !insideRegion(nx, ny)) continue;\n            if (dist[nx][ny] != -1) continue;\n\n            dist[nx][ny] = dist[x][y] + 1;\n            first[nx][ny] = (x == sx && y == sy) ? mvChar[d] : first[x][y];\n            q.push({nx, ny});\n        }\n    }\n}\n\nchar bfsMove(\n    int sx,\n    int sy,\n    const vector<pair<int,int>> &targets,\n    const bool avoid[31][31],\n    bool restrictInside\n) {\n    if (targets.empty()) return '.';\n\n    bool isTarget[31][31] = {};\n    for (auto [x, y] : targets) {\n        if (!inBoard(x, y)) continue;\n        if (!passable(x, y)) continue;\n        if (restrictInside && !insideRegion(x, y)) continue;\n        isTarget[x][y] = true;\n    }\n\n    if (isTarget[sx][sy]) return '.';\n\n    int dist[31][31];\n    char first[31][31];\n    bfsAll(sx, sy, avoid, restrictInside, dist, first);\n\n    int bestD = 1e9;\n    char bestC = '.';\n\n    for (int x = 1; x <= 30; x++) {\n        for (int y = 1; y <= 30; y++) {\n            if (!isTarget[x][y]) continue;\n            if (dist[x][y] == -1) continue;\n\n            if (dist[x][y] < bestD) {\n                bestD = dist[x][y];\n                bestC = first[x][y];\n            }\n        }\n    }\n\n    return bestC;\n}\n\nvector<pair<int,int>> insideCells() {\n    vector<pair<int,int>> res;\n\n    for (int x = x1_; x <= x2_; x++) {\n        for (int y = y1_; y <= y2_; y++) {\n            if (passable(x, y)) res.push_back({x, y});\n        }\n    }\n\n    return res;\n}\n\npair<int,int> centerCell() {\n    return {(x1_ + x2_) / 2, (y1_ + y2_) / 2};\n}\n\nvoid assignMovesByDP(\n    string &ans,\n    const vector<pair<int,int>> &targetsRaw,\n    const bool avoid[31][31]\n) {\n    vector<pair<int,int>> targets;\n    bool seen[31][31] = {};\n\n    for (auto [x, y] : targetsRaw) {\n        if (!inBoard(x, y)) continue;\n        if (!passable(x, y)) continue;\n        if (!insideRegion(x, y)) continue;\n        if (seen[x][y]) continue;\n\n        seen[x][y] = true;\n        targets.push_back({x, y});\n    }\n\n    if (targets.empty()) return;\n\n    vector<int> ids;\n    for (int i = 0; i < M; i++) {\n        if (ans[i] == '.' && insideRegion(humans[i].x, humans[i].y)) {\n            ids.push_back(i);\n        }\n    }\n\n    int K = ids.size();\n    int T = targets.size();\n\n    if (K == 0) return;\n\n    vector<vector<int>> distHT(K, vector<int>(T, -1));\n    vector<vector<char>> firstHT(K, vector<char>(T, '.'));\n\n    for (int i = 0; i < K; i++) {\n        int hid = ids[i];\n\n        int dist[31][31];\n        char first[31][31];\n\n        bfsAll(\n            humans[hid].x,\n            humans[hid].y,\n            avoid,\n            true,\n            dist,\n            first\n        );\n\n        for (int j = 0; j < T; j++) {\n            auto [tx, ty] = targets[j];\n            distHT[i][j] = dist[tx][ty];\n            firstHT[i][j] = first[tx][ty];\n        }\n    }\n\n    const int INF = 1e9;\n    int FULL = 1 << K;\n\n    vector<vector<int>> dp(T + 1, vector<int>(FULL, INF));\n    vector<vector<int>> parMask(T + 1, vector<int>(FULL, -1));\n    vector<vector<int>> parHuman(T + 1, vector<int>(FULL, -2));\n\n    dp[0][0] = 0;\n\n    for (int t = 0; t < T; t++) {\n        for (int mask = 0; mask < FULL; mask++) {\n            if (dp[t][mask] >= INF) continue;\n\n            if (dp[t][mask] < dp[t + 1][mask]) {\n                dp[t + 1][mask] = dp[t][mask];\n                parMask[t + 1][mask] = mask;\n                parHuman[t + 1][mask] = -1;\n            }\n\n            for (int h = 0; h < K; h++) {\n                if (mask >> h & 1) continue;\n                if (distHT[h][t] == -1) continue;\n\n                int nmask = mask | (1 << h);\n                int nd = dp[t][mask] + distHT[h][t];\n\n                if (nd < dp[t + 1][nmask]) {\n                    dp[t + 1][nmask] = nd;\n                    parMask[t + 1][nmask] = mask;\n                    parHuman[t + 1][nmask] = h;\n                }\n            }\n        }\n    }\n\n    int bestMask = 0;\n    int bestPop = -1;\n    int bestCost = INF;\n\n    for (int mask = 0; mask < FULL; mask++) {\n        if (dp[T][mask] >= INF) continue;\n\n        int pc = __builtin_popcount((unsigned)mask);\n\n        if (pc > bestPop || (pc == bestPop && dp[T][mask] < bestCost)) {\n            bestPop = pc;\n            bestCost = dp[T][mask];\n            bestMask = mask;\n        }\n    }\n\n    vector<int> assignedTarget(K, -1);\n    int mask = bestMask;\n\n    for (int t = T; t >= 1; t--) {\n        int ph = parHuman[t][mask];\n        int pm = parMask[t][mask];\n\n        if (ph >= 0) {\n            assignedTarget[ph] = t - 1;\n        }\n\n        if (pm == -1) break;\n        mask = pm;\n    }\n\n    for (int h = 0; h < K; h++) {\n        int hid = ids[h];\n\n        if (assignedTarget[h] != -1) {\n            int t = assignedTarget[h];\n            ans[hid] = firstHT[h][t];\n        } else {\n            ans[hid] = bfsMove(\n                humans[hid].x,\n                humans[hid].y,\n                targets,\n                avoid,\n                true\n            );\n        }\n    }\n}\n\nbool enoughHumansForBuild(int turn) {\n    if (allHumansInside()) return true;\n\n    int cnt = humansInsideCurrent();\n\n    // Conservative early-start rule:\n    // only for strips, because losing one late human can be acceptable\n    // if it lets a large wall finish much earlier.\n    if (plan_.kind == 1 && cnt >= M - 1) {\n        if (M >= 7 && turn >= 45) return true;\n        if (turn >= 70) return true;\n    }\n\n    return false;\n}\n\nvoid applyHumanActions(const string &ans) {\n    for (int i = 0; i < M; i++) {\n        char a = ans[i];\n\n        if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n            for (int d = 0; d < 4; d++) {\n                if (a == mvChar[d]) {\n                    humans[i].x += dx[d];\n                    humans[i].y += dy[d];\n                }\n            }\n        } else if (a == 'u' || a == 'd' || a == 'l' || a == 'r') {\n            for (int d = 0; d < 4; d++) {\n                if (a == buildChar[d]) {\n                    int wx = humans[i].x + dx[d];\n                    int wy = humans[i].y + dy[d];\n\n                    if (inBoard(wx, wy)) {\n                        wall_[wx][wy] = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid readPetMoves() {\n    for (int i = 0; i < N; i++) {\n        string s;\n        if (!(cin >> s)) exit(0);\n\n        if (s == \".\") continue;\n\n        for (char c : s) {\n            if (c == 'U') pets[i].x--;\n            else if (c == 'D') pets[i].x++;\n            else if (c == 'L') pets[i].y--;\n            else if (c == 'R') pets[i].y++;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pets.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n\n    cin >> M;\n    humans.resize(M);\n\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    memset(wall_, false, sizeof(wall_));\n\n    selectPlan(true);\n\n    bool startedBuild = false;\n    bool replanned = false;\n\n    for (int turn = 0; turn < 300; turn++) {\n        bool occH[31][31] = {};\n        bool occP[31][31] = {};\n\n        for (auto &h : humans) occH[h.x][h.y] = true;\n        for (auto &p : pets) occP[p.x][p.y] = true;\n\n        string ans(M, '.');\n        bool avoid[31][31] = {};\n\n        if (\n            !startedBuild &&\n            !replanned &&\n            turn >= 80 &&\n            enoughHumansForBuild(turn) &&\n            petsInsideCurrent() >= 2\n        ) {\n            replanned = true;\n            selectPlan(true);\n        }\n\n        if (!startedBuild && !enoughHumansForBuild(turn)) {\n            auto targets = insideCells();\n\n            for (int i = 0; i < M; i++) {\n                ans[i] = bfsMove(\n                    humans[i].x,\n                    humans[i].y,\n                    targets,\n                    avoid,\n                    false\n                );\n            }\n        } else {\n            if (!startedBuild) {\n                int curPets = petsInsideCurrent();\n\n                if (plan_.plannedPets == 0) {\n                    if (curPets == 0 || turn >= 105) {\n                        startedBuild = true;\n                    }\n                } else {\n                    if (turn >= 35 || curPets <= plan_.plannedPets) {\n                        startedBuild = true;\n                    }\n                }\n            }\n\n            if (!startedBuild) {\n                auto c = centerCell();\n                vector<pair<int,int>> centerTargets = {c};\n                auto insideTargets = insideCells();\n\n                for (int i = 0; i < M; i++) {\n                    if (insideRegion(humans[i].x, humans[i].y)) {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            centerTargets,\n                            avoid,\n                            true\n                        );\n                    } else {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            insideTargets,\n                            avoid,\n                            false\n                        );\n                    }\n                }\n            } else if (!allTasksDone()) {\n                bool scheduledWall[31][31] = {};\n\n                // Build immediately if already standing at a valid construction cell.\n                for (int i = 0; i < M; i++) {\n                    int hx = humans[i].x;\n                    int hy = humans[i].y;\n\n                    for (auto &t : tasks) {\n                        if (wall_[t.wx][t.wy]) continue;\n                        if (scheduledWall[t.wx][t.wy]) continue;\n                        if (t.sx != hx || t.sy != hy) continue;\n                        if (!validBuildTarget(t.wx, t.wy, occH, occP)) continue;\n\n                        ans[i] = dirFromTo(hx, hy, t.wx, t.wy, true);\n                        scheduledWall[t.wx][t.wy] = true;\n                        avoid[t.wx][t.wy] = true;\n                        break;\n                    }\n                }\n\n                vector<pair<int,int>> goodTargets;\n                vector<pair<int,int>> fallbackTargets;\n\n                for (auto &t : tasks) {\n                    if (wall_[t.wx][t.wy]) continue;\n                    if (scheduledWall[t.wx][t.wy]) continue;\n\n                    fallbackTargets.push_back({t.sx, t.sy});\n\n                    if (validBuildTarget(t.wx, t.wy, occH, occP)) {\n                        goodTargets.push_back({t.sx, t.sy});\n                    }\n                }\n\n                if (goodTargets.empty()) goodTargets = fallbackTargets;\n\n                // Humans outside the planned region still try to enter.\n                auto insideTargets = insideCells();\n\n                for (int i = 0; i < M; i++) {\n                    if (ans[i] != '.') continue;\n\n                    if (!insideRegion(humans[i].x, humans[i].y)) {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            insideTargets,\n                            avoid,\n                            false\n                        );\n                    }\n                }\n\n                // Inside humans are assigned to unfinished tasks by min-cost matching.\n                assignMovesByDP(ans, goodTargets, avoid);\n            } else {\n                auto c = centerCell();\n                vector<pair<int,int>> centerTargets = {c};\n                auto insideTargets = insideCells();\n\n                for (int i = 0; i < M; i++) {\n                    if (insideRegion(humans[i].x, humans[i].y)) {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            centerTargets,\n                            avoid,\n                            true\n                        );\n                    } else {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            insideTargets,\n                            avoid,\n                            false\n                        );\n                    }\n                }\n            }\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        applyHumanActions(ans);\n        readPetMoves();\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int V = 400;\nstatic const int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble p_fail, p_succ;\nstring hwall[20], vwall[19];\n\nint start_id, target_id;\nint nxt_cell[4][V];\nint dist_to_t[V];\n\nusing PotTable = array<array<float, V>, MAXL + 1>;\nPotTable pot_nb, pot_mean;\n\nconst string DIRS = \"UDLR\";\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos_of(int x) {\n    return {x / N, x % N};\n}\n\nint dir_id(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\nstruct Node {\n    array<float, V> prob;\n    array<char, MAXL> path;\n    float score;\n    float eval;\n};\n\nvoid build_graph() {\n    for (int x = 0; x < V; x++) {\n        auto [i, j] = pos_of(x);\n\n        if (i == 0 || vwall[i - 1][j] == '1') nxt_cell[0][x] = x;\n        else nxt_cell[0][x] = id(i - 1, j);\n\n        if (i == N - 1 || vwall[i][j] == '1') nxt_cell[1][x] = x;\n        else nxt_cell[1][x] = id(i + 1, j);\n\n        if (j == 0 || hwall[i][j - 1] == '1') nxt_cell[2][x] = x;\n        else nxt_cell[2][x] = id(i, j - 1);\n\n        if (j == N - 1 || hwall[i][j] == '1') nxt_cell[3][x] = x;\n        else nxt_cell[3][x] = id(i, j + 1);\n    }\n}\n\nvoid bfs_distance() {\n    const int INF = 1e9;\n    fill(dist_to_t, dist_to_t + V, INF);\n\n    queue<int> q;\n    dist_to_t[target_id] = 0;\n    q.push(target_id);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int to = nxt_cell[d][v];\n            if (to == v) continue;\n\n            if (dist_to_t[to] > dist_to_t[v] + 1) {\n                dist_to_t[to] = dist_to_t[v] + 1;\n                q.push(to);\n            }\n        }\n    }\n}\n\nvoid build_mean_potential() {\n    for (int t = 0; t <= MAXL; t++) {\n        int rem = MAXL - t;\n\n        for (int c = 0; c < V; c++) {\n            int d = dist_to_t[c];\n\n            if (d > rem) {\n                pot_mean[t][c] = 0.0f;\n                continue;\n            }\n\n            double val = 401.0 - t - d / p_succ;\n            if (val < 0.0) val = 0.0;\n            pot_mean[t][c] = (float)val;\n        }\n    }\n}\n\nvoid build_nb_potential() {\n    static double hit_prob[MAXL + 1][MAXL + 1];\n    static double hit_ksum[MAXL + 1][MAXL + 1];\n\n    for (int rem = 0; rem <= MAXL; rem++) {\n        hit_prob[rem][0] = 1.0;\n        hit_ksum[rem][0] = 0.0;\n\n        for (int d = 1; d <= rem; d++) {\n            double pr = pow(p_succ, d);\n            double psum = 0.0;\n            double ksum = 0.0;\n\n            for (int k = d; k <= rem; k++) {\n                psum += pr;\n                ksum += pr * k;\n\n                if (k < rem) {\n                    pr *= (double)k / (double)(k - d + 1) * p_fail;\n                }\n            }\n\n            hit_prob[rem][d] = psum;\n            hit_ksum[rem][d] = ksum;\n        }\n    }\n\n    for (int t = 0; t <= MAXL; t++) {\n        int rem = MAXL - t;\n\n        for (int c = 0; c < V; c++) {\n            int d = dist_to_t[c];\n\n            if (d > rem) {\n                pot_nb[t][c] = 0.0f;\n                continue;\n            }\n\n            double finite = (401.0 - t) * hit_prob[rem][d] - hit_ksum[rem][d];\n\n            double mean = 401.0 - t - d / p_succ;\n            if (mean < 0.0) mean = 0.0;\n\n            double val = 0.82 * finite + 0.18 * mean;\n            if (val < 0.0) val = 0.0;\n\n            pot_nb[t][c] = (float)val;\n        }\n    }\n}\n\ndouble evaluate_string(const string& s) {\n    static double cur[V], nxt[V];\n\n    for (int i = 0; i < V; i++) cur[i] = 0.0;\n    cur[start_id] = 1.0;\n\n    double score = 0.0;\n\n    for (int t = 0; t < (int)s.size(); t++) {\n        int dir = dir_id(s[t]);\n\n        for (int i = 0; i < V; i++) nxt[i] = 0.0;\n\n        double arrive = 0.0;\n        double remain = 0.0;\n\n        for (int c = 0; c < V; c++) {\n            double pr = cur[c];\n            if (pr < 1e-18) continue;\n\n            int to = nxt_cell[dir][c];\n\n            if (to == target_id) {\n                arrive += pr * p_succ;\n                nxt[c] += pr * p_fail;\n            } else if (to == c) {\n                nxt[c] += pr;\n            } else {\n                nxt[c] += pr * p_fail;\n                nxt[to] += pr * p_succ;\n            }\n        }\n\n        score += arrive * (400 - t);\n\n        for (int i = 0; i < V; i++) {\n            cur[i] = nxt[i];\n            remain += cur[i];\n        }\n\n        if (remain < 1e-18) break;\n    }\n\n    return score;\n}\n\nstring beam_search(const PotTable& pot, int beam_width) {\n    vector<Node> beam;\n    beam.reserve(beam_width);\n\n    Node init;\n    init.prob.fill(0.0f);\n    init.prob[start_id] = 1.0f;\n    init.score = 0.0f;\n    init.eval = pot[0][start_id];\n\n    beam.push_back(init);\n\n    for (int depth = 0; depth < MAXL; depth++) {\n        vector<Node> cand;\n        cand.reserve(beam.size() * 4);\n\n        for (const Node& par : beam) {\n            for (int dir = 0; dir < 4; dir++) {\n                Node ch;\n                ch.prob.fill(0.0f);\n\n                if (depth > 0) {\n                    memcpy(ch.path.data(), par.path.data(), depth);\n                }\n                ch.path[depth] = DIRS[dir];\n\n                float arrive = 0.0f;\n\n                for (int c = 0; c < V; c++) {\n                    float pr = par.prob[c];\n                    if (pr < 1e-12f) continue;\n\n                    int to = nxt_cell[dir][c];\n\n                    if (to == target_id) {\n                        arrive += pr * (float)p_succ;\n                        ch.prob[c] += pr * (float)p_fail;\n                    } else if (to == c) {\n                        ch.prob[c] += pr;\n                    } else {\n                        ch.prob[c] += pr * (float)p_fail;\n                        ch.prob[to] += pr * (float)p_succ;\n                    }\n                }\n\n                int nt = depth + 1;\n                ch.score = par.score + arrive * (400 - depth);\n\n                double future = 0.0;\n                for (int c = 0; c < V; c++) {\n                    float pr = ch.prob[c];\n                    if (pr < 1e-12f) continue;\n                    future += pr * pot[nt][c];\n                }\n\n                ch.eval = (float)(ch.score + future);\n                cand.push_back(std::move(ch));\n            }\n        }\n\n        if ((int)cand.size() > beam_width) {\n            nth_element(\n                cand.begin(),\n                cand.begin() + beam_width,\n                cand.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            );\n            cand.resize(beam_width);\n        }\n\n        beam.swap(cand);\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)beam.size(); i++) {\n        if (beam[i].score > beam[best].score) best = i;\n    }\n\n    string res;\n    res.reserve(MAXL);\n    for (int i = 0; i < MAXL; i++) res.push_back(beam[best].path[i]);\n    return res;\n}\n\nstring shortest_path_by_order(const vector<int>& order) {\n    string res;\n    int cur = start_id;\n\n    while (cur != target_id && (int)res.size() < MAXL) {\n        bool moved = false;\n\n        for (int d : order) {\n            int to = nxt_cell[d][cur];\n\n            if (to != cur && dist_to_t[to] == dist_to_t[cur] - 1) {\n                res.push_back(DIRS[d]);\n                cur = to;\n                moved = true;\n                break;\n            }\n        }\n\n        if (!moved) break;\n    }\n\n    return res;\n}\n\nstring random_shortest_path(mt19937& rng) {\n    string res;\n    int cur = start_id;\n\n    while (cur != target_id && (int)res.size() < MAXL) {\n        vector<int> ds;\n\n        for (int d = 0; d < 4; d++) {\n            int to = nxt_cell[d][cur];\n            if (to != cur && dist_to_t[to] == dist_to_t[cur] - 1) {\n                ds.push_back(d);\n            }\n        }\n\n        if (ds.empty()) break;\n\n        int d = ds[rng() % ds.size()];\n        res.push_back(DIRS[d]);\n        cur = nxt_cell[d][cur];\n    }\n\n    return res;\n}\n\nstring make_cycle_pattern(const string& base) {\n    if (base.empty()) return string(MAXL, 'D');\n\n    string s;\n    s.reserve(MAXL);\n\n    int k = 0;\n    while ((int)s.size() < MAXL) {\n        s.push_back(base[k]);\n        k++;\n        if (k == (int)base.size()) k = 0;\n    }\n\n    return s;\n}\n\nstring make_repeat_each_pattern(const string& base, int rep) {\n    if (base.empty()) return string(MAXL, 'D');\n\n    string s;\n    s.reserve(MAXL);\n\n    while ((int)s.size() < MAXL) {\n        for (char c : base) {\n            for (int r = 0; r < rep && (int)s.size() < MAXL; r++) {\n                s.push_back(c);\n            }\n            if ((int)s.size() >= MAXL) break;\n        }\n    }\n\n    return s;\n}\n\nstring repeat_pattern(const string& pat) {\n    string s;\n    s.reserve(MAXL);\n\n    while ((int)s.size() < MAXL) {\n        for (char c : pat) {\n            if ((int)s.size() >= MAXL) break;\n            s.push_back(c);\n        }\n    }\n\n    return s;\n}\n\nstring greedy_with_potential(const PotTable& pot) {\n    array<float, V> cur{}, nxt{};\n    cur.fill(0.0f);\n    cur[start_id] = 1.0f;\n\n    string s;\n    s.reserve(MAXL);\n\n    double score = 0.0;\n\n    for (int t = 0; t < MAXL; t++) {\n        int best_dir = 0;\n        double best_eval = -1e100;\n\n        for (int dir = 0; dir < 4; dir++) {\n            nxt.fill(0.0f);\n            double arrive = 0.0;\n\n            for (int c = 0; c < V; c++) {\n                float pr = cur[c];\n                if (pr < 1e-12f) continue;\n\n                int to = nxt_cell[dir][c];\n\n                if (to == target_id) {\n                    arrive += pr * p_succ;\n                    nxt[c] += pr * (float)p_fail;\n                } else if (to == c) {\n                    nxt[c] += pr;\n                } else {\n                    nxt[c] += pr * (float)p_fail;\n                    nxt[to] += pr * (float)p_succ;\n                }\n            }\n\n            double future = 0.0;\n            for (int c = 0; c < V; c++) {\n                if (nxt[c] < 1e-12f) continue;\n                future += nxt[c] * pot[t + 1][c];\n            }\n\n            double ev = score + arrive * (400 - t) + future;\n\n            if (ev > best_eval) {\n                best_eval = ev;\n                best_dir = dir;\n            }\n        }\n\n        s.push_back(DIRS[best_dir]);\n\n        nxt.fill(0.0f);\n        double arrive = 0.0;\n\n        for (int c = 0; c < V; c++) {\n            float pr = cur[c];\n            if (pr < 1e-12f) continue;\n\n            int to = nxt_cell[best_dir][c];\n\n            if (to == target_id) {\n                arrive += pr * p_succ;\n                nxt[c] += pr * (float)p_fail;\n            } else if (to == c) {\n                nxt[c] += pr;\n            } else {\n                nxt[c] += pr * (float)p_fail;\n                nxt[to] += pr * (float)p_succ;\n            }\n        }\n\n        score += arrive * (400 - t);\n        cur = nxt;\n    }\n\n    return s;\n}\n\nvector<string> generate_path_candidates() {\n    vector<string> cand;\n\n    vector<int> perm = {0, 1, 2, 3};\n\n    do {\n        string p = shortest_path_by_order(perm);\n        if (p.empty()) continue;\n\n        cand.push_back(make_cycle_pattern(p));\n\n        for (int r = 2; r <= 7; r++) {\n            cand.push_back(make_repeat_each_pattern(p, r));\n        }\n    } while (next_permutation(perm.begin(), perm.end()));\n\n    mt19937 rng(\n        987654321u\n        ^ (unsigned)(si_ * 100000 + sj_ * 10000 + ti_ * 1000 + tj_ * 100)\n        ^ (unsigned)(p_fail * 10000)\n    );\n\n    for (int k = 0; k < 60; k++) {\n        string p = random_shortest_path(rng);\n        if (p.empty()) continue;\n\n        cand.push_back(make_cycle_pattern(p));\n\n        int r = 2 + (rng() % 6);\n        cand.push_back(make_repeat_each_pattern(p, r));\n    }\n\n    cand.push_back(repeat_pattern(\"DR\"));\n    cand.push_back(repeat_pattern(\"RD\"));\n    cand.push_back(repeat_pattern(\"DDRR\"));\n    cand.push_back(repeat_pattern(\"RRDD\"));\n    cand.push_back(repeat_pattern(\"DRDRR\"));\n    cand.push_back(repeat_pattern(\"RDRDD\"));\n\n    return cand;\n}\n\nstatic double F[MAXL + 1][V];\nstatic double B[MAXL + 1][V];\nstatic double pref_score[MAXL + 1];\n\ndouble step_value(int t, int c, int dir, const double* next_val) {\n    int to = nxt_cell[dir][c];\n\n    if (to == target_id) {\n        return p_succ * (400 - t) + p_fail * next_val[c];\n    } else if (to == c) {\n        return next_val[c];\n    } else {\n        return p_fail * next_val[c] + p_succ * next_val[to];\n    }\n}\n\ndouble pair_value(int t, int c, int d1, int d2, const double* next2_val) {\n    int to = nxt_cell[d1][c];\n\n    if (to == target_id) {\n        return p_succ * (400 - t) + p_fail * step_value(t + 1, c, d2, next2_val);\n    } else if (to == c) {\n        return step_value(t + 1, c, d2, next2_val);\n    } else {\n        return p_fail * step_value(t + 1, c, d2, next2_val)\n             + p_succ * step_value(t + 1, to, d2, next2_val);\n    }\n}\n\ndouble triple_value(int t, int c, int d1, int d2, int d3, const double* next3_val) {\n    int to = nxt_cell[d1][c];\n\n    if (to == target_id) {\n        return p_succ * (400 - t) + p_fail * pair_value(t + 1, c, d2, d3, next3_val);\n    } else if (to == c) {\n        return pair_value(t + 1, c, d2, d3, next3_val);\n    } else {\n        return p_fail * pair_value(t + 1, c, d2, d3, next3_val)\n             + p_succ * pair_value(t + 1, to, d2, d3, next3_val);\n    }\n}\n\ndouble quad_value(int t, int c, int d1, int d2, int d3, int d4, const double* next4_val) {\n    int to = nxt_cell[d1][c];\n\n    if (to == target_id) {\n        return p_succ * (400 - t) + p_fail * triple_value(t + 1, c, d2, d3, d4, next4_val);\n    } else if (to == c) {\n        return triple_value(t + 1, c, d2, d3, d4, next4_val);\n    } else {\n        return p_fail * triple_value(t + 1, c, d2, d3, d4, next4_val)\n             + p_succ * triple_value(t + 1, to, d2, d3, d4, next4_val);\n    }\n}\n\ndouble quint_value(int t, int c, int d1, int d2, int d3, int d4, int d5, const double* next5_val) {\n    int to = nxt_cell[d1][c];\n\n    if (to == target_id) {\n        return p_succ * (400 - t) + p_fail * quad_value(t + 1, c, d2, d3, d4, d5, next5_val);\n    } else if (to == c) {\n        return quad_value(t + 1, c, d2, d3, d4, d5, next5_val);\n    } else {\n        return p_fail * quad_value(t + 1, c, d2, d3, d4, d5, next5_val)\n             + p_succ * quad_value(t + 1, to, d2, d3, d4, d5, next5_val);\n    }\n}\n\nvoid exact_local_limited(\n    string& ans,\n    chrono::steady_clock::time_point start_time,\n    double deadline,\n    int max_iter,\n    bool use_triple,\n    bool use_quad,\n    bool use_quint\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    int L = ans.size();\n\n    for (int iter = 0; iter < max_iter && elapsed() < deadline; iter++) {\n        for (int t = 0; t <= L; t++) {\n            for (int c = 0; c < V; c++) {\n                F[t][c] = 0.0;\n                B[t][c] = 0.0;\n            }\n        }\n\n        F[0][start_id] = 1.0;\n        pref_score[0] = 0.0;\n\n        for (int t = 0; t < L; t++) {\n            int dir = dir_id(ans[t]);\n            double arrive = 0.0;\n\n            for (int c = 0; c < V; c++) {\n                double pr = F[t][c];\n                if (pr < 1e-18) continue;\n\n                int to = nxt_cell[dir][c];\n\n                if (to == target_id) {\n                    arrive += pr * p_succ;\n                    F[t + 1][c] += pr * p_fail;\n                } else if (to == c) {\n                    F[t + 1][c] += pr;\n                } else {\n                    F[t + 1][c] += pr * p_fail;\n                    F[t + 1][to] += pr * p_succ;\n                }\n            }\n\n            pref_score[t + 1] = pref_score[t] + arrive * (400 - t);\n        }\n\n        for (int c = 0; c < V; c++) B[L][c] = 0.0;\n\n        for (int t = L - 1; t >= 0; t--) {\n            int dir = dir_id(ans[t]);\n            for (int c = 0; c < V; c++) {\n                B[t][c] = step_value(t, c, dir, B[t + 1]);\n            }\n        }\n\n        double best_score = pref_score[L];\n\n        int best_type = 0;\n        int best_pos = -1;\n        char best_c1 = 0, best_c2 = 0, best_c3 = 0, best_c4 = 0, best_c5 = 0;\n\n        for (int t = 0; t < L; t++) {\n            if (elapsed() > deadline) break;\n\n            char orig = ans[t];\n\n            for (char nc : DIRS) {\n                if (nc == orig) continue;\n\n                int nd = dir_id(nc);\n                double sc = pref_score[t];\n\n                for (int c = 0; c < V; c++) {\n                    double pr = F[t][c];\n                    if (pr < 1e-18) continue;\n                    sc += pr * step_value(t, c, nd, B[t + 1]);\n                }\n\n                if (sc > best_score + 1e-11) {\n                    best_score = sc;\n                    best_type = 1;\n                    best_pos = t;\n                    best_c1 = nc;\n                }\n            }\n        }\n\n        for (int t = 0; t + 1 < L; t++) {\n            if (elapsed() > deadline) break;\n\n            char o1 = ans[t];\n            char o2 = ans[t + 1];\n\n            for (char c1 : DIRS) {\n                for (char c2 : DIRS) {\n                    if (c1 == o1 && c2 == o2) continue;\n\n                    int d1 = dir_id(c1);\n                    int d2 = dir_id(c2);\n\n                    double sc = pref_score[t];\n\n                    for (int c = 0; c < V; c++) {\n                        double pr = F[t][c];\n                        if (pr < 1e-18) continue;\n                        sc += pr * pair_value(t, c, d1, d2, B[t + 2]);\n                    }\n\n                    if (sc > best_score + 1e-11) {\n                        best_score = sc;\n                        best_type = 2;\n                        best_pos = t;\n                        best_c1 = c1;\n                        best_c2 = c2;\n                    }\n                }\n            }\n        }\n\n        if (use_triple && best_type == 0) {\n            for (int t = 0; t + 2 < L; t++) {\n                if (elapsed() > deadline) break;\n\n                char o1 = ans[t];\n                char o2 = ans[t + 1];\n                char o3 = ans[t + 2];\n\n                for (char c1 : DIRS) {\n                    for (char c2 : DIRS) {\n                        for (char c3 : DIRS) {\n                            if (c1 == o1 && c2 == o2 && c3 == o3) continue;\n\n                            int d1 = dir_id(c1);\n                            int d2 = dir_id(c2);\n                            int d3 = dir_id(c3);\n\n                            double sc = pref_score[t];\n\n                            for (int c = 0; c < V; c++) {\n                                double pr = F[t][c];\n                                if (pr < 1e-18) continue;\n                                sc += pr * triple_value(t, c, d1, d2, d3, B[t + 3]);\n                            }\n\n                            if (sc > best_score + 1e-11) {\n                                best_score = sc;\n                                best_type = 3;\n                                best_pos = t;\n                                best_c1 = c1;\n                                best_c2 = c2;\n                                best_c3 = c3;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        if (use_quad && best_type == 0) {\n            for (int t = 0; t + 3 < L; t++) {\n                if (elapsed() > deadline) break;\n\n                char o1 = ans[t];\n                char o2 = ans[t + 1];\n                char o3 = ans[t + 2];\n                char o4 = ans[t + 3];\n\n                for (char c1 : DIRS) {\n                    for (char c2 : DIRS) {\n                        for (char c3 : DIRS) {\n                            for (char c4 : DIRS) {\n                                if (c1 == o1 && c2 == o2 && c3 == o3 && c4 == o4) continue;\n\n                                int d1 = dir_id(c1);\n                                int d2 = dir_id(c2);\n                                int d3 = dir_id(c3);\n                                int d4 = dir_id(c4);\n\n                                double sc = pref_score[t];\n\n                                for (int c = 0; c < V; c++) {\n                                    double pr = F[t][c];\n                                    if (pr < 1e-18) continue;\n                                    sc += pr * quad_value(t, c, d1, d2, d3, d4, B[t + 4]);\n                                }\n\n                                if (sc > best_score + 1e-11) {\n                                    best_score = sc;\n                                    best_type = 4;\n                                    best_pos = t;\n                                    best_c1 = c1;\n                                    best_c2 = c2;\n                                    best_c3 = c3;\n                                    best_c4 = c4;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        if (use_quint && best_type == 0) {\n            for (int t = 0; t + 4 < L; t++) {\n                if (elapsed() > deadline) break;\n\n                char o1 = ans[t];\n                char o2 = ans[t + 1];\n                char o3 = ans[t + 2];\n                char o4 = ans[t + 3];\n                char o5 = ans[t + 4];\n\n                for (char c1 : DIRS) {\n                    for (char c2 : DIRS) {\n                        for (char c3 : DIRS) {\n                            for (char c4 : DIRS) {\n                                for (char c5 : DIRS) {\n                                    if (c1 == o1 && c2 == o2 && c3 == o3 && c4 == o4 && c5 == o5) continue;\n\n                                    int d1 = dir_id(c1);\n                                    int d2 = dir_id(c2);\n                                    int d3 = dir_id(c3);\n                                    int d4 = dir_id(c4);\n                                    int d5 = dir_id(c5);\n\n                                    double sc = pref_score[t];\n\n                                    for (int c = 0; c < V; c++) {\n                                        double pr = F[t][c];\n                                        if (pr < 1e-18) continue;\n                                        sc += pr * quint_value(t, c, d1, d2, d3, d4, d5, B[t + 5]);\n                                    }\n\n                                    if (sc > best_score + 1e-11) {\n                                        best_score = sc;\n                                        best_type = 5;\n                                        best_pos = t;\n                                        best_c1 = c1;\n                                        best_c2 = c2;\n                                        best_c3 = c3;\n                                        best_c4 = c4;\n                                        best_c5 = c5;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        if (best_type == 0) break;\n\n        if (best_type == 1) {\n            ans[best_pos] = best_c1;\n        } else if (best_type == 2) {\n            ans[best_pos] = best_c1;\n            ans[best_pos + 1] = best_c2;\n        } else if (best_type == 3) {\n            ans[best_pos] = best_c1;\n            ans[best_pos + 1] = best_c2;\n            ans[best_pos + 2] = best_c3;\n        } else if (best_type == 4) {\n            ans[best_pos] = best_c1;\n            ans[best_pos + 1] = best_c2;\n            ans[best_pos + 2] = best_c3;\n            ans[best_pos + 3] = best_c4;\n        } else {\n            ans[best_pos] = best_c1;\n            ans[best_pos + 1] = best_c2;\n            ans[best_pos + 2] = best_c3;\n            ans[best_pos + 3] = best_c4;\n            ans[best_pos + 4] = best_c5;\n        }\n    }\n}\n\nvoid random_escape(string& ans, chrono::steady_clock::time_point start_time, double deadline) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    double best_score = evaluate_string(ans);\n\n    mt19937 rng(\n        1234567u\n        ^ (unsigned)(si_ * 100000 + sj_ * 10000 + ti_ * 1000 + tj_ * 100)\n        ^ (unsigned)(p_fail * 1000)\n    );\n\n    while (elapsed() < deadline) {\n        int a = rng() % ans.size();\n        int b = rng() % ans.size();\n        if (a == b) continue;\n\n        char oa = ans[a], ob = ans[b];\n\n        char na = DIRS[rng() % 4];\n        char nb = DIRS[rng() % 4];\n\n        if (na == oa && nb == ob) continue;\n\n        ans[a] = na;\n        ans[b] = nb;\n\n        double sc = evaluate_string(ans);\n\n        if (sc > best_score + 1e-11) {\n            best_score = sc;\n        } else {\n            ans[a] = oa;\n            ans[b] = ob;\n        }\n    }\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    cin >> si_ >> sj_ >> ti_ >> tj_ >> p_fail;\n    p_succ = 1.0 - p_fail;\n\n    for (int i = 0; i < 20; i++) cin >> hwall[i];\n    for (int i = 0; i < 19; i++) cin >> vwall[i];\n\n    start_id = id(si_, sj_);\n    target_id = id(ti_, tj_);\n\n    build_graph();\n    bfs_distance();\n\n    build_nb_potential();\n    build_mean_potential();\n\n    vector<string> candidates;\n\n    string main_beam = beam_search(pot_nb, 320);\n    candidates.push_back(main_beam);\n\n    candidates.push_back(greedy_with_potential(pot_nb));\n    candidates.push_back(greedy_with_potential(pot_mean));\n\n    vector<string> path_cand = generate_path_candidates();\n    for (auto& s : path_cand) candidates.push_back(std::move(s));\n\n    vector<pair<double, string>> scored;\n    scored.reserve(candidates.size());\n\n    for (string& s : candidates) {\n        if ((int)s.size() > MAXL) s.resize(MAXL);\n        while ((int)s.size() < MAXL) s.push_back('D');\n\n        scored.push_back({evaluate_string(s), s});\n    }\n\n    sort(scored.begin(), scored.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n\n    vector<string> local_cands;\n    local_cands.push_back(main_beam);\n\n    for (int i = 0; i < (int)scored.size() && (int)local_cands.size() < 4; i++) {\n        bool same = false;\n        for (const string& s : local_cands) {\n            if (s == scored[i].second) {\n                same = true;\n                break;\n            }\n        }\n        if (!same) local_cands.push_back(scored[i].second);\n    }\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    double phase_deadline = 1.70;\n    vector<pair<double, string>> improved;\n\n    for (int i = 0; i < (int)local_cands.size(); i++) {\n        if (elapsed() > phase_deadline) break;\n\n        string s = local_cands[i];\n\n        if ((int)s.size() > MAXL) s.resize(MAXL);\n        while ((int)s.size() < MAXL) s.push_back('D');\n\n        exact_local_limited(s, start_time, phase_deadline, 4, false, false, false);\n        improved.push_back({evaluate_string(s), s});\n    }\n\n    if (improved.empty()) {\n        improved.push_back(scored[0]);\n    }\n\n    sort(improved.begin(), improved.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n\n    string ans = improved[0].second;\n\n    // Final local search: progressively larger exact adjacent block edits.\n    exact_local_limited(ans, start_time, 1.90, 100, true, true, true);\n\n    random_escape(ans, start_time, 1.945);\n\n    if ((int)ans.size() > MAXL) ans.resize(MAXL);\n    while ((int)ans.size() < MAXL) ans.push_back('D');\n\n    cout << ans << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int MAXP = 2000;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nconst int pieceCntOf[8] = {1,1,1,1,2,2,1,1};\n\nconst int A[8][2] = {\n    {0, -1},\n    {0, -1},\n    {2, -1},\n    {1, -1},\n    {0, 2},\n    {0, 1},\n    {0, -1},\n    {1, -1},\n};\n\nconst int B[8][2] = {\n    {1, -1},\n    {3, -1},\n    {3, -1},\n    {2, -1},\n    {1, 3},\n    {3, 2},\n    {2, -1},\n    {3, -1},\n};\n\nint parent_[MAXP], sz_[MAXP], open_[MAXP];\nint sidePid[V][4];\n\nint findp(int x) {\n    while (parent_[x] != x) {\n        parent_[x] = parent_[parent_[x]];\n        x = parent_[x];\n    }\n    return x;\n}\n\nvoid unite(int a, int b) {\n    int ra = findp(a), rb = findp(b);\n    if (ra == rb) return;\n    if (sz_[ra] < sz_[rb]) swap(ra, rb);\n    parent_[rb] = ra;\n    sz_[ra] += sz_[rb];\n}\n\nstruct Eval {\n    long long actual = 0;\n    int l1 = 0;\n    int l2 = 0;\n    double energy = 0;\n};\n\nEval evaluate(const uint8_t state[V]) {\n    for (int k = 0; k < V; k++) {\n        sidePid[k][0] = sidePid[k][1] = sidePid[k][2] = sidePid[k][3] = -1;\n    }\n\n    int pc = 0;\n\n    for (int k = 0; k < V; k++) {\n        int t = state[k];\n        int c = pieceCntOf[t];\n\n        for (int p = 0; p < c; p++) {\n            int id = pc++;\n            parent_[id] = id;\n            sz_[id] = 1;\n            open_[id] = 0;\n\n            int a = A[t][p];\n            int b = B[t][p];\n            sidePid[k][a] = id;\n            sidePid[k][b] = id;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            if (j + 1 < N) {\n                int a = sidePid[k][2];\n                int b = sidePid[k + 1][0];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n\n            if (i + 1 < N) {\n                int a = sidePid[k][3];\n                int b = sidePid[k + N][1];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            for (int d = 0; d < 4; d++) {\n                int id = sidePid[k][d];\n                if (id == -1) continue;\n\n                int ni = i + di[d];\n                int nj = j + dj[d];\n\n                bool bad = false;\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    bad = true;\n                } else {\n                    int nk = ni * N + nj;\n                    int od = (d + 2) & 3;\n                    if (sidePid[nk][od] == -1) bad = true;\n                }\n\n                if (bad) open_[findp(id)]++;\n            }\n        }\n    }\n\n    Eval res;\n    double potential = 0.0;\n\n    for (int id = 0; id < pc; id++) {\n        int r = findp(id);\n        if (r != id) continue;\n\n        int s = sz_[r];\n        int op = open_[r];\n\n        if (op == 0) {\n            if (s > res.l1) {\n                res.l2 = res.l1;\n                res.l1 = s;\n            } else if (s > res.l2) {\n                res.l2 = s;\n            }\n        } else {\n            potential += (double)s * s / (op + 1);\n        }\n    }\n\n    if (res.l2 > 0) res.actual = 1LL * res.l1 * res.l2;\n\n    res.energy =\n        55.0 * res.actual\n        + 2.0 * res.l1 * res.l1\n        + 4.5 * res.l2 * res.l2\n        + 0.75 * potential;\n\n    return res;\n}\n\nint rotateTile(int t, int r) {\n    if (t < 4) return (t + r) & 3;\n    if (t < 6) return 4 + ((t - 4 + r) & 1);\n    return 6 + ((t - 6 + r) & 1);\n}\n\nint outsideCountState(int k, int t) {\n    int i = k / N;\n    int j = k % N;\n\n    bool has[4] = {};\n    for (int p = 0; p < pieceCntOf[t]; p++) {\n        has[A[t][p]] = true;\n        has[B[t][p]] = true;\n    }\n\n    int cnt = 0;\n    for (int d = 0; d < 4; d++) {\n        if (!has[d]) continue;\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) cnt++;\n    }\n    return cnt;\n}\n\nint stateForPair(int base, int d1, int d2) {\n    if (d1 > d2) swap(d1, d2);\n\n    if (base >= 6) {\n        if (d1 == 0 && d2 == 2) return 6;\n        return 7;\n    }\n\n    bool dbl = (base >= 4);\n\n    int s = 0;\n    if (d1 == 0 && d2 == 1) s = 0;\n    else if (d1 == 0 && d2 == 3) s = 1;\n    else if (d1 == 2 && d2 == 3) s = 2;\n    else s = 3;\n\n    if (!dbl) return s;\n\n    if (s == 0 || s == 2) return 4;\n    return 5;\n}\n\nstruct Cycle {\n    vector<int> cells;\n    vector<uint8_t> states;\n    array<uint64_t, 15> mask{};\n    int len = 0;\n};\n\nvoid buildMask(Cycle& c) {\n    c.mask.fill(0);\n    for (int k : c.cells) {\n        c.mask[k >> 6] |= 1ULL << (k & 63);\n    }\n}\n\nbool disjointCycle(const Cycle& a, const Cycle& b) {\n    for (int i = 0; i < 15; i++) {\n        if (a.mask[i] & b.mask[i]) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto timeStart = chrono::steady_clock::now();\n\n    string input[N];\n    for (int i = 0; i < N; i++) cin >> input[i];\n\n    uint64_t seed = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        for (char c : input[i]) {\n            seed ^= (uint64_t)c;\n            seed *= 1099511628211ULL;\n        }\n    }\n    XorShift rng(seed);\n\n    uint8_t base[V];\n    int dom[V][4], domCnt[V];\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n            int t = input[i][j] - '0';\n            base[k] = t;\n\n            vector<int> states;\n            if (t < 4) states = {0, 1, 2, 3};\n            else if (t < 6) states = {4, 5};\n            else states = {6, 7};\n\n            bool border = (i == 0 || i == N - 1 || j == 0 || j == N - 1);\n\n            if (border) {\n                int bestOut = 100;\n                for (int s : states) bestOut = min(bestOut, outsideCountState(k, s));\n\n                vector<int> filtered;\n                for (int s : states) {\n                    if (outsideCountState(k, s) == bestOut) filtered.push_back(s);\n                }\n                states = filtered;\n            }\n\n            domCnt[k] = (int)states.size();\n            for (int x = 0; x < domCnt[k]; x++) dom[k][x] = states[x];\n        }\n    }\n\n    vector<Cycle> cycles;\n    cycles.reserve(1800);\n\n    static int posStamp[V * 4], posIdx[V * 4];\n    static int cellStamp[V];\n\n    int stamp = 1;\n\n    const int MAX_CYCLES = 1600;\n    auto collectEnd = timeStart + chrono::milliseconds(430);\n\n    while (chrono::steady_clock::now() < collectEnd) {\n        stamp++;\n        if (stamp > 1000000000) {\n            memset(posStamp, 0, sizeof(posStamp));\n            memset(cellStamp, 0, sizeof(cellStamp));\n            stamp = 1;\n        }\n\n        int sk = rng.nextInt(V);\n        int sd = rng.nextInt(4);\n\n        vector<int> ks;\n        vector<int> ds;\n        vector<int> es;\n        ks.reserve(512);\n        ds.reserve(512);\n        es.reserve(512);\n\n        int k = sk;\n        int d = sd;\n\n        for (int step = 0; step < 1200; step++) {\n            int node = k * 4 + d;\n\n            if (posStamp[node] == stamp) break;\n\n            posStamp[node] = stamp;\n            posIdx[node] = (int)ks.size();\n            cellStamp[k] = stamp;\n\n            ks.push_back(k);\n            ds.push_back(d);\n\n            int t = base[k];\n\n            int cand[2];\n            int cc = 0;\n\n            if (t >= 6) {\n                cand[cc++] = (d + 2) & 3;\n            } else {\n                cand[cc++] = (d + 1) & 3;\n                cand[cc++] = (d + 3) & 3;\n                if (rng.nextInt(2)) swap(cand[0], cand[1]);\n            }\n\n            int chosen = -1;\n            int chosenNextK = -1;\n            int chosenNextD = -1;\n\n            for (int ci = 0; ci < cc; ci++) {\n                int e = cand[ci];\n                int ni = k / N + di[e];\n                int nj = k % N + dj[e];\n\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n\n                int nk = ni * N + nj;\n                int nd = (e + 2) & 3;\n                int nn = nk * 4 + nd;\n\n                if (posStamp[nn] == stamp) {\n                    int p = posIdx[nn];\n                    int len = (int)ks.size() - p;\n                    if (len >= 8) {\n                        chosen = e;\n                        chosenNextK = nk;\n                        chosenNextD = nd;\n                        break;\n                    }\n                }\n\n                if (cellStamp[nk] == stamp) continue;\n\n                if (chosen == -1 || rng.nextInt(2)) {\n                    chosen = e;\n                    chosenNextK = nk;\n                    chosenNextD = nd;\n                }\n            }\n\n            if (chosen == -1) break;\n\n            es.push_back(chosen);\n\n            int nextNode = chosenNextK * 4 + chosenNextD;\n\n            if (posStamp[nextNode] == stamp) {\n                int p = posIdx[nextNode];\n                int q = (int)ks.size();\n                int len = q - p;\n\n                if (len >= 8) {\n                    Cycle c;\n                    c.len = len;\n                    c.cells.reserve(len);\n                    c.states.reserve(len);\n\n                    bool ok = true;\n                    static int usedCell[V];\n                    static int usedStamp = 1;\n                    usedStamp++;\n\n                    for (int idx = p; idx < q; idx++) {\n                        int ck = ks[idx];\n                        if (usedCell[ck] == usedStamp) {\n                            ok = false;\n                            break;\n                        }\n                        usedCell[ck] = usedStamp;\n\n                        int cd = ds[idx];\n                        int ce = es[idx];\n                        int cb = base[ck];\n\n                        if (cb >= 6) {\n                            if (((cd + 2) & 3) != ce) {\n                                ok = false;\n                                break;\n                            }\n                        } else {\n                            if (((cd + 2) & 3) == ce || cd == ce) {\n                                ok = false;\n                                break;\n                            }\n                        }\n\n                        c.cells.push_back(ck);\n                        c.states.push_back((uint8_t)stateForPair(cb, cd, ce));\n                    }\n\n                    if (ok) {\n                        buildMask(c);\n\n                        if ((int)cycles.size() < MAX_CYCLES) {\n                            cycles.push_back(std::move(c));\n                        } else {\n                            int mn = 0;\n                            for (int x = 1; x < (int)cycles.size(); x++) {\n                                if (cycles[x].len < cycles[mn].len) mn = x;\n                            }\n                            if (c.len > cycles[mn].len) cycles[mn] = std::move(c);\n                        }\n                    }\n                }\n\n                break;\n            }\n\n            k = chosenNextK;\n            d = chosenNextD;\n        }\n    }\n\n    uint8_t cur[V], best[V], startState[V];\n\n    Eval bestEval;\n    bestEval.actual = -1;\n\n    Eval bestEnergyEval;\n    bestEnergyEval.energy = -1e100;\n\n    auto registerCandidate = [&](const uint8_t s[V]) {\n        Eval ev = evaluate(s);\n\n        if (ev.energy > bestEnergyEval.energy) {\n            bestEnergyEval = ev;\n            memcpy(startState, s, V);\n        }\n\n        if (\n            ev.actual > bestEval.actual ||\n            (ev.actual == bestEval.actual && ev.energy > bestEval.energy)\n        ) {\n            bestEval = ev;\n            memcpy(best, s, V);\n        }\n    };\n\n    for (int k = 0; k < V; k++) {\n        cur[k] = dom[k][rng.nextInt(domCnt[k])];\n    }\n\n    if (!cycles.empty()) {\n        sort(cycles.begin(), cycles.end(), [](const Cycle& a, const Cycle& b) {\n            return a.len > b.len;\n        });\n\n        struct PairCand {\n            long long prod;\n            int i;\n            int j;\n            bool operator<(const PairCand& other) const {\n                return prod > other.prod;\n            }\n        };\n\n        priority_queue<PairCand> pq;\n        const int KEEP_PAIRS = 25;\n\n        int C = (int)cycles.size();\n\n        for (int i = 0; i < C; i++) {\n            if (!pq.empty() && (int)pq.size() >= KEEP_PAIRS &&\n                1LL * cycles[i].len * cycles[i].len <= pq.top().prod) {\n                break;\n            }\n\n            for (int j = i + 1; j < C; j++) {\n                long long p = 1LL * cycles[i].len * cycles[j].len;\n\n                if (!pq.empty() && (int)pq.size() >= KEEP_PAIRS && p <= pq.top().prod) {\n                    break;\n                }\n\n                if (!disjointCycle(cycles[i], cycles[j])) continue;\n\n                if ((int)pq.size() < KEEP_PAIRS) {\n                    pq.push({p, i, j});\n                } else if (p > pq.top().prod) {\n                    pq.pop();\n                    pq.push({p, i, j});\n                }\n            }\n        }\n\n        vector<PairCand> pairs;\n        while (!pq.empty()) {\n            pairs.push_back(pq.top());\n            pq.pop();\n        }\n        sort(pairs.begin(), pairs.end(), [](const PairCand& a, const PairCand& b) {\n            return a.prod > b.prod;\n        });\n\n        for (auto pr : pairs) {\n            for (int rep = 0; rep < 2; rep++) {\n                for (int k = 0; k < V; k++) {\n                    cur[k] = dom[k][rng.nextInt(domCnt[k])];\n                }\n\n                for (int x = 0; x < cycles[pr.i].len; x++) {\n                    cur[cycles[pr.i].cells[x]] = cycles[pr.i].states[x];\n                }\n                for (int x = 0; x < cycles[pr.j].len; x++) {\n                    cur[cycles[pr.j].cells[x]] = cycles[pr.j].states[x];\n                }\n\n                registerCandidate(cur);\n            }\n        }\n\n        int lim = min<int>(45, cycles.size());\n\n        for (int cidx = 0; cidx < lim; cidx++) {\n            for (int k = 0; k < V; k++) {\n                cur[k] = dom[k][rng.nextInt(domCnt[k])];\n            }\n\n            for (int x = 0; x < cycles[cidx].len; x++) {\n                cur[cycles[cidx].cells[x]] = cycles[cidx].states[x];\n            }\n\n            registerCandidate(cur);\n        }\n    }\n\n    constexpr int INIT_TRIALS = 500;\n\n    for (int tr = 0; tr < INIT_TRIALS; tr++) {\n        for (int k = 0; k < V; k++) {\n            cur[k] = dom[k][rng.nextInt(domCnt[k])];\n        }\n        registerCandidate(cur);\n    }\n\n    memcpy(cur, startState, V);\n    Eval curEval = evaluate(cur);\n\n    const double TL = 1.93;\n    const double T0 = 2500.0;\n    const double T1 = 1.0;\n\n    double temp = T0;\n    int iter = 0;\n\n    while (true) {\n        iter++;\n\n        if ((iter & 511) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - timeStart).count();\n            if (elapsed >= TL) break;\n\n            double progress = elapsed / TL;\n            temp = T0 * pow(T1 / T0, progress);\n        }\n\n        int m = 1;\n        int r = rng.nextInt(100);\n        if (r < 8) m = 2;\n        if (r == 0) m = 3;\n\n        int pos[3];\n        uint8_t oldVal[3];\n\n        bool okMove = true;\n\n        for (int x = 0; x < m; x++) {\n            int k = -1;\n\n            for (int tries = 0; tries < 50; tries++) {\n                int cand = rng.nextInt(V);\n                if (domCnt[cand] <= 1) continue;\n\n                bool used = false;\n                for (int y = 0; y < x; y++) {\n                    if (pos[y] == cand) used = true;\n                }\n\n                if (!used) {\n                    k = cand;\n                    break;\n                }\n            }\n\n            if (k == -1) {\n                okMove = false;\n                break;\n            }\n\n            pos[x] = k;\n            oldVal[x] = cur[k];\n\n            int nd;\n            do {\n                nd = dom[k][rng.nextInt(domCnt[k])];\n            } while (nd == cur[k]);\n\n            cur[k] = nd;\n        }\n\n        if (!okMove) {\n            for (int x = 0; x < m; x++) cur[pos[x]] = oldVal[x];\n            continue;\n        }\n\n        Eval ne = evaluate(cur);\n        double diff = ne.energy - curEval.energy;\n\n        bool accept = false;\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double p = exp(diff / temp);\n            if (rng.nextDouble() < p) accept = true;\n        }\n\n        if (\n            ne.actual > bestEval.actual ||\n            (ne.actual == bestEval.actual && ne.energy > bestEval.energy)\n        ) {\n            bestEval = ne;\n            memcpy(best, cur, V);\n        }\n\n        if (accept) {\n            curEval = ne;\n        } else {\n            for (int x = 0; x < m; x++) cur[pos[x]] = oldVal[x];\n        }\n    }\n\n    string ans;\n    ans.reserve(V);\n\n    for (int k = 0; k < V; k++) {\n        int b = base[k];\n        int target = best[k];\n\n        int rr = 0;\n        for (int r = 0; r < 4; r++) {\n            if (rotateTile(b, r) == target) {\n                rr = r;\n                break;\n            }\n        }\n\n        ans.push_back(char('0' + rr));\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint N, T, M, FULLV;\nchrono::steady_clock::time_point START_TIME;\narray<vector<int>, 100> ADJ;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nint hexval(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nvoid build_adj() {\n    for (int p = 0; p < M; p++) {\n        int r = p / N;\n        int c = p % N;\n        if (r > 0) ADJ[p].push_back(p - N);\n        if (r + 1 < N) ADJ[p].push_back(p + N);\n        if (c > 0) ADJ[p].push_back(p - 1);\n        if (c + 1 < N) ADJ[p].push_back(p + 1);\n    }\n}\n\nchar move_char_from_blank_to_tile(int blank, int tile) {\n    if (tile == blank - N) return 'U';\n    if (tile == blank + N) return 'D';\n    if (tile == blank - 1) return 'L';\n    return 'R';\n}\n\nint move_blank_pos(int blank, char c) {\n    if (c == 'U') return blank - N;\n    if (c == 'D') return blank + N;\n    if (c == 'L') return blank - 1;\n    return blank + 1;\n}\n\nbool legal_move(int blank, char c) {\n    int r = blank / N;\n    int col = blank % N;\n    if (c == 'U') return r > 0;\n    if (c == 'D') return r + 1 < N;\n    if (c == 'L') return col > 0;\n    return col + 1 < N;\n}\n\nvoid apply_move(array<unsigned char, 100>& b, int& blank, char c) {\n    int nb = move_blank_pos(blank, c);\n    swap(b[blank], b[nb]);\n    blank = nb;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                                Evaluation                                  */\n/* -------------------------------------------------------------------------- */\n\nstruct Eval {\n    int s;\n    int maxComp;\n    int cyc;\n};\n\nstruct DSU {\n    int p[100], sz[100], ed[100];\n\n    void init(const array<unsigned char, 100>& b) {\n        for (int i = 0; i < M; i++) {\n            if (b[i]) {\n                p[i] = i;\n                sz[i] = 1;\n                ed[i] = 0;\n            } else {\n                p[i] = -1;\n                sz[i] = 0;\n                ed[i] = 0;\n            }\n        }\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    void add_edge(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n\n        if (ra == rb) {\n            ed[ra]++;\n            return;\n        }\n\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        ed[ra] += ed[rb] + 1;\n    }\n};\n\nEval eval_board(const array<unsigned char, 100>& b) {\n    DSU d;\n    d.init(b);\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            if (b[p] == 0) continue;\n\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) d.add_edge(p, p + 1);\n            }\n\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) d.add_edge(p, p + N);\n            }\n        }\n    }\n\n    Eval ev{0, 0, 0};\n\n    for (int i = 0; i < M; i++) {\n        if (b[i] == 0) continue;\n        if (d.find(i) != i) continue;\n\n        ev.maxComp = max(ev.maxComp, d.sz[i]);\n\n        if (d.ed[i] == d.sz[i] - 1) {\n            ev.s = max(ev.s, d.sz[i]);\n        } else if (d.ed[i] >= d.sz[i]) {\n            ev.cyc += d.ed[i] - d.sz[i] + 1;\n        }\n    }\n\n    return ev;\n}\n\nint estimated_score(int S, int K) {\n    if (S < FULLV) {\n        return (int)llround(500000.0 * S / FULLV);\n    } else {\n        return (int)llround(500000.0 * (2.0 - (double)K / T));\n    }\n}\n\npair<int, int> eval_answer(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    const string& ans\n) {\n    array<unsigned char, 100> b = init;\n    int blank = initBlank;\n\n    for (char c : ans) {\n        if (!legal_move(blank, c)) return {-1, -1};\n        apply_move(b, blank, c);\n    }\n\n    Eval ev = eval_board(b);\n    return {ev.s, estimated_score(ev.s, (int)ans.size())};\n}\n\n/* -------------------------------------------------------------------------- */\n/*                          Target Reconstruction                             */\n/* -------------------------------------------------------------------------- */\n\nstruct Edge {\n    int a, b;\n    int ba, bb;\n};\n\nint dir_bit(int from, int to) {\n    if (to == from - 1) return 1;\n    if (to == from - N) return 2;\n    if (to == from + 1) return 4;\n    return 8;\n}\n\nstruct SmallDSU {\n    vector<int> p, sz;\n\n    SmallDSU(int n = 0) : p(n), sz(n, 1) {\n        iota(p.begin(), p.end(), 0);\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n\n        if (a == b) return false;\n\n        if (sz[a] < sz[b]) swap(a, b);\n\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct ReconState {\n    vector<int> mask;\n    vector<int> cnt;\n    vector<char> tree;\n    vector<vector<pair<int, int>>> adj;\n    int diff;\n};\n\nvoid adj_add(vector<vector<pair<int, int>>>& adj, int u, int v, int eid) {\n    adj[u].push_back({v, eid});\n    adj[v].push_back({u, eid});\n}\n\nvoid adj_remove(vector<vector<pair<int, int>>>& adj, int u, int v, int eid) {\n    auto erase_one = [&](int x, int y) {\n        auto& vec = adj[x];\n\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i].first == y && vec[i].second == eid) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n\n    erase_one(u, v);\n    erase_one(v, u);\n}\n\nbool reconstruct_target_any(\n    const vector<int>& targetCnt,\n    array<unsigned char, 100>& target,\n    double time_limit\n) {\n    int emptyPos = M - 1;\n\n    vector<int> posToVid(M, -1);\n    vector<int> vidToPos;\n\n    for (int p = 0; p < M; p++) {\n        if (p == emptyPos) continue;\n        posToVid[p] = (int)vidToPos.size();\n        vidToPos.push_back(p);\n    }\n\n    int V = (int)vidToPos.size();\n\n    vector<Edge> edges;\n\n    for (int p = 0; p < M; p++) {\n        if (p == emptyPos) continue;\n\n        int r = p / N;\n        int c = p % N;\n\n        if (c + 1 < N && p + 1 != emptyPos) {\n            int q = p + 1;\n            edges.push_back({posToVid[p], posToVid[q], dir_bit(p, q), dir_bit(q, p)});\n        }\n\n        if (r + 1 < N && p + N != emptyPos) {\n            int q = p + N;\n            edges.push_back({posToVid[p], posToVid[q], dir_bit(p, q), dir_bit(q, p)});\n        }\n    }\n\n    int E = (int)edges.size();\n    mt19937 rng(712367821);\n\n    auto calc_diff = [&](const vector<int>& cnt) {\n        int d = 0;\n        for (int i = 0; i < 16; i++) d += abs(cnt[i] - targetCnt[i]);\n        return d;\n    };\n\n    auto build_random_tree = [&]() {\n        ReconState st;\n\n        st.mask.assign(V, 0);\n        st.cnt.assign(16, 0);\n        st.tree.assign(E, 0);\n        st.adj.assign(V, {});\n\n        vector<int> ord(E);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n\n        SmallDSU dsu(V);\n\n        int used = 0;\n\n        for (int id : ord) {\n            auto& e = edges[id];\n\n            if (dsu.unite(e.a, e.b)) {\n                st.tree[id] = 1;\n                st.mask[e.a] |= e.ba;\n                st.mask[e.b] |= e.bb;\n                adj_add(st.adj, e.a, e.b, id);\n\n                used++;\n                if (used == V - 1) break;\n            }\n        }\n\n        for (int x : st.mask) st.cnt[x]++;\n        st.diff = calc_diff(st.cnt);\n\n        return st;\n    };\n\n    ReconState best;\n    best.diff = INT_MAX;\n\n    while (elapsed_sec() < time_limit) {\n        ReconState st = build_random_tree();\n\n        if (st.diff < best.diff) best = st;\n\n        if (st.diff == 0) {\n            best = st;\n            break;\n        }\n\n        double local_start = elapsed_sec();\n\n        while (elapsed_sec() < time_limit) {\n            double progress = (elapsed_sec() - local_start) / max(0.001, time_limit - local_start);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 3.5 * (1.0 - progress) + 0.03 * progress;\n\n            int addId = -1;\n\n            for (int tries = 0; tries < 25; tries++) {\n                int id = rng() % E;\n\n                if (!st.tree[id]) {\n                    addId = id;\n                    break;\n                }\n            }\n\n            if (addId == -1) continue;\n\n            int s = edges[addId].a;\n            int g = edges[addId].b;\n\n            vector<int> par(V, -1), parEdge(V, -1);\n            queue<int> q;\n\n            q.push(s);\n            par[s] = s;\n\n            while (!q.empty() && par[g] == -1) {\n                int v = q.front();\n                q.pop();\n\n                for (auto [to, eid] : st.adj[v]) {\n                    if (par[to] == -1) {\n                        par[to] = v;\n                        parEdge[to] = eid;\n                        q.push(to);\n                    }\n                }\n            }\n\n            vector<int> pathEdges;\n\n            int cur = g;\n\n            while (cur != s) {\n                pathEdges.push_back(parEdge[cur]);\n                cur = par[cur];\n            }\n\n            int remId = pathEdges[rng() % pathEdges.size()];\n\n            vector<int> nmask = st.mask;\n            vector<int> ncnt = st.cnt;\n\n            auto& ae = edges[addId];\n            auto& re = edges[remId];\n\n            nmask[ae.a] |= ae.ba;\n            nmask[ae.b] |= ae.bb;\n            nmask[re.a] &= ~re.ba;\n            nmask[re.b] &= ~re.bb;\n\n            int affected[4] = {ae.a, ae.b, re.a, re.b};\n            sort(affected, affected + 4);\n\n            int len = unique(affected, affected + 4) - affected;\n\n            int ndiff = st.diff;\n\n            for (int i = 0; i < len; i++) {\n                int v = affected[i];\n\n                int oldm = st.mask[v];\n                int newm = nmask[v];\n\n                if (oldm == newm) continue;\n\n                ndiff -= abs(ncnt[oldm] - targetCnt[oldm]);\n                ncnt[oldm]--;\n                ndiff += abs(ncnt[oldm] - targetCnt[oldm]);\n\n                ndiff -= abs(ncnt[newm] - targetCnt[newm]);\n                ncnt[newm]++;\n                ndiff += abs(ncnt[newm] - targetCnt[newm]);\n            }\n\n            bool accept = false;\n\n            if (ndiff <= st.diff) {\n                accept = true;\n            } else {\n                double prob = exp((double)(st.diff - ndiff) / temp);\n                double rr = (double)rng() / (double)UINT_MAX;\n\n                if (rr < prob) accept = true;\n            }\n\n            if (accept) {\n                st.diff = ndiff;\n                st.mask.swap(nmask);\n                st.cnt.swap(ncnt);\n\n                st.tree[addId] = 1;\n                st.tree[remId] = 0;\n\n                adj_add(st.adj, ae.a, ae.b, addId);\n                adj_remove(st.adj, re.a, re.b, remId);\n\n                if (st.diff < best.diff) best = st;\n\n                if (st.diff == 0) {\n                    best = st;\n                    goto finish_reconstruction;\n                }\n            }\n        }\n    }\n\nfinish_reconstruction:\n    if (best.diff == INT_MAX) return false;\n\n    target.fill(0);\n    target[emptyPos] = 0;\n\n    for (int v = 0; v < V; v++) {\n        target[vidToPos[v]] = (unsigned char)best.mask[v];\n    }\n\n    return best.diff == 0;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                       Partial Greedy Solve To Target                        */\n/* -------------------------------------------------------------------------- */\n\nbool find_path_to_place(\n    const array<unsigned char, 100>& board,\n    int blank,\n    const vector<char>& fixed,\n    int pos,\n    int val,\n    string& path\n) {\n    path.clear();\n\n    if (board[pos] == val) return true;\n\n    int total = M * M;\n\n    vector<int> pre(total, -2);\n    vector<char> prem(total, 0);\n\n    queue<int> q;\n\n    for (int p = 0; p < M; p++) {\n        if (fixed[p]) continue;\n        if (p == blank) continue;\n\n        if (board[p] == val) {\n            int id = p * M + blank;\n            pre[id] = -1;\n            q.push(id);\n        }\n    }\n\n    int goal = -1;\n\n    while (!q.empty()) {\n        int id = q.front();\n        q.pop();\n\n        int tile = id / M;\n        int z = id % M;\n\n        if (tile == pos) {\n            goal = id;\n            break;\n        }\n\n        for (int nb : ADJ[z]) {\n            if (fixed[nb]) continue;\n\n            int ntile = tile;\n\n            if (nb == tile) ntile = z;\n\n            int nz = nb;\n            int nid = ntile * M + nz;\n\n            if (pre[nid] != -2) continue;\n\n            pre[nid] = id;\n            prem[nid] = move_char_from_blank_to_tile(z, nb);\n\n            q.push(nid);\n        }\n    }\n\n    if (goal == -1) return false;\n\n    int cur = goal;\n\n    while (pre[cur] != -1) {\n        path.push_back(prem[cur]);\n        cur = pre[cur];\n    }\n\n    reverse(path.begin(), path.end());\n\n    return true;\n}\n\nuint64_t encode9(const array<unsigned char, 100>& b, const vector<int>& cells) {\n    uint64_t x = 0;\n\n    for (int i = 0; i < 9; i++) {\n        x |= (uint64_t)b[cells[i]] << (4 * i);\n    }\n\n    return x;\n}\n\nint zero_index9(uint64_t x) {\n    for (int i = 0; i < 9; i++) {\n        if (((x >> (4 * i)) & 15) == 0) return i;\n    }\n\n    return -1;\n}\n\nuint64_t swap_nibble(uint64_t x, int a, int b) {\n    uint64_t va = (x >> (4 * a)) & 15;\n    uint64_t vb = (x >> (4 * b)) & 15;\n\n    x &= ~(15ULL << (4 * a));\n    x &= ~(15ULL << (4 * b));\n\n    x |= va << (4 * b);\n    x |= vb << (4 * a);\n\n    return x;\n}\n\nbool solve_final_3x3(\n    array<unsigned char, 100>& board,\n    int& blank,\n    const array<unsigned char, 100>& target,\n    string& ans\n) {\n    vector<int> cells;\n\n    for (int r = N - 3; r < N; r++) {\n        for (int c = N - 3; c < N; c++) {\n            cells.push_back(r * N + c);\n        }\n    }\n\n    bool blankInside = false;\n\n    for (int p : cells) {\n        if (p == blank) blankInside = true;\n    }\n\n    if (!blankInside) return false;\n\n    uint64_t start = encode9(board, cells);\n    uint64_t goal = encode9(target, cells);\n\n    if (start == goal) return true;\n\n    unordered_map<uint64_t, pair<uint64_t, char>> pre;\n    pre.reserve(400000);\n\n    queue<uint64_t> q;\n    q.push(start);\n    pre[start] = {UINT64_MAX, 0};\n\n    bool ok = false;\n    uint64_t found = 0;\n\n    while (!q.empty()) {\n        uint64_t x = q.front();\n        q.pop();\n\n        int zi = zero_index9(x);\n        int zr = zi / 3;\n        int zc = zi % 3;\n\n        const int dr[4] = {-1, 1, 0, 0};\n        const int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = zr + dr[k];\n            int nc = zc + dc[k];\n\n            if (nr < 0 || nr >= 3 || nc < 0 || nc >= 3) continue;\n\n            int ni = nr * 3 + nc;\n            uint64_t y = swap_nibble(x, zi, ni);\n\n            if (pre.count(y)) continue;\n\n            char mv = move_char_from_blank_to_tile(cells[zi], cells[ni]);\n            pre[y] = {x, mv};\n\n            if (y == goal) {\n                found = y;\n                ok = true;\n                while (!q.empty()) q.pop();\n                break;\n            }\n\n            q.push(y);\n        }\n    }\n\n    if (!ok) return false;\n\n    string path;\n\n    uint64_t cur = found;\n\n    while (pre[cur].first != UINT64_MAX) {\n        path.push_back(pre[cur].second);\n        cur = pre[cur].first;\n    }\n\n    reverse(path.begin(), path.end());\n\n    if ((int)ans.size() + (int)path.size() > T) return false;\n\n    for (char c : path) {\n        apply_move(board, blank, c);\n        ans.push_back(c);\n    }\n\n    return true;\n}\n\nstring partial_solve_to_target(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    const array<unsigned char, 100>& target\n) {\n    array<unsigned char, 100> board = init;\n    int blank = initBlank;\n\n    vector<char> fixed(M, 0);\n\n    string ans;\n    string bestAns;\n\n    Eval ev0 = eval_board(board);\n    int bestScore = estimated_score(ev0.s, 0);\n\n    vector<int> order;\n\n    for (int r = 0; r < N - 3; r++) {\n        for (int c = 0; c < N; c++) {\n            order.push_back(r * N + c);\n        }\n    }\n\n    for (int r = N - 3; r < N; r++) {\n        for (int c = 0; c < N - 3; c++) {\n            order.push_back(r * N + c);\n        }\n    }\n\n    for (int pos : order) {\n        int val = target[pos];\n\n        if (val == 0) break;\n\n        string path;\n\n        if (!find_path_to_place(board, blank, fixed, pos, val, path)) break;\n        if ((int)ans.size() + (int)path.size() > T) break;\n\n        for (char c : path) {\n            apply_move(board, blank, c);\n            ans.push_back(c);\n        }\n\n        if (board[pos] != val) break;\n\n        fixed[pos] = 1;\n\n        Eval ev = eval_board(board);\n        int sc = estimated_score(ev.s, (int)ans.size());\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestAns = ans;\n        }\n\n        if (ev.s == FULLV) return ans;\n    }\n\n    {\n        array<unsigned char, 100> b2 = board;\n        int z2 = blank;\n        string a2 = ans;\n\n        if (solve_final_3x3(b2, z2, target, a2)) {\n            Eval ev = eval_board(b2);\n            int sc = estimated_score(ev.s, (int)a2.size());\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestAns = a2;\n            }\n        }\n    }\n\n    return bestAns;\n}\n\n/* -------------------------------------------------------------------------- */\n/*                                Beam Search                                 */\n/* -------------------------------------------------------------------------- */\n\null zob[100][16];\n\ninline bool edge_adj(const array<unsigned char, 100>& b, int x, int y) {\n    if (y == x - 1) return (b[x] & 1) && (b[y] & 4);\n    if (y == x + 1) return (b[x] & 4) && (b[y] & 1);\n    if (y == x - N) return (b[x] & 2) && (b[y] & 8);\n    if (y == x + N) return (b[x] & 8) && (b[y] & 2);\n    return false;\n}\n\nint local_edges(const array<unsigned char, 100>& b, int a, int c) {\n    int cells[2] = {a, c};\n    int keys[8];\n    int kc = 0;\n    int res = 0;\n\n    for (int ii = 0; ii < 2; ii++) {\n        int x = cells[ii];\n\n        for (int y : ADJ[x]) {\n            int u = min(x, y);\n            int v = max(x, y);\n            int key = u * 100 + v;\n\n            bool seen = false;\n\n            for (int t = 0; t < kc; t++) {\n                if (keys[t] == key) {\n                    seen = true;\n                    break;\n                }\n            }\n\n            if (seen) continue;\n\n            keys[kc++] = key;\n\n            if (edge_adj(b, x, y)) res++;\n        }\n    }\n\n    return res;\n}\n\nint total_edges(const array<unsigned char, 100>& b) {\n    int e = 0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n\n            if (b[p] == 0) continue;\n\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) e++;\n            }\n\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) e++;\n            }\n        }\n    }\n\n    return e;\n}\n\nstruct Node {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    short depth;\n    unsigned char prev;\n    ull hash;\n};\n\nstruct Cand {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    short maxComp;\n    short cyc;\n    short depth;\n    unsigned char prev;\n    ull hash;\n    long long h;\n};\n\nchar inv_move(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return 0;\n}\n\nstring restore_path(const vector<Node>& pool, int idx) {\n    string res;\n\n    while (pool[idx].parent != -1) {\n        res.push_back((char)pool[idx].prev);\n        idx = pool[idx].parent;\n    }\n\n    reverse(res.begin(), res.end());\n\n    return res;\n}\n\nbool add_seed_path(\n    vector<Node>& pool,\n    vector<int>& beam,\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    ull initHash,\n    const string& prefix,\n    int& bestIdx,\n    int& bestScore\n) {\n    if (prefix.empty() || (int)prefix.size() > T) return false;\n\n    array<unsigned char, 100> b = init;\n    int blank = initBlank;\n    ull h = initHash;\n    int parent = 0;\n\n    for (int i = 0; i < (int)prefix.size(); i++) {\n        char c = prefix[i];\n\n        if (!legal_move(blank, c)) return false;\n\n        int nb = move_blank_pos(blank, c);\n        unsigned char tile = b[nb];\n\n        h ^= zob[blank][0];\n        h ^= zob[nb][tile];\n        h ^= zob[blank][tile];\n        h ^= zob[nb][0];\n\n        swap(b[blank], b[nb]);\n        blank = nb;\n\n        Node nd;\n        nd.b = b;\n        nd.parent = parent;\n        nd.blank = blank;\n        nd.e = 0;\n        nd.s = 0;\n        nd.depth = i + 1;\n        nd.prev = (unsigned char)c;\n        nd.hash = h;\n\n        pool.push_back(nd);\n        parent = (int)pool.size() - 1;\n    }\n\n    Node& last = pool[parent];\n    last.e = total_edges(last.b);\n    Eval ev = eval_board(last.b);\n    last.s = ev.s;\n\n    int sc = estimated_score(ev.s, last.depth);\n    if (sc > bestScore) {\n        bestScore = sc;\n        bestIdx = parent;\n    }\n\n    if (last.depth < T) beam.push_back(parent);\n\n    return true;\n}\n\nstring beam_fallback(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    ull initHash,\n    const string& seedPath\n) {\n    int W;\n\n    if (N == 6) W = 2600;\n    else if (N == 7) W = 1850;\n    else if (N == 8) W = 1250;\n    else if (N == 9) W = 850;\n    else W = 600;\n\n    vector<Node> pool;\n    pool.reserve((size_t)W * min(T + 2, 900) + T + 10);\n\n    Node root;\n    root.b = init;\n    root.parent = -1;\n    root.blank = initBlank;\n    root.e = total_edges(init);\n    root.prev = 0;\n    root.hash = initHash;\n    root.depth = 0;\n\n    Eval rootEv = eval_board(init);\n    root.s = rootEv.s;\n\n    pool.push_back(root);\n\n    if (rootEv.s == FULLV) return \"\";\n\n    vector<int> beam{0};\n\n    int bestIdx = 0;\n    int bestScore = estimated_score(rootEv.s, 0);\n\n    if (!seedPath.empty()) {\n        add_seed_path(pool, beam, init, initBlank, initHash, seedPath, bestIdx, bestScore);\n    }\n\n    const char mvChar[4] = {'U', 'D', 'L', 'R'};\n\n    for (int iter = 1; iter <= T; iter++) {\n        if (elapsed_sec() > 2.87) break;\n\n        vector<Cand> cand;\n        cand.reserve(beam.size() * 3 + 10);\n\n        for (int idx : beam) {\n            const Node& nd = pool[idx];\n\n            if (nd.depth >= T) continue;\n\n            int z = nd.blank;\n\n            for (int dir = 0; dir < 4; dir++) {\n                char mc = mvChar[dir];\n\n                if (nd.prev && inv_move((char)nd.prev) == mc) continue;\n                if (!legal_move(z, mc)) continue;\n\n                int nz = move_blank_pos(z, mc);\n\n                Cand x;\n                x.b = nd.b;\n\n                int before = local_edges(x.b, z, nz);\n\n                unsigned char tile = x.b[nz];\n                x.b[z] = tile;\n                x.b[nz] = 0;\n\n                int after = local_edges(x.b, z, nz);\n\n                x.e = nd.e - before + after;\n                x.parent = idx;\n                x.blank = nz;\n                x.prev = (unsigned char)mc;\n                x.s = 0;\n                x.maxComp = 0;\n                x.cyc = 0;\n                x.depth = nd.depth + 1;\n\n                ull h = nd.hash;\n                h ^= zob[z][0];\n                h ^= zob[nz][tile];\n                h ^= zob[z][tile];\n                h ^= zob[nz][0];\n\n                x.hash = h;\n\n                cand.push_back(std::move(x));\n            }\n        }\n\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.hash != b.hash) return a.hash < b.hash;\n            if (a.e != b.e) return a.e > b.e;\n            return a.depth < b.depth;\n        });\n\n        int write = 0;\n\n        for (int i = 0; i < (int)cand.size();) {\n            int j = i + 1;\n            int best = i;\n\n            while (j < (int)cand.size() && cand[j].hash == cand[i].hash) {\n                if (cand[j].e > cand[best].e ||\n                    (cand[j].e == cand[best].e && cand[j].depth < cand[best].depth)) {\n                    best = j;\n                }\n                j++;\n            }\n\n            cand[write++] = std::move(cand[best]);\n            i = j;\n        }\n\n        cand.resize(write);\n\n        int preLimit = min((int)cand.size(), max(W, 3 * W / 2));\n\n        if ((int)cand.size() > preLimit) {\n            nth_element(\n                cand.begin(),\n                cand.begin() + preLimit,\n                cand.end(),\n                [](const Cand& a, const Cand& b) {\n                    return a.e > b.e;\n                }\n            );\n\n            cand.resize(preLimit);\n        }\n\n        for (Cand& x : cand) {\n            Eval ev = eval_board(x.b);\n\n            x.s = ev.s;\n            x.maxComp = ev.maxComp;\n            x.cyc = ev.cyc;\n\n            x.h = 0;\n            x.h += 135000LL * x.s;\n            x.h += 1500LL * x.s * x.s;\n            x.h += 8200LL * x.e;\n            x.h += 900LL * x.maxComp;\n            x.h -= 21000LL * x.cyc;\n            x.h += (long long)(x.hash & 4095ULL);\n\n            int sc = estimated_score(x.s, x.depth);\n\n            if (sc > bestScore) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n                tmp.depth = x.depth;\n\n                pool.push_back(tmp);\n\n                bestIdx = (int)pool.size() - 1;\n                bestScore = sc;\n            }\n\n            if (x.s == FULLV) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n                tmp.depth = x.depth;\n\n                pool.push_back(tmp);\n\n                return restore_path(pool, (int)pool.size() - 1);\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.h != b.h) return a.h > b.h;\n            if (a.e != b.e) return a.e > b.e;\n            return a.depth < b.depth;\n        });\n\n        int keep = min(W, (int)cand.size());\n\n        vector<int> nextBeam;\n        nextBeam.reserve(keep);\n\n        for (int i = 0; i < keep; i++) {\n            Node nd;\n            nd.b = cand[i].b;\n            nd.parent = cand[i].parent;\n            nd.blank = cand[i].blank;\n            nd.e = cand[i].e;\n            nd.s = cand[i].s;\n            nd.prev = cand[i].prev;\n            nd.hash = cand[i].hash;\n            nd.depth = cand[i].depth;\n\n            pool.push_back(nd);\n\n            int ni = (int)pool.size() - 1;\n\n            if (nd.depth < T) nextBeam.push_back(ni);\n\n            int sc = estimated_score(nd.s, nd.depth);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestIdx = ni;\n            }\n        }\n\n        beam.swap(nextBeam);\n    }\n\n    return restore_path(pool, bestIdx);\n}\n\n/* -------------------------------------------------------------------------- */\n/*                                    Main                                    */\n/* -------------------------------------------------------------------------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    cin >> N >> T;\n\n    M = N * N;\n    FULLV = M - 1;\n\n    build_adj();\n\n    mt19937_64 rng(123456789);\n\n    for (int i = 0; i < 100; i++) {\n        for (int v = 0; v < 16; v++) {\n            zob[i][v] = rng();\n        }\n    }\n\n    array<unsigned char, 100> init{};\n    int initBlank = -1;\n    ull initHash = 0;\n\n    vector<int> targetCnt(16, 0);\n\n    for (int r = 0; r < N; r++) {\n        string s;\n        cin >> s;\n\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            int v = hexval(s[c]);\n\n            init[p] = (unsigned char)v;\n\n            if (v == 0) {\n                initBlank = p;\n            } else {\n                targetCnt[v]++;\n            }\n\n            initHash ^= zob[p][v];\n        }\n    }\n\n    string bestAns = \"\";\n    string seedAns = \"\";\n\n    Eval initEval = eval_board(init);\n    int bestScore = estimated_score(initEval.s, 0);\n\n    array<unsigned char, 100> target{};\n\n    double reconLimit;\n\n    if (N <= 7) reconLimit = 0.62;\n    else if (N == 8) reconLimit = 0.72;\n    else reconLimit = 0.82;\n\n    bool haveTarget = reconstruct_target_any(targetCnt, target, reconLimit);\n\n    if (haveTarget || elapsed_sec() < 1.05) {\n        string targetAns = partial_solve_to_target(init, initBlank, target);\n        seedAns = targetAns;\n\n        auto [S, sc] = eval_answer(init, initBlank, targetAns);\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestAns = targetAns;\n        }\n\n        if (S == FULLV && (int)targetAns.size() <= T) {\n            cout << targetAns << '\\n';\n            return 0;\n        }\n    }\n\n    string beamAns = beam_fallback(init, initBlank, initHash, seedAns);\n\n    if ((int)beamAns.size() > T) beamAns.resize(T);\n\n    auto [beamS, beamScore] = eval_answer(init, initBlank, beamAns);\n\n    if (beamScore > bestScore) {\n        bestScore = beamScore;\n        bestAns = beamAns;\n    }\n\n    if ((int)bestAns.size() > T) bestAns.resize(T);\n\n    cout << bestAns << '\\n';\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Line {\n    double a, b, c;\n};\n\nstruct EvalResult {\n    int matched;\n    int diff;\n    array<int, 11> hist;\n    long long value() const {\n        return 100000LL * matched - diff;\n    }\n};\n\nstruct GridCand {\n    double theta;\n    vector<double> cu, cv;\n    long long val;\n};\n\nstruct Key {\n    uint64_t lo, hi;\n    bool operator==(const Key& o) const {\n        return lo == o.lo && hi == o.hi;\n    }\n};\n\nstruct KeyHash {\n    size_t operator()(const Key& k) const {\n        uint64_t x = k.lo ^ (k.hi + 0x9e3779b97f4a7c15ULL + (k.lo << 6) + (k.lo >> 2));\n        x ^= x >> 30;\n        x *= 0xbf58476d1ce4e5b9ULL;\n        x ^= x >> 27;\n        x *= 0x94d049bb133111ebULL;\n        x ^= x >> 31;\n        return (size_t)x;\n    }\n};\n\nstruct Partition {\n    vector<int> pid;\n    vector<int> cnt;\n    vector<vector<int>> members;\n    array<int, 11> hist;\n    EvalResult eval;\n    long long largeSq;\n};\n\nstruct CandidateLine {\n    Line line;\n    double priority;\n    int staticIndex;\n};\n\nstatic const double PI = acos(-1.0);\nstatic const double R = 10000.0;\n\nint N, K;\narray<int, 11> targetA;\nvector<Point> pts;\nchrono::steady_clock::time_point st;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n}\n\nlong long large_contrib(int c) {\n    return c > 10 ? 1LL * c * c : 0LL;\n}\n\nEvalResult make_eval_from_hist(const array<int, 11>& hist) {\n    EvalResult res;\n    res.hist = hist;\n    res.matched = 0;\n    res.diff = 0;\n    for (int d = 1; d <= 10; d++) {\n        res.matched += min(targetA[d], hist[d]);\n        res.diff += abs(targetA[d] - hist[d]);\n    }\n    return res;\n}\n\nEvalResult eval_grid(double theta, const vector<double>& cu, const vector<double>& cv) {\n    int gx = (int)cu.size() + 1;\n    int gy = (int)cv.size() + 1;\n    vector<int> cnt(gx * gy, 0);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double u = p.x * cs + p.y * sn;\n        double v = -p.x * sn + p.y * cs;\n        int ix = int(upper_bound(cu.begin(), cu.end(), u) - cu.begin());\n        int iy = int(upper_bound(cv.begin(), cv.end(), v) - cv.begin());\n        cnt[ix * gy + iy]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n\n    for (int c : cnt) {\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n\n    return make_eval_from_hist(hist);\n}\n\nEvalResult eval_lines(const vector<Line>& lines) {\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(N * 2);\n\n    int L = (int)lines.size();\n\n    for (const auto& p : pts) {\n        uint64_t lo = 0, hi = 0;\n\n        for (int i = 0; i < L; i++) {\n            double v = lines[i].a * p.x + lines[i].b * p.y - lines[i].c;\n            if (v > 0) {\n                if (i < 64) lo |= 1ULL << i;\n                else hi |= 1ULL << (i - 64);\n            }\n        }\n\n        mp[{lo, hi}]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n\n    for (auto& kv : mp) {\n        int c = kv.second;\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n\n    return make_eval_from_hist(hist);\n}\n\nPartition build_partition(const vector<Line>& lines, bool needMembers) {\n    Partition part;\n    part.pid.assign(N, -1);\n    part.cnt.clear();\n    part.members.clear();\n    part.hist.fill(0);\n    part.largeSq = 0;\n\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(N * 2);\n\n    int L = (int)lines.size();\n\n    for (int i = 0; i < N; i++) {\n        const auto& p = pts[i];\n\n        uint64_t lo = 0, hi = 0;\n\n        for (int j = 0; j < L; j++) {\n            double v = lines[j].a * p.x + lines[j].b * p.y - lines[j].c;\n            if (v > 0) {\n                if (j < 64) lo |= 1ULL << j;\n                else hi |= 1ULL << (j - 64);\n            }\n        }\n\n        Key key{lo, hi};\n        auto it = mp.find(key);\n\n        int id;\n        if (it == mp.end()) {\n            id = (int)part.cnt.size();\n            mp[key] = id;\n            part.cnt.push_back(0);\n            if (needMembers) part.members.emplace_back();\n        } else {\n            id = it->second;\n        }\n\n        part.pid[i] = id;\n        part.cnt[id]++;\n        if (needMembers) part.members[id].push_back(i);\n    }\n\n    for (int c : part.cnt) {\n        if (1 <= c && c <= 10) part.hist[c]++;\n        part.largeSq += large_contrib(c);\n    }\n\n    part.eval = make_eval_from_hist(part.hist);\n    return part;\n}\n\nvector<Line> build_grid_lines(double theta, const vector<double>& cu, const vector<double>& cv) {\n    vector<Line> lines;\n    lines.reserve(cu.size() + cv.size());\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (double c : cu) lines.push_back({cs, sn, c});\n    for (double c : cv) lines.push_back({-sn, cs, c});\n\n    return lines;\n}\n\nvector<double> uniform_cuts(int g) {\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    for (int i = 1; i < g; i++) {\n        cuts.push_back(-R + 2.0 * R * i / g);\n    }\n\n    return cuts;\n}\n\nvector<double> projection_quantile_cuts(double theta, int g, bool second_axis) {\n    vector<double> vals;\n    vals.reserve(N);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double z;\n        if (!second_axis) z = p.x * cs + p.y * sn;\n        else z = -p.x * sn + p.y * cs;\n        vals.push_back(z);\n    }\n\n    sort(vals.begin(), vals.end());\n\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    for (int i = 1; i < g; i++) {\n        int r = (long long)N * i / g;\n        r = min(max(r, 1), N - 1);\n\n        double c = (vals[r - 1] + vals[r]) * 0.5;\n        if (fabs(vals[r] - vals[r - 1]) < 1e-9) c = vals[r] + 1e-7;\n\n        c = max(-R + 1e-6, min(R - 1e-6, c));\n        cuts.push_back(c);\n    }\n\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nvector<double> random_dirichlet_cuts(int g, double alpha, mt19937& rng) {\n    vector<double> w(g);\n\n    if (alpha > 500.0) {\n        for (int i = 0; i < g; i++) w[i] = 1.0;\n    } else {\n        gamma_distribution<double> gd(alpha, 1.0);\n        for (int i = 0; i < g; i++) w[i] = max(1e-12, gd(rng));\n    }\n\n    double sum = accumulate(w.begin(), w.end(), 0.0);\n\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    double cur = -R;\n    for (int i = 0; i + 1 < g; i++) {\n        cur += 2.0 * R * w[i] / sum;\n        cuts.push_back(cur);\n    }\n\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nlong long local_split_value(const Partition& part, int c, int p) {\n    if (p <= 0 || p >= c) return LLONG_MIN / 4;\n\n    int q = c - p;\n    array<int, 11> hist = part.hist;\n\n    if (1 <= c && c <= 10) hist[c]--;\n    if (1 <= p && p <= 10) hist[p]++;\n    if (1 <= q && q <= 10) hist[q]++;\n\n    return make_eval_from_hist(hist).value() - part.eval.value();\n}\n\nvector<CandidateLine> generate_cell_candidate_lines(const Partition& part, mt19937& rng, int maxCand) {\n    vector<int> ids(part.cnt.size());\n    iota(ids.begin(), ids.end(), 0);\n\n    auto cell_priority = [&](int id) {\n        int c = part.cnt[id];\n        int pr = 0;\n\n        if (c > 10) pr += 100000 + c * c;\n        else if (part.hist[c] > targetA[c]) pr += 50000 + c;\n        else pr += c;\n\n        return pr;\n    };\n\n    sort(ids.begin(), ids.end(), [&](int x, int y) {\n        return cell_priority(x) > cell_priority(y);\n    });\n\n    vector<double> angles;\n    for (int i = 0; i < 18; i++) angles.push_back(PI * i / 18.0);\n\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n    for (int i = 0; i < 8; i++) angles.push_back(ur01(rng) * PI);\n\n    vector<CandidateLine> cand;\n    cand.reserve(maxCand * 2);\n\n    int usedCells = 0;\n\n    for (int id : ids) {\n        int c = part.cnt[id];\n        if (c <= 1) continue;\n\n        bool interesting = false;\n        if (c > 10) interesting = true;\n        if (c <= 10 && part.hist[c] > targetA[c]) interesting = true;\n        if (!interesting && usedCells >= 10) continue;\n\n        usedCells++;\n        if (usedCells > 50) break;\n\n        vector<int> ranks;\n\n        for (int d = 1; d <= 10; d++) {\n            if (targetA[d] > part.hist[d]) {\n                if (1 <= d && d < c) ranks.push_back(d);\n                if (1 <= c - d && c - d < c) ranks.push_back(c - d);\n            }\n        }\n\n        for (int d = 1; d <= min(10, c - 1); d++) {\n            ranks.push_back(d);\n            ranks.push_back(c - d);\n        }\n\n        if (c > 20) {\n            vector<double> fracs = {0.20, 0.25, 0.30, 0.333333333, 0.40, 0.50,\n                                    0.60, 0.666666667, 0.70, 0.75, 0.80};\n            for (double f : fracs) {\n                int r = (int)llround(c * f);\n                if (1 <= r && r < c) ranks.push_back(r);\n            }\n\n            int step = max(3, c / 12);\n            for (int r = step; r < c; r += step) {\n                if (1 <= r && r < c) ranks.push_back(r);\n            }\n        }\n\n        if (c <= 24) {\n            for (int r = 1; r < c; r++) {\n                if (local_split_value(part, c, r) >= -100000) ranks.push_back(r);\n            }\n        }\n\n        sort(ranks.begin(), ranks.end());\n        ranks.erase(unique(ranks.begin(), ranks.end()), ranks.end());\n\n        if (ranks.empty()) continue;\n\n        for (double th : angles) {\n            double a = cos(th), b = sin(th);\n\n            vector<double> proj;\n            proj.reserve(c);\n\n            for (int idx : part.members[id]) {\n                const auto& p = pts[idx];\n                proj.push_back(a * p.x + b * p.y);\n            }\n\n            sort(proj.begin(), proj.end());\n\n            for (int r : ranks) {\n                if (r <= 0 || r >= c) continue;\n                if (fabs(proj[r] - proj[r - 1]) < 1e-9) continue;\n\n                double cc = (proj[r - 1] + proj[r]) * 0.5;\n\n                long long lv1 = local_split_value(part, c, r);\n                long long lv2 = local_split_value(part, c, c - r);\n                long long lv = max(lv1, lv2);\n\n                long long oldLarge = large_contrib(c);\n                long long newLarge = large_contrib(r) + large_contrib(c - r);\n                long long largeGain = oldLarge - newLarge;\n\n                double priority = (double)lv * 10.0 + largeGain * 0.02 + (c > 10 ? 30000.0 : 0.0) + c;\n\n                cand.push_back({{a, b, cc}, priority, -1});\n            }\n        }\n    }\n\n    sort(cand.begin(), cand.end(), [](const CandidateLine& x, const CandidateLine& y) {\n        return x.priority > y.priority;\n    });\n\n    if ((int)cand.size() > maxCand) cand.resize(maxCand);\n    return cand;\n}\n\nvector<Line> generate_static_extra_candidate_lines(mt19937& rng) {\n    vector<Line> cand;\n\n    int nang = 30;\n    int nq = 70;\n\n    for (int ai = 0; ai < nang; ai++) {\n        double theta = PI * ai / nang;\n        double a = cos(theta), b = sin(theta);\n\n        vector<double> vals;\n        vals.reserve(N);\n\n        for (const auto& p : pts) vals.push_back(a * p.x + b * p.y);\n        sort(vals.begin(), vals.end());\n\n        for (int q = 1; q < nq; q++) {\n            int r = (long long)N * q / nq;\n            r = min(max(r, 1), N - 1);\n\n            double c = (vals[r - 1] + vals[r]) * 0.5;\n            if (fabs(vals[r] - vals[r - 1]) < 1e-9) c = vals[r] + 1e-7;\n\n            cand.push_back({a, b, c});\n        }\n\n        for (int u = 1; u < 35; u++) {\n            double c = -R + 2.0 * R * u / 35.0;\n            cand.push_back({a, b, c});\n        }\n    }\n\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n\n    for (int t = 0; t < 500; t++) {\n        double theta = ur01(rng) * PI;\n        double a = cos(theta), b = sin(theta);\n\n        int id1 = rng() % N;\n        int id2 = rng() % N;\n\n        double c1 = a * pts[id1].x + b * pts[id1].y;\n        double c2 = a * pts[id2].x + b * pts[id2].y;\n        double c = (c1 + c2) * 0.5;\n        c = max(-R + 1e-6, min(R - 1e-6, c));\n\n        cand.push_back({a, b, c});\n    }\n\n    return cand;\n}\n\npair<long long, long long> eval_add_line_full(const Line& ln, const Partition& part, vector<int>& pos, vector<int>& touched) {\n    touched.clear();\n\n    for (int i = 0; i < N; i++) {\n        const auto& p = pts[i];\n        double v = ln.a * p.x + ln.b * p.y - ln.c;\n\n        if (v > 0) {\n            int id = part.pid[i];\n            if (pos[id] == 0) touched.push_back(id);\n            pos[id]++;\n        }\n    }\n\n    array<int, 11> hist = part.hist;\n    long long largeSq = part.largeSq;\n\n    for (int id : touched) {\n        int p = pos[id];\n        int c = part.cnt[id];\n        int q = c - p;\n\n        if (p != 0 && q != 0) {\n            if (1 <= c && c <= 10) hist[c]--;\n            if (1 <= p && p <= 10) hist[p]++;\n            if (1 <= q && q <= 10) hist[q]++;\n\n            largeSq -= large_contrib(c);\n            largeSq += large_contrib(p) + large_contrib(q);\n        }\n\n        pos[id] = 0;\n    }\n\n    return {make_eval_from_hist(hist).value(), largeSq};\n}\n\nvoid greedy_add_lines(vector<Line>& lines, long long& bestValue, double timeLimit, mt19937& rng, vector<Line>& bestGreedyLines) {\n    if ((int)lines.size() >= K) return;\n\n    vector<Line> staticCand = generate_static_extra_candidate_lines(rng);\n    vector<char> staticUsed(staticCand.size(), 0);\n\n    bestGreedyLines = lines;\n    long long bestGreedyValue = eval_lines(lines).value();\n\n    int neutralUsed = 0;\n    const int neutralLimit = 10;\n\n    while ((int)lines.size() < K && elapsed_sec() < timeLimit) {\n        Partition part = build_partition(lines, true);\n        long long curVal = part.eval.value();\n        long long curLarge = part.largeSq;\n\n        int dynamicLimit = 3000;\n        vector<CandidateLine> cand = generate_cell_candidate_lines(part, rng, dynamicLimit);\n\n        for (int i = 0; i < (int)staticCand.size(); i++) {\n            if (!staticUsed[i]) cand.push_back({staticCand[i], 0.0, i});\n        }\n\n        vector<int> pos(part.cnt.size(), 0);\n        vector<int> touched;\n        touched.reserve(part.cnt.size());\n\n        long long bestCandVal = curVal;\n        long long bestCandLarge = curLarge;\n        int bestIdx = -1;\n\n        long long bestNeutralLarge = curLarge;\n        int bestNeutralIdx = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (elapsed_sec() > timeLimit) break;\n\n            auto [v, lg] = eval_add_line_full(cand[i].line, part, pos, touched);\n\n            if (v > bestCandVal || (v == bestCandVal && lg < bestCandLarge)) {\n                bestCandVal = v;\n                bestCandLarge = lg;\n                bestIdx = i;\n            }\n\n            if (v == curVal && lg < bestNeutralLarge) {\n                bestNeutralLarge = lg;\n                bestNeutralIdx = i;\n            }\n        }\n\n        int chosen = -1;\n        bool neutral = false;\n\n        if (bestIdx != -1 && bestCandVal > curVal) {\n            chosen = bestIdx;\n        } else if (neutralUsed < neutralLimit && bestNeutralIdx != -1 && bestNeutralLarge < curLarge) {\n            chosen = bestNeutralIdx;\n            neutral = true;\n        } else {\n            break;\n        }\n\n        lines.push_back(cand[chosen].line);\n\n        if (cand[chosen].staticIndex >= 0) {\n            staticUsed[cand[chosen].staticIndex] = 1;\n        }\n\n        if (neutral) {\n            neutralUsed++;\n        } else {\n            neutralUsed = max(0, neutralUsed - 1);\n            bestValue = max(bestValue, bestCandVal);\n\n            if (bestCandVal > bestGreedyValue) {\n                bestGreedyValue = bestCandVal;\n                bestGreedyLines = lines;\n            }\n        }\n    }\n\n    bestValue = max(bestValue, bestGreedyValue);\n}\n\nlong long extgcd(long long a, long long b, long long& x, long long& y) {\n    if (b == 0) {\n        x = (a >= 0 ? 1 : -1);\n        y = 0;\n        return llabs(a);\n    }\n\n    long long x1, y1;\n    long long g = extgcd(b, a % b, x1, y1);\n\n    x = y1;\n    y = x1 - (a / b) * y1;\n\n    return g;\n}\n\nbool collinear_any_coeff(long long A, long long B, long long C) {\n    for (const auto& p : pts) {\n        __int128 v = (__int128)A * p.x + (__int128)B * p.y;\n        if (v == C) return true;\n    }\n    return false;\n}\n\nbool has_point_x(long long x) {\n    for (const auto& p : pts) if (p.x == x) return true;\n    return false;\n}\n\nbool has_point_y(long long y) {\n    for (const auto& p : pts) if (p.y == y) return true;\n    return false;\n}\n\nlong long nearest_safe_coord(double v, bool isX) {\n    long long base = llround(v);\n    for (long long d = 0; d <= 20000; d++) {\n        long long a = base + d;\n        if (a >= -1000000000LL && a <= 1000000000LL && !(isX ? has_point_x(a) : has_point_y(a))) return a;\n\n        long long b = base - d;\n        if (d && b >= -1000000000LL && b <= 1000000000LL && !(isX ? has_point_x(b) : has_point_y(b))) return b;\n    }\n    return base;\n}\n\narray<long long, 4> line_to_integer_points_scaled(const Line& ln, long long SCALE) {\n    const long long LIM = 1000000000LL;\n    const long long BIG = 100000000LL;\n\n    double norm = hypot(ln.a, ln.b);\n    double aa = ln.a / norm;\n    double bb = ln.b / norm;\n    double cc = ln.c / norm;\n\n    // More faithful exact handling for nearly axis-parallel lines.\n    if (fabs(bb) < 1e-11) {\n        long long x = nearest_safe_coord(cc / aa, true);\n        return {x, -BIG, x, BIG};\n    }\n\n    if (fabs(aa) < 1e-11) {\n        long long y = nearest_safe_coord(cc / bb, false);\n        return {-BIG, y, BIG, y};\n    }\n\n    long long A = llround(aa * SCALE);\n    long long B = llround(bb * SCALE);\n\n    if (A == 0 && B == 0) A = 1;\n    if (A == 0) A = (aa >= 0 ? 1 : -1);\n    if (B == 0) B = (bb >= 0 ? 1 : -1);\n\n    for (int t = 0; std::gcd(llabs(A), llabs(B)) != 1 && t < 20; t++) {\n        if (llabs(A) < llabs(B)) A += (A >= 0 ? 1 : -1);\n        else B += (B >= 0 ? 1 : -1);\n    }\n\n    if (std::gcd(llabs(A), llabs(B)) != 1) {\n        A += (A >= 0 ? 1 : -1);\n        while (std::gcd(llabs(A), llabs(B)) != 1) A += (A >= 0 ? 1 : -1);\n    }\n\n    long double len = sqrt((long double)A * A + (long double)B * B);\n    long long C = llround((long double)cc * len);\n\n    for (int t = 0; t < 80 && collinear_any_coeff(A, B, C); t++) {\n        if (t % 2 == 0) C += 1 + t / 2;\n        else C -= 1 + t / 2;\n    }\n\n    long long xg, yg;\n    extgcd(llabs(A), llabs(B), xg, yg);\n\n    if (A < 0) xg = -xg;\n    if (B < 0) yg = -yg;\n\n    __int128 x0 = (__int128)xg * C;\n    __int128 y0 = (__int128)yg * C;\n\n    long double px = aa * cc;\n    long double py = bb * cc;\n\n    long double dx = B;\n    long double dy = -A;\n    long double denom = dx * dx + dy * dy;\n\n    long double tr = ((px - (long double)x0) * dx + (py - (long double)y0) * dy) / denom;\n    long long t0 = llround(tr);\n\n    __int128 x1b = x0 + (__int128)t0 * B;\n    __int128 y1b = y0 - (__int128)t0 * A;\n\n    long long x1 = (long long)x1b;\n    long long y1 = (long long)y1b;\n\n    long long stepMax = max(llabs(A), llabs(B));\n    long long T = max(1LL, min(900LL, (LIM - 1000000LL) / max(1LL, stepMax)));\n\n    long long x2 = x1 + B * T;\n    long long y2 = y1 - A * T;\n\n    if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) {\n        x2 = x1 - B * T;\n        y2 = y1 + A * T;\n    }\n\n    while ((x1 < -LIM || x1 > LIM || y1 < -LIM || y1 > LIM ||\n            x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) && T > 1) {\n        T /= 2;\n\n        x2 = x1 + B * T;\n        y2 = y1 - A * T;\n\n        if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) {\n            x2 = x1 - B * T;\n            y2 = y1 + A * T;\n        }\n    }\n\n    if (x1 < -LIM || x1 > LIM || y1 < -LIM || y1 > LIM ||\n        x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM ||\n        (x1 == x2 && y1 == y2)) {\n        // Robust fallback using two rounded floating points.\n        double px0 = aa * cc;\n        double py0 = bb * cc;\n        double ux = -bb, uy = aa;\n\n        x1 = llround(px0 + BIG * ux);\n        y1 = llround(py0 + BIG * uy);\n        x2 = llround(px0 - BIG * ux);\n        y2 = llround(py0 - BIG * uy);\n\n        x1 = max(-LIM, min(LIM, x1));\n        y1 = max(-LIM, min(LIM, y1));\n        x2 = max(-LIM, min(LIM, x2));\n        y2 = max(-LIM, min(LIM, y2));\n    }\n\n    if (x1 == x2 && y1 == y2) {\n        if (x2 < LIM) x2++;\n        else x2--;\n    }\n\n    return {x1, y1, x2, y2};\n}\n\nEvalResult eval_output_segments(const vector<array<long long, 4>>& segs) {\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(N * 2);\n\n    int L = (int)segs.size();\n\n    for (const auto& p : pts) {\n        uint64_t lo = 0, hi = 0;\n        bool cut = false;\n\n        for (int i = 0; i < L; i++) {\n            long long x1 = segs[i][0], y1 = segs[i][1], x2 = segs[i][2], y2 = segs[i][3];\n\n            __int128 cross = (__int128)(x2 - x1) * (p.y - y1) - (__int128)(y2 - y1) * (p.x - x1);\n\n            if (cross == 0) {\n                cut = true;\n                break;\n            }\n\n            if (cross > 0) {\n                if (i < 64) lo |= 1ULL << i;\n                else hi |= 1ULL << (i - 64);\n            }\n        }\n\n        if (!cut) mp[{lo, hi}]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n\n    for (auto& kv : mp) {\n        int c = kv.second;\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n\n    return make_eval_from_hist(hist);\n}\n\nvector<Line> remove_improving_lines(vector<Line> lines, double deadline) {\n    long long cur = eval_lines(lines).value();\n\n    bool improved = true;\n\n    while (improved && elapsed_sec() < deadline) {\n        improved = false;\n        int bestIdx = -1;\n        long long bestVal = cur;\n\n        for (int i = 0; i < (int)lines.size(); i++) {\n            if (elapsed_sec() > deadline) break;\n\n            vector<Line> tmp = lines;\n            tmp.erase(tmp.begin() + i);\n\n            long long v = eval_lines(tmp).value();\n\n            if (v > bestVal) {\n                bestVal = v;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx >= 0) {\n            lines.erase(lines.begin() + bestIdx);\n            cur = bestVal;\n            improved = true;\n        }\n    }\n\n    return lines;\n}\n\nvector<array<long long, 4>> remove_output_improving_segments(vector<array<long long, 4>> segs, double deadline) {\n    long long cur = eval_output_segments(segs).value();\n\n    while (elapsed_sec() < deadline) {\n        int bestIdx = -1;\n        long long bestVal = cur;\n\n        for (int i = 0; i < (int)segs.size(); i++) {\n            if (elapsed_sec() > deadline) break;\n\n            vector<array<long long, 4>> tmp = segs;\n            tmp.erase(tmp.begin() + i);\n\n            long long v = eval_output_segments(tmp).value();\n\n            if (v > bestVal) {\n                bestVal = v;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx == -1) break;\n\n        segs.erase(segs.begin() + bestIdx);\n        cur = bestVal;\n    }\n\n    return segs;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st = chrono::steady_clock::now();\n\n    cin >> N >> K;\n    targetA.fill(0);\n\n    int M = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> targetA[d];\n        M += targetA[d];\n    }\n\n    pts.resize(N);\n    for (int i = 0; i < N; i++) cin >> pts[i].x >> pts[i].y;\n\n    mt19937 rng(1234567);\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n\n    vector<Line> bestLines;\n    long long bestValue = LLONG_MIN;\n\n    vector<GridCand> topGrids;\n\n    auto register_grid = [&](double theta, const vector<double>& cu, const vector<double>& cv) {\n        if ((int)cu.size() + (int)cv.size() > K) return;\n\n        EvalResult er = eval_grid(theta, cu, cv);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = build_grid_lines(theta, cu, cv);\n        }\n\n        topGrids.push_back({theta, cu, cv, val});\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n\n        if ((int)topGrids.size() > 18) topGrids.pop_back();\n    };\n\n    auto register_lines = [&](const vector<Line>& lines) {\n        if ((int)lines.size() > K) return;\n\n        EvalResult er = eval_lines(lines);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = lines;\n        }\n    };\n\n    double baseUniformProduct = 4.0 * M / PI;\n\n    vector<double> factors = {0.45, 0.55, 0.65, 0.78, 0.90, 1.00, 1.12, 1.28, 1.50, 1.75, 2.05};\n    vector<double> aspects = {0.50, 0.62, 0.75, 0.88, 1.00, 1.15, 1.33, 1.60, 2.00};\n\n    vector<double> thetas;\n    for (int i = 0; i < 12; i++) thetas.push_back(PI * i / 24.0);\n\n    for (double fac : factors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, baseUniformProduct * fac);\n\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            auto cu = uniform_cuts(gx);\n            auto cv = uniform_cuts(gy);\n\n            for (double th : thetas) register_grid(th, cu, cv);\n        }\n    }\n\n    vector<double> qFactors = {0.50, 0.62, 0.75, 0.88, 1.00, 1.15, 1.32, 1.55, 1.85};\n\n    for (double fac : qFactors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, M * fac);\n\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            for (double th : thetas) {\n                auto cu = projection_quantile_cuts(th, gx, false);\n                auto cv = projection_quantile_cuts(th, gy, true);\n                register_grid(th, cu, cv);\n            }\n        }\n    }\n\n    for (int rep = 0; rep < 40 && elapsed_sec() < 1.1; rep++) {\n        double hbase = sqrt(max(1.0, M / 3.0));\n        double scale = 0.55 + 0.035 * rep;\n\n        int g = max(2, (int)llround(hbase * scale));\n        g = min(g, 34);\n\n        double th0 = (rep % 15) * PI / 45.0;\n\n        vector<Line> lines;\n\n        for (int f = 0; f < 3; f++) {\n            double th = th0 + f * PI / 3.0;\n            double a = cos(th), b = sin(th);\n\n            auto cuts = uniform_cuts(g);\n\n            for (double c : cuts) lines.push_back({a, b, c});\n        }\n\n        register_lines(lines);\n    }\n\n    vector<double> alphaList = {0.25, 0.35, 0.50, 0.75, 1.00, 1.50, 2.50, 5.00, 1000.0};\n\n    while (elapsed_sec() < 1.40) {\n        double logFac = log(0.45) + ur01(rng) * (log(2.15) - log(0.45));\n        double logAsp = log(0.45) + ur01(rng) * (log(2.20) - log(0.45));\n\n        double fac = exp(logFac);\n        double asp = exp(logAsp);\n\n        double prod = max(1.0, baseUniformProduct * fac);\n\n        int gx = max(1, (int)llround(sqrt(prod * asp)));\n        int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n        while (gx + gy - 2 > K) {\n            if (gx > gy) gx--;\n            else gy--;\n        }\n\n        double ax = alphaList[rng() % alphaList.size()];\n        double ay = alphaList[rng() % alphaList.size()];\n\n        auto cu = random_dirichlet_cuts(gx, ax, rng);\n        auto cv = random_dirichlet_cuts(gy, ay, rng);\n\n        double th = ur01(rng) * PI / 2.0;\n\n        register_grid(th, cu, cv);\n    }\n\n    auto improve_grid = [&](GridCand start, double timeLimit) {\n        GridCand cur = start;\n        GridCand best = start;\n\n        double begin = elapsed_sec();\n\n        while (elapsed_sec() < timeLimit) {\n            double now = elapsed_sec();\n            double progress = (now - begin) / max(1e-9, timeLimit - begin);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 30000.0 * (1.0 - progress) + 300.0;\n\n            GridCand nxt = cur;\n            int typ = rng() % 10;\n\n            if ((typ < 4 && !nxt.cu.empty()) || nxt.cv.empty()) {\n                int m = nxt.cu.size();\n                int id = rng() % m;\n\n                double lo = (id == 0 ? -R + 1e-6 : nxt.cu[id - 1] + 1e-6);\n                double hi = (id + 1 == m ? R - 1e-6 : nxt.cu[id + 1] - 1e-6);\n                double width = hi - lo;\n\n                double nv;\n                if (typ == 0) {\n                    normal_distribution<double> nd(0.0, width * 0.08);\n                    nv = nxt.cu[id] + nd(rng);\n                } else {\n                    nv = lo + ur01(rng) * width;\n                }\n\n                nxt.cu[id] = max(lo, min(hi, nv));\n            } else if (typ < 8 && !nxt.cv.empty()) {\n                int m = nxt.cv.size();\n                int id = rng() % m;\n\n                double lo = (id == 0 ? -R + 1e-6 : nxt.cv[id - 1] + 1e-6);\n                double hi = (id + 1 == m ? R - 1e-6 : nxt.cv[id + 1] - 1e-6);\n                double width = hi - lo;\n\n                double nv;\n                if (typ == 4) {\n                    normal_distribution<double> nd(0.0, width * 0.08);\n                    nv = nxt.cv[id] + nd(rng);\n                } else {\n                    nv = lo + ur01(rng) * width;\n                }\n\n                nxt.cv[id] = max(lo, min(hi, nv));\n            } else if (typ == 8) {\n                normal_distribution<double> nd(0.0, 0.015 * (1.0 - progress) + 0.002);\n\n                nxt.theta += nd(rng);\n                while (nxt.theta < 0) nxt.theta += PI;\n                while (nxt.theta >= PI) nxt.theta -= PI;\n            } else {\n                bool axis = rng() & 1;\n                double scale = exp((ur01(rng) - 0.5) * 0.12 * (1.0 - progress));\n\n                vector<double>& arr = axis ? nxt.cu : nxt.cv;\n\n                for (double& x : arr) x = max(-R + 1e-6, min(R - 1e-6, x * scale));\n\n                sort(arr.begin(), arr.end());\n\n                for (int i = 1; i < (int)arr.size(); i++) {\n                    if (arr[i] <= arr[i - 1] + 1e-6) arr[i] = arr[i - 1] + 1e-6;\n                }\n\n                for (double& x : arr) x = max(-R + 1e-6, min(R - 1e-6, x));\n            }\n\n            EvalResult er = eval_grid(nxt.theta, nxt.cu, nxt.cv);\n            nxt.val = er.value();\n\n            long long delta = nxt.val - cur.val;\n\n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else {\n                double prob = exp((double)delta / temp);\n                if (ur01(rng) < prob) accept = true;\n            }\n\n            if (accept) cur = nxt;\n\n            if (nxt.val > best.val) {\n                best = nxt;\n\n                if (nxt.val > bestValue) {\n                    bestValue = nxt.val;\n                    bestLines = build_grid_lines(nxt.theta, nxt.cu, nxt.cv);\n                }\n            }\n        }\n\n        return best;\n    };\n\n    int idx = 0;\n\n    while (elapsed_sec() < 2.32 && idx < (int)topGrids.size()) {\n        double remaining = 2.32 - elapsed_sec();\n        int left = (int)topGrids.size() - idx;\n\n        double slice = min(0.19, max(0.035, remaining / max(1, left)));\n\n        GridCand improved = improve_grid(topGrids[idx], min(2.32, elapsed_sec() + slice));\n        topGrids[idx] = improved;\n\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n\n        idx++;\n    }\n\n    while (elapsed_sec() < 2.40 && !topGrids.empty()) {\n        GridCand improved = improve_grid(topGrids[0], min(2.40, elapsed_sec() + 0.05));\n        topGrids[0] = improved;\n\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n    }\n\n    vector<Line> beforeGreedyLines = bestLines;\n    vector<Line> bestGreedyLines = bestLines;\n\n    greedy_add_lines(bestLines, bestValue, 2.865, rng, bestGreedyLines);\n\n    vector<vector<Line>> candidateSets;\n    candidateSets.push_back(bestLines);\n    candidateSets.push_back(bestGreedyLines);\n    candidateSets.push_back(beforeGreedyLines);\n\n    for (int i = 0; i < min(5, (int)topGrids.size()); i++) {\n        candidateSets.push_back(build_grid_lines(topGrids[i].theta, topGrids[i].cu, topGrids[i].cv));\n    }\n\n    if (elapsed_sec() < 2.91) {\n        candidateSets.push_back(remove_improving_lines(bestLines, 2.915));\n    }\n\n    if (elapsed_sec() < 2.925) {\n        candidateSets.push_back(remove_improving_lines(bestGreedyLines, 2.93));\n    }\n\n    if (bestLines.empty()) {\n        auto cu = uniform_cuts(25);\n        auto cv = uniform_cuts(25);\n        bestLines = build_grid_lines(0.01, cu, cv);\n        candidateSets.push_back(bestLines);\n    }\n\n    long long bestOutVal = LLONG_MIN;\n    vector<array<long long, 4>> bestSegs;\n\n    vector<long long> scales = {10007LL, 100003LL, 1000003LL, 10000019LL, 100000007LL};\n\n    for (auto lines : candidateSets) {\n        if ((int)lines.size() > K) lines.resize(K);\n\n        for (long long sc : scales) {\n            if (elapsed_sec() > 2.965) break;\n\n            vector<array<long long, 4>> segs;\n            segs.reserve(lines.size());\n\n            for (const auto& ln : lines) {\n                segs.push_back(line_to_integer_points_scaled(ln, sc));\n            }\n\n            long long v = eval_output_segments(segs).value();\n\n            if (v > bestOutVal) {\n                bestOutVal = v;\n                bestSegs = segs;\n            }\n        }\n    }\n\n    if (elapsed_sec() < 2.975 && !bestSegs.empty()) {\n        auto improvedSegs = remove_output_improving_segments(bestSegs, 2.985);\n        long long v = eval_output_segments(improvedSegs).value();\n        if (v >= bestOutVal) {\n            bestOutVal = v;\n            bestSegs = improvedSegs;\n        }\n    }\n\n    if ((int)bestSegs.size() > K) bestSegs.resize(K);\n\n    cout << bestSegs.size() << '\\n';\n\n    for (const auto& e : bestSegs) {\n        cout << e[0] << ' ' << e[1] << ' ' << e[2] << ' ' << e[3] << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 61;\n\nint N, M;\nint Weight[MAXN][MAXN];\nint maxWeightGlobal;\nint centerCoord;\nvector<pair<int,int>> initialDots;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int nextInt(int mod) {\n        if (mod <= 0) return 0;\n        return int(next() % mod);\n    }\n};\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nint dx8[8] = {1, 0, -1, 0, 1, -1, -1, 1};\nint dy8[8] = {0, 1, 0, -1, 1, 1, -1, -1};\n\npair<int,int> dirPairs[8] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0},\n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ninline int enc(int x, int y) {\n    return x * N + y;\n}\n\ninline int stepLen(int ax, int ay, int bx, int by) {\n    return max(abs(ax - bx), abs(ay - by));\n}\n\ninline int movePerim(const Move &m) {\n    return stepLen(m.x1, m.y1, m.x2, m.y2)\n         + stepLen(m.x2, m.y2, m.x3, m.y3)\n         + stepLen(m.x3, m.y3, m.x4, m.y4)\n         + stepLen(m.x4, m.y4, m.x1, m.y1);\n}\n\nstruct State {\n    bool dot[MAXN][MAXN];\n    bool seg[4][MAXN][MAXN];\n    vector<Move> ops;\n    long long totalWeight;\n\n    void init() {\n        memset(dot, 0, sizeof(dot));\n        memset(seg, 0, sizeof(seg));\n        ops.clear();\n        ops.reserve(N * N);\n        totalWeight = 0;\n\n        for (auto [x, y] : initialDots) {\n            dot[x][y] = true;\n            totalWeight += Weight[x][y];\n        }\n    }\n\n    bool edgeFree(int ax, int ay, int bx, int by) const {\n        if (ay == by) {\n            int y = ay;\n            int l = min(ax, bx), r = max(ax, bx);\n            for (int x = l; x < r; x++) {\n                if (seg[0][x][y]) return false;\n            }\n            return true;\n        }\n\n        if (ax == bx) {\n            int x = ax;\n            int l = min(ay, by), r = max(ay, by);\n            for (int y = l; y < r; y++) {\n                if (seg[1][x][y]) return false;\n            }\n            return true;\n        }\n\n        if ((bx - ax) == (by - ay)) {\n            int x = ax, y = ay;\n            if (x > bx) {\n                x = bx;\n                y = by;\n            }\n\n            int len = abs(bx - ax);\n            for (int i = 0; i < len; i++) {\n                if (seg[2][x + i][y + i]) return false;\n            }\n            return true;\n        }\n\n        {\n            int x = ax, y = ay;\n            if (x > bx) {\n                x = bx;\n                y = by;\n            }\n\n            int len = abs(bx - ax);\n            for (int i = 0; i < len; i++) {\n                if (seg[3][x + i][y - i - 1]) return false;\n            }\n            return true;\n        }\n    }\n\n    void markEdge(int ax, int ay, int bx, int by) {\n        if (ay == by) {\n            int y = ay;\n            int l = min(ax, bx), r = max(ax, bx);\n            for (int x = l; x < r; x++) seg[0][x][y] = true;\n            return;\n        }\n\n        if (ax == bx) {\n            int x = ax;\n            int l = min(ay, by), r = max(ay, by);\n            for (int y = l; y < r; y++) seg[1][x][y] = true;\n            return;\n        }\n\n        if ((bx - ax) == (by - ay)) {\n            int x = ax, y = ay;\n            if (x > bx) {\n                x = bx;\n                y = by;\n            }\n\n            int len = abs(bx - ax);\n            for (int i = 0; i < len; i++) seg[2][x + i][y + i] = true;\n            return;\n        }\n\n        {\n            int x = ax, y = ay;\n            if (x > bx) {\n                x = bx;\n                y = by;\n            }\n\n            int len = abs(bx - ax);\n            for (int i = 0; i < len; i++) seg[3][x + i][y - i - 1] = true;\n        }\n    }\n\n    bool rectEdgesFree(const Move &m) const {\n        return edgeFree(m.x1, m.y1, m.x2, m.y2)\n            && edgeFree(m.x2, m.y2, m.x3, m.y3)\n            && edgeFree(m.x3, m.y3, m.x4, m.y4)\n            && edgeFree(m.x4, m.y4, m.x1, m.y1);\n    }\n\n    bool isAllowedDotOnPerimeter(int x, int y, const Move &m) const {\n        return (x == m.x2 && y == m.y2)\n            || (x == m.x3 && y == m.y3)\n            || (x == m.x4 && y == m.y4);\n    }\n\n    bool edgeDotsOk(int ax, int ay, int bx, int by, const Move &m) const {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i <= len; i++) {\n            if (dot[x][y] && !isAllowedDotOnPerimeter(x, y, m)) return false;\n            x += dx;\n            y += dy;\n        }\n\n        return true;\n    }\n\n    bool validMove(const Move &m) const {\n        if (!inside(m.x1, m.y1) || !inside(m.x2, m.y2)\n         || !inside(m.x3, m.y3) || !inside(m.x4, m.y4)) return false;\n\n        if (dot[m.x1][m.y1]) return false;\n        if (!dot[m.x2][m.y2] || !dot[m.x3][m.y3] || !dot[m.x4][m.y4]) return false;\n\n        int ax = m.x2 - m.x1;\n        int ay = m.y2 - m.y1;\n        int bx = m.x4 - m.x1;\n        int by = m.y4 - m.y1;\n\n        if (ax == 0 && ay == 0) return false;\n        if (bx == 0 && by == 0) return false;\n\n        if (m.x3 != m.x2 + m.x4 - m.x1) return false;\n        if (m.y3 != m.y2 + m.y4 - m.y1) return false;\n\n        if (ax * bx + ay * by != 0) return false;\n\n        auto allowedVec = [](int x, int y) {\n            if (x == 0 && y != 0) return true;\n            if (y == 0 && x != 0) return true;\n            if (abs(x) == abs(y) && x != 0) return true;\n            return false;\n        };\n\n        if (!allowedVec(ax, ay) || !allowedVec(bx, by)) return false;\n\n        if (!rectEdgesFree(m)) return false;\n\n        if (!edgeDotsOk(m.x1, m.y1, m.x2, m.y2, m)) return false;\n        if (!edgeDotsOk(m.x2, m.y2, m.x3, m.y3, m)) return false;\n        if (!edgeDotsOk(m.x3, m.y3, m.x4, m.y4, m)) return false;\n        if (!edgeDotsOk(m.x4, m.y4, m.x1, m.y1, m)) return false;\n\n        return true;\n    }\n\n    void apply(const Move &m) {\n        markEdge(m.x1, m.y1, m.x2, m.y2);\n        markEdge(m.x2, m.y2, m.x3, m.y3);\n        markEdge(m.x3, m.y3, m.x4, m.y4);\n        markEdge(m.x4, m.y4, m.x1, m.y1);\n\n        dot[m.x1][m.y1] = true;\n        totalWeight += Weight[m.x1][m.y1];\n        ops.push_back(m);\n    }\n};\n\nstruct Param {\n    int wcoef;\n    int pcoef;\n    int qcoef;\n    int dcoef;\n    int ocoef;\n    int acoef;\n    int rcoef;\n    int dircoef;\n    int noise;\n    int topR;\n    int phase;\n};\n\nstruct Result {\n    long long score;\n    vector<Move> ops;\n};\n\nstruct Candidate {\n    long long key;\n    Move mv;\n};\n\nvoid insertTop(vector<Candidate> &top, int R, const Candidate &cand) {\n    if ((int)top.size() < R) {\n        top.push_back(cand);\n        return;\n    }\n\n    int worst = 0;\n    for (int i = 1; i < R; i++) {\n        if (top[i].key < top[worst].key) worst = i;\n    }\n\n    if (cand.key > top[worst].key) top[worst] = cand;\n}\n\nState greedyFill(State st, const Param &param, XorShift &rng, const Timer &timer, double deadline) {\n    static short nearestDot[8][MAXN][MAXN];\n\n    int dirx = 0, diry = 0;\n    if (param.dircoef != 0) {\n        int k = rng.nextInt(8);\n        dirx = dx8[k];\n        diry = dy8[k];\n    }\n\n    while (true) {\n        if (timer.elapsed() > deadline) break;\n\n        for (int d = 0; d < 8; d++) {\n            int xs = dx8[d] > 0 ? N - 1 : 0;\n            int xe = dx8[d] > 0 ? -1 : N;\n            int xi = dx8[d] > 0 ? -1 : 1;\n\n            int ys = dy8[d] > 0 ? N - 1 : 0;\n            int ye = dy8[d] > 0 ? -1 : N;\n            int yi = dy8[d] > 0 ? -1 : 1;\n\n            for (int x = xs; x != xe; x += xi) {\n                for (int y = ys; y != ye; y += yi) {\n                    int nx = x + dx8[d];\n                    int ny = y + dy8[d];\n\n                    if (!inside(nx, ny)) {\n                        nearestDot[d][x][y] = -1;\n                    } else if (st.dot[nx][ny]) {\n                        nearestDot[d][x][y] = enc(nx, ny);\n                    } else {\n                        nearestDot[d][x][y] = nearestDot[d][nx][ny];\n                    }\n                }\n            }\n        }\n\n        bool found = false;\n        Move bestMove{};\n        long long bestKey = LLONG_MIN;\n        vector<Candidate> top;\n\n        if (param.topR > 1) top.reserve(param.topR);\n\n        int opCount = (int)st.ops.size();\n\n        long long pEff = param.pcoef;\n        if (param.phase == 1) {\n            pEff = 1LL * param.pcoef * 260 / (260 + opCount);\n        } else if (param.phase == 2) {\n            pEff = 1LL * param.pcoef * (120 + min(opCount, 400)) / 120;\n        }\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                if (st.dot[x][y]) continue;\n\n                int degree = 0;\n                if (param.dcoef != 0) {\n                    for (int d = 0; d < 8; d++) {\n                        if (nearestDot[d][x][y] >= 0) degree++;\n                    }\n                }\n\n                int opp = 0;\n                if (param.ocoef != 0) {\n                    for (auto [d1, d2] : dirPairs) {\n                        if (nearestDot[d1][x][y] >= 0 && nearestDot[d2][x][y] >= 0) opp++;\n                    }\n                }\n\n                for (auto [d1, d2] : dirPairs) {\n                    int e2 = nearestDot[d1][x][y];\n                    int e4 = nearestDot[d2][x][y];\n\n                    if (e2 < 0 || e4 < 0) continue;\n\n                    int x2 = e2 / N;\n                    int y2 = e2 % N;\n                    int x4 = e4 / N;\n                    int y4 = e4 % N;\n\n                    int x3 = x2 + x4 - x;\n                    int y3 = y2 + y4 - y;\n\n                    if (!inside(x3, y3)) continue;\n                    if (!st.dot[x3][y3]) continue;\n\n                    int e3 = enc(x3, y3);\n                    if (nearestDot[d2][x2][y2] != e3) continue;\n                    if (nearestDot[d1][x4][y4] != e3) continue;\n\n                    Move mv{x, y, x2, y2, x3, y3, x4, y4};\n                    if (!st.rectEdgesFree(mv)) continue;\n\n                    int perim = movePerim(mv);\n                    int area = abs((x2 - x) * (y4 - y) - (y2 - y) * (x4 - x));\n\n                    long long key = 0;\n                    key += 1LL * Weight[x][y] * param.wcoef;\n                    key -= 1LL * perim * pEff;\n                    key -= 1LL * perim * perim * param.qcoef;\n                    key += 1LL * degree * param.dcoef;\n                    key += 1LL * opp * param.ocoef;\n                    key += 1LL * area * param.acoef;\n\n                    if (param.rcoef != 0) {\n                        key += 1LL * param.rcoef * (10000LL * Weight[x][y] / (perim + 4));\n                    }\n\n                    if (param.dircoef != 0) {\n                        int proj = dirx * (x - centerCoord) + diry * (y - centerCoord);\n                        key += 1LL * param.dircoef * proj;\n                    }\n\n                    if (param.noise > 0) key += rng.nextInt(param.noise);\n\n                    if (param.topR <= 1) {\n                        if (!found || key > bestKey || (key == bestKey && rng.nextInt(2))) {\n                            found = true;\n                            bestKey = key;\n                            bestMove = mv;\n                        }\n                    } else {\n                        insertTop(top, param.topR, Candidate{key, mv});\n                    }\n                }\n            }\n        }\n\n        if (param.topR > 1) {\n            if (top.empty()) break;\n\n            sort(top.begin(), top.end(), [](const Candidate &a, const Candidate &b) {\n                return a.key > b.key;\n            });\n\n            int r = (int)top.size();\n            int idx;\n\n            if (r == 1) {\n                idx = 0;\n            } else {\n                int a = rng.nextInt(r);\n                int b = rng.nextInt(r);\n                idx = 1LL * a * b / r;\n                if (idx >= r) idx = r - 1;\n            }\n\n            bestMove = top[idx].mv;\n            found = true;\n        }\n\n        if (!found) break;\n\n        st.apply(bestMove);\n    }\n\n    return st;\n}\n\nState makePerturbedState(const vector<Move> &baseOps, XorShift &rng, int mode) {\n    State st;\n    st.init();\n\n    int K = (int)baseOps.size();\n\n    int prefix = K;\n    int blockL = K + 1;\n    int blockR = K + 1;\n    int dropPct = 0;\n\n    if (mode == 0) {\n        dropPct = 4 + rng.nextInt(16);\n    } else if (mode == 1) {\n        prefix = K * (35 + rng.nextInt(55)) / 100;\n    } else if (mode == 2) {\n        if (K > 0) {\n            blockL = rng.nextInt(K);\n            int len = max(1, K * (5 + rng.nextInt(22)) / 100);\n            blockR = min(K, blockL + len);\n        }\n    }\n\n    for (int i = 0; i < K; i++) {\n        bool keep = true;\n        const Move &m = baseOps[i];\n\n        if (mode == 0) {\n            if (rng.nextInt(100) < dropPct) keep = false;\n        } else if (mode == 1) {\n            if (i >= prefix) keep = false;\n        } else if (mode == 2) {\n            if (blockL <= i && i < blockR) keep = false;\n        } else if (mode == 3) {\n            int w = Weight[m.x1][m.y1];\n            int low = maxWeightGlobal - w;\n            int prob = 3 + 28 * low / max(1, maxWeightGlobal);\n            if (rng.nextInt(100) < prob) keep = false;\n        } else if (mode == 4) {\n            int p = movePerim(m);\n            int prob = 2 + 45 * p / max(1, 4 * N);\n            if (rng.nextInt(100) < prob) keep = false;\n        } else {\n            int p = movePerim(m);\n            int w = Weight[m.x1][m.y1];\n            int bad = max(0, maxWeightGlobal - w) + p * 8;\n            int prob = 2 + min(40, bad * 35 / max(1, maxWeightGlobal + 4 * N));\n            if (rng.nextInt(100) < prob) keep = false;\n        }\n\n        if (!keep) continue;\n\n        if (st.validMove(m)) st.apply(m);\n    }\n\n    return st;\n}\n\nvoid updateElites(vector<Result> &elites, const Result &cand) {\n    elites.push_back(cand);\n\n    sort(elites.begin(), elites.end(), [](const Result &a, const Result &b) {\n        if (a.score != b.score) return a.score > b.score;\n        return a.ops.size() > b.ops.size();\n    });\n\n    vector<Result> filtered;\n    for (auto &e : elites) {\n        bool dup = false;\n        for (auto &f : filtered) {\n            if (e.score == f.score && e.ops.size() == f.ops.size()) {\n                dup = true;\n                break;\n            }\n        }\n\n        if (!dup) filtered.push_back(e);\n        if ((int)filtered.size() >= 7) break;\n    }\n\n    elites.swap(filtered);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    initialDots.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initialDots[i].first >> initialDots[i].second;\n    }\n\n    centerCoord = (N - 1) / 2;\n    maxWeightGlobal = 0;\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            Weight[x][y] = (x - centerCoord) * (x - centerCoord)\n                         + (y - centerCoord) * (y - centerCoord) + 1;\n            maxWeightGlobal = max(maxWeightGlobal, Weight[x][y]);\n        }\n    }\n\n    Timer timer;\n    const double DEADLINE = 4.72;\n\n    vector<Param> params = {\n        // Strong baselines.\n        {1000,    0,   0,     0,     0,    0, 0,    0,      0,  1, 0},\n        {1000,   20,   0,     0,     0,    0, 0,    0,  20000,  1, 0},\n        {1000,   80,   0,     0,     0,    0, 0,    0,  50000,  1, 0},\n        {1000,  200,   0,     0,     0,    0, 0,    0, 100000,  1, 0},\n        {1000,  -20,   0,     0,     0,    0, 0,    0,  50000,  1, 0},\n        {1000,  -80,   0,     0,     0,    0, 0,    0, 100000,  1, 0},\n        {1000,    0,   0,     0,     0,    0, 0,    0, 200000,  1, 0},\n        {1000,  400,   0,     0,     0,    0, 0,    0, 200000,  1, 0},\n\n        // Perimeter / visibility.\n        {1000, 1000,   0,     0,     0,    0, 0,    0,  50000,  4, 1},\n        {1000, 1800,   0,     0,     0,  -15, 0,    0,  80000,  6, 1},\n        {1000, 3000,   0,     0,     0,  -30, 0,    0, 100000,  8, 1},\n        { 950, 4500,   0,     0,     0,  -45, 0,    0, 120000, 10, 1},\n\n        {1000, 1000,   0, 10000,  8000,    0, 0,    0,  70000,  6, 1},\n        {1000, 2000,   0, 20000, 12000,  -15, 0,    0, 100000,  8, 1},\n        { 900, 3500,   0, 35000, 18000,  -30, 0,    0, 130000, 12, 1},\n        { 800, 5000,   0, 50000, 25000,  -45, 0,    0, 160000, 16, 1},\n\n        // Short efficient rectangles.\n        { 900,  500,  10, 10000, 10000,    0, 2,    0,  80000,  6, 1},\n        { 800,  800,  18, 20000, 15000,  -10, 3,    0, 100000,  8, 1},\n        { 750, 1200,  25, 30000, 20000,  -20, 4,    0, 130000, 10, 1},\n        { 700, 1600,  35, 40000, 25000,  -30, 5,    0, 150000, 12, 1},\n\n        // Directional expansion.\n        {1000,  300,   0,  8000,  8000,   10, 0, 2500, 100000,  8, 0},\n        {1000,  800,   0, 12000, 12000,    0, 1, 3500, 120000, 10, 1},\n        { 900, 1200,  12, 20000, 16000,  -15, 2, 4500, 140000, 12, 1},\n\n        // Aggressive expansion.\n        {1000, -300,   0,     0,     0,   20, 0,    0,  80000,  5, 0},\n        {1000, -800,   0,     0,     0,   45, 0,    0, 120000,  8, 0},\n\n        // Late-game tightening.\n        {1000,  800,   0, 10000,  8000,    0, 0,    0,  70000,  6, 2},\n        {1000, 1600,   0, 25000, 15000,  -15, 0,    0, 100000, 10, 2},\n    };\n\n    vector<Param> repairParams = {\n        {1000,    0,   0,     0,     0,    0, 0,    0, 100000,  1, 0},\n        {1000, 1000,   0, 10000, 10000,    0, 0,    0,  70000,  6, 1},\n        {1000, 2000,   0, 20000, 12000,  -15, 0,    0, 100000,  8, 1},\n        { 900, 3500,   0, 35000, 18000,  -30, 0,    0, 130000, 12, 1},\n        {1000, -300,   0,     0,     0,   20, 0,    0, 100000,  6, 0},\n        { 850,  800,  15, 20000, 15000,  -10, 3,    0, 110000,  8, 1},\n        { 750, 1300,  25, 30000, 20000,  -25, 4,    0, 140000, 12, 1},\n        {1000,  500,   0, 12000, 10000,   10, 1, 3000, 120000, 10, 1},\n        { 900, 1200,  12, 25000, 18000,  -15, 2, 4200, 140000, 12, 1},\n    };\n\n    Result best{-1, {}};\n    vector<Result> elites;\n\n    int iter = 0;\n    int normalIter = 0;\n    int repairIter = 0;\n\n    while (timer.elapsed() < DEADLINE) {\n        uint64_t seed = 123456789ULL\n                      + 1000003ULL * iter\n                      + 998244353ULL * N\n                      + 19260817ULL * M;\n\n        XorShift rng(seed);\n\n        State start;\n        Param p;\n\n        bool doRepair = false;\n        if (!elites.empty() && normalIter >= (int)params.size() && iter % 2 == 1) {\n            doRepair = true;\n        }\n\n        if (!doRepair) {\n            start.init();\n            p = params[normalIter % params.size()];\n            normalIter++;\n        } else {\n            int eliteIndex = 0;\n            if ((int)elites.size() >= 2 && rng.nextInt(100) >= 60) {\n                eliteIndex = rng.nextInt((int)elites.size());\n            }\n\n            int mode = rng.nextInt(6);\n            start = makePerturbedState(elites[eliteIndex].ops, rng, mode);\n            p = repairParams[repairIter % repairParams.size()];\n            repairIter++;\n        }\n\n        State fin = greedyFill(std::move(start), p, rng, timer, DEADLINE);\n\n        Result cand{fin.totalWeight, fin.ops};\n\n        if (cand.score > best.score) {\n            best = cand;\n        }\n\n        updateElites(elites, cand);\n        iter++;\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (const auto &m : best.ops) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed = 2463534242u) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n};\n\nusing Board = array<unsigned char, 100>;\n\nint F[101];\nint cntFlavor[4];\n\nint anchorR[4], anchorC[4];\nint distCell[4][100];\nint targetCell[100];\n\nint neighs[100][4];\nint degs[100];\n\nconst int cornerR[4] = {0, 0, 9, 9};\nconst int cornerC[4] = {0, 9, 0, 9};\n\nchar dirChar[4] = {'F', 'B', 'L', 'R'};\n\nvoid initNeighbors() {\n    for (int id = 0; id < 100; id++) {\n        int r = id / 10;\n        int c = id % 10;\n        degs[id] = 0;\n        if (r > 0) neighs[id][degs[id]++] = id - 10;\n        if (r < 9) neighs[id][degs[id]++] = id + 10;\n        if (c > 0) neighs[id][degs[id]++] = id - 1;\n        if (c < 9) neighs[id][degs[id]++] = id + 1;\n    }\n}\n\nBoard tiltBoard(const Board& b, int dir) {\n    Board nb{};\n    nb.fill(0);\n\n    if (dir == 0) { // F\n        for (int c = 0; c < 10; c++) {\n            int w = 0;\n            for (int r = 0; r < 10; r++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w++ * 10 + c] = v;\n            }\n        }\n    } else if (dir == 1) { // B\n        for (int c = 0; c < 10; c++) {\n            int w = 9;\n            for (int r = 9; r >= 0; r--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w-- * 10 + c] = v;\n            }\n        }\n    } else if (dir == 2) { // L\n        for (int r = 0; r < 10; r++) {\n            int w = 0;\n            for (int c = 0; c < 10; c++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w++] = v;\n            }\n        }\n    } else { // R\n        for (int r = 0; r < 10; r++) {\n            int w = 9;\n            for (int c = 9; c >= 0; c--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w--] = v;\n            }\n        }\n    }\n\n    return nb;\n}\n\nvoid placeCandyByP(Board& b, int p, int flavor) {\n    int k = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            k++;\n            if (k == p) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n        }\n    }\n}\n\nvoid placeRandomCandy(Board& b, int emptyCnt, int flavor, XorShift& rng) {\n    int k = rng.randint(emptyCnt);\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            if (k == 0) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n            k--;\n        }\n    }\n}\n\nlong long componentRawScore(const Board& b) {\n    bool vis[100] = {};\n    long long res = 0;\n    int q[100];\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            for (int i = 0; i < degs[v]; i++) {\n                int ni = neighs[v][i];\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        res += 1LL * sz * sz;\n    }\n\n    return res;\n}\n\nlong long evalBoard(const Board& b) {\n    bool vis[100] = {};\n    long long comp = 0;\n    int q[100];\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            for (int i = 0; i < degs[v]; i++) {\n                int ni = neighs[v][i];\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        comp += 1LL * sz * sz;\n    }\n\n    int sameAdj = 0;\n    int diffAdj = 0;\n    int pref = 0;\n    int targetMatch = 0;\n\n    for (int r = 0; r < 10; r++) {\n        for (int c = 0; c < 10; c++) {\n            int id = r * 10 + c;\n            int fl = b[id];\n            if (fl == 0) continue;\n\n            pref += 18 - distCell[fl][id];\n            if (targetCell[id] == fl) targetMatch++;\n\n            if (r + 1 < 10) {\n                int fl2 = b[(r + 1) * 10 + c];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n            if (c + 1 < 10) {\n                int fl2 = b[r * 10 + c + 1];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n        }\n    }\n\n    return comp * 100\n         + sameAdj * 220\n         - diffAdj * 60\n         + pref * 28\n         + targetMatch * 300;\n}\n\nvoid buildTarget() {\n    for (int fl = 1; fl <= 3; fl++) {\n        for (int id = 0; id < 100; id++) {\n            int r = id / 10;\n            int c = id % 10;\n            distCell[fl][id] = abs(r - anchorR[fl]) + abs(c - anchorC[fl]);\n        }\n    }\n\n    fill(targetCell, targetCell + 100, 0);\n\n    struct Item {\n        int dist;\n        int fl;\n        int id;\n    };\n\n    vector<Item> items;\n    items.reserve(300);\n\n    for (int id = 0; id < 100; id++) {\n        for (int fl = 1; fl <= 3; fl++) {\n            items.push_back({distCell[fl][id], fl, id});\n        }\n    }\n\n    sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.fl != b.fl) return a.fl < b.fl;\n        return a.id < b.id;\n    });\n\n    int rem[4];\n    for (int fl = 1; fl <= 3; fl++) rem[fl] = cntFlavor[fl];\n\n    for (auto& it : items) {\n        if (targetCell[it.id] == 0 && rem[it.fl] > 0) {\n            targetCell[it.id] = it.fl;\n            rem[it.fl]--;\n        }\n    }\n}\n\nint choosePolicyDir(const Board& b) {\n    int bestDir = 0;\n    long long bestVal = LLONG_MIN;\n\n    for (int d = 0; d < 4; d++) {\n        Board nb = tiltBoard(b, d);\n        long long val = evalBoard(nb);\n        if (val > bestVal) {\n            bestVal = val;\n            bestDir = d;\n        }\n    }\n\n    return bestDir;\n}\n\nlong long simulatePolicyGame(uint32_t seed) {\n    XorShift rng(seed);\n    Board b{};\n    b.fill(0);\n\n    for (int t = 1; t <= 100; t++) {\n        placeRandomCandy(b, 101 - t, F[t], rng);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long simulateRollout(Board b, int nextT, uint32_t seed) {\n    XorShift rng(seed);\n\n    for (int t = nextT; t <= 100; t++) {\n        placeRandomCandy(b, 101 - t, F[t], rng);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long exactOneStepLookahead(const Board& b, int currentT) {\n    if (currentT >= 100) return evalBoard(b);\n\n    int nt = currentT + 1;\n    int fl = F[nt];\n\n    vector<int> emp;\n    emp.reserve(100);\n\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) emp.push_back(i);\n    }\n\n    long long sum = 0;\n\n    for (int id : emp) {\n        Board tmp = b;\n        tmp[id] = (unsigned char)fl;\n\n        if (nt == 100) {\n            // True final objective is better than heuristic at the last placement.\n            sum += componentRawScore(tmp) * 100;\n        } else {\n            long long best = LLONG_MIN;\n            for (int d = 0; d < 4; d++) {\n                Board nb = tiltBoard(tmp, d);\n                best = max(best, evalBoard(nb));\n            }\n            sum += best;\n        }\n    }\n\n    return sum / max(1, (int)emp.size());\n}\n\nvoid selectCornerAssignment() {\n    double bestScore = -1.0;\n    int bestCorner[4] = {0, 0, 1, 2};\n\n    vector<uint32_t> seeds;\n    for (int i = 0; i < 5; i++) {\n        seeds.push_back(1234567u + i * 1000003u);\n    }\n\n    for (int mask = 0; mask < (1 << 4); mask++) {\n        if (__builtin_popcount((unsigned)mask) != 3) continue;\n\n        vector<int> cs;\n        for (int i = 0; i < 4; i++) {\n            if (mask >> i & 1) cs.push_back(i);\n        }\n\n        sort(cs.begin(), cs.end());\n\n        do {\n            for (int fl = 1; fl <= 3; fl++) {\n                int cid = cs[fl - 1];\n                anchorR[fl] = cornerR[cid];\n                anchorC[fl] = cornerC[cid];\n            }\n\n            buildTarget();\n\n            long long sum = 0;\n            for (uint32_t seed : seeds) {\n                sum += simulatePolicyGame(seed);\n            }\n\n            double avg = (double)sum / seeds.size();\n\n            if (avg > bestScore) {\n                bestScore = avg;\n                for (int fl = 1; fl <= 3; fl++) {\n                    bestCorner[fl] = cs[fl - 1];\n                }\n            }\n\n        } while (next_permutation(cs.begin(), cs.end()));\n    }\n\n    for (int fl = 1; fl <= 3; fl++) {\n        int cid = bestCorner[fl];\n        anchorR[fl] = cornerR[cid];\n        anchorC[fl] = cornerC[cid];\n    }\n\n    buildTarget();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    initNeighbors();\n\n    auto startTime = chrono::steady_clock::now();\n\n    for (int i = 1; i <= 100; i++) {\n        cin >> F[i];\n        cntFlavor[F[i]]++;\n    }\n\n    selectCornerAssignment();\n\n    Board board{};\n    board.fill(0);\n\n    XorShift rolloutRng(987654321u);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        placeCandyByP(board, p, F[t]);\n\n        Board cand[4];\n        long long baseEval[4];\n        long long lookEval[4];\n\n        for (int d = 0; d < 4; d++) {\n            cand[d] = tiltBoard(board, d);\n            baseEval[d] = evalBoard(cand[d]);\n        }\n\n        bool canLook = true;\n        {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > 1.72) canLook = false;\n        }\n\n        for (int d = 0; d < 4; d++) {\n            if (canLook && t < 100) lookEval[d] = exactOneStepLookahead(cand[d], t);\n            else lookEval[d] = baseEval[d];\n        }\n\n        long long rolloutTotal[4] = {};\n        int samples = 0;\n\n        if (t < 100) {\n            double ratio = (double)t / 100.0;\n            double targetTime = 0.03 + 1.77 * pow(ratio, 1.25);\n            const double HARD_LIMIT = 1.86;\n\n            while (true) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - startTime).count();\n\n                if (elapsed > HARD_LIMIT) break;\n                if (elapsed > targetTime && samples >= 1) break;\n\n                uint32_t seed = rolloutRng.next();\n\n                for (int d = 0; d < 4; d++) {\n                    rolloutTotal[d] += simulateRollout(cand[d], t + 1, seed);\n                }\n\n                samples++;\n\n                if (samples >= 250) break;\n            }\n        }\n\n        int bestDir = 0;\n        double bestScore = -1e100;\n\n        for (int d = 0; d < 4; d++) {\n            double score;\n\n            if (samples > 0) {\n                double rolloutAvg = (double)rolloutTotal[d] / samples;\n                double lookPseudoRaw = (double)lookEval[d] / 100.0;\n                double basePseudoRaw = (double)baseEval[d] / 100.0;\n\n                score = rolloutAvg + 0.12 * lookPseudoRaw + 0.03 * basePseudoRaw;\n            } else {\n                score = (double)lookEval[d] + 0.1 * (double)baseEval[d];\n            }\n\n            if (score > bestScore) {\n                bestScore = score;\n                bestDir = d;\n            }\n        }\n\n        board = cand[bestDir];\n\n        cout << dirChar[bestDir] << endl;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing U64 = uint64_t;\nusing Row = array<U64, 2>;\n\nstruct FastRNG {\n    uint64_t x;\n    FastRNG(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline bool bitRow(const vector<Row>& rows, int i, int j) {\n    return (rows[i][j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline bool bitRowArr(const array<Row, 100>& rows, int i, int j) {\n    return (rows[i][j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline void setRow(vector<Row>& rows, int i, int j) {\n    rows[i][j >> 6] |= 1ULL << (j & 63);\n    rows[j][i >> 6] |= 1ULL << (i & 63);\n}\n\nstatic inline void setRowArr(array<Row, 100>& rows, int i, int j) {\n    rows[i][j >> 6] |= 1ULL << (j & 63);\n    rows[j][i >> 6] |= 1ULL << (i & 63);\n}\n\nstruct Candidate {\n    array<unsigned char, 100> deg{};\n    array<unsigned char, 100> origDeg{};\n    array<unsigned char, 100> ord{};\n    array<uint64_t, 2> mask{};\n    array<Row, 100> sortedRows{};\n    int edges = 0;\n};\n\nstruct Codebook {\n    int M = 0;\n    int N = 0;\n    double eps = 0.0;\n    vector<Candidate> code;\n    vector<string> out;\n};\n\nstatic inline bool getMaskBitRaw(const array<uint64_t, 2>& mask, int j) {\n    return (mask[j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline bool getMaskBit(const Candidate& c, int j) {\n    return (c.mask[j >> 6] >> (j & 63)) & 1ULL;\n}\n\nCandidate makeCandidate(int N, const array<uint64_t, 2>& mask) {\n    Candidate c;\n    c.mask = mask;\n\n    int suf[105];\n    suf[N] = 0;\n    for (int i = N - 1; i >= 0; i--) {\n        suf[i] = suf[i + 1] + (i == 0 ? 0 : (getMaskBitRaw(mask, i) ? 1 : 0));\n    }\n\n    vector<int> d(N);\n    int edges = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool b = (i == 0 ? false : getMaskBitRaw(mask, i));\n        d[i] = suf[i + 1] + (b ? i : 0);\n        c.origDeg[i] = (unsigned char)d[i];\n        if (b) edges += i;\n    }\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        if (d[a] != d[b]) return d[a] < d[b];\n        return a < b;\n    });\n\n    for (int i = 0; i < N; i++) {\n        c.ord[i] = (unsigned char)p[i];\n        c.deg[i] = (unsigned char)d[p[i]];\n    }\n\n    for (int i = 0; i < 100; i++) c.sortedRows[i] = Row{0ULL, 0ULL};\n\n    for (int a = 0; a < N; a++) {\n        int va = p[a];\n        for (int b = a + 1; b < N; b++) {\n            int vb = p[b];\n            bool e = getMaskBitRaw(mask, max(va, vb));\n            if (e) setRowArr(c.sortedRows, a, b);\n        }\n    }\n\n    c.edges = edges;\n    return c;\n}\n\nstring thresholdGraphString(const Candidate& c, int N) {\n    string s;\n    s.reserve(N * (N - 1) / 2);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            s.push_back(getMaskBit(c, j) ? '1' : '0');\n        }\n    }\n\n    return s;\n}\n\nint ceilLog2Int(int x) {\n    int p = 1, r = 0;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\ndouble degreeDistanceMetric(const Candidate& a, const Candidate& b, int N) {\n    double ss = 0.0;\n    double sum = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double v = (double)a.deg[i] - (double)b.deg[i];\n        ss += v * v;\n        sum += v;\n    }\n\n    double score = ss - (sum * sum) / max(1.0, 2.0 * N - 2.0);\n    if (score < 0) score = 0;\n    return score;\n}\n\nvector<Candidate> generatePool(int N, int M, double eps, FastRNG& rng) {\n    int target = max(400, min(2400, 20 * M + 350));\n\n    vector<Candidate> pool;\n    pool.reserve(target + 10);\n\n    unordered_set<string> seen;\n    seen.reserve(target * 3);\n\n    auto addCandidate = [&](const array<uint64_t, 2>& mask) {\n        Candidate c = makeCandidate(N, mask);\n\n        string key;\n        key.resize(N);\n        for (int i = 0; i < N; i++) key[i] = (char)c.deg[i];\n\n        if (seen.insert(key).second) {\n            pool.push_back(c);\n        }\n    };\n\n    if (N - 1 <= 20) {\n        uint64_t total = 1ULL << (N - 1);\n        if ((int)total <= target) {\n            for (uint64_t m = 0; m < total; m++) {\n                array<uint64_t, 2> mask{0ULL, 0ULL};\n                mask[0] = m << 1;\n                addCandidate(mask);\n            }\n            return pool;\n        }\n    }\n\n    {\n        array<uint64_t, 2> emptyMask{0ULL, 0ULL};\n        addCandidate(emptyMask);\n\n        array<uint64_t, 2> fullMask{0ULL, 0ULL};\n        for (int j = 1; j < N; j++) {\n            fullMask[j >> 6] |= 1ULL << (j & 63);\n        }\n        addCandidate(fullMask);\n    }\n\n    int attempts = 0;\n    while ((int)pool.size() < target && attempts < target * 70) {\n        attempts++;\n\n        array<uint64_t, 2> mask{0ULL, 0ULL};\n        int mode = rng.nextInt(6);\n\n        if (mode == 0) {\n            double p = rng.nextDouble();\n            for (int j = 1; j < N; j++) {\n                if (rng.nextDouble() < p) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        } else if (mode == 1) {\n            int need = rng.nextInt(N);\n            int rem = N - 1;\n            for (int j = 1; j < N; j++) {\n                if (need > 0 && rng.nextInt(rem) < need) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                    need--;\n                }\n                rem--;\n            }\n        } else if (mode == 2) {\n            int cut = 1 + rng.nextInt(N - 1);\n            for (int j = cut; j < N; j++) {\n                mask[j >> 6] |= 1ULL << (j & 63);\n            }\n            for (int t = 0; t < N / 7 + 1; t++) {\n                int j = 1 + rng.nextInt(N - 1);\n                mask[j >> 6] ^= 1ULL << (j & 63);\n            }\n        } else if (mode == 3) {\n            double p;\n            int r = rng.nextInt(7);\n            if (r == 0) p = 0.04;\n            else if (r == 1) p = 0.10;\n            else if (r == 2) p = 0.22;\n            else if (r == 3) p = 0.50;\n            else if (r == 4) p = 0.78;\n            else if (r == 5) p = 0.90;\n            else p = 0.96;\n\n            for (int j = 1; j < N; j++) {\n                if (rng.nextDouble() < p) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        } else if (mode == 4) {\n            int blocks = 2 + rng.nextInt(6);\n            bool cur = rng.nextInt(2);\n            int pos = 1;\n            for (int b = 0; b < blocks && pos < N; b++) {\n                int denom = max(1, blocks - b);\n                int len = 1 + rng.nextInt(max(1, (N - pos) / denom));\n                int to = min(N, pos + len);\n                for (int j = pos; j < to; j++) {\n                    if (cur) mask[j >> 6] |= 1ULL << (j & 63);\n                }\n                cur = !cur;\n                pos = to;\n            }\n            for (int j = pos; j < N; j++) {\n                if (cur) mask[j >> 6] |= 1ULL << (j & 63);\n            }\n        } else {\n            // Smooth random walk mask: tends to create diverse but structured degree sequences.\n            double x = rng.nextDouble();\n            double drift = (rng.nextDouble() - 0.5) * 0.08;\n            for (int j = 1; j < N; j++) {\n                x += drift + (rng.nextDouble() - 0.5) * 0.18;\n                if (x < 0) x = -x;\n                if (x > 1) x = 2 - x;\n                if (rng.nextDouble() < x) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        }\n\n        addCandidate(mask);\n    }\n\n    return pool;\n}\n\nCodebook buildCodebook(int M, int N, double eps, FastRNG& rng) {\n    vector<Candidate> pool = generatePool(N, M, eps, rng);\n    int K = (int)pool.size();\n\n    Codebook book;\n    book.M = M;\n    book.N = N;\n    book.eps = eps;\n\n    if (K < M) return book;\n\n    vector<int> starts;\n\n    int minEdge = 0, maxEdge = 0;\n    for (int i = 1; i < K; i++) {\n        if (pool[i].edges < pool[minEdge].edges) minEdge = i;\n        if (pool[i].edges > pool[maxEdge].edges) maxEdge = i;\n    }\n\n    starts.push_back(minEdge);\n    starts.push_back(maxEdge);\n    for (int t = 0; t < 3 && K > 0; t++) starts.push_back(rng.nextInt(K));\n\n    double bestMinDist = -1.0;\n    vector<Candidate> bestCode;\n\n    for (int st : starts) {\n        vector<char> used(K, 0);\n        vector<double> mind(K, 1e100);\n        vector<Candidate> cur;\n        cur.reserve(M);\n\n        for (int it = 0; it < M; it++) {\n            int best = -1;\n\n            if (it == 0) {\n                best = st;\n            } else {\n                double bv = -1;\n                for (int i = 0; i < K; i++) {\n                    if (!used[i] && mind[i] > bv) {\n                        bv = mind[i];\n                        best = i;\n                    }\n                }\n            }\n\n            used[best] = 1;\n            Candidate chosen = pool[best];\n\n            for (int i = 0; i < K; i++) {\n                if (!used[i]) {\n                    double d = degreeDistanceMetric(chosen, pool[i], N);\n                    if (d < mind[i]) mind[i] = d;\n                }\n            }\n\n            cur.push_back(chosen);\n        }\n\n        double md = 1e100;\n        for (int i = 0; i < M; i++) {\n            for (int j = i + 1; j < M; j++) {\n                md = min(md, degreeDistanceMetric(cur[i], cur[j], N));\n            }\n        }\n\n        if (md > bestMinDist) {\n            bestMinDist = md;\n            bestCode = std::move(cur);\n        }\n    }\n\n    book.code = std::move(bestCode);\n    book.out.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        book.out[k] = thresholdGraphString(book.code[k], N);\n    }\n\n    return book;\n}\n\nstruct ParsedGraph {\n    vector<Row> rows;\n    vector<int> deg;\n    vector<int> sortedDeg;\n    vector<int> ord;\n};\n\nParsedGraph parseGraph(const string& s, int N) {\n    ParsedGraph g;\n    g.rows.assign(N, Row{0ULL, 0ULL});\n    g.deg.assign(N, 0);\n\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++, idx++) {\n            if (s[idx] == '1') {\n                setRow(g.rows, i, j);\n                g.deg[i]++;\n                g.deg[j]++;\n            }\n        }\n    }\n\n    vector<int> ndSum(N, 0);\n    for (int i = 0; i < N; i++) {\n        int sum = 0;\n        for (int j = 0; j < N; j++) {\n            if (i != j && bitRow(g.rows, i, j)) sum += g.deg[j];\n        }\n        ndSum[i] = sum;\n    }\n\n    g.ord.resize(N);\n    iota(g.ord.begin(), g.ord.end(), 0);\n    sort(g.ord.begin(), g.ord.end(), [&](int a, int b) {\n        if (g.deg[a] != g.deg[b]) return g.deg[a] < g.deg[b];\n        if (ndSum[a] != ndSum[b]) return ndSum[a] < ndSum[b];\n        return a < b;\n    });\n\n    g.sortedDeg.resize(N);\n    for (int i = 0; i < N; i++) g.sortedDeg[i] = g.deg[g.ord[i]];\n\n    return g;\n}\n\ndouble scoreLambda(int N, double eps) {\n    if (eps <= 1e-12) return 0.0;\n\n    double var = max(1e-9, (N - 1) * eps * (1.0 - eps));\n    double logodds = log((1.0 - eps) / eps);\n    logodds = max(0.15, logodds);\n\n    double lambda = 1.0 / (2.0 * var * logodds);\n\n    if (lambda < 0.025) lambda = 0.025;\n    if (lambda > 0.18) lambda = 0.18;\n    return lambda;\n}\n\ndouble degreeScore(const Codebook& book, const Candidate& c, const vector<int>& obsSorted) {\n    int N = book.N;\n    double eps = book.eps;\n    double base = eps * (N - 1);\n    double scale = 1.0 - 2.0 * eps;\n\n    double ss = 0.0;\n    double sum = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double mu = base + scale * (double)c.deg[i];\n        double diff = obsSorted[i] - mu;\n        ss += diff * diff;\n        sum += diff;\n    }\n\n    if (eps <= 1e-12) return ss;\n\n    double score = ss - (sum * sum) / max(1.0, 2.0 * N - 2.0);\n    if (score < 0) score = 0;\n    return score;\n}\n\nint initialAdjCost(const ParsedGraph& h, const Candidate& c, const vector<int>& order, int N) {\n    int cost = 0;\n    for (int i = 0; i < N; i++) {\n        int vi = order[i];\n        for (int j = i + 1; j < N; j++) {\n            bool x = bitRow(h.rows, vi, order[j]);\n            bool y = bitRowArr(c.sortedRows, i, j);\n            cost += (x != y);\n        }\n    }\n    return cost;\n}\n\nint deltaSwap(const ParsedGraph& h, const Candidate& c, const vector<int>& order, int a, int b, int N) {\n    if (a == b) return 0;\n    if (a > b) swap(a, b);\n\n    int va = order[a];\n    int vb = order[b];\n\n    int oldCost = 0;\n    int newCost = 0;\n\n    for (int k = 0; k < N; k++) {\n        if (k == a || k == b) continue;\n\n        int vk = order[k];\n\n        bool h_ak = bitRow(h.rows, va, vk);\n        bool h_bk = bitRow(h.rows, vb, vk);\n\n        bool g_ak = bitRowArr(c.sortedRows, min(a, k), max(a, k));\n        bool g_bk = bitRowArr(c.sortedRows, min(b, k), max(b, k));\n\n        oldCost += (h_ak != g_ak);\n        oldCost += (h_bk != g_bk);\n\n        newCost += (h_bk != g_ak);\n        newCost += (h_ak != g_bk);\n    }\n\n    return newCost - oldCost;\n}\n\nint localAdjCost(const ParsedGraph& h, const Candidate& c, int N) {\n    vector<int> order = h.ord;\n    int cost = initialAdjCost(h, c, order, N);\n\n    int window;\n    if (N <= 30) window = 10;\n    else if (N <= 70) window = 8;\n    else window = 6;\n\n    int passes = (N <= 40 ? 4 : 3);\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool improved = false;\n\n        for (int i = 0; i + 1 < N; i++) {\n            int d = deltaSwap(h, c, order, i, i + 1, N);\n            if (d < 0) {\n                swap(order[i], order[i + 1]);\n                cost += d;\n                improved = true;\n            }\n        }\n\n        for (int i = N - 2; i >= 0; i--) {\n            int d = deltaSwap(h, c, order, i, i + 1, N);\n            if (d < 0) {\n                swap(order[i], order[i + 1]);\n                cost += d;\n                improved = true;\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            int bestJ = -1;\n            int bestD = 0;\n            int lim = min(N, i + window + 1);\n\n            for (int j = i + 2; j < lim; j++) {\n                int d = deltaSwap(h, c, order, i, j, N);\n                if (d < bestD) {\n                    bestD = d;\n                    bestJ = j;\n                }\n            }\n\n            if (bestJ != -1) {\n                swap(order[i], order[bestJ]);\n                cost += bestD;\n                improved = true;\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    return cost;\n}\n\nint decode(const Codebook& book, const ParsedGraph& h) {\n    int M = book.M;\n    int N = book.N;\n\n    vector<double> dscore(M);\n    vector<int> ham0(M);\n    vector<int> ids(M);\n    iota(ids.begin(), ids.end(), 0);\n\n    double lambda = scoreLambda(N, book.eps);\n\n    for (int k = 0; k < M; k++) {\n        dscore[k] = degreeScore(book, book.code[k], h.sortedDeg);\n    }\n\n    if (book.eps <= 1e-12) {\n        return min_element(ids.begin(), ids.end(), [&](int a, int b) {\n            return dscore[a] < dscore[b];\n        }) - ids.begin();\n    }\n\n    for (int k = 0; k < M; k++) {\n        ham0[k] = initialAdjCost(h, book.code[k], h.ord, N);\n    }\n\n    vector<int> cand;\n    vector<char> used(M, 0);\n\n    auto addTopBy = [&](auto valueFunc, int cnt) {\n        vector<int> v(M);\n        iota(v.begin(), v.end(), 0);\n        nth_element(v.begin(), v.begin() + min(cnt, M), v.end(), [&](int a, int b) {\n            return valueFunc(a) < valueFunc(b);\n        });\n        sort(v.begin(), v.begin() + min(cnt, M), [&](int a, int b) {\n            return valueFunc(a) < valueFunc(b);\n        });\n        for (int i = 0; i < min(cnt, M); i++) {\n            int k = v[i];\n            if (!used[k]) {\n                used[k] = 1;\n                cand.push_back(k);\n            }\n        }\n    };\n\n    int topD, topC, topH;\n    if (book.eps <= 0.05) {\n        topD = 6; topC = 8; topH = 4;\n    } else if (book.eps <= 0.20) {\n        topD = 8; topC = 10; topH = 5;\n    } else {\n        topD = 10; topC = 13; topH = 6;\n    }\n\n    addTopBy([&](int k) { return dscore[k]; }, topD);\n    addTopBy([&](int k) { return (double)ham0[k] + lambda * dscore[k]; }, topC);\n    addTopBy([&](int k) { return (double)ham0[k]; }, topH);\n\n    int best = cand.empty() ? 0 : cand[0];\n    double bestFinal = 1e100;\n\n    for (int k : cand) {\n        int ham = localAdjCost(h, book.code[k], N);\n        double finalScore = (double)ham + lambda * dscore[k];\n\n        // Slightly trust the cheap global ordering too, useful when local search falls into poor swap minima.\n        finalScore += 0.03 * ((double)ham0[k] + lambda * dscore[k]);\n\n        if (finalScore < bestFinal) {\n            bestFinal = finalScore;\n            best = k;\n        }\n    }\n\n    return best;\n}\n\nvector<int> simulateNoisyDegrees(const Candidate& c, int N, double eps, FastRNG& rng) {\n    vector<int> deg(N, 0);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = getMaskBit(c, j);\n            if (rng.nextDouble() < eps) e = !e;\n            if (e) {\n                deg[i]++;\n                deg[j]++;\n            }\n        }\n    }\n\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint decodeDegreeOnly(const Codebook& book, const vector<int>& obsSorted) {\n    int best = 0;\n    double bestScore = 1e100;\n\n    for (int k = 0; k < book.M; k++) {\n        double sc = degreeScore(book, book.code[k], obsSorted);\n        if (sc < bestScore) {\n            bestScore = sc;\n            best = k;\n        }\n    }\n\n    return best;\n}\n\nint simulateErrorsDegreeOnly(const Codebook& book, int T, FastRNG& rng) {\n    int err = 0;\n\n    for (int t = 0; t < T; t++) {\n        int s = rng.nextInt(book.M);\n        vector<int> obs = simulateNoisyDegrees(book.code[s], book.N, book.eps, rng);\n        int pred = decodeDegreeOnly(book, obs);\n        if (pred != s) err++;\n    }\n\n    return err;\n}\n\nvector<int> candidateNs(int M, double eps) {\n    int minN = max(4, ceilLog2Int(M) + 1);\n    vector<int> ns;\n\n    if (eps <= 1e-12) {\n        ns.push_back(minN);\n        return ns;\n    }\n\n    int maxN;\n    if (eps <= 0.01) maxN = min(100, minN + 15);\n    else if (eps <= 0.05) maxN = min(100, minN + 40);\n    else if (eps <= 0.15) maxN = 85;\n    else maxN = 100;\n\n    for (int n = minN; n <= maxN; ) {\n        ns.push_back(n);\n\n        int step;\n        if (eps <= 0.05) {\n            if (n < 30) step = 1;\n            else if (n < 60) step = 3;\n            else step = 5;\n        } else {\n            if (n < 30) step = 2;\n            else if (n < 70) step = 5;\n            else step = 10;\n        }\n\n        n += step;\n    }\n\n    if (ns.empty() || ns.back() != maxN) ns.push_back(maxN);\n    if (eps >= 0.18 && ns.back() != 100) ns.push_back(100);\n\n    sort(ns.begin(), ns.end());\n    ns.erase(unique(ns.begin(), ns.end()), ns.end());\n    return ns;\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 epsInt = (int)llround(eps * 100);\n    FastRNG rng(123456789ULL + 10007ULL * M + 1000003ULL * epsInt);\n\n    Codebook bestBook;\n    double bestValue = -1.0;\n\n    vector<int> ns = candidateNs(M, eps);\n\n    for (int N : ns) {\n        Codebook book = buildCodebook(M, N, eps, rng);\n        if ((int)book.code.size() != M) continue;\n\n        double value;\n\n        if (eps <= 1e-12) {\n            value = 1.0 / N;\n        } else {\n            int T;\n            if (eps <= 0.03) T = 260;\n            else if (eps <= 0.15) T = 210;\n            else T = 170;\n\n            int err = simulateErrorsDegreeOnly(book, T, rng);\n            double p = (err + 0.25) / (T + 0.5);\n\n            // Slightly favor larger N at high noise because the final decoder uses adjacency too.\n            value = exp(100.0 * log(max(1e-12, 1.0 - 0.1 * p))) / N;\n            if (eps >= 0.25) value *= pow((double)N / 100.0, 0.12);\n        }\n\n        if (value > bestValue) {\n            bestValue = value;\n            bestBook = std::move(book);\n        }\n    }\n\n    if ((int)bestBook.code.size() != M) {\n        int N = max(4, ceilLog2Int(M) + 1);\n        bestBook = buildCodebook(M, N, eps, rng);\n    }\n\n    cout << bestBook.N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << bestBook.out[k] << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        ParsedGraph h = parseGraph(H, bestBook.N);\n        int ans = decode(bestBook, h);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF = (1LL << 60);\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int root(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = root(a);\n        b = root(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    int mx, my;\n    ll len2;\n};\n\nstruct Adj {\n    int to, w, id;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<vector<Adj>> g;\nvector<int> X, Y;\nvector<int> degv;\n\nmt19937 rng(1234567);\n\nuint64_t morton_key(int x, int y) {\n    uint64_t r = 0;\n    for (int i = 0; i < 12; i++) {\n        r |= uint64_t((x >> i) & 1) << (2 * i);\n        r |= uint64_t((y >> i) & 1) << (2 * i + 1);\n    }\n    return r;\n}\n\nvoid dijkstra_fill(int s, const vector<int>* assign, int ban_day, vector<ll>& dist) {\n    fill(dist.begin(), dist.end(), INF);\n\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\n    while (!pq.empty()) {\n        auto [du, u] = pq.top();\n        pq.pop();\n\n        if (du != dist[u]) continue;\n\n        for (const auto& e : g[u]) {\n            if (assign && (*assign)[e.id] == ban_day) continue;\n\n            ll nd = du + e.w;\n            if (nd < dist[e.to]) {\n                dist[e.to] = nd;\n                pq.push({nd, e.to});\n            }\n        }\n    }\n}\n\nbool connected_day(const vector<int>& assign, int day) {\n    DSU uf(N);\n\n    for (int i = 0; i < M; i++) {\n        if (assign[i] != day) {\n            uf.unite(edges[i].u, edges[i].v);\n        }\n    }\n\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n\n    return true;\n}\n\nbool all_connected(const vector<int>& assign) {\n    for (int d = 0; d < D; d++) {\n        if (!connected_day(assign, d)) return false;\n    }\n    return true;\n}\n\nbool can_add_removal_keep_connected(const vector<int>& assign, int day, int eid) {\n    DSU uf(N);\n\n    for (int i = 0; i < M; i++) {\n        if (assign[i] == day || i == eid) continue;\n        uf.unite(edges[i].u, edges[i].v);\n    }\n\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n\n    return true;\n}\n\nvoid repair_isolated(vector<int>& assign) {\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n\n    for (int i = 0; i < M; i++) {\n        int d = assign[i];\n        load[d]++;\n        vc[edges[i].u][d]++;\n        vc[edges[i].v][d]++;\n    }\n\n    bool changed = true;\n\n    for (int loop = 0; changed && loop < 20; loop++) {\n        changed = false;\n\n        for (int v = 0; v < N; v++) {\n            for (int d = 0; d < D; d++) {\n                if (vc[v][d] < degv[v]) continue;\n\n                int eid = -1;\n                for (auto& a : g[v]) {\n                    if (assign[a.id] == d) {\n                        eid = a.id;\n                        break;\n                    }\n                }\n\n                if (eid == -1) continue;\n\n                int u = edges[eid].u;\n                int w = edges[eid].v;\n                int best = -1;\n\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == d) continue;\n                    if (load[nd] >= K) continue;\n                    if (vc[u][nd] + 1 >= degv[u]) continue;\n                    if (vc[w][nd] + 1 >= degv[w]) continue;\n\n                    best = nd;\n                    break;\n                }\n\n                if (best == -1) {\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd != d && load[nd] < K) {\n                            best = nd;\n                            break;\n                        }\n                    }\n                }\n\n                if (best != -1) {\n                    assign[eid] = best;\n                    load[d]--;\n                    load[best]++;\n                    vc[u][d]--;\n                    vc[w][d]--;\n                    vc[u][best]++;\n                    vc[w][best]++;\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\nvoid repair_connectivity(vector<int>& assign, const Timer& timer, double limit_time) {\n    vector<int> load(D, 0);\n    for (int x : assign) load[x]++;\n\n    for (int iter = 0; iter < 200 && timer.elapsed() < limit_time; iter++) {\n        bool changed = false;\n\n        for (int day = 0; day < D && timer.elapsed() < limit_time; day++) {\n            DSU uf(N);\n\n            for (int i = 0; i < M; i++) {\n                if (assign[i] != day) {\n                    uf.unite(edges[i].u, edges[i].v);\n                }\n            }\n\n            int r0 = uf.root(0);\n            bool ok = true;\n\n            for (int i = 1; i < N; i++) {\n                if (uf.root(i) != r0) {\n                    ok = false;\n                    break;\n                }\n            }\n\n            if (ok) continue;\n\n            vector<int> cand;\n            cand.reserve(load[day]);\n\n            for (int i = 0; i < M; i++) {\n                if (assign[i] == day && uf.root(edges[i].u) != uf.root(edges[i].v)) {\n                    cand.push_back(i);\n                }\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            bool moved = false;\n\n            for (int eid : cand) {\n                int best_day = -1;\n                int best_cost = INT_MAX;\n\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == day) continue;\n                    if (load[nd] >= K) continue;\n\n                    int cost = load[nd];\n                    if (!can_add_removal_keep_connected(assign, nd, eid)) {\n                        cost += 1000000;\n                    }\n\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_day = nd;\n                    }\n                }\n\n                if (best_day != -1) {\n                    assign[eid] = best_day;\n                    load[day]--;\n                    load[best_day]++;\n                    changed = true;\n                    moved = true;\n                    break;\n                }\n            }\n\n            if (moved) break;\n        }\n\n        if (!changed) break;\n        if (all_connected(assign)) break;\n    }\n}\n\nvector<int> make_order(int type) {\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    if (type == 0) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) < morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 1) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) > morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 2) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].mx != edges[b].mx) return edges[a].mx < edges[b].mx;\n            return edges[a].my < edges[b].my;\n        });\n    } else if (type == 3) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].my != edges[b].my) return edges[a].my < edges[b].my;\n            return edges[a].mx < edges[b].mx;\n        });\n    } else if (type == 4) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx + edges[a].my < edges[b].mx + edges[b].my;\n        });\n    } else if (type == 5) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx - edges[a].my < edges[b].mx - edges[b].my;\n        });\n    } else if (type == 6) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].len2 > edges[b].len2;\n        });\n    } else {\n        int A = uniform_int_distribution<int>(-1000, 1000)(rng);\n        int B = uniform_int_distribution<int>(-1000, 1000)(rng);\n\n        if (A == 0 && B == 0) A = 1;\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ll va = 1LL * A * edges[a].mx + 1LL * B * edges[a].my;\n            ll vb = 1LL * A * edges[b].mx + 1LL * B * edges[b].my;\n\n            if (va != vb) return va < vb;\n            return a < b;\n        });\n    }\n\n    return ord;\n}\n\nvector<int> construct_cyclic(int type) {\n    vector<int> ord = make_order(type);\n\n    vector<int> perm(D);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n\n    int shift = uniform_int_distribution<int>(0, D - 1)(rng);\n\n    vector<int> assign(M);\n\n    for (int i = 0; i < M; i++) {\n        assign[ord[i]] = perm[(i + shift) % D];\n    }\n\n    repair_isolated(assign);\n    return assign;\n}\n\nvector<int> construct_greedy(int type) {\n    vector<int> ord;\n\n    if (type == 100) {\n        ord.resize(M);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n    } else {\n        ord = make_order(type);\n    }\n\n    vector<int> target(D, M / D);\n    for (int i = 0; i < M % D; i++) target[i]++;\n    shuffle(target.begin(), target.end(), rng);\n\n    vector<int> assign(M, -1);\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n\n    const int G = 18;\n    vector<vector<int>> cell(D, vector<int>(G * G, 0));\n\n    auto cid = [&](int eid) {\n        int cx = min(G - 1, max(0, edges[eid].mx * G / 2001));\n        int cy = min(G - 1, max(0, edges[eid].my * G / 2001));\n        return pair<int,int>(cx, cy);\n    };\n\n    for (int eid : ord) {\n        int u = edges[eid].u;\n        int v = edges[eid].v;\n\n        auto [cx, cy] = cid(eid);\n\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int pass = 0; pass < 2; pass++) {\n            best = -1;\n            best_cost = INT_MAX;\n\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= target[d]) continue;\n\n                if (pass == 0) {\n                    if (vc[u][d] + 1 >= degv[u]) continue;\n                    if (vc[v][d] + 1 >= degv[v]) continue;\n                }\n\n                int near = 0;\n\n                for (int dx = -1; dx <= 1; dx++) {\n                    for (int dy = -1; dy <= 1; dy++) {\n                        int nx = cx + dx;\n                        int ny = cy + dy;\n\n                        if (0 <= nx && nx < G && 0 <= ny && ny < G) {\n                            near += cell[d][nx * G + ny];\n                        }\n                    }\n                }\n\n                int cost = 0;\n                cost += (vc[u][d] + vc[v][d]) * 100000;\n                cost += near * 700;\n                cost += load[d] * 5;\n                cost += uniform_int_distribution<int>(0, 999)(rng);\n\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best = d;\n                }\n            }\n\n            if (best != -1) break;\n        }\n\n        if (best == -1) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] < target[d]) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n\n        assign[eid] = best;\n        load[best]++;\n        vc[u][best]++;\n        vc[v][best]++;\n        cell[best][cx * G + cy]++;\n    }\n\n    repair_isolated(assign);\n    return assign;\n}\n\nll score_one_day(\n    const vector<int>& assign,\n    int day,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist\n) {\n    ll score = 0;\n    vector<ll> dist(N);\n\n    for (int si = 0; si < S; si++) {\n        int s = sources[si];\n\n        dijkstra_fill(s, &assign, day, dist);\n\n        const auto& bd = base_dist[si];\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n\n            if (dist[v] >= INF / 2) {\n                score += 1000000000LL - bd[v];\n            } else {\n                score += dist[v] - bd[v];\n            }\n        }\n    }\n\n    return score;\n}\n\nll evaluate_schedule(\n    const vector<int>& assign,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist\n) {\n    vector<int> load(D, 0);\n\n    for (int x : assign) {\n        if (x < 0 || x >= D) return (ll)4e18;\n        load[x]++;\n    }\n\n    for (int d = 0; d < D; d++) {\n        if (load[d] > K) return (ll)4e18;\n    }\n\n    if (!all_connected(assign)) {\n        return (ll)3e18;\n    }\n\n    ll score = 0;\n\n    for (int day = 0; day < D; day++) {\n        score += score_one_day(assign, day, S, sources, base_dist);\n    }\n\n    return score;\n}\n\nvoid sampled_local_search(\n    vector<int>& assign,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist,\n    const Timer& timer,\n    double limit_time\n) {\n    if (!all_connected(assign)) return;\n\n    vector<vector<int>> byday(D);\n    vector<int> pos(M, -1);\n    vector<int> load(D, 0);\n\n    for (int i = 0; i < M; i++) {\n        int d = assign[i];\n        pos[i] = (int)byday[d].size();\n        byday[d].push_back(i);\n        load[d]++;\n    }\n\n    vector<ll> day_cost(D, 0);\n\n    for (int d = 0; d < D; d++) {\n        if (timer.elapsed() > limit_time) return;\n        day_cost[d] = score_one_day(assign, d, S, sources, base_dist);\n    }\n\n    auto choose_high_day = [&]() {\n        int a = uniform_int_distribution<int>(0, D - 1)(rng);\n        for (int t = 0; t < 4; t++) {\n            int x = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (day_cost[x] > day_cost[a]) a = x;\n        }\n        return a;\n    };\n\n    auto choose_low_day = [&](int forbid, bool need_capacity) {\n        int b = uniform_int_distribution<int>(0, D - 1)(rng);\n\n        for (int tries = 0; tries < 20 && (b == forbid || (need_capacity && load[b] >= K)); tries++) {\n            b = uniform_int_distribution<int>(0, D - 1)(rng);\n        }\n\n        for (int t = 0; t < 4; t++) {\n            int x = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (x == forbid) continue;\n            if (need_capacity && load[x] >= K) continue;\n            if (b == forbid || (need_capacity && load[b] >= K) || day_cost[x] < day_cost[b]) b = x;\n        }\n\n        return b;\n    };\n\n    int trials = 0;\n\n    while (timer.elapsed() < limit_time && trials < 100000) {\n        trials++;\n\n        bool do_move = (uniform_int_distribution<int>(0, 99)(rng) < 55);\n\n        if (do_move) {\n            int a = choose_high_day();\n            if (byday[a].empty()) continue;\n\n            int b = choose_low_day(a, true);\n            if (b == a || b < 0 || b >= D || load[b] >= K) continue;\n\n            int ia = uniform_int_distribution<int>(0, (int)byday[a].size() - 1)(rng);\n            int e = byday[a][ia];\n\n            assign[e] = b;\n\n            // Removing an edge from day a cannot make day a worse in connectivity,\n            // so only day b must be checked.\n            if (!connected_day(assign, b)) {\n                assign[e] = a;\n                continue;\n            }\n\n            ll old_cost = day_cost[a] + day_cost[b];\n\n            ll ca = score_one_day(assign, a, S, sources, base_dist);\n            if (timer.elapsed() >= limit_time) {\n                assign[e] = a;\n                return;\n            }\n\n            ll cb = score_one_day(assign, b, S, sources, base_dist);\n            ll new_cost = ca + cb;\n\n            if (new_cost < old_cost) {\n                day_cost[a] = ca;\n                day_cost[b] = cb;\n\n                int last = byday[a].back();\n                byday[a][ia] = last;\n                pos[last] = ia;\n                byday[a].pop_back();\n\n                pos[e] = (int)byday[b].size();\n                byday[b].push_back(e);\n\n                load[a]--;\n                load[b]++;\n            } else {\n                assign[e] = a;\n            }\n        } else {\n            int a = choose_high_day();\n            int b = choose_low_day(a, false);\n\n            if (a == b) continue;\n            if (byday[a].empty() || byday[b].empty()) continue;\n\n            int ia = uniform_int_distribution<int>(0, (int)byday[a].size() - 1)(rng);\n            int ib = uniform_int_distribution<int>(0, (int)byday[b].size() - 1)(rng);\n\n            int e1 = byday[a][ia];\n            int e2 = byday[b][ib];\n\n            assign[e1] = b;\n            assign[e2] = a;\n\n            bool ok = connected_day(assign, a) && connected_day(assign, b);\n\n            if (!ok) {\n                assign[e1] = a;\n                assign[e2] = b;\n                continue;\n            }\n\n            ll old_cost = day_cost[a] + day_cost[b];\n\n            ll ca = score_one_day(assign, a, S, sources, base_dist);\n            if (timer.elapsed() >= limit_time) {\n                assign[e1] = a;\n                assign[e2] = b;\n                return;\n            }\n\n            ll cb = score_one_day(assign, b, S, sources, base_dist);\n            ll new_cost = ca + cb;\n\n            if (new_cost < old_cost) {\n                day_cost[a] = ca;\n                day_cost[b] = cb;\n\n                byday[a][ia] = e2;\n                byday[b][ib] = e1;\n                pos[e1] = ib;\n                pos[e2] = ia;\n            } else {\n                assign[e1] = a;\n                assign[e2] = b;\n            }\n        }\n    }\n}\n\nvector<int> make_sources(int Smax) {\n    vector<int> sources;\n    vector<char> used(N, 0);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return morton_key(X[a], Y[a]) < morton_key(X[b], Y[b]);\n    });\n\n    int strat = min(Smax, min(N, Smax * 2 / 3));\n\n    for (int i = 0; i < strat; i++) {\n        int idx = (ll)(2 * i + 1) * N / (2 * strat);\n        idx = min(N - 1, max(0, idx));\n\n        int v = ord[idx];\n        if (!used[v]) {\n            used[v] = 1;\n            sources.push_back(v);\n        }\n    }\n\n    vector<int> rest(N);\n    iota(rest.begin(), rest.end(), 0);\n    shuffle(rest.begin(), rest.end(), rng);\n\n    for (int v : rest) {\n        if ((int)sources.size() >= Smax) break;\n        if (!used[v]) {\n            used[v] = 1;\n            sources.push_back(v);\n        }\n    }\n\n    return sources;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> D >> K;\n\n    edges.resize(M);\n    g.assign(N, {});\n    degv.assign(N, 0);\n\n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n\n        g[u].push_back({v, w, i});\n        g[v].push_back({u, w, i});\n\n        degv[u]++;\n        degv[v]++;\n    }\n\n    X.resize(N);\n    Y.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> X[i] >> Y[i];\n    }\n\n    for (int i = 0; i < M; i++) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n\n        edges[i].mx = X[u] + X[v];\n        edges[i].my = Y[u] + Y[v];\n\n        ll dx = X[u] - X[v];\n        ll dy = Y[u] - Y[v];\n\n        edges[i].len2 = dx * dx + dy * dy;\n    }\n\n    int Smax = min(N, 96);\n    int Ssmall = min(Smax, (D >= 20 ? 24 : 32));\n    int Sfinal = min(Smax, 80);\n    int Slocal = min(Smax, (D >= 20 ? 7 : 9));\n\n    vector<int> sources = make_sources(Smax);\n\n    vector<vector<ll>> base_dist(Smax, vector<ll>(N));\n\n    for (int i = 0; i < Smax; i++) {\n        dijkstra_fill(sources[i], nullptr, -1, base_dist[i]);\n    }\n\n    vector<pair<ll, vector<int>>> top;\n\n    auto add_candidate = [&](vector<int> assign) {\n        if (!all_connected(assign) && timer.elapsed() < 4.45) {\n            repair_connectivity(assign, timer, 4.60);\n        }\n\n        ll sc = evaluate_schedule(assign, Ssmall, sources, base_dist);\n\n        if ((int)top.size() < 10) {\n            top.push_back({sc, assign});\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        } else if (sc < top.back().first) {\n            top.back() = {sc, assign};\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        }\n    };\n\n    for (int t = 0; t < 10 && timer.elapsed() < 4.05; t++) {\n        add_candidate(construct_cyclic(t % 8));\n    }\n\n    for (int t = 0; t < 10 && timer.elapsed() < 4.25; t++) {\n        add_candidate(construct_greedy(t % 8));\n    }\n\n    int iter = 0;\n\n    while (timer.elapsed() < 4.50) {\n        vector<int> cand;\n\n        if (iter % 3 == 0) {\n            cand = construct_greedy(100);\n        } else if (iter % 3 == 1) {\n            cand = construct_greedy(8 + iter);\n        } else {\n            cand = construct_cyclic(8 + iter);\n        }\n\n        add_candidate(std::move(cand));\n        iter++;\n    }\n\n    if (top.empty()) {\n        vector<int> fallback(M);\n        for (int i = 0; i < M; i++) fallback[i] = i % D;\n        repair_isolated(fallback);\n        top.push_back({0, fallback});\n    }\n\n    vector<int> best = top[0].second;\n    ll best_score = (ll)4e18;\n\n    // Compare all promising candidates using the same final sample size.\n    for (auto& p : top) {\n        if (timer.elapsed() > 5.30) break;\n\n        ll sc = evaluate_schedule(p.second, Sfinal, sources, base_dist);\n\n        if (sc < best_score) {\n            best_score = sc;\n            best = p.second;\n        }\n    }\n\n    if (best_score >= (ll)4e18 / 2) {\n        best = top[0].second;\n        best_score = evaluate_schedule(best, Ssmall, sources, base_dist);\n    }\n\n    vector<int> before_local = best;\n    ll before_score = best_score;\n\n    vector<int> improved = best;\n\n    if (timer.elapsed() < 5.35 && all_connected(improved)) {\n        sampled_local_search(improved, Slocal, sources, base_dist, timer, 5.68);\n    }\n\n    if (timer.elapsed() < 5.88) {\n        ll imp_score = evaluate_schedule(improved, Sfinal, sources, base_dist);\n\n        if (imp_score < before_score) {\n            best = improved;\n            best_score = imp_score;\n        } else {\n            best = before_local;\n            best_score = before_score;\n        }\n    }\n\n    if (!all_connected(best) && timer.elapsed() < 5.78) {\n        repair_connectivity(best, timer, 5.88);\n    }\n\n    vector<int> load(D, 0);\n    for (int x : best) load[x]++;\n\n    for (int i = 0; i < M; i++) {\n        if (load[best[i]] <= K) continue;\n\n        for (int d = 0; d < D; d++) {\n            if (load[d] < K) {\n                load[best[i]]--;\n                best[i] = d;\n                load[d]++;\n                break;\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << best[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nstring F[2][14], Rg[2][14];\n\ninline int idx3(int x, int y, int z) {\n    return x * D * D + y * D + z;\n}\n\ninline void xyz(int id, int& x, int& y, int& z) {\n    x = id / (D * D);\n    int t = id % (D * D);\n    y = t / D;\n    z = t % D;\n}\n\nuint32_t hash32(uint32_t x) {\n    x ^= x >> 16;\n    x *= 0x7feb352dU;\n    x ^= x >> 15;\n    x *= 0x846ca68bU;\n    x ^= x >> 16;\n    return x;\n}\n\nint hrand(uint32_t seed, int x, int y, int z, int mod) {\n    uint32_t v = seed;\n    v ^= (uint32_t)(x + 17) * 1000003U;\n    v ^= (uint32_t)(y + 31) * 1000033U;\n    v ^= (uint32_t)(z + 47) * 1000037U;\n    return (int)(hash32(v) % mod);\n}\n\nstruct Candidate {\n    vector<unsigned char> occ;\n    int volume = 0;\n};\n\nstruct Rod {\n    vector<int> cells;\n};\n\nstruct LineDecomp {\n    vector<Rod> rods;\n    vector<int> lens;\n    int volume = 0;\n};\n\nstruct Cuboid {\n    vector<int> cells;\n    int dx, dy, dz;\n    int key;\n    int vol;\n};\n\nstruct CuboidDecomp {\n    vector<Cuboid> cuboids;\n    int volume = 0;\n};\n\nstruct Params {\n    int extra;\n    int contW;\n    int futW;\n    int randAmp;\n    int reverse;\n    int favor;\n    int commonBonus;\n    uint32_t seed;\n};\n\nint cuboid_key(int dx, int dy, int dz) {\n    int a[3] = {dx, dy, dz};\n    sort(a, a + 3);\n    return a[0] * 256 + a[1] * 16 + a[2];\n}\n\nint cuboid_volume_from_key(int key) {\n    int a = key / 256;\n    int b = (key / 16) % 16;\n    int c = key % 16;\n    return a * b * c;\n}\n\nvector<pair<int,int>> solve_edge_cover(const vector<int>& X, const vector<int>& Y, int w[14][14]) {\n    int nx = (int)X.size();\n    int ny = (int)Y.size();\n    vector<pair<int,int>> res;\n\n    if (nx >= ny) {\n        int A = nx, B = ny;\n        int M = 1 << B;\n        const int NEG = -1000000000;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[i]][Y[j]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[i + 1][nm] = mask;\n                        ch[i + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int i = A; i >= 1; i--) {\n            int j = ch[i][mask];\n            int pm = pre[i][mask];\n            res.push_back({X[i - 1], Y[j]});\n            mask = pm;\n        }\n    } else {\n        int A = ny, B = nx;\n        int M = 1 << B;\n        const int NEG = -1000000000;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[j]][Y[i]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[i + 1][nm] = mask;\n                        ch[i + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int i = A; i >= 1; i--) {\n            int j = ch[i][mask];\n            int pm = pre[i][mask];\n            res.push_back({X[j], Y[i - 1]});\n            mask = pm;\n        }\n    }\n\n    return res;\n}\n\nCandidate build_candidate(int id, const Params& p) {\n    Candidate cand;\n    cand.occ.assign(D * D * D, 0);\n\n    bool prev[14][14] = {};\n\n    vector<int> zs;\n    if (!p.reverse) {\n        for (int z = 0; z < D; z++) zs.push_back(z);\n    } else {\n        for (int z = D - 1; z >= 0; z--) zs.push_back(z);\n    }\n\n    int other = id ^ 1;\n\n    for (int ord = 0; ord < D; ord++) {\n        int z = zs[ord];\n        int zn = -1;\n        if (ord + 1 < D) zn = zs[ord + 1];\n\n        vector<int> X, Y;\n        for (int x = 0; x < D; x++) if (F[id][z][x] == '1') X.push_back(x);\n        for (int y = 0; y < D; y++) if (Rg[id][z][y] == '1') Y.push_back(y);\n\n        int w[14][14] = {};\n\n        for (int x : X) {\n            for (int y : Y) {\n                int val = 0;\n                if (prev[x][y]) val += p.contW;\n                if (zn != -1 && F[id][zn][x] == '1' && Rg[id][zn][y] == '1') val += p.futW;\n                if (F[other][z][x] == '1' && Rg[other][z][y] == '1') val += p.commonBonus;\n                if (p.randAmp > 0) val += hrand(p.seed, x, y, z, p.randAmp);\n                w[x][y] = val;\n            }\n        }\n\n        auto base = solve_edge_cover(X, Y, w);\n\n        bool sel[14][14] = {};\n        int cnt = 0;\n\n        for (auto [x, y] : base) {\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        int maxEdges = (int)X.size() * (int)Y.size();\n        int target = min(maxEdges, max((int)X.size(), (int)Y.size()) + p.extra);\n\n        vector<tuple<int,int,int>> add;\n\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) continue;\n\n                int sc = 0;\n                if (prev[x][y]) sc += 100000;\n                if (zn != -1 && F[id][zn][x] == '1' && Rg[id][zn][y] == '1') sc += 20000;\n                if (F[other][z][x] == '1' && Rg[other][z][y] == '1') sc += p.commonBonus;\n\n                if (p.favor == 1 || p.favor == 3) {\n                    if (x > 0 && sel[x - 1][y]) sc += 8000;\n                    if (x + 1 < D && sel[x + 1][y]) sc += 8000;\n                }\n                if (p.favor == 2 || p.favor == 3) {\n                    if (y > 0 && sel[x][y - 1]) sc += 8000;\n                    if (y + 1 < D && sel[x][y + 1]) sc += 8000;\n                }\n\n                sc += hrand(p.seed ^ 0x9e3779b9U, x, y, z, 1000);\n                add.push_back({sc, x, y});\n            }\n        }\n\n        sort(add.rbegin(), add.rend());\n\n        for (auto [sc, x, y] : add) {\n            if (cnt >= target) break;\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        memset(prev, 0, sizeof(prev));\n\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) {\n                    cand.occ[idx3(x, y, z)] = 1;\n                    prev[x][y] = true;\n                }\n            }\n        }\n    }\n\n    for (unsigned char c : cand.occ) cand.volume += c;\n    return cand;\n}\n\nLineDecomp decompose_lines_from_occ(const vector<unsigned char>& occ, int volume, int axis) {\n    LineDecomp dec;\n    dec.volume = volume;\n\n    if (axis == 0) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                int x = 0;\n                while (x < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        x++;\n                        continue;\n                    }\n\n                    Rod r;\n                    while (x < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        x++;\n                    }\n\n                    dec.lens.push_back((int)r.cells.size());\n                    dec.rods.push_back(move(r));\n                }\n            }\n        }\n    } else if (axis == 1) {\n        for (int x = 0; x < D; x++) {\n            for (int z = 0; z < D; z++) {\n                int y = 0;\n                while (y < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        y++;\n                        continue;\n                    }\n\n                    Rod r;\n                    while (y < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        y++;\n                    }\n\n                    dec.lens.push_back((int)r.cells.size());\n                    dec.rods.push_back(move(r));\n                }\n            }\n        }\n    } else {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                int z = 0;\n                while (z < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        z++;\n                        continue;\n                    }\n\n                    Rod r;\n                    while (z < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        z++;\n                    }\n\n                    dec.lens.push_back((int)r.cells.size());\n                    dec.rods.push_back(move(r));\n                }\n            }\n        }\n    }\n\n    return dec;\n}\n\nLineDecomp decompose_lines(const Candidate& cand, int axis) {\n    return decompose_lines_from_occ(cand.occ, cand.volume, axis);\n}\n\nlong double eval_lines(const LineDecomp& A, const LineDecomp& B) {\n    priority_queue<int> p, q;\n    for (int x : A.lens) p.push(x);\n    for (int x : B.lens) q.push(x);\n\n    long double score = 0;\n\n    for (int len = D; len >= 1; len--) {\n        while (!p.empty() && !q.empty() && p.top() >= len && q.top() >= len) {\n            int a = p.top(); p.pop();\n            int b = q.top(); q.pop();\n\n            score += 1.0L / len;\n\n            if (a - len > 0) p.push(a - len);\n            if (b - len > 0) q.push(b - len);\n        }\n    }\n\n    while (!p.empty()) {\n        score += p.top();\n        p.pop();\n    }\n    while (!q.empty()) {\n        score += q.top();\n        q.pop();\n    }\n\n    return score;\n}\n\nbool box_free_occ(const vector<unsigned char>& occ, const vector<unsigned char>& used, int lo[3], int hi[3]) {\n    for (int x = lo[0]; x < hi[0]; x++) {\n        for (int y = lo[1]; y < hi[1]; y++) {\n            for (int z = lo[2]; z < hi[2]; z++) {\n                int id = idx3(x, y, z);\n                if (!occ[id] || used[id]) return false;\n            }\n        }\n    }\n    return true;\n}\n\nCuboidDecomp decompose_cuboids_occ(const vector<unsigned char>& occ, int volume, array<int,3> growOrder) {\n    CuboidDecomp dec;\n    dec.volume = volume;\n\n    vector<unsigned char> used(D * D * D, 0);\n\n    for (int x0 = 0; x0 < D; x0++) {\n        for (int y0 = 0; y0 < D; y0++) {\n            for (int z0 = 0; z0 < D; z0++) {\n                int start = idx3(x0, y0, z0);\n                if (!occ[start] || used[start]) continue;\n\n                int lo[3] = {x0, y0, z0};\n                int hi[3] = {x0 + 1, y0 + 1, z0 + 1};\n\n                for (int ax : growOrder) {\n                    while (hi[ax] < D) {\n                        int nlo[3] = {lo[0], lo[1], lo[2]};\n                        int nhi[3] = {hi[0], hi[1], hi[2]};\n                        nhi[ax]++;\n                        if (box_free_occ(occ, used, nlo, nhi)) hi[ax]++;\n                        else break;\n                    }\n                }\n\n                Cuboid c;\n                c.dx = hi[0] - lo[0];\n                c.dy = hi[1] - lo[1];\n                c.dz = hi[2] - lo[2];\n                c.vol = c.dx * c.dy * c.dz;\n                c.key = cuboid_key(c.dx, c.dy, c.dz);\n\n                for (int x = lo[0]; x < hi[0]; x++) {\n                    for (int y = lo[1]; y < hi[1]; y++) {\n                        for (int z = lo[2]; z < hi[2]; z++) {\n                            int id = idx3(x, y, z);\n                            used[id] = 1;\n                            c.cells.push_back(id);\n                        }\n                    }\n                }\n\n                dec.cuboids.push_back(move(c));\n            }\n        }\n    }\n\n    return dec;\n}\n\nCuboidDecomp decompose_cuboids_candidate(const Candidate& cand, array<int,3> growOrder) {\n    return decompose_cuboids_occ(cand.occ, cand.volume, growOrder);\n}\n\nstruct HybridEval {\n    long double score;\n    int ax0;\n    int ax1;\n};\n\nHybridEval eval_cuboid_hybrid(const CuboidDecomp& A, const CuboidDecomp& B) {\n    unordered_map<int, vector<int>> ma, mb;\n    ma.reserve(512);\n    mb.reserve(512);\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) ma[A.cuboids[i].key].push_back(i);\n    for (int i = 0; i < (int)B.cuboids.size(); i++) mb[B.cuboids[i].key].push_back(i);\n\n    vector<unsigned char> usedA(A.cuboids.size(), 0), usedB(B.cuboids.size(), 0);\n\n    long double base = 0;\n\n    for (auto& kv : ma) {\n        int key = kv.first;\n        if (!mb.count(key)) continue;\n\n        int vol = cuboid_volume_from_key(key);\n        if (vol <= 1) continue;\n\n        auto& va = kv.second;\n        auto& vb = mb[key];\n\n        int m = min((int)va.size(), (int)vb.size());\n\n        for (int i = 0; i < m; i++) {\n            usedA[va[i]] = 1;\n            usedB[vb[i]] = 1;\n            base += 1.0L / vol;\n        }\n    }\n\n    vector<unsigned char> remA(D * D * D, 0), remB(D * D * D, 0);\n    int volA = 0, volB = 0;\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) {\n        if (usedA[i]) continue;\n        for (int id : A.cuboids[i].cells) {\n            remA[id] = 1;\n            volA++;\n        }\n    }\n\n    for (int i = 0; i < (int)B.cuboids.size(); i++) {\n        if (usedB[i]) continue;\n        for (int id : B.cuboids[i].cells) {\n            remB[id] = 1;\n            volB++;\n        }\n    }\n\n    array<LineDecomp, 3> la, lb;\n    for (int ax = 0; ax < 3; ax++) {\n        la[ax] = decompose_lines_from_occ(remA, volA, ax);\n        lb[ax] = decompose_lines_from_occ(remB, volB, ax);\n    }\n\n    HybridEval ret;\n    ret.score = 1e100L;\n    ret.ax0 = ret.ax1 = 0;\n\n    for (int ax0 = 0; ax0 < 3; ax0++) {\n        for (int ax1 = 0; ax1 < 3; ax1++) {\n            long double sc = base + eval_lines(la[ax0], lb[ax1]);\n            if (sc < ret.score) {\n                ret.score = sc;\n                ret.ax0 = ax0;\n                ret.ax1 = ax1;\n            }\n        }\n    }\n\n    return ret;\n}\n\nvector<vector<int>> components_of_occ(const vector<unsigned char>& occ) {\n    int N = D * D * D;\n    vector<unsigned char> vis(N, 0);\n    vector<vector<int>> comps;\n\n    const int dx[6] = {1, -1, 0, 0, 0, 0};\n    const int dy[6] = {0, 0, 1, -1, 0, 0};\n    const int dz[6] = {0, 0, 0, 0, 1, -1};\n\n    for (int s = 0; s < N; s++) {\n        if (vis[s] || !occ[s]) continue;\n\n        vector<int> comp;\n        queue<int> q;\n        q.push(s);\n        vis[s] = 1;\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            comp.push_back(v);\n\n            int x, y, z;\n            xyz(v, x, y, z);\n\n            for (int d = 0; d < 6; d++) {\n                int nx = x + dx[d];\n                int ny = y + dy[d];\n                int nz = z + dz[d];\n\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n\n                int ni = idx3(nx, ny, nz);\n                if (vis[ni] || !occ[ni]) continue;\n\n                vis[ni] = 1;\n                q.push(ni);\n            }\n        }\n\n        comps.push_back(move(comp));\n    }\n\n    return comps;\n}\n\nstruct CommonCore {\n    vector<vector<int>> comps;\n    vector<unsigned char> rem[2];\n    int vol[2] = {0, 0};\n    long double baseCost = 0;\n};\n\nvoid add_partial_cover(\n    int obj,\n    int z,\n    const vector<unsigned char>& usedCommon,\n    vector<unsigned char>& rem,\n    bool prev[14][14],\n    uint32_t seed\n) {\n    bool preX[14] = {};\n    bool preY[14] = {};\n\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            if (usedCommon[idx3(x, y, z)]) {\n                preX[x] = true;\n                preY[y] = true;\n            }\n        }\n    }\n\n    vector<int> X, Y, RX, RY;\n\n    for (int x = 0; x < D; x++) {\n        if (F[obj][z][x] == '1') {\n            X.push_back(x);\n            if (!preX[x]) RX.push_back(x);\n        }\n    }\n\n    for (int y = 0; y < D; y++) {\n        if (Rg[obj][z][y] == '1') {\n            Y.push_back(y);\n            if (!preY[y]) RY.push_back(y);\n        }\n    }\n\n    if (RX.empty() && RY.empty()) {\n        memset(prev, 0, sizeof(bool) * 14 * 14);\n        return;\n    }\n\n    vector<pair<int,int>> edges;\n\n    auto weight = [&](int x, int y) {\n        int w = 0;\n        if (prev[x][y]) w += 100000;\n        if (z + 1 < D && F[obj][z + 1][x] == '1' && Rg[obj][z + 1][y] == '1') w += 20000;\n        w += hrand(seed, x, y, z, 1000);\n        return w;\n    };\n\n    if ((int)RX.size() >= (int)RY.size() && !RX.empty()) {\n        int A = (int)RX.size();\n        int B = (int)RY.size();\n        int M = 1 << B;\n\n        const int NEG = -1000000000;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> preMask(A + 1, vector<int>(M, -1));\n        vector<vector<short>> choice(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n\n                for (int y : Y) {\n                    int nm = mask;\n\n                    for (int j = 0; j < B; j++) {\n                        if (RY[j] == y) nm |= (1 << j);\n                    }\n\n                    int val = dp[mask] + weight(RX[i], y);\n\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        preMask[i + 1][nm] = mask;\n                        choice[i + 1][nm] = y;\n                    }\n                }\n            }\n\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n\n        for (int i = A; i >= 1; i--) {\n            int y = choice[i][mask];\n            int pm = preMask[i][mask];\n            edges.push_back({RX[i - 1], y});\n            mask = pm;\n        }\n    } else {\n        int A = (int)RY.size();\n        int B = (int)RX.size();\n        int M = 1 << B;\n\n        const int NEG = -1000000000;\n\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> preMask(A + 1, vector<int>(M, -1));\n        vector<vector<short>> choice(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n\n                for (int x : X) {\n                    int nm = mask;\n\n                    for (int j = 0; j < B; j++) {\n                        if (RX[j] == x) nm |= (1 << j);\n                    }\n\n                    int val = dp[mask] + weight(x, RY[i]);\n\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        preMask[i + 1][nm] = mask;\n                        choice[i + 1][nm] = x;\n                    }\n                }\n            }\n\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n\n        for (int i = A; i >= 1; i--) {\n            int x = choice[i][mask];\n            int pm = preMask[i][mask];\n            edges.push_back({x, RY[i - 1]});\n            mask = pm;\n        }\n    }\n\n    memset(prev, 0, sizeof(bool) * 14 * 14);\n\n    for (auto [x, y] : edges) {\n        int id = idx3(x, y, z);\n        if (!usedCommon[id]) {\n            rem[id] = 1;\n            prev[x][y] = true;\n        }\n    }\n}\n\nCommonCore build_common_core_from_components(const vector<vector<int>>& allComps, int minSize, int maxCount) {\n    CommonCore cc;\n\n    vector<unsigned char> usedCommon(D * D * D, 0);\n\n    int cnt = 0;\n\n    for (auto& c : allComps) {\n        if ((int)c.size() < minSize) continue;\n        if (cnt >= maxCount) break;\n\n        cc.baseCost += 1.0L / (int)c.size();\n        cc.comps.push_back(c);\n\n        for (int id : c) usedCommon[id] = 1;\n\n        cnt++;\n    }\n\n    cc.rem[0].assign(D * D * D, 0);\n    cc.rem[1].assign(D * D * D, 0);\n\n    bool prev0[14][14] = {};\n    bool prev1[14][14] = {};\n\n    for (int z = 0; z < D; z++) {\n        add_partial_cover(0, z, usedCommon, cc.rem[0], prev0, 111111U + minSize * 1009U + maxCount * 17U);\n        add_partial_cover(1, z, usedCommon, cc.rem[1], prev1, 222222U + minSize * 1009U + maxCount * 17U);\n    }\n\n    for (int i = 0; i < D * D * D; i++) {\n        cc.vol[0] += cc.rem[0][i];\n        cc.vol[1] += cc.rem[1][i];\n    }\n\n    return cc;\n}\n\nstruct CorePlan {\n    long double score = 1e100L;\n    int ax0 = 0;\n    int ax1 = 0;\n    bool useCuboid = false;\n    int strat0 = 0;\n    int strat1 = 0;\n};\n\nCorePlan eval_common_core(const CommonCore& cc, const vector<array<int,3>>& growOrders) {\n    CorePlan best;\n\n    array<LineDecomp, 3> la, lb;\n\n    for (int ax = 0; ax < 3; ax++) {\n        la[ax] = decompose_lines_from_occ(cc.rem[0], cc.vol[0], ax);\n        lb[ax] = decompose_lines_from_occ(cc.rem[1], cc.vol[1], ax);\n    }\n\n    for (int ax0 = 0; ax0 < 3; ax0++) {\n        for (int ax1 = 0; ax1 < 3; ax1++) {\n            long double sc = cc.baseCost + eval_lines(la[ax0], lb[ax1]);\n\n            if (sc < best.score) {\n                best.score = sc;\n                best.ax0 = ax0;\n                best.ax1 = ax1;\n                best.useCuboid = false;\n            }\n        }\n    }\n\n    vector<CuboidDecomp> ca, cb;\n\n    for (auto ord : growOrders) {\n        ca.push_back(decompose_cuboids_occ(cc.rem[0], cc.vol[0], ord));\n        cb.push_back(decompose_cuboids_occ(cc.rem[1], cc.vol[1], ord));\n    }\n\n    for (int i = 0; i < (int)ca.size(); i++) {\n        for (int j = 0; j < (int)cb.size(); j++) {\n            HybridEval he = eval_cuboid_hybrid(ca[i], cb[j]);\n            long double sc = cc.baseCost + he.score;\n\n            if (sc < best.score) {\n                best.score = sc;\n                best.ax0 = he.ax0;\n                best.ax1 = he.ax1;\n                best.useCuboid = true;\n                best.strat0 = i;\n                best.strat1 = j;\n            }\n        }\n    }\n\n    return best;\n}\n\nstruct Piece {\n    int len;\n    int rod;\n    int off;\n\n    bool operator<(const Piece& other) const {\n        if (len != other.len) return len < other.len;\n        if (rod != other.rod) return rod < other.rod;\n        return off < other.off;\n    }\n};\n\nvoid mark_line_piece(vector<int>& out, const LineDecomp& dec, const Piece& p, int useLen, int blockId) {\n    const Rod& r = dec.rods[p.rod];\n\n    for (int i = 0; i < useLen; i++) {\n        out[r.cells[p.off + i]] = blockId;\n    }\n}\n\nvoid add_line_solution(vector<int>& outA, vector<int>& outB, const LineDecomp& A, const LineDecomp& B, int& blockId) {\n    priority_queue<Piece> p, q;\n\n    for (int i = 0; i < (int)A.rods.size(); i++) p.push({(int)A.rods[i].cells.size(), i, 0});\n    for (int i = 0; i < (int)B.rods.size(); i++) q.push({(int)B.rods[i].cells.size(), i, 0});\n\n    for (int len = D; len >= 1; len--) {\n        while (!p.empty() && !q.empty() && p.top().len >= len && q.top().len >= len) {\n            Piece a = p.top(); p.pop();\n            Piece b = q.top(); q.pop();\n\n            blockId++;\n\n            mark_line_piece(outA, A, a, len, blockId);\n            mark_line_piece(outB, B, b, len, blockId);\n\n            if (a.len - len > 0) p.push({a.len - len, a.rod, a.off + len});\n            if (b.len - len > 0) q.push({b.len - len, b.rod, b.off + len});\n        }\n    }\n\n    while (!p.empty()) {\n        Piece a = p.top(); p.pop();\n        blockId++;\n        mark_line_piece(outA, A, a, a.len, blockId);\n    }\n\n    while (!q.empty()) {\n        Piece b = q.top(); q.pop();\n        blockId++;\n        mark_line_piece(outB, B, b, b.len, blockId);\n    }\n}\n\nvoid mark_cuboid(vector<int>& out, const Cuboid& c, int blockId) {\n    for (int id : c.cells) out[id] = blockId;\n}\n\nvoid add_cuboid_hybrid_solution(\n    vector<int>& outA,\n    vector<int>& outB,\n    const CuboidDecomp& A,\n    const CuboidDecomp& B,\n    int axA,\n    int axB,\n    int& blockId\n) {\n    unordered_map<int, vector<int>> ma, mb;\n    ma.reserve(512);\n    mb.reserve(512);\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) ma[A.cuboids[i].key].push_back(i);\n    for (int i = 0; i < (int)B.cuboids.size(); i++) mb[B.cuboids[i].key].push_back(i);\n\n    vector<unsigned char> usedA(A.cuboids.size(), 0), usedB(B.cuboids.size(), 0);\n\n    for (auto& kv : ma) {\n        int key = kv.first;\n        if (!mb.count(key)) continue;\n\n        int vol = cuboid_volume_from_key(key);\n        if (vol <= 1) continue;\n\n        auto& va = kv.second;\n        auto& vb = mb[key];\n\n        int m = min((int)va.size(), (int)vb.size());\n\n        for (int i = 0; i < m; i++) {\n            int ia = va[i];\n            int ib = vb[i];\n\n            usedA[ia] = 1;\n            usedB[ib] = 1;\n\n            blockId++;\n\n            mark_cuboid(outA, A.cuboids[ia], blockId);\n            mark_cuboid(outB, B.cuboids[ib], blockId);\n        }\n    }\n\n    vector<unsigned char> remA(D * D * D, 0), remB(D * D * D, 0);\n    int volA = 0, volB = 0;\n\n    for (int i = 0; i < (int)A.cuboids.size(); i++) {\n        if (usedA[i]) continue;\n\n        for (int id : A.cuboids[i].cells) {\n            remA[id] = 1;\n            volA++;\n        }\n    }\n\n    for (int i = 0; i < (int)B.cuboids.size(); i++) {\n        if (usedB[i]) continue;\n\n        for (int id : B.cuboids[i].cells) {\n            remB[id] = 1;\n            volB++;\n        }\n    }\n\n    LineDecomp la = decompose_lines_from_occ(remA, volA, axA);\n    LineDecomp lb = decompose_lines_from_occ(remB, volB, axB);\n\n    add_line_solution(outA, outB, la, lb, blockId);\n}\n\nvoid print_output(int blockId, const vector<int>& outA, const vector<int>& outB) {\n    cout << blockId << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << outA[i];\n    }\n    cout << '\\n';\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << outB[i];\n    }\n    cout << '\\n';\n}\n\nvoid output_line_solution(const LineDecomp& A, const LineDecomp& B) {\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n    int blockId = 0;\n    add_line_solution(outA, outB, A, B, blockId);\n    print_output(blockId, outA, outB);\n}\n\nvoid output_cuboid_hybrid_solution(const CuboidDecomp& A, const CuboidDecomp& B, int axA, int axB) {\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n    int blockId = 0;\n    add_cuboid_hybrid_solution(outA, outB, A, B, axA, axB, blockId);\n    print_output(blockId, outA, outB);\n}\n\nvoid output_common_core_solution(\n    const CommonCore& cc,\n    const CorePlan& plan,\n    const vector<array<int,3>>& growOrders\n) {\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n    int blockId = 0;\n\n    for (auto& c : cc.comps) {\n        blockId++;\n\n        for (int id : c) {\n            outA[id] = blockId;\n            outB[id] = blockId;\n        }\n    }\n\n    if (!plan.useCuboid) {\n        LineDecomp la = decompose_lines_from_occ(cc.rem[0], cc.vol[0], plan.ax0);\n        LineDecomp lb = decompose_lines_from_occ(cc.rem[1], cc.vol[1], plan.ax1);\n\n        add_line_solution(outA, outB, la, lb, blockId);\n    } else {\n        CuboidDecomp ca = decompose_cuboids_occ(cc.rem[0], cc.vol[0], growOrders[plan.strat0]);\n        CuboidDecomp cb = decompose_cuboids_occ(cc.rem[1], cc.vol[1], growOrders[plan.strat1]);\n\n        add_cuboid_hybrid_solution(outA, outB, ca, cb, plan.ax0, plan.ax1, blockId);\n    }\n\n    print_output(blockId, outA, outB);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D;\n\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) cin >> F[i][z];\n        for (int z = 0; z < D; z++) cin >> Rg[i][z];\n    }\n\n    vector<Params> params;\n    vector<int> extras = {0, 1, 2, 4, 7, 12, 1000};\n    uint32_t baseSeed = 246813579U;\n\n    for (int e : extras) {\n        for (int rev = 0; rev < 2; rev++) {\n            for (int rep = 0; rep < 2; rep++) {\n                Params p;\n                p.extra = e;\n                p.contW = 1000 + rep * 400;\n                p.futW = 80 + rep * 80;\n                p.randAmp = 60;\n                p.reverse = rev;\n                p.favor = rep + 1;\n                p.commonBonus = 0;\n                p.seed = baseSeed + e * 10007U + rev * 1000003U + rep * 9176U;\n                params.push_back(p);\n            }\n        }\n    }\n\n    for (int e : {0, 2, 4, 7, 12, 1000}) {\n        for (int rev = 0; rev < 2; rev++) {\n            Params p;\n            p.extra = e;\n            p.contW = 1400;\n            p.futW = 160;\n            p.randAmp = 50;\n            p.reverse = rev;\n            p.favor = 3;\n            p.commonBonus = 900;\n            p.seed = baseSeed ^ (0xabcdefU + e * 31337U + rev * 99991U);\n            params.push_back(p);\n        }\n    }\n\n    vector<Candidate> cand[2];\n\n    for (int id = 0; id < 2; id++) {\n        for (auto p : params) {\n            cand[id].push_back(build_candidate(id, p));\n        }\n    }\n\n    int n0 = (int)cand[0].size();\n    int n1 = (int)cand[1].size();\n\n    vector<array<LineDecomp, 3>> lines[2];\n    lines[0].resize(n0);\n    lines[1].resize(n1);\n\n    for (int id = 0; id < 2; id++) {\n        int n = (int)cand[id].size();\n\n        for (int i = 0; i < n; i++) {\n            for (int ax = 0; ax < 3; ax++) {\n                lines[id][i][ax] = decompose_lines(cand[id][i], ax);\n            }\n        }\n    }\n\n    vector<array<int,3>> growOrders = {\n        array<int,3>{0,1,2},\n        array<int,3>{0,2,1},\n        array<int,3>{1,0,2},\n        array<int,3>{1,2,0},\n        array<int,3>{2,0,1},\n        array<int,3>{2,1,0}\n    };\n\n    struct CubRef {\n        CuboidDecomp dec;\n    };\n\n    vector<CubRef> cubs[2];\n\n    for (int id = 0; id < 2; id++) {\n        for (int i = 0; i < (int)cand[id].size(); i++) {\n            for (int s = 0; s < (int)growOrders.size(); s++) {\n                CubRef cr;\n                cr.dec = decompose_cuboids_candidate(cand[id][i], growOrders[s]);\n                cubs[id].push_back(move(cr));\n            }\n        }\n    }\n\n    vector<unsigned char> feasible(D * D * D, 0);\n\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (F[0][z][x] == '1' && F[1][z][x] == '1' &&\n                    Rg[0][z][y] == '1' && Rg[1][z][y] == '1') {\n                    feasible[idx3(x, y, z)] = 1;\n                }\n            }\n        }\n    }\n\n    auto commonComps = components_of_occ(feasible);\n\n    sort(commonComps.begin(), commonComps.end(), [](const vector<int>& a, const vector<int>& b) {\n        return a.size() > b.size();\n    });\n\n    vector<pair<int,int>> coreConfigs;\n    const int INF_COUNT = 1000000;\n\n    for (int th : {1, 2, 3, 4, 5, 6, 8, 10, 14, 20, 28}) {\n        coreConfigs.push_back({th, INF_COUNT});\n    }\n\n    for (int k : {1, 2, 3, 4, 5, 8, 12, 16, 24}) {\n        coreConfigs.push_back({1, k});\n        coreConfigs.push_back({2, k});\n        coreConfigs.push_back({3, k});\n        coreConfigs.push_back({4, k});\n    }\n\n    vector<CommonCore> commonCores;\n    vector<CorePlan> commonPlans;\n\n    commonCores.reserve(coreConfigs.size());\n    commonPlans.reserve(coreConfigs.size());\n\n    for (auto [minSize, maxCnt] : coreConfigs) {\n        CommonCore cc = build_common_core_from_components(commonComps, minSize, maxCnt);\n        CorePlan cp = eval_common_core(cc, growOrders);\n\n        commonPlans.push_back(cp);\n        commonCores.push_back(move(cc));\n    }\n\n    long double bestScore = 1e100L;\n    int bestMode = 0;\n\n    int bestI = 0, bestJ = 0;\n    int bestAx0 = 0, bestAx1 = 0;\n    int bestCubA = 0, bestCubB = 0;\n    int bestCore = 0;\n\n    for (int i = 0; i < n0; i++) {\n        for (int j = 0; j < n1; j++) {\n            for (int ax0 = 0; ax0 < 3; ax0++) {\n                for (int ax1 = 0; ax1 < 3; ax1++) {\n                    long double sc = eval_lines(lines[0][i][ax0], lines[1][j][ax1]);\n\n                    if (sc < bestScore) {\n                        bestScore = sc;\n                        bestMode = 0;\n                        bestI = i;\n                        bestJ = j;\n                        bestAx0 = ax0;\n                        bestAx1 = ax1;\n                    }\n                }\n            }\n        }\n    }\n\n    for (int ia = 0; ia < (int)cubs[0].size(); ia++) {\n        for (int ib = 0; ib < (int)cubs[1].size(); ib++) {\n            HybridEval he = eval_cuboid_hybrid(cubs[0][ia].dec, cubs[1][ib].dec);\n\n            if (he.score < bestScore) {\n                bestScore = he.score;\n                bestMode = 1;\n                bestCubA = ia;\n                bestCubB = ib;\n                bestAx0 = he.ax0;\n                bestAx1 = he.ax1;\n            }\n        }\n    }\n\n    for (int i = 0; i < (int)commonCores.size(); i++) {\n        if (commonPlans[i].score < bestScore) {\n            bestScore = commonPlans[i].score;\n            bestMode = 2;\n            bestCore = i;\n        }\n    }\n\n    if (bestMode == 0) {\n        output_line_solution(lines[0][bestI][bestAx0], lines[1][bestJ][bestAx1]);\n    } else if (bestMode == 1) {\n        output_cuboid_hybrid_solution(cubs[0][bestCubA].dec, cubs[1][bestCubB].dec, bestAx0, bestAx1);\n    } else {\n        output_common_core_solution(commonCores[bestCore], commonPlans[bestCore], growOrders);\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) x = p[x] = p[p[x]];\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstatic const long long INF = (1LL << 60);\n\nint N, M, K;\nvector<int> X, Y;\nvector<Edge> edges;\nvector<int> A, RY;\n\nvector<vector<int>> cdist;\nvector<vector<pair<int,int>>> sortedRes;\n\nvector<vector<long long>> fw;\nvector<vector<int>> nxtv;\nvector<vector<int>> directEdge;\n\nchrono::steady_clock::time_point st_time;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st_time).count();\n}\n\nint ceil_sqrt_ll(long long x) {\n    long long r = sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r > 0 && (r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nvoid add_path_edges(int s, int t, vector<char>& sel) {\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n    }\n}\n\nvoid add_path_edges_mark(int s, int t, vector<char>& sel, vector<char>& inTree) {\n    inTree[s] = 1;\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n        inTree[s] = 1;\n    }\n}\n\npair<long long, vector<int>> build_best_tree(const vector<int>& P) {\n    long long bestCost = INF;\n    vector<int> bestB(M, 0);\n\n    auto consider = [&](vector<char> sel) {\n        vector<char> terminal(N, 0);\n        terminal[0] = 1;\n        for (int i = 0; i < N; i++) if (P[i] > 0) terminal[i] = 1;\n\n        vector<vector<pair<int,int>>> g(N);\n        vector<int> deg(N, 0);\n\n        for (int e = 0; e < M; e++) if (sel[e]) {\n            int u = edges[e].u, v = edges[e].v;\n            g[u].push_back({v, e});\n            g[v].push_back({u, e});\n            deg[u]++;\n            deg[v]++;\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (!terminal[i] && deg[i] <= 1) q.push(i);\n        }\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            if (terminal[v] || deg[v] != 1) continue;\n\n            for (auto [to, eid] : g[v]) {\n                if (!sel[eid]) continue;\n                sel[eid] = 0;\n                deg[v]--;\n                deg[to]--;\n                if (!terminal[to] && deg[to] == 1) q.push(to);\n                break;\n            }\n        }\n\n        long long cost = 0;\n        vector<int> B(M, 0);\n        for (int e = 0; e < M; e++) {\n            if (sel[e]) {\n                cost += edges[e].w;\n                B[e] = 1;\n            }\n        }\n\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestB = B;\n        }\n    };\n\n    vector<int> terms;\n    terms.push_back(0);\n    for (int i = 1; i < N; i++) if (P[i] > 0) terms.push_back(i);\n\n    int T = (int)terms.size();\n\n    // Metric-closure MST over terminals.\n    {\n        vector<char> sel(M, 0);\n\n        if (T >= 2) {\n            vector<long long> minD(T, INF);\n            vector<int> par(T, -1);\n            vector<char> used(T, 0);\n            minD[0] = 0;\n\n            for (int it = 0; it < T; it++) {\n                int v = -1;\n                for (int i = 0; i < T; i++) {\n                    if (!used[i] && (v == -1 || minD[i] < minD[v])) v = i;\n                }\n\n                if (v == -1) break;\n                used[v] = 1;\n\n                if (par[v] != -1) {\n                    add_path_edges(terms[v], terms[par[v]], sel);\n                }\n\n                for (int to = 0; to < T; to++) {\n                    if (!used[to] && fw[terms[v]][terms[to]] < minD[to]) {\n                        minD[to] = fw[terms[v]][terms[to]];\n                        par[to] = v;\n                    }\n                }\n            }\n        }\n\n        consider(sel);\n    }\n\n    // Union of shortest paths from root.\n    {\n        vector<char> sel(M, 0);\n        for (int i = 1; i < N; i++) {\n            if (P[i] > 0) add_path_edges(0, i, sel);\n        }\n        consider(sel);\n    }\n\n    // Ordinary graph MST, pruned.\n    {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].w < edges[b].w;\n        });\n\n        DSU dsu(N);\n        vector<char> sel(M, 0);\n\n        for (int eid : ord) {\n            if (dsu.unite(edges[eid].u, edges[eid].v)) {\n                sel[eid] = 1;\n            }\n        }\n\n        consider(sel);\n    }\n\n    // Incremental Steiner-style candidates.\n    {\n        vector<int> base;\n        for (int i = 1; i < N; i++) if (P[i] > 0) base.push_back(i);\n\n        vector<vector<int>> orders;\n\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return fw[0][a] < fw[0][b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return fw[0][a] > fw[0][b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return P[a] > P[b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return P[a] < P[b];\n            });\n            orders.push_back(v);\n        }\n\n        for (auto ord : orders) {\n            vector<char> sel(M, 0);\n            vector<char> inTree(N, 0);\n            inTree[0] = 1;\n\n            for (int t : ord) {\n                int best = -1;\n                long long bd = INF;\n\n                for (int v = 0; v < N; v++) {\n                    if (inTree[v] && fw[t][v] < bd) {\n                        bd = fw[t][v];\n                        best = v;\n                    }\n                }\n\n                if (best != -1) {\n                    add_path_edges_mark(t, best, sel, inTree);\n                }\n            }\n\n            consider(sel);\n        }\n    }\n\n    return {bestCost, bestB};\n}\n\nlong long total_cost(const vector<int>& P) {\n    long long radio = 0;\n    for (int p : P) radio += 1LL * p * p;\n\n    auto tr = build_best_tree(P);\n    return radio + tr.first;\n}\n\nbool compute_covered(const vector<int>& P, vector<char>& covered) {\n    covered.assign(K, 0);\n    int cnt = 0;\n\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                covered[k] = 1;\n                cnt++;\n                break;\n            }\n        }\n    }\n\n    return cnt == K;\n}\n\nvoid reduce_powers_order(vector<int>& P, const vector<int>& order) {\n    vector<int> coverCnt(K, 0);\n\n    for (int i = 0; i < N; i++) if (P[i] > 0) {\n        for (int k = 0; k < K; k++) {\n            if (cdist[i][k] <= P[i]) coverCnt[k]++;\n        }\n    }\n\n    bool changed = true;\n    int loop = 0;\n\n    while (changed && loop < 12) {\n        loop++;\n        changed = false;\n\n        for (int i : order) {\n            int old = P[i];\n            if (old == 0) continue;\n\n            int req = 0;\n\n            for (int k = 0; k < K; k++) {\n                if (cdist[i][k] <= old && coverCnt[k] == 1) {\n                    req = max(req, cdist[i][k]);\n                }\n            }\n\n            if (req < old) {\n                for (int k = 0; k < K; k++) {\n                    if (cdist[i][k] <= old && cdist[i][k] > req) {\n                        coverCnt[k]--;\n                    }\n                }\n\n                P[i] = req;\n                changed = true;\n            }\n        }\n    }\n}\n\nvoid reduce_powers(vector<int>& P) {\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    reduce_powers_order(P, order);\n}\n\nint lower_existing_radius(int station, int limit) {\n    int res = 0;\n    for (auto [d, k] : sortedRes[station]) {\n        if (d <= limit) res = d;\n        else break;\n    }\n    return res;\n}\n\nbool greedy_complete(\n    vector<int>& P,\n    double alpha,\n    bool dynamicConn,\n    int capStation = -1,\n    int capRadius = 5000\n) {\n    vector<char> covered(K, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; k++) {\n        bool ok = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                ok = true;\n                break;\n            }\n        }\n\n        covered[k] = ok;\n        if (!ok) uncovered++;\n    }\n\n    vector<int> activeList;\n    activeList.push_back(0);\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0 && i != 0) activeList.push_back(i);\n    }\n\n    vector<double> rootPen(N, 0.0);\n    for (int i = 0; i < N; i++) rootPen[i] = alpha * (double)fw[0][i];\n\n    while (uncovered > 0) {\n        int bestI = -1;\n        int bestR = -1;\n        int bestGain = 0;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            int old = P[i];\n\n            if (i == capStation && old >= capRadius) continue;\n\n            double connPen = 0.0;\n\n            if (old == 0) {\n                if (dynamicConn) {\n                    long long md = INF;\n                    for (int a : activeList) md = min(md, fw[i][a]);\n                    connPen = alpha * (double)md;\n                } else {\n                    connPen = rootPen[i];\n                }\n            }\n\n            int gain = 0;\n            const auto& vec = sortedRes[i];\n\n            for (int idx = 0; idx < (int)vec.size();) {\n                int r = vec[idx].first;\n\n                if (r > 5000) break;\n                if (i == capStation && r > capRadius) break;\n\n                int add = 0;\n                while (idx < (int)vec.size() && vec[idx].first == r) {\n                    int k = vec[idx].second;\n                    if (r > old && !covered[k]) add++;\n                    idx++;\n                }\n\n                if (r <= old) continue;\n\n                gain += add;\n\n                if (gain > 0) {\n                    double delta = (double)r * r - (double)old * old;\n                    if (old == 0) delta += connPen;\n\n                    double score = delta / gain;\n\n                    if (score < bestScore ||\n                        (abs(score - bestScore) < 1e-9 && gain > bestGain)) {\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestGain = gain;\n                    }\n                }\n            }\n        }\n\n        if (bestI == -1) return false;\n\n        bool wasZero = (P[bestI] == 0);\n        P[bestI] = bestR;\n\n        if (wasZero) activeList.push_back(bestI);\n\n        for (auto [r, k] : sortedRes[bestI]) {\n            if (r > bestR) break;\n            if (!covered[k]) {\n                covered[k] = 1;\n                uncovered--;\n            }\n        }\n    }\n\n    return true;\n}\n\nbool greedy_repair_active_only(vector<int>& P, const vector<char>& allowed, const vector<int>& maxR) {\n    vector<char> covered(K, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; k++) {\n        bool ok = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                ok = true;\n                break;\n            }\n        }\n        covered[k] = ok;\n        if (!ok) uncovered++;\n    }\n\n    while (uncovered > 0) {\n        int bestI = -1;\n        int bestR = -1;\n        int bestGain = 0;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            if (!allowed[i]) continue;\n\n            int old = P[i];\n            if (old >= maxR[i]) continue;\n\n            int gain = 0;\n            const auto& vec = sortedRes[i];\n\n            for (int idx = 0; idx < (int)vec.size();) {\n                int r = vec[idx].first;\n                if (r > maxR[i]) break;\n\n                int add = 0;\n                while (idx < (int)vec.size() && vec[idx].first == r) {\n                    int k = vec[idx].second;\n                    if (r > old && !covered[k]) add++;\n                    idx++;\n                }\n\n                if (r <= old) continue;\n\n                gain += add;\n\n                if (gain > 0) {\n                    double delta = (double)r * r - (double)old * old;\n                    double score = delta / gain;\n\n                    if (score < bestScore ||\n                        (abs(score - bestScore) < 1e-9 && gain > bestGain)) {\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestGain = gain;\n                    }\n                }\n            }\n        }\n\n        if (bestI == -1) return false;\n\n        P[bestI] = bestR;\n\n        for (auto [r, k] : sortedRes[bestI]) {\n            if (r > bestR) break;\n            if (!covered[k]) {\n                covered[k] = 1;\n                uncovered--;\n            }\n        }\n    }\n\n    return true;\n}\n\nvector<int> initial_nearest_solution() {\n    vector<int> P(N, 0);\n\n    for (int k = 0; k < K; k++) {\n        int bi = -1;\n        int bd = 1e9;\n\n        for (int i = 0; i < N; i++) {\n            if (cdist[i][k] <= 5000 && cdist[i][k] < bd) {\n                bd = cdist[i][k];\n                bi = i;\n            }\n        }\n\n        if (bi == -1) {\n            for (int i = 0; i < N; i++) {\n                if (cdist[i][k] < bd) {\n                    bd = cdist[i][k];\n                    bi = i;\n                }\n            }\n        }\n\n        P[bi] = max(P[bi], bd);\n    }\n\n    reduce_powers(P);\n    return P;\n}\n\nvector<int> initial_weighted_nearest_solution(double lambda) {\n    vector<int> P(N, 0);\n\n    for (int k = 0; k < K; k++) {\n        int bi = -1;\n        long double best = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            int d = cdist[i][k];\n            if (d > 5000) continue;\n\n            long double val = (long double)d * d + lambda * (long double)fw[0][i];\n\n            if (val < best) {\n                best = val;\n                bi = i;\n            }\n        }\n\n        if (bi == -1) {\n            int bd = 1e9;\n            for (int i = 0; i < N; i++) {\n                if (cdist[i][k] < bd) {\n                    bd = cdist[i][k];\n                    bi = i;\n                }\n            }\n        }\n\n        P[bi] = max(P[bi], cdist[bi][k]);\n    }\n\n    reduce_powers(P);\n    return P;\n}\n\nvoid optimize_reduction_orders(vector<int>& bestP, long long& bestS) {\n    vector<vector<int>> orders;\n\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return bestP[a] > bestP[b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return bestP[a] < bestP[b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return fw[0][a] < fw[0][b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return fw[0][a] > fw[0][b];\n        });\n        orders.push_back(ord);\n    }\n\n    for (auto& ord : orders) {\n        if (elapsed_sec() > 1.96) break;\n\n        vector<int> P = bestP;\n        reduce_powers_order(P, ord);\n\n        vector<char> covered;\n        if (!compute_covered(P, covered)) continue;\n\n        long long S = total_cost(P);\n        if (S < bestS) {\n            bestS = S;\n            bestP = P;\n        }\n    }\n}\n\nvoid fixed_active_local_search(vector<int>& bestP, long long& bestS, double timeLimit) {\n    while (elapsed_sec() < timeLimit) {\n        bool improved = false;\n        vector<int> nextP = bestP;\n        long long nextS = bestS;\n\n        vector<int> active;\n        vector<char> allowed(N, 0);\n\n        for (int i = 0; i < N; i++) {\n            if (bestP[i] > 0) {\n                active.push_back(i);\n                allowed[i] = 1;\n            }\n        }\n\n        sort(active.begin(), active.end(), [&](int a, int b) {\n            return bestP[a] > bestP[b];\n        });\n\n        for (int s : active) {\n            if (elapsed_sec() > timeLimit) break;\n\n            int old = bestP[s];\n            vector<int> limits;\n\n            limits.push_back(0);\n            limits.push_back(lower_existing_radius(s, old / 5));\n            limits.push_back(lower_existing_radius(s, old / 3));\n            limits.push_back(lower_existing_radius(s, old / 2));\n            limits.push_back(lower_existing_radius(s, old * 2 / 3));\n            limits.push_back(lower_existing_radius(s, old * 4 / 5));\n\n            sort(limits.begin(), limits.end());\n            limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n            for (int lim : limits) {\n                if (elapsed_sec() > timeLimit) break;\n                if (lim >= old) continue;\n\n                vector<int> P = bestP;\n                vector<int> maxR(N, 5000);\n\n                P[s] = lim;\n                maxR[s] = lim;\n\n                bool ok = greedy_repair_active_only(P, allowed, maxR);\n                if (!ok) continue;\n\n                reduce_powers(P);\n\n                vector<char> covered;\n                if (!compute_covered(P, covered)) continue;\n\n                long long S = total_cost(P);\n\n                if (S < nextS) {\n                    nextS = S;\n                    nextP = P;\n                    improved = true;\n                }\n            }\n        }\n\n        if (improved) {\n            bestP = nextP;\n            bestS = nextS;\n        } else {\n            break;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st_time = chrono::steady_clock::now();\n\n    cin >> N >> M >> K;\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n        edges[i] = {u, v, w};\n    }\n\n    A.resize(K);\n    RY.resize(K);\n    for (int k = 0; k < K; k++) cin >> A[k] >> RY[k];\n\n    fw.assign(N, vector<long long>(N, INF));\n    nxtv.assign(N, vector<int>(N, -1));\n    directEdge.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; i++) {\n        fw[i][i] = 0;\n        nxtv[i][i] = i;\n    }\n\n    for (int e = 0; e < M; e++) {\n        int u = edges[e].u;\n        int v = edges[e].v;\n        long long w = edges[e].w;\n\n        if (w < fw[u][v]) {\n            fw[u][v] = fw[v][u] = w;\n            nxtv[u][v] = v;\n            nxtv[v][u] = u;\n            directEdge[u][v] = directEdge[v][u] = e;\n        }\n    }\n\n    for (int k = 0; k < N; k++) {\n        for (int i = 0; i < N; i++) if (fw[i][k] < INF) {\n            for (int j = 0; j < N; j++) if (fw[k][j] < INF) {\n                long long nd = fw[i][k] + fw[k][j];\n\n                if (nd < fw[i][j]) {\n                    fw[i][j] = nd;\n                    nxtv[i][j] = nxtv[i][k];\n                }\n            }\n        }\n    }\n\n    cdist.assign(N, vector<int>(K));\n    sortedRes.assign(N, {});\n\n    for (int i = 0; i < N; i++) {\n        sortedRes[i].reserve(K);\n\n        for (int k = 0; k < K; k++) {\n            long long dx = X[i] - A[k];\n            long long dy = Y[i] - RY[k];\n            int d = ceil_sqrt_ll(dx * dx + dy * dy);\n\n            cdist[i][k] = d;\n\n            if (d <= 5000) {\n                sortedRes[i].push_back({d, k});\n            }\n        }\n\n        sort(sortedRes[i].begin(), sortedRes[i].end());\n    }\n\n    vector<int> bestP = initial_nearest_solution();\n    long long bestS = total_cost(bestP);\n    double bestAlpha = 0.2;\n\n    // Cheap extra initial diversification: connection-aware nearest assignment.\n    for (double lambda : {0.05, 0.12, 0.25, 0.5, 0.9, 1.5, 2.5}) {\n        if (elapsed_sec() > 0.18) break;\n\n        vector<int> P = initial_weighted_nearest_solution(lambda);\n        long long S = total_cost(P);\n\n        if (S < bestS) {\n            bestS = S;\n            bestP = P;\n        }\n    }\n\n    vector<double> alphas = {\n        0.0, 0.02, 0.05, 0.08, 0.12, 0.18,\n        0.27, 0.4, 0.6, 0.9, 1.3\n    };\n\n    // Static and dynamic greedy initial constructions.\n    for (double alpha : alphas) {\n        if (elapsed_sec() > 1.08) break;\n\n        for (int dyn = 0; dyn <= 1; dyn++) {\n            if (elapsed_sec() > 1.18) break;\n\n            vector<int> P(N, 0);\n            bool ok = greedy_complete(P, alpha, dyn == 1);\n\n            if (!ok) continue;\n\n            reduce_powers(P);\n            long long S = total_cost(P);\n\n            if (S < bestS) {\n                bestS = S;\n                bestP = P;\n                bestAlpha = alpha;\n            }\n        }\n    }\n\n    optimize_reduction_orders(bestP, bestS);\n\n    // Safe local search: repair only with already active stations.\n    if (elapsed_sec() < 1.40) {\n        fixed_active_local_search(bestP, bestS, 1.55);\n    }\n\n    vector<double> repairAlphas = {\n        0.0,\n        max(0.05, min(0.7, bestAlpha)),\n        0.25,\n        0.55\n    };\n\n    // Robust global local search: remove or shrink active stations, then repair globally.\n    while (elapsed_sec() < 1.86) {\n        bool improved = false;\n        vector<int> nextBestP = bestP;\n        long long nextBestS = bestS;\n\n        vector<int> active;\n        for (int i = 0; i < N; i++) {\n            if (bestP[i] > 0) active.push_back(i);\n        }\n\n        sort(active.begin(), active.end(), [&](int a, int b) {\n            long long ca = 1LL * bestP[a] * bestP[a];\n            long long cb = 1LL * bestP[b] * bestP[b];\n            return ca > cb;\n        });\n\n        for (int s : active) {\n            if (elapsed_sec() > 1.91) break;\n\n            int old = bestP[s];\n            vector<int> limits;\n\n            limits.push_back(0);\n            limits.push_back(lower_existing_radius(s, old / 4));\n            limits.push_back(lower_existing_radius(s, old / 2));\n            limits.push_back(lower_existing_radius(s, old * 3 / 4));\n\n            sort(limits.begin(), limits.end());\n            limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n            for (int lim : limits) {\n                if (elapsed_sec() > 1.93) break;\n                if (lim >= old) continue;\n\n                for (double ra : repairAlphas) {\n                    if (elapsed_sec() > 1.95) break;\n\n                    vector<int> P = bestP;\n                    P[s] = lim;\n\n                    bool ok = greedy_complete(P, ra, true, s, lim);\n                    if (!ok) continue;\n\n                    reduce_powers(P);\n                    long long S = total_cost(P);\n\n                    if (S < nextBestS) {\n                        nextBestS = S;\n                        nextBestP = P;\n                        improved = true;\n                    }\n                }\n            }\n        }\n\n        if (improved) {\n            bestS = nextBestS;\n            bestP = nextBestP;\n\n            if (elapsed_sec() < 1.88) {\n                optimize_reduction_orders(bestP, bestS);\n            }\n        } else {\n            break;\n        }\n    }\n\n    optimize_reduction_orders(bestP, bestS);\n\n    vector<char> covered;\n    if (!compute_covered(bestP, covered)) {\n        greedy_complete(bestP, 0.0, true);\n        reduce_powers(bestP);\n    }\n\n    auto tree = build_best_tree(bestP);\n    vector<int> ansB = tree.second;\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n\n    for (int e = 0; e < M; e++) {\n        if (e) cout << ' ';\n        cout << ansB[e];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = N * (N + 1) / 2;\nconstexpr int MAX_OPS = 10000;\n\nstruct Op {\n    int u, v;\n};\n\nint ID[N][N];\nint X[M], Y[M];\n\narray<int, M> initialA;\n\nvector<int> adj[M];\nvector<pair<int,int>> adjEdges;\nvector<pair<int,int>> downEdges;\nvector<vector<int>> incidentDown;\nbool isAdj[M][M];\n\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsedSec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nstruct RNG {\n    uint32_t x;\n    RNG(uint32_t seed = 1) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int range(int l, int r) {\n        return l + (int)(next() % (uint32_t)(r - l + 1));\n    }\n};\n\nuint32_t splitmix32(uint32_t x) {\n    x += 0x9e3779b9;\n    x = (x ^ (x >> 16)) * 0x85ebca6b;\n    x = (x ^ (x >> 13)) * 0xc2b2ae35;\n    x ^= (x >> 16);\n    return x;\n}\n\nint calcE(const array<int, M>& a) {\n    int e = 0;\n    for (auto [p, c] : downEdges) {\n        if (a[p] > a[c]) e++;\n    }\n    return e;\n}\n\nbool isValidFinal(const array<int, M>& a) {\n    for (auto [p, c] : downEdges) {\n        if (a[p] > a[c]) return false;\n    }\n    return true;\n}\n\nstruct State {\n    array<int, M> a;\n    vector<Op> ops;\n    int E = 0;\n};\n\nvector<int> parentsOf(int u) {\n    vector<int> ps;\n\n    int x = X[u];\n    int y = Y[u];\n\n    if (x == 0) return ps;\n\n    if (y > 0) ps.push_back(ID[x - 1][y - 1]);\n    if (y < x) ps.push_back(ID[x - 1][y]);\n\n    return ps;\n}\n\nvector<int> childrenOf(int u) {\n    vector<int> cs;\n\n    int x = X[u];\n    int y = Y[u];\n\n    if (x + 1 >= N) return cs;\n\n    cs.push_back(ID[x + 1][y]);\n    cs.push_back(ID[x + 1][y + 1]);\n\n    return cs;\n}\n\nint deltaSwapLocal(const array<int, M>& a, int u, int v) {\n    int ids[16], cnt = 0;\n\n    auto add = [&](int e) {\n        for (int i = 0; i < cnt; i++) {\n            if (ids[i] == e) return;\n        }\n        ids[cnt++] = e;\n    };\n\n    for (int e : incidentDown[u]) add(e);\n    for (int e : incidentDown[v]) add(e);\n\n    int before = 0;\n    int after = 0;\n\n    for (int i = 0; i < cnt; i++) {\n        auto [p, c] = downEdges[ids[i]];\n\n        before += (a[p] > a[c]);\n\n        int vp = a[p];\n        int vc = a[c];\n\n        if (p == u) vp = a[v];\n        else if (p == v) vp = a[u];\n\n        if (c == u) vc = a[v];\n        else if (c == v) vc = a[u];\n\n        after += (vp > vc);\n    }\n\n    return before - after;\n}\n\nvoid applySwap(State& s, int u, int v) {\n    int d = deltaSwapLocal(s.a, u, v);\n    s.E -= d;\n    swap(s.a[u], s.a[v]);\n    s.ops.push_back({u, v});\n}\n\nvoid applySwapWithPos(State& s, array<int, M>& pos, int u, int v) {\n    int au = s.a[u];\n    int av = s.a[v];\n\n    applySwap(s, u, v);\n\n    pos[au] = v;\n    pos[av] = u;\n}\n\nbool sameEdge(const Op& a, const Op& b) {\n    return (a.u == b.u && a.v == b.v) || (a.u == b.v && a.v == b.u);\n}\n\nbool shareVertex(const Op& a, const Op& b) {\n    return a.u == b.u || a.u == b.v || a.v == b.u || a.v == b.v;\n}\n\nbool triangleReplace(const Op& a, const Op& b, Op& r) {\n    if (!shareVertex(a, b)) return false;\n    if (sameEdge(a, b)) return false;\n\n    int common = -1;\n\n    if (a.u == b.u || a.u == b.v) common = a.u;\n    if (a.v == b.u || a.v == b.v) {\n        if (common != -1) return false;\n        common = a.v;\n    }\n\n    if (common == -1) return false;\n\n    int x = (a.u == common ? a.v : a.u);\n    int y = (b.u == common ? b.v : b.u);\n\n    if (!isAdj[x][y]) return false;\n\n    r = {x, y};\n    return true;\n}\n\nvector<Op> localReduceOps(const vector<Op>& ops) {\n    vector<Op> st;\n    st.reserve(ops.size());\n\n    auto normalizeTail = [&]() {\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n            int n = (int)st.size();\n\n            if (n >= 2 && sameEdge(st[n - 1], st[n - 2])) {\n                st.pop_back();\n                st.pop_back();\n                changed = true;\n                continue;\n            }\n\n            n = (int)st.size();\n\n            if (n >= 3 && sameEdge(st[n - 1], st[n - 3])) {\n                Op r;\n                if (triangleReplace(st[n - 3], st[n - 2], r)) {\n                    st.pop_back();\n                    st.pop_back();\n                    st.pop_back();\n                    st.push_back(r);\n                    changed = true;\n                    continue;\n                }\n            }\n        }\n    };\n\n    for (auto op : ops) {\n        st.push_back(op);\n        normalizeTail();\n    }\n\n    return st;\n}\n\nvector<Op> reduceOps(vector<Op> ops) {\n    ops = localReduceOps(ops);\n\n    for (int pass = 0; pass < 3; pass++) {\n        vector<Op> st;\n        st.reserve(ops.size());\n\n        for (auto op : ops) {\n            bool cancelled = false;\n\n            for (int i = (int)st.size() - 1; i >= 0; i--) {\n                if (sameEdge(st[i], op)) {\n                    st.erase(st.begin() + i);\n                    cancelled = true;\n                    break;\n                }\n\n                if (shareVertex(st[i], op)) break;\n            }\n\n            if (!cancelled) {\n                st.push_back(op);\n            }\n        }\n\n        st = localReduceOps(st);\n\n        if (st.size() == ops.size()) {\n            ops = move(st);\n            break;\n        }\n\n        ops = move(st);\n    }\n\n    return ops;\n}\n\nbool validateOps(const vector<Op>& ops) {\n    if ((int)ops.size() > MAX_OPS) return false;\n\n    array<int, M> a = initialA;\n\n    for (auto [u, v] : ops) {\n        if (!isAdj[u][v]) return false;\n        swap(a[u], a[v]);\n    }\n\n    return isValidFinal(a);\n}\n\nvector<int> yOrder(int x, int type) {\n    vector<int> ys;\n    for (int y = 0; y <= x; y++) ys.push_back(y);\n\n    if (type == 1) {\n        reverse(ys.begin(), ys.end());\n    } else if (type == 2) {\n        if (x & 1) reverse(ys.begin(), ys.end());\n    } else if (type == 3) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da < db;\n            return a < b;\n        });\n    } else if (type == 4) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da > db;\n            return a < b;\n        });\n    }\n\n    return ys;\n}\n\nState runHeapify(State s, int yType) {\n    for (int x = N - 2; x >= 0; x--) {\n        auto ys = yOrder(x, yType);\n\n        for (int sy : ys) {\n            int cur = ID[x][sy];\n\n            while (X[cur] + 1 < N) {\n                int cx = X[cur];\n                int cy = Y[cur];\n\n                int c1 = ID[cx + 1][cy];\n                int c2 = ID[cx + 1][cy + 1];\n\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[cur] > s.a[ch]) {\n                    applySwap(s, cur, ch);\n                    cur = ch;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    return s;\n}\n\nint estimateSiftUpSteps(array<int, M> a, int u, int p, int val) {\n    swap(a[u], a[p]);\n\n    int cur = p;\n    int cnt = 1;\n\n    while (true) {\n        vector<int> cand;\n        for (int q : parentsOf(cur)) {\n            if (a[q] > val) cand.push_back(q);\n        }\n\n        if (cand.empty()) break;\n\n        int best = cand[0];\n        for (int q : cand) {\n            if (a[q] > a[best]) best = q;\n        }\n\n        swap(a[cur], a[best]);\n        cur = best;\n        cnt++;\n\n        if (cnt > N) break;\n    }\n\n    return cnt;\n}\n\n// Exact minimum number of additional upward swaps needed by value val\n// if it is currently at u. Since only val moves upward, the set of blocking\n// parents depends only on labels currently above u.\nint exactMinSiftUpDistRec(const array<int, M>& a, int u, int val, array<int, M>& memo) {\n    if (memo[u] != -1) return memo[u];\n\n    int best = 1000000;\n\n    for (int p : parentsOf(u)) {\n        if (a[p] > val) {\n            best = min(best, 1 + exactMinSiftUpDistRec(a, p, val, memo));\n        }\n    }\n\n    if (best == 1000000) best = 0;\n    memo[u] = best;\n    return best;\n}\n\nint exactMinSiftUpDist(const array<int, M>& a, int u, int val) {\n    array<int, M> memo;\n    memo.fill(-1);\n    return exactMinSiftUpDistRec(a, u, val, memo);\n}\n\nint exactMaxSiftUpDistRec(const array<int, M>& a, int u, int val, array<int, M>& memo) {\n    if (memo[u] != -1) return memo[u];\n\n    int best = -1;\n\n    for (int p : parentsOf(u)) {\n        if (a[p] > val) {\n            best = max(best, 1 + exactMaxSiftUpDistRec(a, p, val, memo));\n        }\n    }\n\n    if (best == -1) best = 0;\n    memo[u] = best;\n    return best;\n}\n\nint exactMaxSiftUpDist(const array<int, M>& a, int u, int val) {\n    array<int, M> memo;\n    memo.fill(-1);\n    return exactMaxSiftUpDistRec(a, u, val, memo);\n}\n\nState runSiftUpByLabel(State s, int mode, int uptoLabel, int limitOps) {\n    array<int, M> pos;\n    for (int i = 0; i < M; i++) pos[s.a[i]] = i;\n\n    for (int val = 0; val < uptoLabel; val++) {\n        if ((int)s.ops.size() >= limitOps) break;\n\n        while ((int)s.ops.size() < limitOps) {\n            int u = pos[val];\n\n            vector<int> cand;\n            for (int p : parentsOf(u)) {\n                if (s.a[p] > val) cand.push_back(p);\n            }\n\n            if (cand.empty()) break;\n\n            int best = cand[0];\n            long long bestScore = LLONG_MIN;\n\n            for (int p : cand) {\n                int imp = deltaSwapLocal(s.a, u, p);\n                int est = 0;\n                int minDist = 0;\n                int maxDist = 0;\n\n                if (mode >= 5 && mode <= 9) {\n                    est = estimateSiftUpSteps(s.a, u, p, val);\n                }\n\n                if (mode >= 10) {\n                    // After swapping u and p, val is at p.\n                    // The values above p are unchanged, so exact distance from p\n                    // can be computed on the current array.\n                    minDist = exactMinSiftUpDist(s.a, p, val);\n                    maxDist = exactMaxSiftUpDist(s.a, p, val);\n                }\n\n                long long score = 0;\n\n                if (mode == 0) {\n                    score = 100000LL * s.a[p] + imp;\n                } else if (mode == 1) {\n                    score = -100000LL * s.a[p] + imp;\n                } else if (mode == 2) {\n                    score = 100000LL * imp + s.a[p];\n                } else if (mode == 3) {\n                    score = -1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                } else if (mode == 4) {\n                    score = 1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                } else if (mode == 5) {\n                    score = -100000LL * est + 1000LL * imp + s.a[p];\n                } else if (mode == 6) {\n                    score = -100000LL * est + 1000LL * s.a[p] + imp;\n                } else if (mode == 7) {\n                    score = 100000LL * imp - 1000LL * est + s.a[p];\n                } else if (mode == 8) {\n                    score = 10000LL * s.a[p] - 1000LL * abs(2 * Y[p] - X[p]) - est;\n                } else if (mode == 9) {\n                    score = 10000LL * s.a[p] + 1000LL * abs(2 * Y[p] - X[p]) - est;\n                } else if (mode == 10) {\n                    score = -1000000LL * minDist + 1000LL * s.a[p] + imp;\n                } else if (mode == 11) {\n                    score = -1000000LL * minDist + 100000LL * imp + s.a[p];\n                } else if (mode == 12) {\n                    score = -1000000LL * minDist - 1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                } else if (mode == 13) {\n                    score = -1000000LL * minDist + 1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                } else {\n                    score = 100000LL * maxDist + 1000LL * imp + s.a[p];\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = p;\n                }\n            }\n\n            applySwapWithPos(s, pos, u, best);\n        }\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nstruct RandSiftParam {\n    int wp;\n    int wi;\n    int wd;\n    int wc;\n    int noise;\n};\n\nState runRandomSiftUp(State s, RandSiftParam rp, uint32_t seed, int limitOps) {\n    RNG rng(seed);\n\n    array<int, M> pos;\n    for (int i = 0; i < M; i++) pos[s.a[i]] = i;\n\n    for (int val = 0; val < M; val++) {\n        if ((int)s.ops.size() >= limitOps) break;\n\n        while ((int)s.ops.size() < limitOps) {\n            int u = pos[val];\n\n            vector<int> cand;\n            for (int p : parentsOf(u)) {\n                if (s.a[p] > val) cand.push_back(p);\n            }\n\n            if (cand.empty()) break;\n\n            int best = cand[0];\n            long long bestScore = LLONG_MIN;\n\n            for (int p : cand) {\n                int imp = deltaSwapLocal(s.a, u, p);\n                int center = abs(2 * Y[p] - X[p]);\n\n                long long score = 0;\n                score += 1LL * rp.wp * s.a[p];\n                score += 1LL * rp.wi * imp;\n                score += 1LL * rp.wd * X[p];\n                score += 1LL * rp.wc * center;\n\n                if (rp.noise > 0) {\n                    score += rng.range(-rp.noise, rp.noise);\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = p;\n                }\n            }\n\n            applySwapWithPos(s, pos, u, best);\n        }\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nState runSiftDownByLabel(State s, int mode, int fromLabel, int limitOps) {\n    array<int, M> pos;\n    for (int i = 0; i < M; i++) pos[s.a[i]] = i;\n\n    for (int val = M - 1; val >= fromLabel; val--) {\n        if ((int)s.ops.size() >= limitOps) break;\n\n        while ((int)s.ops.size() < limitOps) {\n            int u = pos[val];\n\n            vector<int> cand;\n            for (int c : childrenOf(u)) {\n                if (s.a[c] < val) cand.push_back(c);\n            }\n\n            if (cand.empty()) break;\n\n            int best = cand[0];\n            long long bestScore = LLONG_MIN;\n\n            for (int c : cand) {\n                int imp = deltaSwapLocal(s.a, u, c);\n\n                long long score = 0;\n\n                if (mode == 0) {\n                    score = -100000LL * s.a[c] + imp;\n                } else if (mode == 1) {\n                    score = 100000LL * s.a[c] + imp;\n                } else if (mode == 2) {\n                    score = 100000LL * imp - s.a[c];\n                } else if (mode == 3) {\n                    score = -1000LL * abs(2 * Y[c] - X[c]) - s.a[c];\n                } else {\n                    score = 1000LL * abs(2 * Y[c] - X[c]) - s.a[c];\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = c;\n                }\n            }\n\n            applySwapWithPos(s, pos, u, best);\n        }\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nstruct GreedyParam {\n    int wImp;\n    int wDiff;\n    int wChild;\n    int wParent;\n    int wDepth;\n    int wCenter;\n    int noise;\n};\n\nState runWeightedViolationGreedy(State s, GreedyParam gp, int seed, int limitOps) {\n    int step = 0;\n\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        int bu = -1;\n        int bv = -1;\n        long long bestScore = LLONG_MIN;\n\n        for (int ei = 0; ei < (int)downEdges.size(); ei++) {\n            auto [p, c] = downEdges[ei];\n\n            if (s.a[p] <= s.a[c]) continue;\n\n            int imp = deltaSwapLocal(s.a, p, c);\n            int diff = s.a[p] - s.a[c];\n            int center = abs(2 * Y[c] - X[c]);\n\n            long long score = 0;\n            score += 1LL * gp.wImp * imp;\n            score += 1LL * gp.wDiff * diff;\n            score += 1LL * gp.wChild * s.a[c];\n            score += 1LL * gp.wParent * s.a[p];\n            score += 1LL * gp.wDepth * X[p];\n            score += 1LL * gp.wCenter * center;\n\n            if (gp.noise > 0) {\n                uint32_t h = splitmix32(seed ^ (step * 1009u) ^ (ei * 9176u));\n                score += (int)(h % (2 * gp.noise + 1)) - gp.noise;\n            }\n\n            if (score > bestScore) {\n                bestScore = score;\n                bu = p;\n                bv = c;\n            }\n        }\n\n        if (bu == -1) break;\n\n        applySwap(s, bu, bv);\n        step++;\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nState runScanBubble(State s, int rowType, int yType, int limitOps) {\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        bool changed = false;\n\n        vector<int> rows;\n        if (rowType == 0) {\n            for (int x = N - 2; x >= 0; x--) rows.push_back(x);\n        } else {\n            for (int x = 0; x <= N - 2; x++) rows.push_back(x);\n        }\n\n        for (int x : rows) {\n            auto ys = yOrder(x, yType);\n\n            for (int y : ys) {\n                if ((int)s.ops.size() >= limitOps) break;\n\n                int p = ID[x][y];\n                int c1 = ID[x + 1][y];\n                int c2 = ID[x + 1][y + 1];\n\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[p] > s.a[ch]) {\n                    applySwap(s, p, ch);\n                    changed = true;\n                }\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nint encodePerm(const vector<int>& p, int base) {\n    int code = 0;\n    int mul = 1;\n    for (int x : p) {\n        code += x * mul;\n        mul *= base;\n    }\n    return code;\n}\n\nvector<int> decodePerm(int code, int k) {\n    vector<int> p(k);\n    for (int i = 0; i < k; i++) {\n        p[i] = code % k;\n        code /= k;\n    }\n    return p;\n}\n\nbool shortestReplacementBlock(const vector<Op>& ops, int l, int len, vector<Op>& rep) {\n    vector<int> verts;\n\n    auto addv = [&](int v) {\n        for (int x : verts) if (x == v) return;\n        verts.push_back(v);\n    };\n\n    for (int i = 0; i < len; i++) {\n        addv(ops[l + i].u);\n        addv(ops[l + i].v);\n    }\n\n    int k = (int)verts.size();\n    if (k > 7) return false;\n\n    int idx[M];\n    fill(idx, idx + M, -1);\n    for (int i = 0; i < k; i++) idx[verts[i]] = i;\n\n    vector<pair<int,int>> edges;\n    for (int i = 0; i < k; i++) {\n        for (int j = i + 1; j < k; j++) {\n            if (isAdj[verts[i]][verts[j]]) {\n                edges.push_back({i, j});\n            }\n        }\n    }\n\n    vector<int> target(k);\n    iota(target.begin(), target.end(), 0);\n\n    for (int i = 0; i < len; i++) {\n        int a = idx[ops[l + i].u];\n        int b = idx[ops[l + i].v];\n        swap(target[a], target[b]);\n    }\n\n    vector<int> start(k);\n    iota(start.begin(), start.end(), 0);\n\n    int startCode = encodePerm(start, k);\n    int targetCode = encodePerm(target, k);\n\n    if (startCode == targetCode) {\n        rep.clear();\n        return true;\n    }\n\n    int depthLimit = len - 1;\n\n    queue<int> q;\n    unordered_map<int, int> dist;\n    unordered_map<int, int> parent;\n    unordered_map<int, int> parentEdge;\n\n    dist.reserve(2048);\n    parent.reserve(2048);\n    parentEdge.reserve(2048);\n\n    dist[startCode] = 0;\n    parent[startCode] = -1;\n    q.push(startCode);\n\n    bool found = false;\n\n    while (!q.empty()) {\n        int code = q.front();\n        q.pop();\n\n        int d = dist[code];\n        if (d >= depthLimit) continue;\n\n        vector<int> p = decodePerm(code, k);\n\n        for (int ei = 0; ei < (int)edges.size(); ei++) {\n            auto [a, b] = edges[ei];\n\n            vector<int> np = p;\n            swap(np[a], np[b]);\n\n            int nc = encodePerm(np, k);\n            if (dist.count(nc)) continue;\n\n            dist[nc] = d + 1;\n            parent[nc] = code;\n            parentEdge[nc] = ei;\n\n            if (nc == targetCode) {\n                found = true;\n                q = queue<int>();\n                break;\n            }\n\n            q.push(nc);\n        }\n    }\n\n    if (!found && !dist.count(targetCode)) return false;\n    if (dist[targetCode] >= len) return false;\n\n    vector<Op> rev;\n\n    int cur = targetCode;\n    while (cur != startCode) {\n        int ei = parentEdge[cur];\n        auto [a, b] = edges[ei];\n        rev.push_back({verts[a], verts[b]});\n        cur = parent[cur];\n    }\n\n    reverse(rev.begin(), rev.end());\n    rep = move(rev);\n\n    return true;\n}\n\nvector<Op> peepholeOptimize(vector<Op> ops) {\n    ops = reduceOps(ops);\n\n    int i = 0;\n\n    while (i < (int)ops.size() && elapsedSec() < 1.975) {\n        bool changed = false;\n\n        int maxLen = min(7, (int)ops.size() - i);\n\n        for (int len = maxLen; len >= 3; len--) {\n            vector<Op> rep;\n\n            if (shortestReplacementBlock(ops, i, len, rep) && (int)rep.size() < len) {\n                ops.erase(ops.begin() + i, ops.begin() + i + len);\n                ops.insert(ops.begin() + i, rep.begin(), rep.end());\n\n                int ni = max(0, i - 8);\n                i = ni;\n\n                changed = true;\n                break;\n            }\n        }\n\n        if (!changed) i++;\n    }\n\n    return reduceOps(ops);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    int id = 0;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            ID[x][y] = id;\n            X[id] = x;\n            Y[id] = y;\n            id++;\n        }\n    }\n\n    incidentDown.assign(M, {});\n    memset(isAdj, 0, sizeof(isAdj));\n\n    auto addAdj = [&](int u, int v) {\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n        adjEdges.push_back({u, v});\n        isAdj[u][v] = isAdj[v][u] = true;\n    };\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int u = ID[x][y];\n\n            if (y + 1 <= x) {\n                int v = ID[x][y + 1];\n                addAdj(u, v);\n            }\n\n            if (x + 1 < N) {\n                int v1 = ID[x + 1][y];\n                int v2 = ID[x + 1][y + 1];\n\n                addAdj(u, v1);\n                addAdj(u, v2);\n\n                int e1 = (int)downEdges.size();\n                downEdges.push_back({u, v1});\n                incidentDown[u].push_back(e1);\n                incidentDown[v1].push_back(e1);\n\n                int e2 = (int)downEdges.size();\n                downEdges.push_back({u, v2});\n                incidentDown[u].push_back(e2);\n                incidentDown[v2].push_back(e2);\n            }\n        }\n    }\n\n    uint32_t inputSeed = 1234567;\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> initialA[ID[x][y]];\n            inputSeed = inputSeed * 1000003u + initialA[ID[x][y]] + 97u;\n        }\n    }\n\n    State base;\n    base.a = initialA;\n    base.E = calcE(initialA);\n\n    vector<Op> bestOps;\n    bool haveBest = false;\n\n    auto tryCandidate = [&](const State& s) {\n        if (s.E != 0) return;\n\n        vector<Op> ops = reduceOps(s.ops);\n\n        if ((int)ops.size() > MAX_OPS) return;\n        if (!validateOps(ops)) return;\n\n        if (!haveBest || ops.size() < bestOps.size()) {\n            bestOps = move(ops);\n            haveBest = true;\n        }\n    };\n\n    // 1. Safe heapify fallback.\n    for (int t = 0; t < 5; t++) {\n        State s = runHeapify(base, t);\n        tryCandidate(s);\n    }\n\n    if (!haveBest) {\n        State s = runHeapify(base, 0);\n        bestOps = reduceOps(s.ops);\n        haveBest = true;\n    }\n\n    // 2. Deterministic sift-up candidates, now including exact path-distance modes.\n    if (elapsedSec() < 0.95) {\n        for (int mode = 0; mode < 15; mode++) {\n            if (elapsedSec() > 1.23) break;\n\n            int limit = min(MAX_OPS, (int)bestOps.size() - 1);\n            State s = runSiftUpByLabel(base, mode, M, limit);\n            tryCandidate(s);\n        }\n    }\n\n    // 3. Randomized sift-up candidates.\n    vector<RandSiftParam> rparams = {\n        {100000, 1000, 0, 0, 50000},\n        {100000, 3000, 0, -1000, 80000},\n        {100000, 3000, 0, 1000, 80000},\n        {50000, 10000, 0, 0, 100000},\n        {10000, 50000, 0, 0, 100000},\n        {100000, 1000, -500, 0, 60000},\n        {100000, 1000, 500, 0, 60000},\n        {-100000, 1000, 0, 0, 80000},\n        {70000, 5000, -500, -500, 120000},\n        {70000, 5000, 500, 500, 120000},\n        {30000, 30000, 0, -2000, 150000},\n        {30000, 30000, 0, 2000, 150000},\n        {120000, 2000, -1000, 0, 90000},\n        {120000, 2000, 1000, 0, 90000},\n        {40000, 40000, -500, -1500, 180000},\n        {40000, 40000, 500, 1500, 180000}\n    };\n\n    if (elapsedSec() < 1.23) {\n        int run = 0;\n        while (elapsedSec() < 1.62) {\n            int limit = min(MAX_OPS, (int)bestOps.size() - 1);\n            if (limit <= 0) break;\n\n            RandSiftParam rp = rparams[run % rparams.size()];\n            uint32_t seed = splitmix32(inputSeed + 19260817u * run + 998244353u);\n\n            State s = runRandomSiftUp(base, rp, seed, limit);\n            tryCandidate(s);\n\n            run++;\n            if (run >= 64) break;\n        }\n    }\n\n    // 4. Large-label sift-down candidates.\n    if (elapsedSec() < 1.62) {\n        for (int mode = 0; mode < 5; mode++) {\n            if (elapsedSec() > 1.70) break;\n\n            int limit = min(MAX_OPS, (int)bestOps.size() - 1);\n            State s = runSiftDownByLabel(base, mode, 0, limit);\n            tryCandidate(s);\n        }\n    }\n\n    // 5. Weighted global greedy over violating edges.\n    vector<GreedyParam> params = {\n        {100000, 100, -10, 10, 0, 0, 0},\n        {100000, 10, -100, 20, 0, 0, 0},\n        {50000, 200, -50, 50, 0, 0, 0},\n        {10000, 1000, 0, 0, 0, 0, 0},\n        {10000, 100, -1000, 0, 0, 0, 0},\n        {10000, 100, 0, 1000, 0, 0, 0},\n        {100000, 50, -20, 20, -100, 0, 0},\n        {100000, 50, -20, 20, 100, 0, 0},\n        {100000, 50, -20, 20, 0, -100, 0},\n        {100000, 50, -20, 20, 0, 100, 0},\n        {50000, 100, -100, 100, -50, -50, 200},\n        {50000, 100, -100, 100, 50, 50, 200},\n        {20000, 500, -200, 50, 0, -100, 300},\n        {20000, 500, -50, 200, 0, 100, 300},\n        {100000, 0, -1000, 1000, 0, 0, 500},\n        {80000, 300, -300, 300, -100, 0, 500},\n        {80000, 300, -300, 300, 100, 0, 500},\n        {80000, 300, -300, 300, 0, -100, 500},\n        {80000, 300, -300, 300, 0, 100, 500},\n        {120000, 0, -500, 500, -200, -100, 1000},\n        {120000, 0, -500, 500, 200, 100, 1000},\n        {30000, 1000, -500, 500, 0, 0, 1000}\n    };\n\n    if (elapsedSec() < 1.70) {\n        for (int i = 0; i < (int)params.size(); i++) {\n            if (elapsedSec() > 1.83) break;\n\n            int limit = min(MAX_OPS, (int)bestOps.size() - 1);\n            if (limit <= 0) break;\n\n            State s = runWeightedViolationGreedy(base, params[i], inputSeed + i * 19260817u, limit);\n            tryCandidate(s);\n        }\n    }\n\n    // 6. Prefix sift-up followed by heapify.\n    if (elapsedSec() < 1.83) {\n        vector<int> prefixes = {10, 20, 40, 70, 100, 150, 220, 300};\n\n        for (int p : prefixes) {\n            if (elapsedSec() > 1.89) break;\n\n            for (int mode = 0; mode < 8; mode++) {\n                if (elapsedSec() > 1.91) break;\n\n                int limit = min(MAX_OPS, (int)bestOps.size() - 1);\n                State pre = runSiftUpByLabel(base, mode, p, limit);\n\n                if ((int)pre.ops.size() >= (int)bestOps.size()) continue;\n\n                for (int t = 0; t < 5; t++) {\n                    if (elapsedSec() > 1.93) break;\n\n                    State s = runHeapify(pre, t);\n                    tryCandidate(s);\n                }\n            }\n        }\n    }\n\n    // 7. Scan bubble fallback diversifier.\n    if (elapsedSec() < 1.90) {\n        for (int rowType = 0; rowType < 2; rowType++) {\n            for (int yType = 0; yType < 5; yType++) {\n                if (elapsedSec() > 1.94) break;\n\n                int limit = min(MAX_OPS, (int)bestOps.size() - 1);\n                if (limit <= 0) break;\n\n                State s = runScanBubble(base, rowType, yType, limit);\n                tryCandidate(s);\n            }\n        }\n    }\n\n    // 8. Exact short-block peephole compression of the selected sequence.\n    if (elapsedSec() < 1.94) {\n        vector<Op> opt = peepholeOptimize(bestOps);\n        if ((int)opt.size() <= MAX_OPS && opt.size() < bestOps.size() && validateOps(opt)) {\n            bestOps = move(opt);\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n    for (auto [u, v] : bestOps) {\n        cout << X[u] << ' ' << Y[u] << ' ' << X[v] << ' ' << Y[v] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint D, N;\nint ENT;\nvector<int> freeIds;\nbool obstacleCell[100];\nint labelAt[100];\nint rankOfCell[100];\nbool usedLabel[100];\n\nint nb[100][4];\nint nbcnt[100];\n\nchrono::steady_clock::time_point START_TIME;\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nint id_of(int r, int c) {\n    return r * D + c;\n}\n\npair<int,int> rc_of(int id) {\n    return {id / D, id % D};\n}\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nint elapsed_ms() {\n    auto now = chrono::steady_clock::now();\n    return (int)chrono::duration_cast<chrono::milliseconds>(now - START_TIME).count();\n}\n\nbool time_over(int ms) {\n    return elapsed_ms() >= ms;\n}\n\nvoid build_neighbors() {\n    for (int id = 0; id < D * D; id++) {\n        auto [r, c] = rc_of(id);\n        nbcnt[id] = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc)) {\n                nb[id][nbcnt[id]++] = id_of(nr, nc);\n            }\n        }\n    }\n}\n\ninline void set_bit(ull &lo, ull &hi, int x) {\n    if (x < 64) lo |= 1ULL << x;\n    else hi |= 1ULL << (x - 64);\n}\n\ninline int popcnt2(ull lo, ull hi) {\n    return __builtin_popcountll(lo) + __builtin_popcountll(hi);\n}\n\nbool legal_fill(int cand) {\n    int totalEmptyAfter = 0;\n    for (int id : freeIds) {\n        if (id != cand && labelAt[id] == -1) totalEmptyAfter++;\n    }\n\n    bool vis[100] = {};\n    int que[100];\n    int head = 0, tail = 0;\n\n    vis[ENT] = true;\n    que[tail++] = ENT;\n\n    int reached = 0;\n\n    while (head < tail) {\n        int v = que[head++];\n\n        for (int z = 0; z < nbcnt[v]; z++) {\n            int to = nb[v][z];\n            if (vis[to]) continue;\n            if (obstacleCell[to]) continue;\n            if (to == cand) continue;\n            if (to != ENT && labelAt[to] != -1) continue;\n\n            vis[to] = true;\n            que[tail++] = to;\n            if (to != ENT) reached++;\n        }\n    }\n\n    return reached == totalEmptyAfter;\n}\n\ninline bool is_accessible_container(int id, const bool emptyCell[]) {\n    for (int z = 0; z < nbcnt[id]; z++) {\n        if (emptyCell[nb[id][z]]) return true;\n    }\n    return false;\n}\n\nint evaluate_candidate(\n    int cand,\n    int t,\n    const vector<int>& emptySorted,\n    const vector<int>& remLabels\n) {\n    int val[100];\n    fill(val, val + 100, -1);\n\n    for (int id : freeIds) {\n        if (labelAt[id] >= 0) val[id] = labelAt[id];\n    }\n    val[cand] = t;\n\n    int p = 0;\n    for (int id : emptySorted) {\n        if (id == cand) continue;\n        val[id] = remLabels[p++];\n    }\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    int seq[100];\n\n    int M = (int)freeIds.size();\n\n    for (int step = 0; step < M; step++) {\n        int best = -1;\n        int bestVal = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (val[id] < bestVal ||\n                (val[id] == bestVal && (best == -1 || rankOfCell[id] < rankOfCell[best]))) {\n                bestVal = val[id];\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    bestVal = val[id];\n                    break;\n                }\n            }\n        }\n\n        seq[step] = bestVal;\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    int inv = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (seq[i] > seq[j]) inv++;\n        }\n    }\n    return inv;\n}\n\nvector<int> greedy_removal_order() {\n    int M = (int)freeIds.size();\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    vector<int> order;\n    order.reserve(M);\n\n    for (int step = 0; step < M; step++) {\n        int best = -1;\n        int bestLabel = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (labelAt[id] < bestLabel) {\n                bestLabel = labelAt[id];\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    break;\n                }\n            }\n        }\n\n        order.push_back(best);\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    return order;\n}\n\nint inversion_count_of_order(const vector<int>& order) {\n    int M = (int)order.size();\n    int inv = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (labelAt[order[i]] > labelAt[order[j]]) inv++;\n        }\n    }\n    return inv;\n}\n\nstruct Key {\n    ull lo, hi;\n    bool operator==(const Key& other) const {\n        return lo == other.lo && hi == other.hi;\n    }\n};\n\nstruct KeyHash {\n    static uint64_t splitmix64(uint64_t x) {\n        x += 0x9e3779b97f4a7c15ULL;\n        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;\n        return x ^ (x >> 31);\n    }\n\n    size_t operator()(const Key& k) const {\n        return splitmix64(k.lo) ^ (splitmix64(k.hi) << 1);\n    }\n};\n\nstruct BeamState {\n    ull lo, hi;\n    ull flo, fhi;\n    int cost;\n    int prev;\n    int add;\n    int score;\n};\n\nvector<int> beam_removal_order(int WIDTH) {\n    int M = (int)freeIds.size();\n\n    vector<int> idToIdx(D * D, -1);\n    vector<int> idxToId(M);\n\n    for (int i = 0; i < M; i++) {\n        idToIdx[freeIds[i]] = i;\n        idxToId[i] = freeIds[i];\n    }\n\n    vector<int> lab(M);\n    for (int i = 0; i < M; i++) {\n        lab[i] = labelAt[idxToId[i]];\n    }\n\n    vector<ull> adjLo(M, 0), adjHi(M, 0);\n    ull initLo = 0, initHi = 0;\n\n    for (int i = 0; i < M; i++) {\n        int id = idxToId[i];\n\n        for (int z = 0; z < nbcnt[id]; z++) {\n            int to = nb[id][z];\n\n            if (to == ENT) {\n                set_bit(initLo, initHi, i);\n            } else if (idToIdx[to] != -1) {\n                int j = idToIdx[to];\n                set_bit(adjLo[i], adjHi[i], j);\n            }\n        }\n    }\n\n    vector<ull> lessLo(M, 0), lessHi(M, 0);\n\n    for (int x = 0; x < M; x++) {\n        ull lo = 0, hi = 0;\n        for (int i = 0; i < M; i++) {\n            if (lab[i] < x) set_bit(lo, hi, i);\n        }\n        lessLo[x] = lo;\n        lessHi[x] = hi;\n    }\n\n    auto calc_score = [&](int cost, ull flo, ull fhi) {\n        int mn1 = 100, mn2 = 100;\n\n        ull b = flo;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int x = lab[t];\n\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n\n            b &= b - 1;\n        }\n\n        b = fhi;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int idx = 64 + t;\n            int x = lab[idx];\n\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n\n            b &= b - 1;\n        }\n\n        return cost * 10000 + mn1 * 100 + mn2;\n    };\n\n    vector<vector<BeamState>> layers;\n    layers.reserve(M + 1);\n\n    BeamState start;\n    start.lo = start.hi = 0;\n    start.flo = initLo;\n    start.fhi = initHi;\n    start.cost = 0;\n    start.prev = -1;\n    start.add = -1;\n    start.score = calc_score(0, initLo, initHi);\n\n    layers.push_back(vector<BeamState>{start});\n\n    for (int depth = 0; depth < M; depth++) {\n        vector<BeamState>& cur = layers.back();\n\n        vector<BeamState> nxt;\n        nxt.reserve(min((int)cur.size() * 20, WIDTH * 45));\n\n        unordered_map<Key, int, KeyHash> mp;\n        mp.reserve(WIDTH * 55);\n\n        for (int pi = 0; pi < (int)cur.size(); pi++) {\n            const BeamState& s = cur[pi];\n\n            auto expand_one = [&](int idx) {\n                ull bitLo = 0, bitHi = 0;\n                set_bit(bitLo, bitHi, idx);\n\n                ull nlo = s.lo | bitLo;\n                ull nhi = s.hi | bitHi;\n\n                int label = lab[idx];\n                int removedLess = popcnt2(s.lo & lessLo[label], s.hi & lessHi[label]);\n                int inc = label - removedLess;\n                int ncost = s.cost + inc;\n\n                ull nflo = ((s.flo & ~bitLo) | adjLo[idx]) & ~nlo;\n                ull nfhi = ((s.fhi & ~bitHi) | adjHi[idx]) & ~nhi;\n\n                BeamState ns;\n                ns.lo = nlo;\n                ns.hi = nhi;\n                ns.flo = nflo;\n                ns.fhi = nfhi;\n                ns.cost = ncost;\n                ns.prev = pi;\n                ns.add = idx;\n                ns.score = calc_score(ncost, nflo, nfhi);\n\n                Key key{nlo, nhi};\n                auto it = mp.find(key);\n\n                if (it == mp.end()) {\n                    int pos = (int)nxt.size();\n                    mp.emplace(key, pos);\n                    nxt.push_back(ns);\n                } else {\n                    int pos = it->second;\n                    if (ns.cost < nxt[pos].cost ||\n                        (ns.cost == nxt[pos].cost && ns.score < nxt[pos].score)) {\n                        nxt[pos] = ns;\n                    }\n                }\n            };\n\n            ull b = s.flo;\n            while (b) {\n                int idx = __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n\n            b = s.fhi;\n            while (b) {\n                int idx = 64 + __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n        }\n\n        if ((int)nxt.size() > WIDTH) {\n            nth_element(\n                nxt.begin(),\n                nxt.begin() + WIDTH,\n                nxt.end(),\n                [](const BeamState& a, const BeamState& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.cost < b.cost;\n                }\n            );\n            nxt.resize(WIDTH);\n        }\n\n        layers.push_back(move(nxt));\n    }\n\n    if (layers.back().empty()) {\n        return greedy_removal_order();\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)layers[M].size(); i++) {\n        if (layers[M][i].cost < layers[M][best].cost) {\n            best = i;\n        }\n    }\n\n    vector<int> idxOrder;\n    idxOrder.reserve(M);\n\n    int curIdx = best;\n    for (int depth = M; depth >= 1; depth--) {\n        const BeamState& s = layers[depth][curIdx];\n        idxOrder.push_back(s.add);\n        curIdx = s.prev;\n    }\n\n    reverse(idxOrder.begin(), idxOrder.end());\n\n    vector<int> order;\n    order.reserve(M);\n\n    for (int idx : idxOrder) {\n        order.push_back(idxToId[idx]);\n    }\n\n    return order;\n}\n\nint main() {\n    START_TIME = chrono::steady_clock::now();\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    build_neighbors();\n\n    ENT = id_of(0, (D - 1) / 2);\n\n    fill(obstacleCell, obstacleCell + 100, false);\n    fill(labelAt, labelAt + 100, -1);\n    fill(usedLabel, usedLabel + 100, false);\n\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        obstacleCell[id_of(r, c)] = true;\n    }\n\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            int id = id_of(r, c);\n            if (id == ENT) continue;\n            if (obstacleCell[id]) continue;\n            freeIds.push_back(id);\n        }\n    }\n\n    int M = (int)freeIds.size();\n\n    const int INF = 1e9;\n    vector<int> dist(D * D, INF);\n\n    int que[100];\n    int head = 0, tail = 0;\n\n    dist[ENT] = 0;\n    que[tail++] = ENT;\n\n    while (head < tail) {\n        int v = que[head++];\n\n        for (int z = 0; z < nbcnt[v]; z++) {\n            int to = nb[v][z];\n            if (obstacleCell[to]) continue;\n            if (dist[to] != INF) continue;\n\n            dist[to] = dist[v] + 1;\n            que[tail++] = to;\n        }\n    }\n\n    int center = (D - 1) / 2;\n\n    sort(freeIds.begin(), freeIds.end(), [&](int a, int b) {\n        auto [ra, ca] = rc_of(a);\n        auto [rb, cb] = rc_of(b);\n\n        tuple<int,int,int,int> ka = {\n            dist[a],\n            abs(ca - center),\n            ra,\n            ca\n        };\n        tuple<int,int,int,int> kb = {\n            dist[b],\n            abs(cb - center),\n            rb,\n            cb\n        };\n\n        return ka < kb;\n    });\n\n    for (int i = 0; i < M; i++) {\n        rankOfCell[freeIds[i]] = i;\n    }\n\n    // Arrival phase.\n    for (int step = 0; step < M; step++) {\n        int t;\n        cin >> t;\n\n        vector<int> emptySorted;\n        emptySorted.reserve(M - step);\n\n        for (int id : freeIds) {\n            if (labelAt[id] == -1) emptySorted.push_back(id);\n        }\n\n        vector<int> remLabels;\n        remLabels.reserve(M - step - 1);\n\n        for (int x = 0; x < M; x++) {\n            if (!usedLabel[x] && x != t) remLabels.push_back(x);\n        }\n\n        vector<int> legal;\n        legal.reserve(emptySorted.size());\n\n        for (int id : emptySorted) {\n            if (legal_fill(id)) legal.push_back(id);\n        }\n\n        if (legal.empty()) {\n            legal = emptySorted;\n        }\n\n        int bestCell = legal[0];\n        long long bestScore = (1LL << 60);\n\n        for (int cand : legal) {\n            int inv = evaluate_candidate(cand, t, emptySorted, remLabels);\n\n            long long mismatch = abs(rankOfCell[cand] - t);\n            long long score = inv * 1000LL + mismatch;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestCell = cand;\n            }\n        }\n\n        labelAt[bestCell] = t;\n        usedLabel[t] = true;\n\n        auto [r, c] = rc_of(bestCell);\n        cout << r << ' ' << c << endl;\n    }\n\n    // Final removal phase.\n    vector<int> greedyOrder = greedy_removal_order();\n    int greedyInv = inversion_count_of_order(greedyOrder);\n\n    int e = elapsed_ms();\n    int width = 8000;\n\n    if (e > 1300) width = 5000;\n    else if (e > 1100) width = 6500;\n\n    vector<int> beamOrder;\n\n    if (!time_over(1650)) {\n        beamOrder = beam_removal_order(width);\n    }\n\n    int beamInv = INT_MAX;\n    if (!beamOrder.empty()) {\n        beamInv = inversion_count_of_order(beamOrder);\n    }\n\n    const vector<int>& finalOrder =\n        (!beamOrder.empty() && beamInv <= greedyInv) ? beamOrder : greedyOrder;\n\n    for (int id : finalOrder) {\n        auto [r, c] = rc_of(id);\n        cout << r << ' ' << c << '\\n';\n    }\n\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXC = 101;\nstatic const int INF = 1e9;\n\nint n, m;\nbool allowedAdj[MAXC][MAXC];\n\nstruct State {\n    vector<vector<int>> g;\n    int cnt[MAXC]{};\n    int edgeCnt[MAXC][MAXC]{};\n\n    int stamp[MAXN][MAXN]{};\n    int curStamp = 1;\n\n    State() {\n        g.assign(n, vector<int>(n, 0));\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(stamp, 0, sizeof(stamp));\n    }\n\n    static void normPair(int &a, int &b) {\n        if (a > b) swap(a, b);\n    }\n\n    bool inside(int r, int c) const {\n        return 0 <= r && r < n && 0 <= c && c < n;\n    }\n\n    void addEdgeCount(int a, int b, int v) {\n        if (a == b) return;\n        normPair(a, b);\n        edgeCnt[a][b] += v;\n    }\n\n    void init(const vector<vector<int>> &src) {\n        g = src;\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                cnt[g[i][j]]++;\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = g[i][j];\n\n                if (i == 0) addEdgeCount(c, 0, 1);\n                if (i == n - 1) addEdgeCount(c, 0, 1);\n                if (j == 0) addEdgeCount(c, 0, 1);\n                if (j == n - 1) addEdgeCount(c, 0, 1);\n\n                if (i + 1 < n) addEdgeCount(c, g[i + 1][j], 1);\n                if (j + 1 < n) addEdgeCount(c, g[i][j + 1], 1);\n            }\n        }\n    }\n\n    bool adjacentZeroOrOutside(int r, int c) const {\n        if (r == 0 || r == n - 1 || c == 0 || c == n - 1) return true;\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == 0) return true;\n        }\n        return false;\n    }\n\n    bool oldColorConnectedAfterRemoval(int r, int c, int col) {\n        vector<pair<int, int>> starts;\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) {\n                starts.push_back({nr, nc});\n            }\n        }\n\n        if (starts.size() <= 1) return true;\n\n        curStamp++;\n        if (curStamp == INT_MAX) {\n            memset(stamp, 0, sizeof(stamp));\n            curStamp = 1;\n        }\n\n        queue<pair<int, int>> q;\n        q.push(starts[0]);\n        stamp[starts[0].first][starts[0].second] = curStamp;\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dr[k], ny = y + dc[k];\n                if (!inside(nx, ny)) continue;\n                if (nx == r && ny == c) continue;\n                if (stamp[nx][ny] == curStamp) continue;\n                if (g[nx][ny] != col) continue;\n\n                stamp[nx][ny] = curStamp;\n                q.push({nx, ny});\n            }\n        }\n\n        for (auto [x, y] : starts) {\n            if (stamp[x][y] != curStamp) return false;\n        }\n        return true;\n    }\n\n    bool zeroConnectedAfterRemoval(int r, int c) const {\n        if (cnt[0] <= 1) return true;\n\n        bool vis[MAXN][MAXN]{};\n        queue<pair<int, int>> q;\n\n        auto push = [&](int x, int y) {\n            if (!inside(x, y)) return;\n            if (x == r && y == c) return;\n            if (g[x][y] != 0) return;\n            if (vis[x][y]) return;\n            vis[x][y] = true;\n            q.push({x, y});\n        };\n\n        for (int i = 0; i < n; i++) {\n            push(i, 0);\n            push(i, n - 1);\n            push(0, i);\n            push(n - 1, i);\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dr[k], ny = y + dc[k];\n                push(nx, ny);\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (i == r && j == c) continue;\n                if (g[i][j] == 0 && !vis[i][j]) return false;\n            }\n        }\n        return true;\n    }\n\n    struct Delta {\n        int a, b, d;\n    };\n\n    void addDelta(vector<Delta> &ds, int a, int b, int d) const {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n\n        for (auto &x : ds) {\n            if (x.a == a && x.b == b) {\n                x.d += d;\n                return;\n            }\n        }\n        ds.push_back({a, b, d});\n    }\n\n    vector<Delta> makeDelta(int r, int c, int to) const {\n        vector<Delta> ds;\n        int from = g[r][c];\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n\n            int nb = 0;\n            if (inside(nr, nc)) nb = g[nr][nc];\n\n            addDelta(ds, from, nb, -1);\n            addDelta(ds, to, nb, +1);\n        }\n\n        return ds;\n    }\n\n    bool touchesColor(int r, int c, int col) const {\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) return true;\n        }\n        return false;\n    }\n\n    bool validChange(int r, int c, int to) {\n        int from = g[r][c];\n        if (from == to) return false;\n\n        if (from != 0 && cnt[from] <= 1) return false;\n\n        if (to == 0) {\n            if (from == 0) return false;\n            if (!adjacentZeroOrOutside(r, c)) return false;\n        } else {\n            if (!touchesColor(r, c, to)) return false;\n        }\n\n        if (from == 0) {\n            if (!zeroConnectedAfterRemoval(r, c)) return false;\n        } else {\n            if (!oldColorConnectedAfterRemoval(r, c, from)) return false;\n        }\n\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            int now = edgeCnt[x.a][x.b] + x.d;\n\n            if (allowedAdj[x.a][x.b]) {\n                if (now <= 0) return false;\n            } else {\n                if (now != 0) return false;\n            }\n        }\n\n        return true;\n    }\n\n    void applyChange(int r, int c, int to) {\n        int from = g[r][c];\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            edgeCnt[x.a][x.b] += x.d;\n        }\n\n        cnt[from]--;\n        cnt[to]++;\n        g[r][c] = to;\n    }\n\n    vector<int> computeDistanceToZero() const {\n        vector<int> dist(n * n, INF);\n        queue<int> q;\n\n        auto id = [&](int r, int c) {\n            return r * n + c;\n        };\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int v = id(i, j);\n\n                if (g[i][j] == 0) {\n                    dist[v] = 0;\n                    q.push(v);\n                } else if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    dist[v] = 1;\n                    q.push(v);\n                }\n            }\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            int r = v / n, c = v % n;\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!inside(nr, nc)) continue;\n\n                int nv = id(nr, nc);\n                if (dist[nv] > dist[v] + 1) {\n                    dist[nv] = dist[v] + 1;\n                    q.push(nv);\n                }\n            }\n        }\n\n        return dist;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    vector<vector<int>> original(n, vector<int>(n));\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> original[i][j];\n        }\n    }\n\n    memset(allowedAdj, 0, sizeof(allowedAdj));\n\n    auto addAllowed = [&](int a, int b) {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n        allowedAdj[a][b] = true;\n    };\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = original[i][j];\n\n            if (i == 0) addAllowed(c, 0);\n            if (i == n - 1) addAllowed(c, 0);\n            if (j == 0) addAllowed(c, 0);\n            if (j == n - 1) addAllowed(c, 0);\n\n            if (i + 1 < n) addAllowed(c, original[i + 1][j]);\n            if (j + 1 < n) addAllowed(c, original[i][j + 1]);\n        }\n    }\n\n    State st;\n    st.init(original);\n\n    vector<vector<int>> best = st.g;\n    int bestZero = st.cnt[0];\n\n    mt19937 rng(123456789);\n\n    auto startTime = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    vector<int> cells(n * n);\n    iota(cells.begin(), cells.end(), 0);\n\n    auto updateBest = [&]() {\n        if (st.cnt[0] > bestZero) {\n            bestZero = st.cnt[0];\n            best = st.g;\n        }\n    };\n\n    auto peelPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 255) == 0 && elapsed() > 1.88) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            if (st.g[r][c] == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n            }\n        }\n\n        updateBest();\n        return changed;\n    };\n\n    auto boundaryRecolorPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 700) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n                applied++;\n                continue;\n            }\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n                used[to] = true;\n\n                int sameAround = 0;\n                for (int t = 0; t < 4; t++) {\n                    int ar = r + dr[t], ac = c + dc[t];\n                    if (st.inside(ar, ac) && st.g[ar][ac] == to) sameAround++;\n                }\n\n                cand.push_back({-sameAround, to});\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto inwardRecolorPass = [&]() {\n        bool changed = false;\n\n        auto dist = st.computeDistanceToZero();\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        stable_sort(cells.begin(), cells.end(), [&](int a, int b) {\n            return dist[a] < dist[b];\n        });\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 700) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            int cd = dist[v];\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                int nd = dist[nr * n + nc];\n\n                if (nd <= cd) {\n                    used[to] = true;\n                    cand.push_back({nd, to});\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto randomRecolorPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > 1.88) break;\n            if (applied >= 350) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<int> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                used[to] = true;\n                cand.push_back(to);\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            for (int to : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    int stagnant = 0;\n\n    while (elapsed() < 1.88) {\n        int beforeBest = bestZero;\n\n        bool any = false;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        any |= boundaryRecolorPass();\n        if (elapsed() > 1.88) break;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        any |= inwardRecolorPass();\n        if (elapsed() > 1.88) break;\n\n        any |= peelPass();\n        if (elapsed() > 1.88) break;\n\n        updateBest();\n\n        if (bestZero == beforeBest) stagnant++;\n        else stagnant = 0;\n\n        if (stagnant >= 2) {\n            randomRecolorPass();\n            peelPass();\n            stagnant = 0;\n        }\n\n        if (!any && elapsed() < 1.88) {\n            bool r = randomRecolorPass();\n            if (!r) break;\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (j) cout << ' ';\n            cout << best[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct QueryManager {\n    int N, D, Q;\n    int used = 0;\n\n    QueryManager(int N_, int D_, int Q_) : N(N_), D(D_), Q(Q_) {}\n\n    char query(const vector<int>& L, const vector<int>& R) {\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        string s;\n        if (!(cin >> s)) exit(0);\n\n        used++;\n        return s[0];\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query(L, R);\n    }\n};\n\nint ceil_log2_int(int x) {\n    int r = 0, p = 1;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\nstruct Solver {\n    int N, D, Q;\n    QueryManager qm;\n\n    vector<double> estWeight;\n    vector<int> order;\n\n    vector<vector<int>> bins;\n    vector<double> estSum;\n    vector<int> answer;\n\n    mt19937 rng;\n\n    Solver(int N_, int D_, int Q_)\n        : N(N_), D(D_), Q(Q_), qm(N_, D_, Q_),\n          rng(1234567u + 1009u * N_ + 917u * D_ + 37u * Q_) {}\n\n    bool heavier_single(int a, int b) {\n        char c = qm.query_single(a, b);\n        return c == '>';\n    }\n\n    vector<int> merge_sort_rec(const vector<int>& v) {\n        int n = (int)v.size();\n        if (n <= 1) return v;\n\n        int mid = n / 2;\n        vector<int> L(v.begin(), v.begin() + mid);\n        vector<int> R(v.begin() + mid, v.end());\n\n        L = merge_sort_rec(L);\n        R = merge_sort_rec(R);\n\n        vector<int> res;\n        res.reserve(n);\n\n        int i = 0, j = 0;\n        while (i < (int)L.size() && j < (int)R.size()) {\n            if (heavier_single(L[i], R[j])) res.push_back(L[i++]);\n            else res.push_back(R[j++]);\n        }\n        while (i < (int)L.size()) res.push_back(L[i++]);\n        while (j < (int)R.size()) res.push_back(R[j++]);\n\n        return res;\n    }\n\n    void exact_sort_items() {\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        order = merge_sort_rec(order);\n    }\n\n    void approximate_sort_items(int targetQueries) {\n        targetQueries = min(targetQueries, Q);\n\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        vector<int> gaps;\n        for (int g = N / 2; g >= 1; g /= 2) {\n            gaps.push_back(g);\n            if (g == 1) break;\n        }\n\n        while (qm.used < targetQueries) {\n            bool anySwap = false;\n\n            for (int gap : gaps) {\n                for (int i = gap; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - gap];\n                    int b = order[i];\n\n                    char c = qm.query_single(a, b);\n                    if (c == '<') {\n                        swap(order[i - gap], order[i]);\n                        anySwap = true;\n                    }\n                }\n                if (qm.used >= targetQueries) break;\n            }\n\n            if (!anySwap) {\n                for (int i = 1; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - 1];\n                    int b = order[i];\n\n                    char c = qm.query_single(a, b);\n                    if (c == '<') swap(order[i - 1], order[i]);\n                }\n            }\n        }\n    }\n\n    void normalize_est() {\n        double s = 0.0;\n        for (double x : estWeight) s += x;\n        if (s <= 0.0) return;\n\n        double mul = (double)N / s;\n        for (double& x : estWeight) x *= mul;\n    }\n\n    void make_estimated_weights() {\n        estWeight.assign(N, 0.0);\n\n        vector<double> H(N + 1, 0.0);\n        for (int i = 1; i <= N; i++) H[i] = H[i - 1] + 1.0 / i;\n\n        double T = (double)N / (double)D;\n        double A = 1.0 - exp(-T);\n\n        for (int k = 0; k < N; k++) {\n            int item = order[k];\n\n            double untr = H[N] - H[k];\n\n            double p = ((double)N - (double)k - 0.5) / (double)N;\n            p = min(1.0 - 1e-12, max(1e-12, p));\n\n            double u = p * A;\n            u = min(1.0 - 1e-12, max(1e-12, u));\n\n            double trunc = -log(1.0 - u);\n\n            double alpha = 0.25;\n            if (D * 5 >= N) alpha = 0.40;\n\n            estWeight[item] = (1.0 - alpha) * untr + alpha * trunc;\n        }\n\n        normalize_est();\n    }\n\n    int compare_bins_by_est(int a, int b) const {\n        const double eps = 1e-12;\n        if (estSum[a] + eps < estSum[b]) return -1;\n        if (estSum[a] > estSum[b] + eps) return 1;\n        return 0;\n    }\n\n    int compare_bins(int a, int b, bool allowQuery = true) {\n        if (a == b) return 0;\n\n        if (allowQuery && qm.used < Q) {\n            char c = qm.query(bins[a], bins[b]);\n            if (c == '<') return -1;\n            if (c == '>') return 1;\n            return 0;\n        }\n\n        return compare_bins_by_est(a, b);\n    }\n\n    vector<int> sort_bins_est(vector<int> v) {\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            if (fabs(estSum[a] - estSum[b]) > 1e-12) return estSum[a] < estSum[b];\n            return a < b;\n        });\n        return v;\n    }\n\n    vector<int> sort_bins_with_queries_if_possible(vector<int> v) {\n        int lg = max(1, ceil_log2_int((int)v.size()));\n        int estimatedCost = (int)v.size() * lg;\n\n        if (qm.used + estimatedCost > Q) return sort_bins_est(v);\n\n        vector<int> res;\n        res.reserve(v.size());\n\n        for (int b : v) {\n            int lo = 0, hi = (int)res.size();\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int cmp = compare_bins(b, res[mid], true);\n                if (cmp <= 0) hi = mid;\n                else lo = mid + 1;\n            }\n            res.insert(res.begin() + lo, b);\n        }\n\n        return res;\n    }\n\n    void build_partition() {\n        bins.assign(D, {});\n        estSum.assign(D, 0.0);\n        answer.assign(N, 0);\n\n        for (int i = 0; i < D; i++) {\n            int item = order[i];\n            bins[i].push_back(item);\n            estSum[i] += estWeight[item];\n            answer[item] = i;\n        }\n\n        vector<int> binOrder(D);\n        iota(binOrder.begin(), binOrder.end(), 0);\n\n        if (qm.used < Q && Q - qm.used > D)\n            binOrder = sort_bins_with_queries_if_possible(binOrder);\n        else\n            binOrder = sort_bins_est(binOrder);\n\n        for (int idx = D; idx < N; idx++) {\n            int item = order[idx];\n\n            int b = binOrder.front();\n            binOrder.erase(binOrder.begin());\n\n            bins[b].push_back(item);\n            estSum[b] += estWeight[item];\n            answer[item] = b;\n\n            int lo = 0, hi = (int)binOrder.size();\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int cmp = compare_bins(b, binOrder[mid], true);\n                if (cmp <= 0) hi = mid;\n                else lo = mid + 1;\n            }\n            binOrder.insert(binOrder.begin() + lo, b);\n        }\n    }\n\n    int minmax_query_need() const {\n        if (D <= 1) return 0;\n        int need = 1;\n        int rem = D - 2;\n        need += (rem / 2) * 3;\n        if (rem % 2) need += 2;\n        return need;\n    }\n\n    bool find_min_max_bins(int& mn, int& mx) {\n        if (D == 1) {\n            mn = mx = 0;\n            return true;\n        }\n\n        if (qm.used + minmax_query_need() > Q) return false;\n\n        char c = qm.query(bins[0], bins[1]);\n        if (c == '<') {\n            mn = 0;\n            mx = 1;\n        } else if (c == '>') {\n            mn = 1;\n            mx = 0;\n        } else {\n            mn = 0;\n            mx = 0;\n        }\n\n        int i = 2;\n        for (; i + 1 < D; i += 2) {\n            int a = i, b = i + 1;\n            char p = qm.query(bins[a], bins[b]);\n\n            int small, large;\n            if (p == '<') {\n                small = a;\n                large = b;\n            } else if (p == '>') {\n                small = b;\n                large = a;\n            } else {\n                small = a;\n                large = a;\n            }\n\n            int c1 = compare_bins(small, mn, true);\n            if (c1 < 0) mn = small;\n\n            int c2 = compare_bins(large, mx, true);\n            if (c2 > 0) mx = large;\n        }\n\n        if (i < D) {\n            int b = i;\n            int c1 = compare_bins(b, mn, true);\n            if (c1 < 0) mn = b;\n\n            int c2 = compare_bins(b, mx, true);\n            if (c2 > 0) mx = b;\n        }\n\n        return true;\n    }\n\n    void do_move(int from, int to, int x) {\n        auto it = find(bins[from].begin(), bins[from].end(), x);\n        if (it != bins[from].end()) bins[from].erase(it);\n\n        bins[to].push_back(x);\n        estSum[from] -= estWeight[x];\n        estSum[to] += estWeight[x];\n        answer[x] = to;\n    }\n\n    void do_swap(int a, int b, int x, int y) {\n        auto itx = find(bins[a].begin(), bins[a].end(), x);\n        auto ity = find(bins[b].begin(), bins[b].end(), y);\n\n        if (itx != bins[a].end()) *itx = y;\n        if (ity != bins[b].end()) *ity = x;\n\n        estSum[a] += estWeight[y] - estWeight[x];\n        estSum[b] += estWeight[x] - estWeight[y];\n\n        answer[x] = b;\n        answer[y] = a;\n    }\n\n    bool try_safe_move(int lo, int hi) {\n        if ((int)bins[hi].size() <= 1) return false;\n\n        double diff = max(0.0, estSum[hi] - estSum[lo]);\n        double ideal = diff / 2.0;\n\n        vector<int> cand = bins[hi];\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            double da = fabs(estWeight[a] - ideal);\n            double db = fabs(estWeight[b] - ideal);\n            if (fabs(da - db) > 1e-12) return da < db;\n            return estWeight[a] > estWeight[b];\n        });\n\n        for (int x : cand) {\n            if (qm.used >= Q) break;\n            if ((int)bins[hi].size() <= 1) break;\n\n            vector<int> leftSet;\n            leftSet.reserve(bins[hi].size() - 1);\n            for (int y : bins[hi]) {\n                if (y != x) leftSet.push_back(y);\n            }\n\n            if (leftSet.empty()) continue;\n\n            // Verifies actual condition sum(hi)-sum(lo) > w[x].\n            char c = qm.query(leftSet, bins[lo]);\n\n            if (c == '>') {\n                do_move(hi, lo, x);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    bool try_safe_swap(int lo, int hi) {\n        if (qm.used + 2 > Q) return false;\n        if ((int)bins[hi].size() <= 1) return false;\n        if ((int)bins[lo].size() <= 1) return false;\n\n        vector<int> heavy = bins[hi];\n        vector<int> light = bins[lo];\n\n        sort(heavy.begin(), heavy.end(), [&](int a, int b) {\n            return estWeight[a] > estWeight[b];\n        });\n        sort(light.begin(), light.end(), [&](int a, int b) {\n            return estWeight[a] < estWeight[b];\n        });\n\n        int limitH = min<int>(6, heavy.size());\n        int limitL = min<int>(6, light.size());\n\n        struct Cand {\n            double score;\n            int x, y;\n        };\n        vector<Cand> cands;\n\n        double diff = max(0.0, estSum[hi] - estSum[lo]);\n        double ideal = diff / 2.0;\n\n        for (int i = 0; i < limitH; i++) {\n            for (int j = 0; j < limitL; j++) {\n                int x = heavy[i];\n                int y = light[j];\n\n                double delta = estWeight[x] - estWeight[y];\n                if (delta <= 1e-12) continue;\n\n                double score = fabs(delta - ideal);\n                cands.push_back({score, x, y});\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            return a.score < b.score;\n        });\n\n        for (auto [score, x, y] : cands) {\n            if (qm.used + 2 > Q) break;\n\n            char cy = qm.query_single(x, y);\n            if (cy != '>') continue;\n\n            vector<int> Lset, Rset;\n\n            for (int v : bins[hi]) {\n                if (v != x) Lset.push_back(v);\n            }\n            for (int v : bins[lo]) {\n                if (v != y) Rset.push_back(v);\n            }\n\n            if (Lset.empty() || Rset.empty()) continue;\n\n            // Verifies actual condition sum(hi)-sum(lo) > w[x]-w[y].\n            char c = qm.query(Lset, Rset);\n\n            if (c == '>') {\n                do_swap(hi, lo, x, y);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    void local_improve() {\n        int iteration = 0;\n\n        while (qm.used < Q && iteration < 10000) {\n            iteration++;\n\n            int lo, hi;\n            if (!find_min_max_bins(lo, hi)) break;\n            if (lo == hi) break;\n\n            bool changed = false;\n\n            if (!changed && (int)bins[hi].size() > 1) {\n                changed = try_safe_move(lo, hi);\n            }\n\n            if (!changed && qm.used + 2 <= Q) {\n                changed = try_safe_swap(lo, hi);\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    bool opportunistic_move_once() {\n        vector<int> desc(D), asc(D);\n        iota(desc.begin(), desc.end(), 0);\n        iota(asc.begin(), asc.end(), 0);\n\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            return estSum[a] > estSum[b];\n        });\n        sort(asc.begin(), asc.end(), [&](int a, int b) {\n            return estSum[a] < estSum[b];\n        });\n\n        int limH = min(D, 6);\n        int limL = min(D, 6);\n\n        struct MCand {\n            double score;\n            int hi, lo, x;\n        };\n        vector<MCand> cands;\n\n        for (int ih = 0; ih < limH; ih++) {\n            int hi = desc[ih];\n            if ((int)bins[hi].size() <= 1) continue;\n\n            for (int il = 0; il < limL; il++) {\n                int lo = asc[il];\n                if (hi == lo) continue;\n\n                double diff = estSum[hi] - estSum[lo];\n                if (diff <= 0.0) continue;\n\n                double ideal = diff / 2.0;\n\n                vector<int> items = bins[hi];\n                sort(items.begin(), items.end(), [&](int a, int b) {\n                    double da = fabs(estWeight[a] - ideal);\n                    double db = fabs(estWeight[b] - ideal);\n                    if (fabs(da - db) > 1e-12) return da < db;\n                    return estWeight[a] > estWeight[b];\n                });\n\n                int limI = min<int>(8, items.size());\n                for (int i = 0; i < limI; i++) {\n                    int x = items[i];\n                    double score = fabs(estWeight[x] - ideal);\n                    cands.push_back({score, hi, lo, x});\n                }\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const MCand& a, const MCand& b) {\n            return a.score < b.score;\n        });\n\n        for (auto [score, hi, lo, x] : cands) {\n            if (qm.used >= Q) break;\n            if (hi == lo) continue;\n            if ((int)bins[hi].size() <= 1) continue;\n\n            bool exists = false;\n            for (int v : bins[hi]) {\n                if (v == x) {\n                    exists = true;\n                    break;\n                }\n            }\n            if (!exists) continue;\n\n            vector<int> Lset;\n            Lset.reserve(bins[hi].size() - 1);\n            for (int v : bins[hi]) {\n                if (v != x) Lset.push_back(v);\n            }\n            if (Lset.empty()) continue;\n\n            char c = qm.query(Lset, bins[lo]);\n\n            if (c == '>') {\n                do_move(hi, lo, x);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    bool opportunistic_swap_once() {\n        if (qm.used + 2 > Q) return false;\n\n        vector<int> desc(D), asc(D);\n        iota(desc.begin(), desc.end(), 0);\n        iota(asc.begin(), asc.end(), 0);\n\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            return estSum[a] > estSum[b];\n        });\n        sort(asc.begin(), asc.end(), [&](int a, int b) {\n            return estSum[a] < estSum[b];\n        });\n\n        int limH = min(D, 5);\n        int limL = min(D, 5);\n\n        struct SCand {\n            double score;\n            int hi, lo, x, y;\n        };\n        vector<SCand> cands;\n\n        for (int ih = 0; ih < limH; ih++) {\n            int hi = desc[ih];\n            if ((int)bins[hi].size() <= 1) continue;\n\n            vector<int> heavy = bins[hi];\n            sort(heavy.begin(), heavy.end(), [&](int a, int b) {\n                return estWeight[a] > estWeight[b];\n            });\n            int hItems = min<int>(5, heavy.size());\n\n            for (int il = 0; il < limL; il++) {\n                int lo = asc[il];\n                if (hi == lo) continue;\n                if ((int)bins[lo].size() <= 1) continue;\n\n                vector<int> light = bins[lo];\n                sort(light.begin(), light.end(), [&](int a, int b) {\n                    return estWeight[a] < estWeight[b];\n                });\n                int lItems = min<int>(5, light.size());\n\n                double diff = estSum[hi] - estSum[lo];\n                if (diff <= 0.0) continue;\n                double ideal = diff / 2.0;\n\n                for (int i = 0; i < hItems; i++) {\n                    for (int j = 0; j < lItems; j++) {\n                        int x = heavy[i];\n                        int y = light[j];\n\n                        double delta = estWeight[x] - estWeight[y];\n                        if (delta <= 1e-12) continue;\n\n                        double score = fabs(delta - ideal);\n                        cands.push_back({score, hi, lo, x, y});\n                    }\n                }\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const SCand& a, const SCand& b) {\n            return a.score < b.score;\n        });\n\n        for (auto [score, hi, lo, x, y] : cands) {\n            if (qm.used + 2 > Q) break;\n            if (hi == lo) continue;\n            if ((int)bins[hi].size() <= 1 || (int)bins[lo].size() <= 1) continue;\n\n            bool ex = false, ey = false;\n            for (int v : bins[hi]) if (v == x) ex = true;\n            for (int v : bins[lo]) if (v == y) ey = true;\n            if (!ex || !ey) continue;\n\n            char cy = qm.query_single(x, y);\n            if (cy != '>') continue;\n\n            vector<int> Lset, Rset;\n            for (int v : bins[hi]) {\n                if (v != x) Lset.push_back(v);\n            }\n            for (int v : bins[lo]) {\n                if (v != y) Rset.push_back(v);\n            }\n\n            if (Lset.empty() || Rset.empty()) continue;\n\n            char c = qm.query(Lset, Rset);\n\n            if (c == '>') {\n                do_swap(hi, lo, x, y);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    void opportunistic_improve() {\n        int noChangeRounds = 0;\n\n        while (qm.used < Q && noChangeRounds < 3) {\n            bool changed = false;\n\n            if (!changed) changed = opportunistic_move_once();\n            if (!changed && qm.used + 2 <= Q) changed = opportunistic_swap_once();\n\n            if (changed) noChangeRounds = 0;\n            else noChangeRounds++;\n        }\n    }\n\n    void spend_remaining_queries() {\n        while (qm.used < Q) {\n            qm.query_single(0, 1);\n        }\n    }\n\n    void output_answer() {\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << answer[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n\n    void solve() {\n        int lgN = ceil_log2_int(N);\n        int mergeWorst = N * lgN - (1 << lgN) + 1;\n        mergeWorst = max(0, mergeWorst);\n\n        int lgD = max(1, ceil_log2_int(D));\n        int constructionCostApprox = max(0, N - D) * lgD + D * lgD;\n\n        // Reverted to the more stable policy from the previous better version.\n        bool useExactSort = false;\n        int neededAfterSort = max(D, constructionCostApprox / 3);\n        if (Q >= mergeWorst + neededAfterSort) useExactSort = true;\n\n        if (useExactSort) {\n            exact_sort_items();\n        } else {\n            int reserve = min(constructionCostApprox, (int)(Q * 0.40));\n            int target = max(0, Q - reserve);\n            approximate_sort_items(target);\n        }\n\n        make_estimated_weights();\n\n        build_partition();\n\n        if (qm.used < Q) {\n            local_improve();\n        }\n\n        if (qm.used < Q) {\n            opportunistic_improve();\n        }\n\n        spend_remaining_queries();\n\n        output_answer();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    cin >> N >> D >> Q;\n\n    Solver solver(N, D, Q);\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int v, to;\n};\n\nstruct Result {\n    vector<Op> ops;\n    int energy = INT_MAX;\n    bool valid = false;\n};\n\nstatic const int N = 200;\nstatic const int M = 10;\nstatic const int EMPTY_VAL = 1000;\n\nint seg_max(const vector<int>& a) {\n    int mx = 0;\n    for (int x : a) mx = max(mx, x);\n    return mx;\n}\n\nint stack_min_value(const vector<int>& st) {\n    if (st.empty()) return EMPTY_VAL;\n    int mn = EMPTY_VAL;\n    for (int x : st) mn = min(mn, x);\n    return mn;\n}\n\nint stack_badness(const vector<int>& st) {\n    int bad = 0;\n    for (int i = 1; i < (int)st.size(); i++) {\n        if (st[i - 1] < st[i]) bad += st[i] - st[i - 1];\n    }\n    return bad;\n}\n\nint segment_bad_pairs(const vector<int>& st, int l, int r) {\n    int bad = 0;\n    for (int i = l + 1; i < r; i++) {\n        if (st[i - 1] < st[i]) bad++;\n    }\n    return bad;\n}\n\nbool has_good_destination_top(const vector<vector<int>>& stacks, int src, const vector<int>& vals) {\n    int mx = seg_max(vals);\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n        if (stacks[d].empty()) return true;\n        if (stacks[d].back() > mx) return true;\n    }\n    return false;\n}\n\nint future_penalty_stack(const vector<int>& st, int cur, int W) {\n    int p = 0;\n    for (int x : st) {\n        if (x >= cur && x < cur + W) {\n            p += cur + W - x;\n        }\n    }\n    return p;\n}\n\nint future_min_stack(const vector<int>& st, int cur) {\n    int mn = EMPTY_VAL;\n    for (int x : st) {\n        if (x >= cur) mn = min(mn, x);\n    }\n    return mn;\n}\n\nint choose_destination(\n    const vector<vector<int>>& stacks,\n    int src,\n    const vector<int>& vals,\n    int policy,\n    int cur,\n    mt19937& rng,\n    double noise_amp\n) {\n    int p = policy % 32;\n    int mx = seg_max(vals);\n    int len = (int)vals.size();\n\n    uniform_real_distribution<double> dist(0.0, noise_amp);\n\n    int best = -1;\n    double best_score = 1e100;\n\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n\n        int h = (int)stacks[d].size();\n        bool empty = stacks[d].empty();\n\n        int top = empty ? EMPTY_VAL : stacks[d].back();\n        int mn = stack_min_value(stacks[d]);\n\n        bool good_top = empty || top > mx;\n        bool good_all = empty || mn > mx;\n\n        double score = 0.0;\n\n        switch (p) {\n            case 0:\n                if (good_top) score = top * 100.0 + h;\n                else score = 1e6 - top * 100.0 + h;\n                break;\n\n            case 1:\n                score = (good_top ? 0.0 : 100000.0) + h * 100.0 + top;\n                break;\n\n            case 2:\n                if (good_all) score = mn * 100.0 + h;\n                else if (good_top) score = 200000.0 + top * 100.0 + h;\n                else score = 1e6 - mn * 50.0 - top * 10.0 + h;\n                break;\n\n            case 3:\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0;\n                else score = 1e6 + (mx - top) * 100.0 + h;\n                break;\n\n            case 4:\n                score = h * 100.0 + (good_top ? 0.0 : 50000.0) + top;\n                break;\n\n            case 5:\n                if (good_top) score = top * 100.0 - h * 20.0;\n                else score = 1e6 - top * 100.0 - h * 10.0;\n                break;\n\n            case 6:\n                score = (good_top ? 0.0 : 500000.0) - top * 100.0 + h * 10.0;\n                break;\n\n            case 7:\n                score = (good_top ? 0.0 : 300000.0) - mn * 100.0 - top * 10.0 + h;\n                break;\n\n            case 8:\n                if (good_top) score = (top - mx) * 200.0 + h;\n                else score = 1e6 + (mx - top) * 200.0 + h;\n                break;\n\n            case 9:\n                if (good_top) score = top * 100.0 + h * 20.0 + stack_badness(stacks[d]) * 2.0;\n                else score = 1e6 - top * 100.0 + h * 20.0 + stack_badness(stacks[d]) * 2.0;\n                break;\n\n            case 10:\n                if (empty) {\n                    score = 50000.0 + h;\n                } else {\n                    int violation = max(0, mx - top);\n                    score = violation * 10000.0 + (good_top ? top : -top) * 10.0 + h;\n                }\n                break;\n\n            case 11:\n                if (empty) {\n                    score = good_top ? 150000.0 : 1000000.0;\n                } else if (good_top) {\n                    score = (top - mx) * 100.0 + h * 3.0;\n                } else {\n                    score = 1e6 - top * 200.0 + h;\n                }\n                break;\n\n            case 12:\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0 - len * 20.0;\n                else score = 1e6 + (mx - top) * 100.0 + h - len * 20.0;\n                break;\n\n            case 13:\n                if (empty) score = 10000.0 + h;\n                else {\n                    int add = max(0, mx - top);\n                    score = add * 20000.0 + abs(top - mx) * 20.0 + h;\n                }\n                break;\n\n            case 14:\n                if (good_top) score = (top - mx) * 150.0 + h * 12.0 + stack_badness(stacks[d]);\n                else score = 1e6 + (mx - top) * 300.0 - h * 5.0;\n                break;\n\n            case 15:\n                if (good_top) score = (top - mx) * 80.0 - mn * 20.0 + h * 10.0;\n                else score = 1e6 - top * 120.0 - mn * 20.0 + h;\n                break;\n\n            case 16:\n                if (empty) score = 80000.0 - len * 500.0;\n                else if (good_top) score = (top - mx) * 120.0 + h;\n                else score = 1e6 - top * 100.0 + h;\n                break;\n\n            case 17:\n                if (empty) score = 20000.0 - mx * 50.0 - len * 200.0;\n                else if (good_top) score = (top - mx) * 100.0 + h * 8.0;\n                else score = 1e6 + (mx - top) * 100.0 + h;\n                break;\n\n            case 18:\n                if (good_top) score = (top - mx) * 100.0 + h * 4.0 - stack_badness(stacks[d]) * 3.0;\n                else score = 1e6 - top * 100.0 - stack_badness(stacks[d]) * 5.0;\n                break;\n\n            case 19:\n                if (good_top) score = (top - mx) * 120.0 + stack_badness(stacks[d]) * 8.0 + h;\n                else score = 1e6 - top * 150.0 + h;\n                break;\n\n            case 20: {\n                int f20 = future_penalty_stack(stacks[d], cur, 20);\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0 + f20 * len * 35.0;\n                else score = 1e6 + (mx - top) * 150.0 + f20 * len * 25.0;\n                break;\n            }\n\n            case 21: {\n                int f40 = future_penalty_stack(stacks[d], cur, 40);\n                if (empty) score = 20000.0 - len * 300.0;\n                else if (good_top) score = (top - mx) * 80.0 + f40 * len * 18.0 + h;\n                else score = 1e6 - top * 100.0 + f40 * len * 15.0;\n                break;\n            }\n\n            case 22: {\n                int f20 = future_penalty_stack(stacks[d], cur, 20);\n                int fmin = future_min_stack(stacks[d], cur);\n                if (good_top) score = (top - mx) * 90.0 - fmin * 8.0 + f20 * 120.0 + h;\n                else score = 1e6 + (mx - top) * 120.0 - fmin * 5.0 + f20 * 80.0;\n                break;\n            }\n\n            case 23: {\n                int f20 = future_penalty_stack(stacks[d], cur, 20);\n                int f40 = future_penalty_stack(stacks[d], cur, 40);\n                if (good_all) score = (mn - mx) * 70.0 + h * 4.0;\n                else if (good_top) score = 50000.0 + (top - mx) * 70.0 + f40 * len * 20.0;\n                else score = 1e6 + (mx - top) * 200.0 + f20 * len * 30.0;\n                break;\n            }\n\n            case 24: {\n                int f20 = future_penalty_stack(stacks[d], cur, 20);\n                if (empty) score = 15000.0 - len * 250.0;\n                else if (good_top) score = (top - mx) * 110.0 + f20 * len * 45.0 + h;\n                else score = 1e6 - top * 100.0 + f20 * len * 30.0;\n                break;\n            }\n\n            case 25: {\n                int f40 = future_penalty_stack(stacks[d], cur, 40);\n                if (good_top) score = (top - mx) * 70.0 - mn * 12.0 + f40 * len * 12.0 + h;\n                else score = 1e6 - top * 100.0 - mn * 10.0 + f40 * len * 10.0;\n                break;\n            }\n\n            case 26: {\n                int fmin = future_min_stack(stacks[d], cur);\n                int f20 = future_penalty_stack(stacks[d], cur, 20);\n                if (good_top) {\n                    int urgent = max(0, cur + 15 - fmin);\n                    score = (top - mx) * 100.0 + urgent * len * 300.0 + h;\n                } else {\n                    score = 1e6 + (mx - top) * 200.0 + f20 * len * 40.0;\n                }\n                break;\n            }\n\n            case 27: {\n                int f20 = future_penalty_stack(stacks[d], cur, 20);\n                if (empty) score = 30000.0 - len * 600.0;\n                else if (good_top) score = (top - mx) * 60.0 + f20 * len * 60.0 - h * 5.0;\n                else score = 1e6 + (mx - top) * 150.0 + f20 * len * 40.0;\n                break;\n            }\n\n            case 28: {\n                int f25 = future_penalty_stack(stacks[d], cur, 25);\n                int bad = stack_badness(stacks[d]);\n                if (good_top) score = (top - mx) * 85.0 + f25 * len * 32.0 + bad * 4.0 + h;\n                else score = 1e6 + (mx - top) * 170.0 + f25 * len * 25.0 - bad * 2.0;\n                break;\n            }\n\n            case 29: {\n                int fmin = future_min_stack(stacks[d], cur);\n                int urgent = max(0, cur + 25 - fmin);\n                if (empty) score = 25000.0 - len * 350.0;\n                else if (good_top) score = (top - mx) * 75.0 + urgent * len * 180.0 + h * 3.0;\n                else score = 1e6 + (mx - top) * 180.0 + urgent * len * 120.0;\n                break;\n            }\n\n            case 30: {\n                int f35 = future_penalty_stack(stacks[d], cur, 35);\n                if (good_all) score = (mn - mx) * 45.0 + f35 * len * 8.0 + h;\n                else if (good_top) score = 40000.0 + (top - mx) * 65.0 + f35 * len * 16.0;\n                else score = 1e6 - top * 100.0 + f35 * len * 14.0;\n                break;\n            }\n\n            case 31: {\n                int f20 = future_penalty_stack(stacks[d], cur, 20);\n                int bad = stack_badness(stacks[d]);\n                if (empty) score = 18000.0 - len * 450.0;\n                else if (good_top) score = (top - mx) * 55.0 + f20 * len * 70.0 - bad * 4.0 - h * 3.0;\n                else score = 1e6 + (mx - top) * 130.0 + f20 * len * 40.0 - bad * 5.0;\n                break;\n            }\n        }\n\n        if (noise_amp > 0.0) score += dist(rng);\n\n        if (score < best_score) {\n            best_score = score;\n            best = d;\n        }\n    }\n\n    return best;\n}\n\nint choose_left_index(\n    const vector<vector<int>>& stacks,\n    int s,\n    int pos,\n    int split_mode\n) {\n    const auto& st = stacks[s];\n    int h = (int)st.size();\n\n    if (split_mode == 0) return pos + 1;\n    if (split_mode == 2) return h - 1;\n\n    int run_start = h - 1;\n    while (run_start - 1 > pos && st[run_start - 1] > st[run_start]) {\n        run_start--;\n    }\n\n    if (split_mode == 1) return run_start;\n\n    auto suffix_vals = [&](int l) {\n        return vector<int>(st.begin() + l, st.end());\n    };\n\n    if (split_mode == 3) {\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            if (has_good_destination_top(stacks, s, vals)) return l;\n        }\n        return run_start;\n    }\n\n    if (split_mode == 4) {\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            if (has_good_destination_top(stacks, s, vals)) return l;\n        }\n        return pos + 1;\n    }\n\n    if (split_mode == 5) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = run_start; l <= h - 1; l++) {\n            vector<int> vals = suffix_vals(l);\n            bool good = has_good_destination_top(stacks, s, vals);\n            int len = h - l;\n            int mx = seg_max(vals);\n\n            double score = (good ? 0.0 : 100000.0 + mx * 10.0) - len * 120.0;\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 6) {\n        vector<int> vals = suffix_vals(run_start);\n        if (has_good_destination_top(stacks, s, vals)) return run_start;\n\n        vector<int> one = suffix_vals(h - 1);\n        if (has_good_destination_top(stacks, s, one)) return h - 1;\n\n        return run_start;\n    }\n\n    if (split_mode == 7) {\n        int best_l = pos + 1;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            vector<int> vals = suffix_vals(l);\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            int mx = seg_max(vals);\n            bool good = has_good_destination_top(stacks, s, vals);\n\n            double score = bad * 550.0 + (good ? 0.0 : 5000.0) - len * 80.0 + mx * 0.03;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 8) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            vector<int> vals = suffix_vals(l);\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            bool good = has_good_destination_top(stacks, s, vals);\n\n            double score = (good ? 0.0 : 8000.0) + bad * 1000.0 - len * 45.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 9) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            vector<int> vals = suffix_vals(l);\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            bool good = has_good_destination_top(stacks, s, vals);\n\n            double score = (good ? 0.0 : 3000.0) + bad * 700.0 - len * 100.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 10) {\n        for (int l = h - 1; l >= run_start; l--) {\n            vector<int> vals = suffix_vals(l);\n            if (has_good_destination_top(stacks, s, vals)) return l;\n        }\n        return h - 1;\n    }\n\n    if (split_mode == 11) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = run_start; l < h; l++) {\n            vector<int> vals = suffix_vals(l);\n            int len = h - l;\n            int mx = seg_max(vals);\n            bool good = has_good_destination_top(stacks, s, vals);\n\n            double score = (good ? 0.0 : 20000.0) + mx * 2.0 + len * 18.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 12) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = run_start; l < h; l++) {\n            vector<int> vals = suffix_vals(l);\n            int len = h - l;\n            bool good = has_good_destination_top(stacks, s, vals);\n            int mx = seg_max(vals);\n\n            double score = (good ? 0.0 : 15000.0) + abs(len - 4) * 90.0 + mx * 0.5;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 13) {\n        vector<int> vals = suffix_vals(run_start);\n        if (has_good_destination_top(stacks, s, vals)) return run_start;\n\n        for (int l = run_start + 1; l < h; l++) {\n            vector<int> v2 = suffix_vals(l);\n            if (has_good_destination_top(stacks, s, v2)) return l;\n        }\n\n        return h - 1;\n    }\n\n    if (split_mode == 14) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            vector<int> vals = suffix_vals(l);\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            int mx = seg_max(vals);\n            bool good = has_good_destination_top(stacks, s, vals);\n\n            double score = bad * 850.0 + (good ? 0.0 : 12000.0)\n                         + abs(len - 3) * 70.0 + mx * 0.8;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 15) {\n        int best_l = h - 1;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            vector<int> vals = suffix_vals(l);\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            bool good = has_good_destination_top(stacks, s, vals);\n\n            double score = (good ? -200.0 : 5000.0) + bad * 1200.0 - len * 30.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    return run_start;\n}\n\nResult simulate(\n    const vector<vector<int>>& initial,\n    int split_mode,\n    int policy,\n    uint32_t seed,\n    double noise_amp\n) {\n    mt19937 rng(seed);\n\n    vector<vector<int>> stacks = initial;\n    vector<Op> ops;\n    int energy = 0;\n\n    for (int cur = 1; cur <= N; cur++) {\n        int s = -1, pos = -1;\n\n        for (int i = 0; i < M; i++) {\n            for (int j = 0; j < (int)stacks[i].size(); j++) {\n                if (stacks[i][j] == cur) {\n                    s = i;\n                    pos = j;\n                }\n            }\n        }\n\n        if (s == -1) return Result{};\n\n        while (pos != (int)stacks[s].size() - 1) {\n            if ((int)ops.size() >= 5000) return Result{};\n\n            int h = (int)stacks[s].size();\n\n            int l;\n            if ((int)ops.size() > 4600) {\n                l = pos + 1;\n            } else {\n                l = choose_left_index(stacks, s, pos, split_mode);\n            }\n\n            if (l <= pos || l >= h) return Result{};\n\n            vector<int> vals(stacks[s].begin() + l, stacks[s].end());\n\n            int d = choose_destination(stacks, s, vals, policy, cur, rng, noise_amp);\n            if (d < 0 || d == s) return Result{};\n\n            ops.push_back({vals.front(), d + 1});\n            energy += (int)vals.size() + 1;\n\n            stacks[s].erase(stacks[s].begin() + l, stacks[s].end());\n            stacks[d].insert(stacks[d].end(), vals.begin(), vals.end());\n\n            if ((int)ops.size() > 5000) return Result{};\n        }\n\n        if (stacks[s].empty() || stacks[s].back() != cur) {\n            return Result{};\n        }\n\n        ops.push_back({cur, 0});\n        stacks[s].pop_back();\n\n        if ((int)ops.size() > 5000) return Result{};\n    }\n\n    Result res;\n    res.ops = move(ops);\n    res.energy = energy;\n    res.valid = true;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> initial(M);\n\n    for (int i = 0; i < M; i++) {\n        initial[i].resize(N / M);\n        for (int j = 0; j < N / M; j++) {\n            cin >> initial[i][j];\n        }\n    }\n\n    uint32_t base_seed = 123456789u;\n    for (int i = 0; i < M; i++) {\n        for (int x : initial[i]) {\n            base_seed = base_seed * 1000003u + (uint32_t)x;\n        }\n    }\n\n    Result best;\n\n    auto try_result = [&](const Result& r) {\n        if (!r.valid) return;\n        if ((int)r.ops.size() > 5000) return;\n\n        if (!best.valid ||\n            r.energy < best.energy ||\n            (r.energy == best.energy && r.ops.size() < best.ops.size())) {\n            best = r;\n        }\n    };\n\n    auto start_time = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    // Strong deterministic baseline.\n    for (int split = 0; split <= 6; split++) {\n        for (int policy = 0; policy < 14; policy++) {\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + split * 1009u + policy * 9176u,\n                0.0\n            );\n            try_result(r);\n        }\n    }\n\n    mt19937 rng(base_seed ^ 0x9e3779b9u);\n\n    // Strong randomized baseline.\n    int iter = 0;\n    while (elapsed() <= 1.80) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 10) split = 0;\n        else if (sr < 35) split = 1;\n        else if (sr < 45) split = 2;\n        else if (sr < 70) split = 3;\n        else if (sr < 82) split = 4;\n        else if (sr < 94) split = 5;\n        else split = 6;\n\n        int policy = rng() % 14;\n\n        double noise;\n        int nr = rng() % 7;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 3.0;\n        else if (nr == 2) noise = 10.0;\n        else if (nr == 3) noise = 30.0;\n        else if (nr == 4) noise = 100.0;\n        else if (nr == 5) noise = 400.0;\n        else noise = 1500.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 1000003u + (uint32_t)iter * 17777u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    // Previous successful extra deterministic variants.\n    bool stop_det = false;\n    for (int split = 7; split <= 9 && !stop_det; split++) {\n        for (int policy = 0; policy < 20; policy++) {\n            if (elapsed() > 1.86) {\n                stop_det = true;\n                break;\n            }\n\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + 777777u + split * 2003u + policy * 10007u,\n                0.0\n            );\n            try_result(r);\n        }\n    }\n\n    // Previous successful extra randomized variants.\n    while (elapsed() <= 1.88) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 8) split = 0;\n        else if (sr < 22) split = 1;\n        else if (sr < 30) split = 2;\n        else if (sr < 45) split = 3;\n        else if (sr < 55) split = 4;\n        else if (sr < 65) split = 5;\n        else if (sr < 72) split = 6;\n        else if (sr < 84) split = 7;\n        else if (sr < 94) split = 8;\n        else split = 9;\n\n        int policy = rng() % 20;\n\n        double noise;\n        int nr = rng() % 8;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 2.0;\n        else if (nr == 2) noise = 8.0;\n        else if (nr == 3) noise = 25.0;\n        else if (nr == 4) noise = 80.0;\n        else if (nr == 5) noise = 250.0;\n        else if (nr == 6) noise = 800.0;\n        else noise = 2000.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 3000001u + (uint32_t)iter * 31417u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    // Late future-aware extras.\n    bool stop_future_det = false;\n    for (int split = 0; split <= 13 && !stop_future_det; split++) {\n        for (int policy = 20; policy < 28; policy++) {\n            if (elapsed() > 1.905) {\n                stop_future_det = true;\n                break;\n            }\n\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + 9876543u + split * 1237u + policy * 7919u,\n                0.0\n            );\n            try_result(r);\n        }\n    }\n\n    while (elapsed() <= 1.92) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 7) split = 0;\n        else if (sr < 18) split = 1;\n        else if (sr < 25) split = 2;\n        else if (sr < 38) split = 3;\n        else if (sr < 48) split = 4;\n        else if (sr < 58) split = 5;\n        else if (sr < 65) split = 6;\n        else if (sr < 73) split = 7;\n        else if (sr < 80) split = 8;\n        else if (sr < 86) split = 9;\n        else if (sr < 91) split = 10;\n        else if (sr < 95) split = 11;\n        else if (sr < 98) split = 12;\n        else split = 13;\n\n        int policy = 20 + (rng() % 8);\n\n        double noise;\n        int nr = rng() % 6;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 5.0;\n        else if (nr == 2) noise = 20.0;\n        else if (nr == 3) noise = 80.0;\n        else if (nr == 4) noise = 300.0;\n        else noise = 1000.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 5555555u + (uint32_t)iter * 27183u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    // New very late experimental variants.\n    while (elapsed() <= 1.94) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 8) split = 3;\n        else if (sr < 18) split = 5;\n        else if (sr < 28) split = 7;\n        else if (sr < 40) split = 8;\n        else if (sr < 52) split = 9;\n        else if (sr < 62) split = 10;\n        else if (sr < 72) split = 11;\n        else if (sr < 82) split = 12;\n        else if (sr < 90) split = 13;\n        else if (sr < 96) split = 14;\n        else split = 15;\n\n        int policy = 20 + (rng() % 12);\n\n        double noise;\n        int nr = rng() % 7;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 3.0;\n        else if (nr == 2) noise = 12.0;\n        else if (nr == 3) noise = 40.0;\n        else if (nr == 4) noise = 120.0;\n        else if (nr == 5) noise = 400.0;\n        else noise = 1200.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 24681357u + (uint32_t)iter * 19249u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    if (!best.valid) {\n        best = simulate(initial, 0, 0, base_seed, 0.0);\n    }\n\n    for (const auto& op : best.ops) {\n        cout << op.v << ' ' << op.to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const uint16_t INF16 = 65535;\n\nstruct Edge {\n    int to;\n    char c;\n};\n\nstruct XorShift {\n    uint32_t x = 2463534242u;\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    double real01() {\n        return (next() >> 8) * (1.0 / 16777216.0);\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    int N;\n    cin >> N;\n\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    int V = N * N;\n    vector<int> dirt(V);\n    long long sumD = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> dirt[i * N + j];\n            sumD += dirt[i * N + j];\n        }\n    }\n\n    double avgD = (double)sumD / V;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    vector<vector<Edge>> g(V);\n\n    auto add_edge = [&](int a, int b, char c1, char c2) {\n        g[a].push_back({b, c1});\n        g[b].push_back({a, c2});\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (i + 1 < N && h[i][j] == '0') {\n                add_edge(id(i, j), id(i + 1, j), 'D', 'U');\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                add_edge(id(i, j), id(i, j + 1), 'R', 'L');\n            }\n        }\n    }\n\n    auto rev_dir = [&](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    // Guaranteed legal fallback.\n    auto make_fallback_dfs = [&]() {\n        vector<char> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n            for (const auto &e : g[cur]) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n                    route.push_back(rev_dir(e.c));\n                }\n            }\n        };\n\n        dfs(0);\n        return route;\n    };\n\n    string fallbackRoute = make_fallback_dfs();\n\n    auto legal_route = [&](const string &route) -> bool {\n        if (route.empty() || route.size() > 100000) return false;\n\n        vector<char> vis(V, 0);\n        int cur = 0;\n        vis[0] = 1;\n\n        for (char c : route) {\n            bool ok = false;\n            for (const auto &e : g[cur]) {\n                if (e.c == c) {\n                    cur = e.to;\n                    ok = true;\n                    break;\n                }\n            }\n            if (!ok) return false;\n            vis[cur] = 1;\n        }\n\n        if (cur != 0) return false;\n\n        for (int i = 0; i < V; i++) {\n            if (!vis[i]) return false;\n        }\n\n        return true;\n    };\n\n    // All-pairs shortest paths.\n    vector<uint16_t> dist((size_t)V * V, INF16);\n    vector<int> que(V);\n\n    for (int s = 0; s < V; s++) {\n        uint16_t *ds = &dist[(size_t)s * V];\n        int head = 0, tail = 0;\n        ds[s] = 0;\n        que[tail++] = s;\n\n        while (head < tail) {\n            int cur = que[head++];\n            uint16_t nd = ds[cur] + 1;\n\n            for (const auto &e : g[cur]) {\n                if (ds[e.to] == INF16) {\n                    ds[e.to] = nd;\n                    que[tail++] = e.to;\n                }\n            }\n        }\n    }\n\n    int maxDist = 0;\n    for (int i = 0; i < V; i++) {\n        for (int j = 0; j < V; j++) {\n            maxDist = max(maxDist, (int)dist[(size_t)i * V + j]);\n        }\n    }\n\n    vector<double> alphas = {1.0, 1.35, 1.7, 2.1, 2.7, 3.5};\n    vector<vector<double>> denom(alphas.size(), vector<double>(maxDist + 3));\n\n    for (int a = 0; a < (int)alphas.size(); a++) {\n        for (int d = 0; d <= maxDist + 2; d++) {\n            denom[a][d] = pow((double)max(1, d), alphas[a]);\n        }\n    }\n\n    auto score_route = [&](const string &route) -> long double {\n        int L = (int)route.size();\n        if (L <= 0 || L > 100000) return 1e100L;\n\n        vector<int> first(V, -1), prev(V, -1);\n        vector<long long> gapSum(V, 0);\n\n        auto visit = [&](int x, int t) {\n            if (first[x] == -1) {\n                first[x] = prev[x] = t;\n            } else {\n                long long gap = t - prev[x];\n                gapSum[x] += gap * (gap - 1);\n                prev[x] = t;\n            }\n        };\n\n        int cur = 0;\n        visit(0, 0);\n\n        for (int t = 1; t <= L; t++) {\n            char c = route[t - 1];\n            bool ok = false;\n\n            for (const auto &e : g[cur]) {\n                if (e.c == c) {\n                    cur = e.to;\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return 1e100L;\n\n            if (t < L) {\n                visit(cur, t);\n            }\n        }\n\n        if (cur != 0) return 1e100L;\n\n        long double total = 0.0L;\n\n        for (int x = 0; x < V; x++) {\n            if (first[x] == -1) return 1e100L;\n\n            long long gap = L - prev[x] + first[x];\n            long long s = gapSum[x] + gap * (gap - 1);\n\n            total += (long double)dirt[x] * (long double)s / (2.0L * L);\n        }\n\n        return total;\n    };\n\n    string bestRoute = fallbackRoute;\n    long double bestScore = score_route(bestRoute);\n\n    auto consider = [&](const string &route) {\n        if (route.empty() || route.size() > 100000) return;\n        if (!legal_route(route)) return;\n\n        long double sc = score_route(route);\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n        }\n    };\n\n    XorShift rng;\n\n    // ------------------------------------------------------------------\n    // DFS candidates.\n    // ------------------------------------------------------------------\n    auto make_dfs_route = [&](int mode, double rndWeight) {\n        vector<char> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n\n            vector<Edge> es = g[cur];\n\n            if (mode == 1) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] > dirt[b.to];\n                });\n            } else if (mode == 2) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] < dirt[b.to];\n                });\n            } else if (mode == 3) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return a.c < b.c;\n                });\n            } else if (mode == 4) {\n                // Safe randomized ordering: keys are generated before sorting.\n                vector<pair<double, Edge>> keyed;\n                keyed.reserve(es.size());\n\n                for (const auto &e : es) {\n                    double key = log(1.0 + dirt[e.to]) + rndWeight * rng.real01();\n                    keyed.push_back({-key, e});\n                }\n\n                sort(keyed.begin(), keyed.end(), [](const auto &a, const auto &b) {\n                    return a.first < b.first;\n                });\n\n                es.clear();\n                for (const auto &p : keyed) es.push_back(p.second);\n            }\n\n            for (const auto &e : es) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n                    route.push_back(rev_dir(e.c));\n                }\n            }\n        };\n\n        dfs(0);\n        return route;\n    };\n\n    for (int mode = 0; mode < 4; mode++) {\n        consider(make_dfs_route(mode, 0.0));\n    }\n\n    for (int rep = 0; rep < 60 && elapsed() < 0.35; rep++) {\n        consider(make_dfs_route(4, 0.5 + 4.0 * rng.real01()));\n    }\n\n    // ------------------------------------------------------------------\n    // Shortest path appender.\n    // ------------------------------------------------------------------\n    auto append_path = [&](string &route,\n                           int &cur,\n                           int target,\n                           int &t,\n                           vector<int> &last,\n                           vector<char> &visited,\n                           int &visitedCnt) {\n        while (cur != target) {\n            uint16_t dc = dist[(size_t)cur * V + target];\n\n            int bestNext = -1;\n            char bestChar = '?';\n            double bestVal = -1e100;\n\n            for (const auto &e : g[cur]) {\n                if (dist[(size_t)e.to * V + target] + 1 == dc) {\n                    double val = 0.0;\n\n                    if (!visited[e.to]) {\n                        val += avgD * 1000000.0;\n                    }\n\n                    val += (double)dirt[e.to] * (double)(t - last[e.to] + 1);\n                    val += 0.001 * rng.real01();\n\n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestNext = e.to;\n                        bestChar = e.c;\n                    }\n                }\n            }\n\n            if (bestNext == -1) return;\n\n            route.push_back(bestChar);\n            cur = bestNext;\n            t++;\n\n            last[cur] = t;\n\n            if (!visited[cur]) {\n                visited[cur] = 1;\n                visitedCnt++;\n            }\n\n            if ((int)route.size() > 100000) return;\n        }\n    };\n\n    // ------------------------------------------------------------------\n    // Coverage first, then patrol candidates.\n    // ------------------------------------------------------------------\n    auto generate_cover_then_patrol = [&](int cap,\n                                          int covAlphaIdx,\n                                          int patAlphaIdx,\n                                          double coverBiasMul,\n                                          bool noise) {\n        string route;\n        route.reserve(min(100000, max(cap, 2 * V)));\n\n        vector<int> last(V, 0);\n        vector<char> visited(V, 0);\n\n        int visitedCnt = 1;\n        int cur = 0;\n        int t = 0;\n\n        visited[0] = 1;\n\n        double coverBias = avgD * coverBiasMul;\n\n        while (visitedCnt < V && (int)route.size() <= 100000) {\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                if (visited[x]) continue;\n\n                int ds = dist[(size_t)cur * V + x];\n                double val = (coverBias + dirt[x]) / denom[covAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n\n            if ((int)route.size() > 100000) break;\n        }\n\n        int limit = cap;\n        if (limit <= 0) limit = (int)route.size();\n        limit = min(limit, 100000);\n\n        int loop = 0;\n\n        while ((int)route.size() + dist[(size_t)cur * V + 0] < limit &&\n               (int)route.size() < 100000) {\n            if ((++loop & 255) == 0 && elapsed() > 1.82) break;\n\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                int ds = dist[(size_t)cur * V + x];\n                if (ds == 0) continue;\n\n                int ret = dist[(size_t)x * V + 0];\n\n                if ((int)route.size() + ds + ret > limit) continue;\n\n                int age = t - last[x];\n\n                double val = (double)dirt[x] * (age + 1) / denom[patAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n        }\n\n        append_path(route, cur, 0, t, last, visited, visitedCnt);\n\n        return route;\n    };\n\n    // ------------------------------------------------------------------\n    // Mixed candidates: sometimes revisit before complete coverage.\n    // ------------------------------------------------------------------\n    auto generate_mixed = [&](int cap,\n                              int alphaIdx,\n                              double unvisitedWeight,\n                              int betaMode,\n                              double forceRatio,\n                              int minPatrolDist,\n                              bool noise) {\n        string route;\n        route.reserve(min(100000, max(cap, 2 * V)));\n\n        vector<int> last(V, 0);\n        vector<char> visited(V, 0);\n\n        int visitedCnt = 1;\n        int cur = 0;\n        int t = 0;\n\n        visited[0] = 1;\n\n        int hardLimit = min(100000, cap);\n        if (hardLimit <= 0) hardLimit = 100000;\n\n        int loop = 0;\n\n        while ((int)route.size() < hardLimit) {\n            if ((++loop & 127) == 0 && elapsed() > 1.84) break;\n\n            int retNow = dist[(size_t)cur * V + 0];\n            if ((int)route.size() + retNow >= hardLimit) break;\n\n            bool forceCover = false;\n            if (visitedCnt < V && (int)route.size() > (int)(hardLimit * forceRatio)) {\n                forceCover = true;\n            }\n\n            int target = -1;\n            double bestVal = -1e100;\n\n            for (int x = 0; x < V; x++) {\n                if (x == cur) continue;\n\n                if (forceCover && visited[x]) continue;\n\n                int ds = dist[(size_t)cur * V + x];\n                int ret = dist[(size_t)x * V + 0];\n\n                if ((int)route.size() + ds + ret > hardLimit) continue;\n\n                if (visitedCnt == V && ds < minPatrolDist) continue;\n\n                int age = t - last[x];\n                double a = age + ds + 1.0;\n\n                double val;\n\n                if (betaMode == 2) {\n                    val = (double)dirt[x] * a * a / denom[alphaIdx][ds + 1];\n                } else {\n                    val = (double)dirt[x] * a / denom[alphaIdx][ds + 1];\n                }\n\n                if (!visited[x]) {\n                    double remainRatio = (double)V / max(1, V - visitedCnt);\n                    val += unvisitedWeight * avgD * remainRatio * (t + 50.0) / denom[alphaIdx][ds + 1];\n                }\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) {\n                if (visitedCnt == V && minPatrolDist > 1) {\n                    minPatrolDist = 1;\n                    continue;\n                }\n                break;\n            }\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n\n            if ((int)route.size() > 100000) break;\n        }\n\n        append_path(route, cur, 0, t, last, visited, visitedCnt);\n\n        return route;\n    };\n\n    vector<int> caps = {\n        2 * V,\n        3 * V,\n        4 * V,\n        5 * V,\n        7 * V,\n        10 * V,\n        14 * V,\n        20000,\n        30000,\n        45000,\n        65000,\n        100000\n    };\n\n    for (int &x : caps) {\n        x = min(100000, max(1, x));\n    }\n\n    sort(caps.begin(), caps.end());\n    caps.erase(unique(caps.begin(), caps.end()), caps.end());\n\n    struct CP {\n        int cap;\n        int ca;\n        int pa;\n        double bias;\n        bool noise;\n    };\n\n    vector<CP> cps;\n\n    cps.push_back({0, 4, 1, 20.0, false});\n    cps.push_back({0, 3, 1, 20.0, false});\n    cps.push_back({0, 3, 1, 5.0, false});\n    cps.push_back({0, 2, 1, 0.0, false});\n\n    for (int cap : caps) {\n        cps.push_back({cap, 3, 1, 10.0, false});\n        cps.push_back({cap, 2, 1, 5.0, false});\n    }\n\n    cps.push_back({30000, 3, 0, 10.0, false});\n    cps.push_back({60000, 3, 0, 10.0, false});\n    cps.push_back({100000, 3, 0, 10.0, false});\n    cps.push_back({60000, 3, 1, 10.0, true});\n    cps.push_back({100000, 3, 1, 10.0, true});\n\n    for (const auto &p : cps) {\n        if (elapsed() > 1.70) break;\n        consider(generate_cover_then_patrol(p.cap, p.ca, p.pa, p.bias, p.noise));\n    }\n\n    struct MP {\n        int cap;\n        int alpha;\n        double uw;\n        int beta;\n        double forceRatio;\n        int minDist;\n        bool noise;\n    };\n\n    vector<MP> mps;\n\n    for (int cap : caps) {\n        mps.push_back({cap, 2, 25.0, 1, 0.55, 3, false});\n        mps.push_back({cap, 2, 40.0, 1, 0.65, 4, false});\n    }\n\n    mps.push_back({30000, 1, 20.0, 2, 0.60, 3, false});\n    mps.push_back({45000, 1, 20.0, 2, 0.60, 4, false});\n    mps.push_back({65000, 1, 20.0, 2, 0.65, 5, false});\n    mps.push_back({100000, 1, 15.0, 2, 0.70, 6, false});\n\n    mps.push_back({30000, 2, 30.0, 1, 0.60, 3, true});\n    mps.push_back({65000, 2, 30.0, 1, 0.65, 4, true});\n    mps.push_back({100000, 2, 25.0, 1, 0.70, 5, true});\n\n    for (const auto &p : mps) {\n        if (elapsed() > 1.86) break;\n        consider(generate_mixed(p.cap, p.alpha, p.uw, p.beta, p.forceRatio, p.minDist, p.noise));\n    }\n\n    int extra = 0;\n    while (elapsed() < 1.90 && extra < 20) {\n        int cap = caps[rng.randint((int)caps.size())];\n        int ca = 2 + rng.randint(3);\n        int pa = rng.randint(3);\n        double bias = 2.0 + 25.0 * rng.real01();\n\n        consider(generate_cover_then_patrol(cap, ca, pa, bias, true));\n        extra++;\n    }\n\n    if (!legal_route(bestRoute)) {\n        bestRoute = fallbackRoute;\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\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 nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nint N, M;\nint si, sj;\nvector<string> Agrid;\nvector<string> t;\nvector<pair<int,int>> occ[26];\nint mindist_ch[26][26];\n\nconst int POW5 = 26 * 26 * 26 * 26 * 26;\nvector<int> codeId;\n\nchrono::steady_clock::time_point timeStart;\n\ndouble elapsedTime() {\n    return chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n}\n\nint manhattan(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nint wordCode(const string& s) {\n    int c = 0;\n    for (char ch : s) c = c * 26 + (ch - 'A');\n    return c;\n}\n\nint overlap_word(const string& a, const string& b) {\n    for (int k = 4; k >= 1; --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) return k;\n    }\n    return 0;\n}\n\nint overlap_suffix_string(const string& s, const string& w) {\n    int lim = min<int>(4, s.size());\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (s[(int)s.size() - k + i] != w[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nint typingCostOnly(const string& s) {\n    const int INF = 1e9;\n    vector<int> dp_prev, dp_cur;\n\n    for (int pos = 0; pos < (int)s.size(); ++pos) {\n        int c = s[pos] - 'A';\n        int C = (int)occ[c].size();\n\n        dp_cur.assign(C, INF);\n\n        if (pos == 0) {\n            pair<int,int> start = {si, sj};\n            for (int i = 0; i < C; ++i) {\n                dp_cur[i] = manhattan(start, occ[c][i]) + 1;\n            }\n        } else {\n            int pc = s[pos - 1] - 'A';\n            int P = (int)occ[pc].size();\n\n            for (int i = 0; i < C; ++i) {\n                int best = INF;\n                for (int j = 0; j < P; ++j) {\n                    int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                    if (val < best) best = val;\n                }\n                dp_cur[i] = best;\n            }\n        }\n\n        dp_prev.swap(dp_cur);\n    }\n\n    return *min_element(dp_prev.begin(), dp_prev.end());\n}\n\nint segmentCostFromChar(int prevChar, const string& w, int from) {\n    const int INF = 1e9;\n\n    vector<int> dp_prev((int)occ[prevChar].size(), 0), dp_cur;\n    int pc = prevChar;\n\n    for (int k = from; k < 5; ++k) {\n        int c = w[k] - 'A';\n        int C = (int)occ[c].size();\n        int P = (int)occ[pc].size();\n\n        dp_cur.assign(C, INF);\n\n        for (int i = 0; i < C; ++i) {\n            int best = INF;\n            for (int j = 0; j < P; ++j) {\n                int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                if (val < best) best = val;\n            }\n            dp_cur[i] = best;\n        }\n\n        dp_prev.swap(dp_cur);\n        pc = c;\n    }\n\n    return *min_element(dp_prev.begin(), dp_prev.end());\n}\n\nint suffixCostFromPos(pair<int,int> pos, const string& w, int from) {\n    const int INF = 1e9;\n    if (from >= 5) return 0;\n\n    vector<int> dp_prev, dp_cur;\n\n    int c0 = w[from] - 'A';\n    int C0 = (int)occ[c0].size();\n    dp_prev.assign(C0, INF);\n\n    for (int i = 0; i < C0; ++i) {\n        dp_prev[i] = manhattan(pos, occ[c0][i]) + 1;\n    }\n\n    int pc = c0;\n\n    for (int k = from + 1; k < 5; ++k) {\n        int c = w[k] - 'A';\n        int C = (int)occ[c].size();\n        int P = (int)occ[pc].size();\n\n        dp_cur.assign(C, INF);\n\n        for (int i = 0; i < C; ++i) {\n            int best = INF;\n            for (int j = 0; j < P; ++j) {\n                int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                if (val < best) best = val;\n            }\n            dp_cur[i] = best;\n        }\n\n        dp_prev.swap(dp_cur);\n        pc = c;\n    }\n\n    return *min_element(dp_prev.begin(), dp_prev.end());\n}\n\npair<int,int> representativeEndPos(const string& w) {\n    const int INF = 1e9;\n\n    int c0 = w[0] - 'A';\n    vector<int> dp_prev((int)occ[c0].size(), 0), dp_cur;\n    int pc = c0;\n\n    for (int k = 1; k < 5; ++k) {\n        int c = w[k] - 'A';\n        int C = (int)occ[c].size();\n        int P = (int)occ[pc].size();\n\n        dp_cur.assign(C, INF);\n\n        for (int i = 0; i < C; ++i) {\n            int best = INF;\n            for (int j = 0; j < P; ++j) {\n                int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                if (val < best) best = val;\n            }\n            dp_cur[i] = best;\n        }\n\n        dp_prev.swap(dp_cur);\n        pc = c;\n    }\n\n    int bestIdx = min_element(dp_prev.begin(), dp_prev.end()) - dp_prev.begin();\n    return occ[w[4] - 'A'][bestIdx];\n}\n\nlong long pathCost(const vector<int>& p, const vector<vector<int>>& W, const vector<int>& startCost) {\n    long long c = startCost[p[0]];\n    for (int i = 0; i + 1 < (int)p.size(); ++i) c += W[p[i]][p[i + 1]];\n    return c;\n}\n\nlong long edgeContrib(const vector<int>& p, int idx, const vector<vector<int>>& W, const vector<int>& startCost) {\n    int n = (int)p.size();\n    if (idx == -1) return startCost[p[0]];\n    if (0 <= idx && idx + 1 < n) return W[p[idx]][p[idx + 1]];\n    return 0;\n}\n\nlong long deltaSwapFast(const vector<int>& p, int a, int b, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (a == b) return 0;\n    if (a > b) swap(a, b);\n\n    int n = (int)p.size();\n    int ids[5] = {-1, a - 1, a, b - 1, b};\n    sort(ids, ids + 5);\n\n    auto nodeAfter = [&](int idx) -> int {\n        if (idx == a) return p[b];\n        if (idx == b) return p[a];\n        return p[idx];\n    };\n\n    auto newContrib = [&](int idx) -> long long {\n        if (idx == -1) return startCost[nodeAfter(0)];\n        if (0 <= idx && idx + 1 < n) return W[nodeAfter(idx)][nodeAfter(idx + 1)];\n        return 0LL;\n    };\n\n    long long oldv = 0, newv = 0;\n    int last = -100;\n\n    for (int z = 0; z < 5; ++z) {\n        int id = ids[z];\n        if (id == last) continue;\n        last = id;\n\n        oldv += edgeContrib(p, id, W, startCost);\n        newv += newContrib(id);\n    }\n\n    return newv - oldv;\n}\n\ninline long long linkCostNode(int leftNode, int rightNode, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (rightNode == -1) return 0;\n    if (leftNode == -1) return startCost[rightNode];\n    return W[leftNode][rightNode];\n}\n\n// Move p[a] to final index b, equivalent to erase(a), insert(b).\nlong long deltaMoveCorrect(const vector<int>& p, int a, int b, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (a == b) return 0;\n\n    int n = (int)p.size();\n    int x = p[a];\n\n    long long oldv = 0, newv = 0;\n\n    if (a < b) {\n        int Aprev = (a > 0 ? p[a - 1] : -1);\n        int Anext = p[a + 1];\n        int B = p[b];\n        int Bnext = (b + 1 < n ? p[b + 1] : -1);\n\n        oldv += linkCostNode(Aprev, x, W, startCost);\n        oldv += linkCostNode(x, Anext, W, startCost);\n        oldv += linkCostNode(B, Bnext, W, startCost);\n\n        newv += linkCostNode(Aprev, Anext, W, startCost);\n        newv += linkCostNode(B, x, W, startCost);\n        newv += linkCostNode(x, Bnext, W, startCost);\n    } else {\n        int Bprev = (b > 0 ? p[b - 1] : -1);\n        int B = p[b];\n        int Aprev = p[a - 1];\n        int Anext = (a + 1 < n ? p[a + 1] : -1);\n\n        oldv += linkCostNode(Bprev, B, W, startCost);\n        oldv += linkCostNode(Aprev, x, W, startCost);\n        oldv += linkCostNode(x, Anext, W, startCost);\n\n        newv += linkCostNode(Bprev, x, W, startCost);\n        newv += linkCostNode(x, B, W, startCost);\n        newv += linkCostNode(Aprev, Anext, W, startCost);\n    }\n\n    return newv - oldv;\n}\n\nvoid applyMove(vector<int>& p, int a, int b) {\n    if (a == b) return;\n\n    if (a < b) {\n        rotate(p.begin() + a, p.begin() + a + 1, p.begin() + b + 1);\n    } else {\n        rotate(p.begin() + b, p.begin() + a, p.begin() + a + 1);\n    }\n}\n\nvector<int> greedyOrder(const vector<vector<int>>& W, const vector<int>& startCost, const vector<vector<int>>& ov) {\n    vector<int> best;\n    long long bestCost = (1LL << 60);\n\n    for (int st = 0; st < M; ++st) {\n        vector<int> p;\n        vector<char> used(M, 0);\n        p.reserve(M);\n\n        p.push_back(st);\n        used[st] = 1;\n\n        for (int step = 1; step < M; ++step) {\n            int last = p.back();\n            int bj = -1;\n            pair<int,int> bestKey = {INT_MAX, INT_MAX};\n\n            for (int j = 0; j < M; ++j) if (!used[j]) {\n                pair<int,int> key = {W[last][j], -ov[last][j]};\n                if (key < bestKey) {\n                    bestKey = key;\n                    bj = j;\n                }\n            }\n\n            used[bj] = 1;\n            p.push_back(bj);\n        }\n\n        long long c = pathCost(p, W, startCost);\n        if (c < bestCost) {\n            bestCost = c;\n            best = p;\n        }\n    }\n\n    return best;\n}\n\nvoid annealOrder(\n    vector<int>& perm,\n    long long& curCost,\n    vector<int>& bestPerm,\n    long long& bestCost,\n    const vector<vector<int>>& W,\n    const vector<int>& startCost,\n    double endTime,\n    double tempStart,\n    double tempEnd,\n    XorShift& rng\n) {\n    double beginTime = elapsedTime();\n    double temp = tempStart;\n    int iter = 0;\n\n    while (true) {\n        if ((iter & 255) == 0) {\n            double now = elapsedTime();\n            if (now > endTime) break;\n\n            double progress = (now - beginTime) / max(1e-9, endTime - beginTime);\n            progress = min(1.0, max(0.0, progress));\n            temp = tempStart * pow(tempEnd / tempStart, progress);\n        }\n        ++iter;\n\n        if (rng.nextInt(100) < 55) {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            long long d = deltaSwapFast(perm, a, b, W, startCost);\n\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                swap(perm[a], perm[b]);\n                curCost += d;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        } else {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            long long d = deltaMoveCorrect(perm, a, b, W, startCost);\n\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                applyMove(perm, a, b);\n                curCost += d;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        }\n    }\n}\n\nstring buildStringFromOrder(const vector<int>& ord) {\n    string s;\n    s.reserve(1200);\n\n    vector<char> covered(M, 0);\n    int code = 0;\n    int seen = 0;\n\n    auto appendChar = [&](char ch) {\n        s.push_back(ch);\n        code = (code * 26 + (ch - 'A')) % POW5;\n        ++seen;\n\n        if (seen >= 5) {\n            int id = codeId[code];\n            if (id != -1) covered[id] = 1;\n        }\n    };\n\n    auto appendWord = [&](int id) {\n        if (covered[id]) return;\n        int o = overlap_suffix_string(s, t[id]);\n        for (int k = o; k < 5; ++k) appendChar(t[id][k]);\n    };\n\n    for (int id : ord) appendWord(id);\n\n    for (int i = 0; i < M; ++i) {\n        if (!covered[i]) appendWord(i);\n    }\n\n    return s;\n}\n\nbool coversAllAfterDeleting(const string& s, int delPos) {\n    vector<char> covered(M, 0);\n    int cnt = 0;\n    int code = 0;\n    int seen = 0;\n\n    for (int i = 0; i < (int)s.size(); ++i) {\n        if (i == delPos) continue;\n\n        code = (code * 26 + (s[i] - 'A')) % POW5;\n        ++seen;\n\n        if (seen >= 5) {\n            int id = codeId[code];\n            if (id != -1 && !covered[id]) {\n                covered[id] = 1;\n                ++cnt;\n                if (cnt == M) return true;\n            }\n        }\n    }\n\n    return cnt == M;\n}\n\nstring pruneStringByDeletion(string s, int& curCost) {\n    if (elapsedTime() > 1.90) return s;\n\n    bool improved = true;\n\n    while (improved && elapsedTime() < 1.93) {\n        improved = false;\n\n        for (int pos = 0; pos < (int)s.size(); ++pos) {\n            if ((pos & 15) == 0 && elapsedTime() > 1.93) break;\n\n            if (!coversAllAfterDeleting(s, pos)) continue;\n\n            string ns;\n            ns.reserve(s.size() - 1);\n            ns.append(s.begin(), s.begin() + pos);\n            ns.append(s.begin() + pos + 1, s.end());\n\n            int nc = typingCostOnly(ns);\n            if (nc < curCost) {\n                s.swap(ns);\n                curCost = nc;\n                improved = true;\n                break;\n            }\n        }\n    }\n\n    return s;\n}\n\npair<int, vector<pair<int,int>>> solveTypingDP(const string& s) {\n    const int INF = 1e9;\n    int L = (int)s.size();\n\n    vector<vector<int>> par(L);\n    vector<int> dp_prev, dp_cur;\n\n    for (int pos = 0; pos < L; ++pos) {\n        int c = s[pos] - 'A';\n        int C = (int)occ[c].size();\n\n        dp_cur.assign(C, INF);\n        par[pos].assign(C, -1);\n\n        if (pos == 0) {\n            pair<int,int> start = {si, sj};\n            for (int i = 0; i < C; ++i) {\n                dp_cur[i] = manhattan(start, occ[c][i]) + 1;\n            }\n        } else {\n            int pc = s[pos - 1] - 'A';\n            int P = (int)occ[pc].size();\n\n            for (int i = 0; i < C; ++i) {\n                for (int j = 0; j < P; ++j) {\n                    int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                    if (val < dp_cur[i]) {\n                        dp_cur[i] = val;\n                        par[pos][i] = j;\n                    }\n                }\n            }\n        }\n\n        dp_prev.swap(dp_cur);\n    }\n\n    int bestIdx = 0;\n    int bestCost = INF;\n\n    for (int i = 0; i < (int)dp_prev.size(); ++i) {\n        if (dp_prev[i] < bestCost) {\n            bestCost = dp_prev[i];\n            bestIdx = i;\n        }\n    }\n\n    vector<pair<int,int>> path(L);\n    int idx = bestIdx;\n\n    for (int pos = L - 1; pos >= 0; --pos) {\n        int c = s[pos] - 'A';\n        path[pos] = occ[c][idx];\n        idx = par[pos][idx];\n    }\n\n    return {bestCost, path};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    timeStart = chrono::steady_clock::now();\n\n    cin >> N >> M;\n    cin >> si >> sj;\n\n    Agrid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> Agrid[i];\n\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    codeId.assign(POW5, -1);\n    for (int i = 0; i < M; ++i) {\n        codeId[wordCode(t[i])] = i;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            occ[Agrid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) {\n            int best = 1e9;\n            for (auto pa : occ[a]) {\n                for (auto pb : occ[b]) {\n                    best = min(best, manhattan(pa, pb));\n                }\n            }\n            mindist_ch[a][b] = best;\n        }\n    }\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i != j) ov[i][j] = overlap_word(t[i], t[j]);\n        }\n    }\n\n    vector<vector<int>> Wapprox(M, vector<int>(M, 100000000));\n    vector<vector<int>> Wexact(M, vector<int>(M, 100000000));\n    vector<vector<int>> Wrep(M, vector<int>(M, 100000000));\n\n    vector<pair<int,int>> repEnd(M);\n    for (int i = 0; i < M; ++i) {\n        repEnd[i] = representativeEndPos(t[i]);\n    }\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            int o = ov[i][j];\n\n            int prev = t[i][4] - 'A';\n            int cost = 0;\n\n            for (int k = o; k < 5; ++k) {\n                int c = t[j][k] - 'A';\n                cost += mindist_ch[prev][c] + 1;\n                prev = c;\n            }\n\n            Wapprox[i][j] = cost;\n            Wexact[i][j] = segmentCostFromChar(t[i][4] - 'A', t[j], o);\n            Wrep[i][j] = suffixCostFromPos(repEnd[i], t[j], o);\n        }\n    }\n\n    vector<int> startApprox(M, 0);\n    vector<int> startExact(M, 0);\n    pair<int,int> startPos = {si, sj};\n\n    for (int i = 0; i < M; ++i) {\n        int cost = 1e9;\n        int c0 = t[i][0] - 'A';\n\n        for (auto p : occ[c0]) {\n            cost = min(cost, manhattan(startPos, p) + 1);\n        }\n\n        for (int k = 1; k < 5; ++k) {\n            int a = t[i][k - 1] - 'A';\n            int b = t[i][k] - 'A';\n            cost += mindist_ch[a][b] + 1;\n        }\n\n        startApprox[i] = cost;\n        startExact[i] = typingCostOnly(t[i]);\n    }\n\n    vector<string> candidates;\n    XorShift rng;\n\n    vector<int> perm = greedyOrder(Wapprox, startApprox, ov);\n    long long curCost = pathCost(perm, Wapprox, startApprox);\n    vector<int> bestPerm = perm;\n    long long bestCost = curCost;\n\n    annealOrder(\n        perm,\n        curCost,\n        bestPerm,\n        bestCost,\n        Wapprox,\n        startApprox,\n        1.78,\n        18.0,\n        0.03,\n        rng\n    );\n\n    candidates.push_back(buildStringFromOrder(bestPerm));\n    candidates.push_back(buildStringFromOrder(perm));\n\n    vector<vector<int>> Wover(M, vector<int>(M, 1000000));\n    vector<int> zeroStart(M, 0);\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            Wover[i][j] = 5 - ov[i][j];\n        }\n    }\n\n    candidates.push_back(buildStringFromOrder(greedyOrder(Wover, zeroStart, ov)));\n\n    if (elapsedTime() < 1.84) {\n        vector<int> eperm = greedyOrder(Wexact, startExact, ov);\n        long long ecur = pathCost(eperm, Wexact, startExact);\n        vector<int> ebestPerm = eperm;\n        long long ebest = ecur;\n\n        annealOrder(\n            eperm,\n            ecur,\n            ebestPerm,\n            ebest,\n            Wexact,\n            startExact,\n            1.88,\n            12.0,\n            0.05,\n            rng\n        );\n\n        candidates.push_back(buildStringFromOrder(ebestPerm));\n        candidates.push_back(buildStringFromOrder(eperm));\n    }\n\n    vector<int> lexPerm(M);\n    iota(lexPerm.begin(), lexPerm.end(), 0);\n    candidates.push_back(buildStringFromOrder(lexPerm));\n\n    reverse(lexPerm.begin(), lexPerm.end());\n    candidates.push_back(buildStringFromOrder(lexPerm));\n\n    if (elapsedTime() < 1.90) {\n        for (int bonus : {2, 4}) {\n            vector<vector<int>> Wb = Wapprox;\n\n            for (int i = 0; i < M; ++i) {\n                for (int j = 0; j < M; ++j) if (i != j) {\n                    Wb[i][j] = Wapprox[i][j] - bonus * ov[i][j];\n                }\n            }\n\n            candidates.push_back(buildStringFromOrder(greedyOrder(Wb, startApprox, ov)));\n        }\n    }\n\n    // Additional low-risk representative-end candidates.\n    if (elapsedTime() < 1.91) {\n        candidates.push_back(buildStringFromOrder(greedyOrder(Wrep, startExact, ov)));\n\n        vector<vector<int>> Wmix(M, vector<int>(M, 100000000));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) if (i != j) {\n                Wmix[i][j] = (Wapprox[i][j] + Wrep[i][j]) / 2;\n            }\n        }\n        candidates.push_back(buildStringFromOrder(greedyOrder(Wmix, startApprox, ov)));\n    }\n\n    sort(candidates.begin(), candidates.end());\n    candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n    int bestStringCost = INT_MAX;\n    string bestString;\n\n    for (const string& s : candidates) {\n        int c = typingCostOnly(s);\n        if (c < bestStringCost) {\n            bestStringCost = c;\n            bestString = s;\n        }\n    }\n\n    if (elapsedTime() < 1.90) {\n        bestString = pruneStringByDeletion(bestString, bestStringCost);\n    }\n\n    auto answer = solveTypingDP(bestString);\n    vector<pair<int,int>> answerPath = move(answer.second);\n\n    if ((int)answerPath.size() > 5000) {\n        answerPath.resize(5000);\n    }\n\n    for (auto [i, j] : answerPath) {\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXC = 400;\n\nint N, M, C;\ndouble EPSV;\nint MAX_OPS;\nint op_cnt = 0;\n\nstruct Placement {\n    vector<int> cells;\n    bitset<MAXC> mask;\n};\n\nstruct Obs {\n    bitset<MAXC> mask;\n    int k;\n    double target;\n    double weight;\n    bool drill;\n    int cell;\n    int value;\n};\n\nstruct State {\n    vector<int> pos;\n    double score;\n    bitset<MAXC> uni;\n};\n\nvector<vector<pair<int,int>>> shapes;\nvector<vector<Placement>> placements;\nvector<Obs> observations;\nvector<int> drilled;\n\nbitset<MAXC> zeroMask;\nbitset<MAXC> positiveMask;\n\nvector<vector<int>> seed_positions;\nunordered_set<string> failed_masks;\n\nmt19937 rng(1234567);\nauto time_start = chrono::steady_clock::now();\n\ndouble elapsed_ms() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double, milli>(now - time_start).count();\n}\n\nint id_of(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> coord_of(int id) {\n    return {id / N, id % N};\n}\n\nint unknown_count() {\n    int ret = 0;\n    for (int x : drilled) {\n        if (x == -1) ret++;\n    }\n    return ret;\n}\n\nstring mask_key(const bitset<MAXC>& mask) {\n    string s;\n    s.reserve(C);\n    for (int id = 0; id < C; id++) {\n        s.push_back(mask.test(id) ? '1' : '0');\n    }\n    return s;\n}\n\nint ask_query(const vector<int>& cells) {\n    cout << \"q \" << cells.size();\n    for (int id : cells) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n    return res;\n}\n\nbool ask_answer(bitset<MAXC> mask, const string& key = \"\") {\n    for (int id = 0; id < C; id++) {\n        if (positiveMask.test(id)) mask.set(id);\n    }\n\n    vector<int> ans;\n    for (int id = 0; id < C; id++) {\n        if (mask.test(id)) ans.push_back(id);\n    }\n\n    cout << \"a \" << ans.size();\n    for (int id : ans) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n\n    if (res == 1) exit(0);\n    if (!key.empty()) failed_masks.insert(key);\n    return false;\n}\n\nvoid add_divination_observation(const vector<int>& cells, int y) {\n    Obs obs;\n    obs.mask.reset();\n    for (int id : cells) obs.mask.set(id);\n\n    obs.k = (int)cells.size();\n    obs.drill = false;\n    obs.cell = -1;\n    obs.value = -1;\n\n    double a = 1.0 - 2.0 * EPSV;\n    double target = (y - obs.k * EPSV) / max(1e-9, a);\n    target = max(0.0, min(target, (double)M * obs.k));\n\n    double var = obs.k * EPSV * (1.0 - EPSV) + 0.35;\n    double weight = a * a / max(1e-9, var);\n\n    obs.target = target;\n    obs.weight = weight;\n    observations.push_back(obs);\n}\n\nvoid add_drill_observation(int cell, int val) {\n    Obs obs;\n    obs.mask.reset();\n    obs.mask.set(cell);\n\n    obs.k = 1;\n    obs.target = val;\n    obs.weight = 20000.0;\n    obs.drill = true;\n    obs.cell = cell;\n    obs.value = val;\n\n    observations.push_back(obs);\n}\n\nvoid do_divination(const vector<int>& cells) {\n    if ((int)cells.size() < 2) return;\n    int y = ask_query(cells);\n    add_divination_observation(cells, y);\n}\n\nint do_drill(int cell) {\n    vector<int> q = {cell};\n    int v = ask_query(q);\n\n    drilled[cell] = v;\n    if (v == 0) zeroMask.set(cell);\n    if (v > 0) positiveMask.set(cell);\n\n    add_drill_observation(cell, v);\n    return v;\n}\n\nvoid build_placements() {\n    placements.assign(M, {});\n\n    for (int m = 0; m < M; m++) {\n        int imax = 0, jmax = 0;\n        for (auto [i, j] : shapes[m]) {\n            imax = max(imax, i);\n            jmax = max(jmax, j);\n        }\n\n        for (int di = 0; di + imax < N; di++) {\n            for (int dj = 0; dj + jmax < N; dj++) {\n                Placement p;\n                p.mask.reset();\n\n                for (auto [i, j] : shapes[m]) {\n                    int id = id_of(di + i, dj + j);\n                    p.cells.push_back(id);\n                    p.mask.set(id);\n                }\n\n                placements[m].push_back(p);\n            }\n        }\n    }\n}\n\nvoid initial_queries() {\n    // Whole-grid query is skipped because total reserve is known from shape areas.\n\n    for (int i = 0; i < N; i++) {\n        vector<int> cells;\n        for (int j = 0; j < N; j++) {\n            cells.push_back(id_of(i, j));\n        }\n        do_divination(cells);\n    }\n\n    for (int j = 0; j < N; j++) {\n        vector<int> cells;\n        for (int i = 0; i < N; i++) {\n            cells.push_back(id_of(i, j));\n        }\n        do_divination(cells);\n    }\n\n    int B = 4;\n    for (int si = 0; si < N; si += B) {\n        for (int sj = 0; sj < N; sj += B) {\n            vector<int> cells;\n            for (int i = si; i < min(N, si + B); i++) {\n                for (int j = sj; j < min(N, sj + B); j++) {\n                    cells.push_back(id_of(i, j));\n                }\n            }\n            if ((int)cells.size() >= 2) do_divination(cells);\n        }\n    }\n\n    int R = (N <= 10 ? 18 : 30);\n    vector<int> ids(C);\n    iota(ids.begin(), ids.end(), 0);\n\n    for (int r = 0; r < R; r++) {\n        shuffle(ids.begin(), ids.end(), rng);\n\n        vector<int> cells;\n        int sz = max(2, C / 2);\n        for (int t = 0; t < sz; t++) {\n            cells.push_back(ids[t]);\n        }\n\n        do_divination(cells);\n    }\n}\n\nbitset<MAXC> union_of_state(const vector<int>& pos) {\n    bitset<MAXC> res;\n    res.reset();\n\n    for (int m = 0; m < M; m++) {\n        res |= placements[m][pos[m]].mask;\n    }\n\n    return res;\n}\n\nbool union_consistent_with_drills(const bitset<MAXC>& mask) {\n    if ((mask & zeroMask).any()) return false;\n\n    for (int id = 0; id < C; id++) {\n        if (positiveMask.test(id) && !mask.test(id)) return false;\n    }\n\n    return true;\n}\n\nbool placement_valid_by_zero(int m, int p) {\n    return !((placements[m][p].mask & zeroMask).any());\n}\n\nbool position_vector_valid_by_zero(const vector<int>& pos) {\n    if ((int)pos.size() != M) return false;\n\n    for (int m = 0; m < M; m++) {\n        if (pos[m] < 0 || pos[m] >= (int)placements[m].size()) return false;\n        if (!placement_valid_by_zero(m, pos[m])) return false;\n    }\n\n    return true;\n}\n\nvector<State> finalize_candidates(vector<State>& result, int want) {\n    sort(result.begin(), result.end(), [](const State& a, const State& b) {\n        return a.score < b.score;\n    });\n\n    vector<State> uniq;\n    unordered_set<string> seen;\n\n    for (auto &st : result) {\n        string key = mask_key(st.uni);\n        if (seen.insert(key).second) {\n            uniq.push_back(st);\n            if ((int)uniq.size() >= want) break;\n        }\n    }\n\n    seed_positions.clear();\n    for (int i = 0; i < (int)uniq.size() && i < 20; i++) {\n        if (position_vector_valid_by_zero(uniq[i].pos)) {\n            seed_positions.push_back(uniq[i].pos);\n        }\n    }\n\n    return uniq;\n}\n\nvector<State> find_candidates(int want, int time_ms) {\n    int O = observations.size();\n\n    vector<vector<int>> active(M);\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p < (int)placements[m].size(); p++) {\n            if (placement_valid_by_zero(m, p)) {\n                active[m].push_back(p);\n            }\n        }\n\n        // Robust fallback. Should not occur for valid exact drilling info.\n        if (active[m].empty()) {\n            for (int p = 0; p < (int)placements[m].size(); p++) {\n                active[m].push_back(p);\n            }\n        }\n    }\n\n    vector<vector<vector<unsigned char>>> contrib(M);\n    for (int m = 0; m < M; m++) {\n        int P = placements[m].size();\n        contrib[m].assign(P, vector<unsigned char>(O, 0));\n\n        for (int p : active[m]) {\n            for (int o = 0; o < O; o++) {\n                contrib[m][p][o] =\n                    (unsigned char)((placements[m][p].mask & observations[o].mask).count());\n            }\n        }\n    }\n\n    auto score_of_sums = [&](const vector<int>& sums) {\n        double sc = 0.0;\n        for (int o = 0; o < O; o++) {\n            double e = sums[o] - observations[o].target;\n            sc += observations[o].weight * e * e;\n        }\n        return sc;\n    };\n\n    vector<State> result;\n    auto deadline = chrono::steady_clock::now() + chrono::milliseconds(max(3, time_ms));\n\n    int restarts = 0;\n    int min_restarts = (time_ms <= 5 ? 1 : 3);\n\n    while (restarts < min_restarts || chrono::steady_clock::now() < deadline) {\n        restarts++;\n\n        vector<int> pos(M, -1);\n\n        if (!seed_positions.empty() && restarts % 3 == 0) {\n            pos = seed_positions[rng() % seed_positions.size()];\n\n            for (int m = 0; m < M; m++) {\n                if (pos[m] < 0 || pos[m] >= (int)placements[m].size() ||\n                    !placement_valid_by_zero(m, pos[m])) {\n                    pos[m] = active[m][rng() % active[m].size()];\n                }\n            }\n\n            int changes = max(1, M / 5);\n            for (int t = 0; t < changes; t++) {\n                int m = rng() % M;\n                pos[m] = active[m][rng() % active[m].size()];\n            }\n        } else {\n            for (int m = 0; m < M; m++) {\n                pos[m] = active[m][rng() % active[m].size()];\n            }\n        }\n\n        vector<int> sums(O, 0);\n        for (int m = 0; m < M; m++) {\n            for (int o = 0; o < O; o++) {\n                sums[o] += contrib[m][pos[m]][o];\n            }\n        }\n\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n\n        int sweeps = (time_ms <= 5 ? 3 : 7);\n        for (int sweep = 0; sweep < sweeps; sweep++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool changed = false;\n\n            for (int mm = 0; mm < M; mm++) {\n                int m = order[mm];\n                int oldp = pos[m];\n\n                for (int o = 0; o < O; o++) {\n                    sums[o] -= contrib[m][oldp][o];\n                }\n\n                int bestp = oldp;\n                double bestsc = numeric_limits<double>::infinity();\n\n                for (int p : active[m]) {\n                    double sc = 0.0;\n\n                    for (int o = 0; o < O; o++) {\n                        double v = sums[o] + contrib[m][p][o];\n                        double e = v - observations[o].target;\n                        sc += observations[o].weight * e * e;\n\n                        if (sc >= bestsc) break;\n                    }\n\n                    if (sc < bestsc) {\n                        bestsc = sc;\n                        bestp = p;\n                    }\n                }\n\n                pos[m] = bestp;\n\n                for (int o = 0; o < O; o++) {\n                    sums[o] += contrib[m][bestp][o];\n                }\n\n                if (bestp != oldp) changed = true;\n            }\n\n            if (!changed) break;\n        }\n\n        State st;\n        st.pos = pos;\n        st.score = score_of_sums(sums);\n        st.uni = union_of_state(pos);\n        result.push_back(st);\n\n        if (elapsed_ms() > 2800.0) break;\n    }\n\n    return finalize_candidates(result, want);\n}\n\nint choose_drill_cell(const vector<State>& cand, int wrong_same_count) {\n    int K = (int)cand.size();\n    vector<int> freq(C, 0);\n\n    for (auto &st : cand) {\n        for (int id = 0; id < C; id++) {\n            if (st.uni.test(id)) freq[id]++;\n        }\n    }\n\n    int best = -1;\n    int bestScore = -1;\n\n    // Prefer cells where candidate unions disagree.\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] != -1) continue;\n\n        int f = freq[id];\n        if (f == 0 || f == K) continue;\n\n        int score = min(f, K - f);\n        if (score > bestScore) {\n            bestScore = score;\n            best = id;\n        }\n    }\n\n    if (best != -1) return best;\n\n    // If candidates agree, verify the predicted union.\n    if (!cand.empty()) {\n        const bitset<MAXC>& mask = cand[0].uni;\n\n        // First verify predicted positive cells.\n        if (wrong_same_count % 2 == 0) {\n            for (int id = 0; id < C; id++) {\n                if (drilled[id] == -1 && mask.test(id)) {\n                    return id;\n                }\n            }\n        }\n\n        // Then inspect boundary negatives.\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] != -1 || mask.test(id)) continue;\n\n            int i = id / N, j = id % N;\n            bool near = false;\n\n            const int di[4] = {-1, 1, 0, 0};\n            const int dj[4] = {0, 0, -1, 1};\n\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    if (mask.test(id_of(ni, nj))) {\n                        near = true;\n                    }\n                }\n            }\n\n            if (near) return id;\n        }\n\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] == -1 && !mask.test(id)) {\n                return id;\n            }\n        }\n    }\n\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) return id;\n    }\n\n    return -1;\n}\n\nvoid fallback_drill_all_and_answer() {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) {\n            do_drill(id);\n        }\n    }\n\n    bitset<MAXC> ans;\n    ans.reset();\n\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] > 0) ans.set(id);\n    }\n\n    ask_answer(ans);\n    exit(0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> EPSV;\n\n    C = N * N;\n    MAX_OPS = 2 * C;\n\n    shapes.resize(M);\n    for (int m = 0; m < M; m++) {\n        int d;\n        cin >> d;\n\n        shapes[m].resize(d);\n        for (int k = 0; k < d; k++) {\n            cin >> shapes[m][k].first >> shapes[m][k].second;\n        }\n    }\n\n    drilled.assign(C, -1);\n    zeroMask.reset();\n    positiveMask.reset();\n\n    build_placements();\n    initial_queries();\n\n    unordered_set<string> guessed;\n    int heuristic_drills = 0;\n    int guesses = 0;\n    int wrong_same_count = 0;\n\n    while (true) {\n        int unknown = unknown_count();\n\n        // Always reserve enough operations to drill all unknown cells and submit.\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        if (elapsed_ms() > 2850.0) {\n            fallback_drill_all_and_answer();\n        }\n\n        // Longer than previous best. Drills are not wasted if fallback happens.\n        if (heuristic_drills >= min(C, 160)) {\n            fallback_drill_all_and_answer();\n        }\n\n        int tlim;\n        if (heuristic_drills == 0) {\n            tlim = 350;\n        } else if (heuristic_drills < 25) {\n            tlim = 80;\n        } else if (heuristic_drills < 60) {\n            tlim = 30;\n        } else if (heuristic_drills < 100) {\n            tlim = 5;\n        } else {\n            tlim = 3;\n        }\n\n        if (elapsed_ms() > 2300.0) {\n            tlim = min(tlim, 3);\n        }\n\n        vector<State> cand = find_candidates(12, tlim);\n        if (cand.empty()) {\n            fallback_drill_all_and_answer();\n        }\n\n        // Guess best unfailed candidate when consistent with exact drilling info.\n        bitset<MAXC> bestMask = cand[0].uni;\n        string key = mask_key(bestMask);\n\n        bool can_try_answer =\n            guesses < 25 &&\n            op_cnt + unknown + 2 <= MAX_OPS &&\n            guessed.find(key) == guessed.end() &&\n            failed_masks.find(key) == failed_masks.end() &&\n            union_consistent_with_drills(bestMask);\n\n        if (can_try_answer) {\n            guessed.insert(key);\n            guesses++;\n\n            bool ok = ask_answer(bestMask, key);\n            if (ok) return 0;\n\n            wrong_same_count++;\n        }\n\n        unknown = unknown_count();\n\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        int cell = choose_drill_cell(cand, wrong_same_count);\n        if (cell == -1) {\n            fallback_drill_all_and_answer();\n        }\n\n        do_drill(cell);\n        heuristic_drills++;\n    }\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int W = 1000;\nusing ll = long long;\nusing ull = unsigned long long;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nstruct Option {\n    int l, r;\n    int h;\n    ll cost;\n    bool stat;\n};\n\nint D, N;\nvector<vector<int>> A;\nvector<int> maxA;\n\ninline int ceil_div(int x, int y) {\n    return (x + y - 1) / y;\n}\n\nvector<vector<Rect>> make_empty_solution() {\n    return vector<vector<Rect>>(D, vector<Rect>(N));\n}\n\nbool valid_solution(const vector<vector<Rect>>& sol) {\n    if ((int)sol.size() != D) return false;\n    for (int d = 0; d < D; d++) {\n        if ((int)sol[d].size() != N) return false;\n        for (int k = 0; k < N; k++) {\n            auto r = sol[d][k];\n            if (!(0 <= r.i0 && r.i0 < r.i1 && r.i1 <= W)) return false;\n            if (!(0 <= r.j0 && r.j0 < r.j1 && r.j1 <= W)) return false;\n        }\n    }\n    return true;\n}\n\nstruct Scorer {\n    int HN = 999 * 1000;\n    int VN = 1000 * 999;\n    int HW, VW;\n\n    Scorer() {\n        HW = (HN + 63) >> 6;\n        VW = (VN + 63) >> 6;\n    }\n\n    inline void setbit(vector<ull>& b, int idx) const {\n        b[idx >> 6] |= 1ULL << (idx & 63);\n    }\n\n    ll score(const vector<vector<Rect>>& sol) const {\n        vector<ull> prevH(HW, 0), prevV(VW, 0), curH(HW), curV(VW);\n        ll total = 0;\n\n        for (int d = 0; d < D; d++) {\n            fill(curH.begin(), curH.end(), 0);\n            fill(curV.begin(), curV.end(), 0);\n\n            for (int k = 0; k < N; k++) {\n                const Rect& r = sol[d][k];\n\n                ll area = 1LL * (r.i1 - r.i0) * (r.j1 - r.j0);\n                if (area < A[d][k]) total += 100LL * (A[d][k] - area);\n\n                if (r.i0 > 0) {\n                    int row = r.i0 - 1;\n                    for (int x = r.j0; x < r.j1; x++) setbit(curH, row * 1000 + x);\n                }\n                if (r.i1 < W) {\n                    int row = r.i1 - 1;\n                    for (int x = r.j0; x < r.j1; x++) setbit(curH, row * 1000 + x);\n                }\n                if (r.j0 > 0) {\n                    int col = r.j0 - 1;\n                    for (int y = r.i0; y < r.i1; y++) setbit(curV, y * 999 + col);\n                }\n                if (r.j1 < W) {\n                    int col = r.j1 - 1;\n                    for (int y = r.i0; y < r.i1; y++) setbit(curV, y * 999 + col);\n                }\n            }\n\n            if (d > 0) {\n                for (int i = 0; i < HW; i++) total += __builtin_popcountll(prevH[i] ^ curH[i]);\n                for (int i = 0; i < VW; i++) total += __builtin_popcountll(prevV[i] ^ curV[i]);\n            }\n\n            prevH.swap(curH);\n            prevV.swap(curV);\n        }\n\n        return total;\n    }\n};\n\n// ------------------------------------------------------------\n// Treemap / guillotine packer.\n// mode=0: cut-length tie score.\n// mode=1: balanced-count tie score.\n// ------------------------------------------------------------\n\nstruct TreemapPacker {\n    vector<int> weight;\n    vector<Rect> out;\n    int mode = 0;\n\n    ll sum_weight(const vector<int>& ids) {\n        ll s = 0;\n        for (int id : ids) s += weight[id];\n        return s;\n    }\n\n    void rec(const vector<int>& ids, int x, int y, int w, int h) {\n        int m = ids.size();\n\n        if (m == 1) {\n            int id = ids[0];\n            out[id] = {y, x, y + h, x + w};\n            return;\n        }\n\n        ll total = max(1LL, sum_weight(ids));\n        ll area = 1LL * w * h;\n\n        vector<vector<int>> orders;\n\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (weight[a] != weight[b]) return weight[a] < weight[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (weight[a] != weight[b]) return weight[a] > weight[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end());\n            orders.push_back(v);\n        }\n\n        struct Cand {\n            ll score;\n            bool vertical;\n            int cut;\n            vector<int> a, b;\n        };\n\n        vector<Cand> cands;\n\n        auto add_candidate = [&](vector<int> left) {\n            sort(left.begin(), left.end());\n            left.erase(unique(left.begin(), left.end()), left.end());\n\n            if (left.empty() || (int)left.size() == m) return;\n\n            vector<int> mark(N, 0);\n            for (int id : left) mark[id] = 1;\n\n            vector<int> right;\n            for (int id : ids) {\n                if (!mark[id]) right.push_back(id);\n            }\n            if (right.empty()) return;\n\n            ll s1 = 0, s2 = 0;\n            for (int id : left) s1 += weight[id];\n            for (int id : right) s2 += weight[id];\n\n            int n1 = left.size();\n            int n2 = right.size();\n\n            {\n                int lo = ceil_div(n1, h);\n                int hi = w - ceil_div(n2, h);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)w * s1 / total);\n                    vector<int> cuts = {\n                        lo, hi,\n                        max(lo, min(hi, ideal)),\n                        max(lo, min(hi, ideal - 1)),\n                        max(lo, min(hi, ideal + 1))\n                    };\n\n                    for (int cut : cuts) {\n                        if (cut < lo || cut > hi) continue;\n\n                        ll cap1 = 1LL * cut * h;\n                        ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - 1LL * (w - cut) * h);\n                        ll dev = llabs(cap1 * total - s1 * area) / total;\n                        ll aspect = 1000LL * max(cut, h) / max(1, min(cut, h))\n                                  + 1000LL * max(w - cut, h) / max(1, min(w - cut, h));\n\n                        ll extra = (mode == 0 ? h : abs(n1 - n2) * 10LL);\n                        ll score = shortage * 1000000000LL + dev * 1000LL + aspect + extra;\n                        cands.push_back({score, true, cut, left, right});\n                    }\n                }\n            }\n\n            {\n                int lo = ceil_div(n1, w);\n                int hi = h - ceil_div(n2, w);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)h * s1 / total);\n                    vector<int> cuts = {\n                        lo, hi,\n                        max(lo, min(hi, ideal)),\n                        max(lo, min(hi, ideal - 1)),\n                        max(lo, min(hi, ideal + 1))\n                    };\n\n                    for (int cut : cuts) {\n                        if (cut < lo || cut > hi) continue;\n\n                        ll cap1 = 1LL * w * cut;\n                        ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - 1LL * w * (h - cut));\n                        ll dev = llabs(cap1 * total - s1 * area) / total;\n                        ll aspect = 1000LL * max(w, cut) / max(1, min(w, cut))\n                                  + 1000LL * max(w, h - cut) / max(1, min(w, h - cut));\n\n                        ll extra = (mode == 0 ? w : abs(n1 - n2) * 10LL);\n                        ll score = shortage * 1000000000LL + dev * 1000LL + aspect + extra;\n                        cands.push_back({score, false, cut, left, right});\n                    }\n                }\n            }\n        };\n\n        for (auto ord : orders) {\n            vector<int> pref;\n            for (int k = 0; k + 1 < (int)ord.size(); k++) {\n                pref.push_back(ord[k]);\n                add_candidate(pref);\n            }\n        }\n\n        vector<double> targets = {0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80};\n        auto desc = ids;\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            if (weight[a] != weight[b]) return weight[a] > weight[b];\n            return a < b;\n        });\n\n        for (double t : targets) {\n            ll target = (ll)(total * t);\n            vector<int> group;\n            ll s = 0;\n            for (int id : desc) {\n                if (group.empty() || s + weight[id] <= target) {\n                    group.push_back(id);\n                    s += weight[id];\n                }\n            }\n            add_candidate(group);\n        }\n\n        if (cands.empty()) {\n            vector<int> a, b;\n            for (int i = 0; i < m; i++) {\n                if (i < m / 2) a.push_back(ids[i]);\n                else b.push_back(ids[i]);\n            }\n\n            if (w >= h && w >= 2) {\n                int cut = max(1, min(w - 1, w / 2));\n                rec(a, x, y, cut, h);\n                rec(b, x + cut, y, w - cut, h);\n            } else {\n                int cut = max(1, min(h - 1, h / 2));\n                rec(a, x, y, w, cut);\n                rec(b, x, y + cut, w, h - cut);\n            }\n            return;\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            return a.score < b.score;\n        });\n\n        const Cand& best = cands[0];\n\n        if (best.vertical) {\n            rec(best.a, x, y, best.cut, h);\n            rec(best.b, x + best.cut, y, w - best.cut, h);\n        } else {\n            rec(best.a, x, y, w, best.cut);\n            rec(best.b, x, y + best.cut, w, h - best.cut);\n        }\n    }\n\n    vector<Rect> pack(const vector<int>& wgt, int m = 0) {\n        mode = m;\n        weight = wgt;\n        out.assign(N, {-1, -1, -1, -1});\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        rec(ids, 0, 0, W, W);\n        return out;\n    }\n};\n\nvector<int> average_area_vector() {\n    vector<int> avg(N);\n    for (int k = 0; k < N; k++) {\n        ll s = 0;\n        for (int d = 0; d < D; d++) s += A[d][k];\n        avg[k] = max(1, (int)((s + D - 1) / D));\n    }\n    return avg;\n}\n\nvector<int> percentile_area_vector(double p) {\n    vector<int> res(N);\n    for (int k = 0; k < N; k++) {\n        vector<int> v;\n        for (int d = 0; d < D; d++) v.push_back(A[d][k]);\n        sort(v.begin(), v.end());\n        int idx = min(D - 1, max(0, (int)floor(p * (D - 1) + 1e-9)));\n        res[k] = v[idx];\n    }\n    return res;\n}\n\nvector<vector<Rect>> treemap_dynamic_solution(int mode) {\n    auto sol = make_empty_solution();\n    for (int d = 0; d < D; d++) {\n        TreemapPacker tp;\n        auto r = tp.pack(A[d], mode);\n        for (int k = 0; k < N; k++) sol[d][k] = r[k];\n    }\n    return sol;\n}\n\nvector<vector<Rect>> treemap_static_solution(const vector<int>& base, int mode) {\n    auto sol = make_empty_solution();\n    TreemapPacker tp;\n    auto r = tp.pack(base, mode);\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) sol[d][k] = r[k];\n    }\n    return sol;\n}\n\n// ------------------------------------------------------------\n// Fixed-topology guillotine.\n// ------------------------------------------------------------\n\nstruct FixedGuillotine {\n    struct Node {\n        bool leaf = false;\n        int id = -1;\n        bool vertical = false;\n        int left = -1, right = -1;\n        int cnt = 0;\n    };\n\n    vector<int> base;\n    vector<Node> nodes;\n\n    int new_node() {\n        nodes.push_back(Node());\n        return (int)nodes.size() - 1;\n    }\n\n    ll sum_base(const vector<int>& ids) const {\n        ll s = 0;\n        for (int id : ids) s += base[id];\n        return s;\n    }\n\n    int build_rec(const vector<int>& ids, int w, int h) {\n        int idx = new_node();\n        nodes[idx].cnt = ids.size();\n\n        if ((int)ids.size() == 1) {\n            nodes[idx].leaf = true;\n            nodes[idx].id = ids[0];\n            return idx;\n        }\n\n        int m = ids.size();\n        ll total = max(1LL, sum_base(ids));\n        ll area = 1LL * w * h;\n\n        struct Cand {\n            ll score;\n            bool vertical;\n            vector<int> a, b;\n        };\n\n        vector<Cand> cands;\n\n        auto add_candidate = [&](vector<int> left) {\n            sort(left.begin(), left.end());\n            left.erase(unique(left.begin(), left.end()), left.end());\n\n            if (left.empty() || (int)left.size() == m) return;\n\n            vector<int> mark(N, 0);\n            for (int id : left) mark[id] = 1;\n\n            vector<int> right;\n            for (int id : ids) {\n                if (!mark[id]) right.push_back(id);\n            }\n            if (right.empty()) return;\n\n            ll s1 = 0, s2 = 0;\n            for (int id : left) s1 += base[id];\n            for (int id : right) s2 += base[id];\n\n            int n1 = left.size();\n            int n2 = right.size();\n\n            {\n                int lo = ceil_div(n1, h);\n                int hi = w - ceil_div(n2, h);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)w * s1 / total);\n                    int cut = max(lo, min(hi, ideal));\n                    ll cap1 = 1LL * cut * h;\n                    ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - 1LL * (w - cut) * h);\n                    ll dev = llabs(cap1 * total - s1 * area) / total;\n                    ll aspect = 1000LL * max(cut, h) / max(1, min(cut, h))\n                              + 1000LL * max(w - cut, h) / max(1, min(w - cut, h));\n                    ll score = shortage * 1000000000LL + dev * 1000LL + aspect + h;\n                    cands.push_back({score, true, left, right});\n                }\n            }\n\n            {\n                int lo = ceil_div(n1, w);\n                int hi = h - ceil_div(n2, w);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)h * s1 / total);\n                    int cut = max(lo, min(hi, ideal));\n                    ll cap1 = 1LL * w * cut;\n                    ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - 1LL * w * (h - cut));\n                    ll dev = llabs(cap1 * total - s1 * area) / total;\n                    ll aspect = 1000LL * max(w, cut) / max(1, min(w, cut))\n                              + 1000LL * max(w, h - cut) / max(1, min(w, h - cut));\n                    ll score = shortage * 1000000000LL + dev * 1000LL + aspect + w;\n                    cands.push_back({score, false, left, right});\n                }\n            }\n        };\n\n        vector<vector<int>> orders;\n\n        {\n            auto v = ids;\n            sort(v.begin(), v.end());\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (base[a] != base[b]) return base[a] > base[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (base[a] != base[b]) return base[a] < base[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n\n        for (auto ord : orders) {\n            vector<int> pref;\n            for (int i = 0; i + 1 < (int)ord.size(); i++) {\n                pref.push_back(ord[i]);\n                add_candidate(pref);\n            }\n        }\n\n        vector<double> targets = {0.25, 0.33, 0.40, 0.50, 0.60, 0.67, 0.75};\n        auto desc = ids;\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            if (base[a] != base[b]) return base[a] > base[b];\n            return a < b;\n        });\n\n        for (double t : targets) {\n            ll target = (ll)(total * t);\n            vector<int> group;\n            ll s = 0;\n            for (int id : desc) {\n                if (group.empty() || s + base[id] <= target) {\n                    group.push_back(id);\n                    s += base[id];\n                }\n            }\n            add_candidate(group);\n        }\n\n        if (cands.empty()) {\n            vector<int> a, b;\n            for (int i = 0; i < m; i++) {\n                if (i < m / 2) a.push_back(ids[i]);\n                else b.push_back(ids[i]);\n            }\n\n            bool vertical = (w >= h);\n            nodes[idx].vertical = vertical;\n\n            if (vertical) {\n                int cut = max(1, min(w - 1, w / 2));\n                nodes[idx].left = build_rec(a, cut, h);\n                nodes[idx].right = build_rec(b, w - cut, h);\n            } else {\n                int cut = max(1, min(h - 1, h / 2));\n                nodes[idx].left = build_rec(a, w, cut);\n                nodes[idx].right = build_rec(b, w, h - cut);\n            }\n            return idx;\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            return a.score < b.score;\n        });\n\n        auto best = cands[0];\n        nodes[idx].vertical = best.vertical;\n\n        ll s1 = 0;\n        for (int id : best.a) s1 += base[id];\n\n        if (best.vertical) {\n            int lo = ceil_div((int)best.a.size(), h);\n            int hi = w - ceil_div((int)best.b.size(), h);\n            int cut = max(lo, min(hi, (int)llround((long double)w * s1 / total)));\n            nodes[idx].left = build_rec(best.a, cut, h);\n            nodes[idx].right = build_rec(best.b, w - cut, h);\n        } else {\n            int lo = ceil_div((int)best.a.size(), w);\n            int hi = h - ceil_div((int)best.b.size(), w);\n            int cut = max(lo, min(hi, (int)llround((long double)h * s1 / total)));\n            nodes[idx].left = build_rec(best.a, w, cut);\n            nodes[idx].right = build_rec(best.b, w, h - cut);\n        }\n\n        return idx;\n    }\n\n    ll sum_weight(int idx, const vector<int>& weight) const {\n        const Node& nd = nodes[idx];\n        if (nd.leaf) return weight[nd.id];\n        return sum_weight(nd.left, weight) + sum_weight(nd.right, weight);\n    }\n\n    void layout_rec(int idx, int x, int y, int w, int h,\n                    const vector<int>& weight, vector<Rect>& out) const {\n        const Node& nd = nodes[idx];\n\n        if (nd.leaf) {\n            out[nd.id] = {y, x, y + h, x + w};\n            return;\n        }\n\n        const Node& L = nodes[nd.left];\n        const Node& R = nodes[nd.right];\n\n        ll sl = sum_weight(nd.left, weight);\n        ll sr = sum_weight(nd.right, weight);\n        ll total = max(1LL, sl + sr);\n\n        if (nd.vertical) {\n            int lo = ceil_div(L.cnt, h);\n            int hi = w - ceil_div(R.cnt, h);\n\n            int cut;\n            if (lo <= hi) {\n                int ideal = (int)llround((long double)w * sl / total);\n                cut = max(lo, min(hi, ideal));\n            } else {\n                cut = max(1, min(w - 1, w / 2));\n            }\n\n            layout_rec(nd.left, x, y, cut, h, weight, out);\n            layout_rec(nd.right, x + cut, y, w - cut, h, weight, out);\n        } else {\n            int lo = ceil_div(L.cnt, w);\n            int hi = h - ceil_div(R.cnt, w);\n\n            int cut;\n            if (lo <= hi) {\n                int ideal = (int)llround((long double)h * sl / total);\n                cut = max(lo, min(hi, ideal));\n            } else {\n                cut = max(1, min(h - 1, h / 2));\n            }\n\n            layout_rec(nd.left, x, y, w, cut, weight, out);\n            layout_rec(nd.right, x, y + cut, w, h - cut, weight, out);\n        }\n    }\n\n    vector<vector<Rect>> solve(const vector<int>& baseWeight, int alphaNum, int alphaDen) {\n        base = baseWeight;\n        nodes.clear();\n\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        int root = build_rec(ids, W, W);\n\n        auto sol = make_empty_solution();\n\n        for (int d = 0; d < D; d++) {\n            vector<int> mixed(N);\n            for (int k = 0; k < N; k++) {\n                ll v = 1LL * (alphaDen - alphaNum) * base[k] + 1LL * alphaNum * A[d][k];\n                mixed[k] = max(1, (int)((v + alphaDen / 2) / alphaDen));\n            }\n\n            vector<Rect> out(N);\n            layout_rec(root, 0, 0, W, W, mixed, out);\n\n            for (int k = 0; k < N; k++) sol[d][k] = out[k];\n        }\n\n        return sol;\n    }\n};\n\nvector<vector<Rect>> fixed_guillotine_solution(const vector<int>& base, int alphaNum, int alphaDen) {\n    FixedGuillotine fg;\n    return fg.solve(base, alphaNum, alphaDen);\n}\n\n// ------------------------------------------------------------\n// BFD shelf layouts.\n// ------------------------------------------------------------\n\nbool pack_bfd(const vector<int>& widths, int h, vector<vector<int>>& rows) {\n    rows.clear();\n    if (h <= 0 || h > 1000) return false;\n\n    int maxRows = 1000 / h;\n    if (maxRows <= 0) return false;\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 (widths[x] != widths[y]) return widths[x] > widths[y];\n        return x < y;\n    });\n\n    vector<int> rem;\n\n    for (int id : ids) {\n        int w = widths[id];\n        if (w <= 0 || w > 1000) return false;\n\n        int best = -1;\n        int bestRem = 1000000;\n\n        for (int r = 0; r < (int)rows.size(); r++) {\n            if (rem[r] >= w && rem[r] - w < bestRem) {\n                bestRem = rem[r] - w;\n                best = r;\n            }\n        }\n\n        if (best == -1) {\n            if ((int)rows.size() >= maxRows) return false;\n            rows.push_back(vector<int>{id});\n            rem.push_back(1000 - w);\n        } else {\n            rows[best].push_back(id);\n            rem[best] -= w;\n        }\n    }\n\n    for (auto& row : rows) sort(row.begin(), row.end());\n\n    sort(rows.begin(), rows.end(), [](const vector<int>& a, const vector<int>& b) {\n        return a.front() < b.front();\n    });\n\n    return true;\n}\n\nvector<vector<Rect>> build_from_rows_dynamic_height(\n    const vector<vector<vector<int>>>& allRows,\n    const vector<int>& hs\n) {\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        int h = hs[d];\n        int y = 0;\n\n        for (const auto& row : allRows[d]) {\n            int x = 0;\n            for (int t = 0; t < (int)row.size(); t++) {\n                int k = row[t];\n                int w;\n                if (t + 1 == (int)row.size()) w = W - x;\n                else w = ceil_div(A[d][k], h);\n                if (w <= 0) w = 1;\n\n                sol[d][k] = {y, x, y + h, x + w};\n                x += w;\n            }\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> static_bfd_solution() {\n    ll bestEst = (1LL << 60);\n    int bestH = -1;\n    vector<vector<int>> bestRows;\n\n    for (int h = 1; h <= 1000; h++) {\n        vector<int> widths(N);\n        bool ok = true;\n        for (int k = 0; k < N; k++) {\n            widths[k] = ceil_div(maxA[k], h);\n            if (widths[k] > 1000) ok = false;\n        }\n        if (!ok) continue;\n\n        vector<vector<int>> rows;\n        if (!pack_bfd(widths, h, rows)) continue;\n\n        ll est = 1LL * rows.size() * h;\n        if (est < bestEst) {\n            bestEst = est;\n            bestH = h;\n            bestRows = rows;\n        }\n    }\n\n    if (bestH == -1) return {};\n\n    auto sol = make_empty_solution();\n    int y = 0;\n\n    for (const auto& row : bestRows) {\n        int x = 0;\n        for (int t = 0; t < (int)row.size(); t++) {\n            int k = row[t];\n            int w;\n            if (t + 1 == (int)row.size()) w = W - x;\n            else w = ceil_div(maxA[k], bestH);\n\n            for (int d = 0; d < D; d++) {\n                sol[d][k] = {y, x, y + bestH, x + w};\n            }\n            x += w;\n        }\n        y += bestH;\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> per_day_bfd_solution() {\n    vector<vector<vector<int>>> allRows(D);\n    vector<int> hs(D, -1);\n\n    for (int d = 0; d < D; d++) {\n        ll bestEst = (1LL << 60);\n        int bestH = -1;\n        vector<vector<int>> bestRows;\n\n        for (int h = 1; h <= 1000; h++) {\n            vector<int> widths(N);\n            bool ok = true;\n            for (int k = 0; k < N; k++) {\n                widths[k] = ceil_div(A[d][k], h);\n                if (widths[k] > 1000) ok = false;\n            }\n            if (!ok) continue;\n\n            vector<vector<int>> rows;\n            if (!pack_bfd(widths, h, rows)) continue;\n\n            int R = (int)rows.size();\n            ll est = 1000LL * max(0, R - 1) + 1LL * h * max(0, N - R);\n            est += abs(h - 50);\n\n            if (est < bestEst) {\n                bestEst = est;\n                bestH = h;\n                bestRows = rows;\n            }\n        }\n\n        if (bestH == -1) return {};\n        hs[d] = bestH;\n        allRows[d] = bestRows;\n    }\n\n    return build_from_rows_dynamic_height(allRows, hs);\n}\n\nvector<vector<Rect>> fixed_h_bfd_solution(int h) {\n    vector<vector<vector<int>>> allRows(D);\n    vector<int> hs(D, h);\n\n    for (int d = 0; d < D; d++) {\n        vector<int> widths(N);\n        bool ok = true;\n        for (int k = 0; k < N; k++) {\n            widths[k] = ceil_div(A[d][k], h);\n            if (widths[k] > 1000) ok = false;\n        }\n        if (!ok) return {};\n\n        vector<vector<int>> rows;\n        if (!pack_bfd(widths, h, rows)) return {};\n        allRows[d] = rows;\n    }\n\n    return build_from_rows_dynamic_height(allRows, hs);\n}\n\nvector<int> promising_fixed_heights() {\n    vector<pair<ll,int>> cand;\n\n    for (int h = 1; h <= 1000; h++) {\n        bool allok = true;\n        ll est = 0;\n\n        for (int d = 0; d < D; d++) {\n            vector<int> widths(N);\n            bool ok = true;\n            for (int k = 0; k < N; k++) {\n                widths[k] = ceil_div(A[d][k], h);\n                if (widths[k] > 1000) ok = false;\n            }\n\n            if (!ok) {\n                allok = false;\n                break;\n            }\n\n            vector<vector<int>> rows;\n            if (!pack_bfd(widths, h, rows)) {\n                allok = false;\n                break;\n            }\n\n            int R = (int)rows.size();\n            est += 1000LL * max(0, R - 1);\n            est += 1LL * h * max(0, N - R);\n        }\n\n        if (allok) {\n            est += (1000 % h);\n            cand.push_back({est, h});\n        }\n    }\n\n    sort(cand.begin(), cand.end());\n\n    vector<int> res;\n    for (auto [e, h] : cand) {\n        bool close = false;\n        for (int x : res) if (abs(x - h) <= 2) close = true;\n        if (!close) res.push_back(h);\n        if ((int)res.size() >= 8) break;\n    }\n\n    return res;\n}\n\n// ------------------------------------------------------------\n// Contiguous shelf DP with arbitrary reservation order.\n// ord[pos] = original reservation index.\n// ------------------------------------------------------------\n\nvector<vector<Rect>> stable_shelf_dp_order(const vector<int>& ord) {\n    vector<vector<int>> B(D, vector<int>(N));\n    vector<int> maxB(N, 0);\n\n    for (int d = 0; d < D; d++) {\n        for (int p = 0; p < N; p++) {\n            B[d][p] = A[d][ord[p]];\n            maxB[p] = max(maxB[p], B[d][p]);\n        }\n    }\n\n    int K = N + 1;\n    int HD = 1001;\n\n    vector<int> pref(HD * D * K, 0);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) {\n                P(h, d, k + 1) = P(h, d, k) + ceil_div(B[d][k], h);\n            }\n        }\n    }\n\n    vector<int> prefMax(HD * K, 0);\n    auto PM = [&](int h, int k) -> int& {\n        return prefMax[h * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        PM(h, 0) = 0;\n        for (int k = 0; k < N; k++) {\n            PM(h, k + 1) = PM(h, k) + ceil_div(maxB[k], h);\n        }\n    }\n\n    auto dyn_feasible = [&](int l, int r, int h) {\n        for (int d = 0; d < D; d++) {\n            int s = P(h, d, r + 1) - P(h, d, l);\n            if (s > W) return false;\n        }\n        return true;\n    };\n\n    auto stat_feasible = [&](int l, int r, int h) {\n        int s = PM(h, r + 1) - PM(h, l);\n        return s <= W;\n    };\n\n    auto dyn_cost = [&](int l, int r, int h) -> ll {\n        int m = r - l + 1;\n        if (m <= 1) return 0;\n\n        ll res = 0;\n        vector<int> a, b;\n        a.reserve(m - 1);\n        b.reserve(m - 1);\n\n        for (int d = 1; d < D; d++) {\n            a.clear();\n            b.clear();\n\n            for (int t = l; t < r; t++) {\n                a.push_back(P(h, d - 1, t + 1) - P(h, d - 1, l));\n                b.push_back(P(h, d, t + 1) - P(h, d, l));\n            }\n\n            int i = 0, j = 0, common = 0;\n            while (i < (int)a.size() && j < (int)b.size()) {\n                if (a[i] == b[j]) {\n                    common++;\n                    i++;\n                    j++;\n                } else if (a[i] < b[j]) i++;\n                else j++;\n            }\n\n            int sym = 2 * (m - 1) - 2 * common;\n            res += 1LL * sym * h;\n        }\n\n        return res;\n    };\n\n    vector<Option> opts;\n    vector<vector<int>> byStart(N);\n\n    for (int l = 0; l < N; l++) {\n        for (int r = l; r < N; r++) {\n            int hmin = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (dyn_feasible(l, r, h)) {\n                    hmin = h;\n                    break;\n                }\n            }\n            if (hmin == -1) continue;\n\n            vector<Option> tmp;\n\n            auto add_dyn = [&](int h) {\n                if (h < hmin || h > 1000) return;\n                if (!dyn_feasible(l, r, h)) return;\n                tmp.push_back({l, r, h, dyn_cost(l, r, h), false});\n            };\n\n            add_dyn(hmin);\n            for (int x = 1; x <= 8; x++) add_dyn(hmin + x);\n\n            vector<pair<int,int>> fs = {\n                {11,10}, {6,5}, {5,4}, {4,3}, {3,2},\n                {2,1}, {5,2}, {3,1}, {4,1}, {5,1},\n                {6,1}, {8,1}, {10,1}\n            };\n\n            for (auto [num, den] : fs) {\n                int h = (hmin * num + den - 1) / den;\n                add_dyn(h);\n            }\n\n            int hs = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (stat_feasible(l, r, h)) {\n                    hs = h;\n                    break;\n                }\n            }\n            if (hs != -1) tmp.push_back({l, r, hs, 0, true});\n\n            sort(tmp.begin(), tmp.end(), [](const Option& a, const Option& b) {\n                if (a.h != b.h) return a.h < b.h;\n                if (a.cost != b.cost) return a.cost < b.cost;\n                return a.stat > b.stat;\n            });\n\n            vector<Option> uniq;\n            for (auto& op : tmp) {\n                if (uniq.empty() || uniq.back().h != op.h) uniq.push_back(op);\n                else if (op.cost < uniq.back().cost) uniq.back() = op;\n            }\n\n            ll best = (1LL << 60);\n            for (auto& op : uniq) {\n                if (op.cost < best) {\n                    best = op.cost;\n                    int id = (int)opts.size();\n                    opts.push_back(op);\n                    byStart[l].push_back(id);\n                }\n            }\n        }\n    }\n\n    const ll INF = (1LL << 60);\n    vector<vector<ll>> dp(N + 1, vector<ll>(1001, INF));\n    vector<vector<int>> parH(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parK(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parO(N + 1, vector<int>(1001, -1));\n\n    dp[0][0] = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int used = 0; used <= 1000; used++) {\n            if (dp[i][used] == INF) continue;\n\n            for (int id : byStart[i]) {\n                const Option& op = opts[id];\n                int nu = used + op.h;\n                if (nu > 1000) continue;\n\n                int ni = op.r + 1;\n                ll nv = dp[i][used] + op.cost;\n\n                if (nv < dp[ni][nu]) {\n                    dp[ni][nu] = nv;\n                    parH[ni][nu] = used;\n                    parK[ni][nu] = i;\n                    parO[ni][nu] = id;\n                }\n            }\n        }\n    }\n\n    int bestH = -1;\n    ll bestV = INF;\n\n    for (int h = 0; h <= 1000; h++) {\n        if (dp[N][h] < bestV) {\n            bestV = dp[N][h];\n            bestH = h;\n        }\n    }\n\n    if (bestH == -1 || bestV == INF) return {};\n\n    vector<Option> rows;\n    int curK = N, curH = bestH;\n\n    while (curK > 0) {\n        int id = parO[curK][curH];\n        if (id < 0) return {};\n\n        rows.push_back(opts[id]);\n\n        int pk = parK[curK][curH];\n        int ph = parH[curK][curH];\n        curK = pk;\n        curH = ph;\n    }\n\n    reverse(rows.begin(), rows.end());\n\n    auto sol = make_empty_solution();\n\n    int y = 0;\n    for (auto& op : rows) {\n        int l = op.l, r = op.r, h = op.h;\n\n        if (op.stat) {\n            vector<int> widths(r - l + 1);\n            int sum = 0;\n\n            for (int p = l; p < r; p++) {\n                widths[p - l] = ceil_div(maxB[p], h);\n                sum += widths[p - l];\n            }\n            widths[r - l] = W - sum;\n\n            for (int d = 0; d < D; d++) {\n                int x = 0;\n                for (int p = l; p <= r; p++) {\n                    int w = widths[p - l];\n                    int k = ord[p];\n                    sol[d][k] = {y, x, y + h, x + w};\n                    x += w;\n                }\n            }\n        } else {\n            for (int d = 0; d < D; d++) {\n                vector<int> widths(r - l + 1);\n                int sum = 0;\n\n                for (int p = l; p < r; p++) {\n                    widths[p - l] = ceil_div(B[d][p], h);\n                    sum += widths[p - l];\n                }\n                widths[r - l] = W - sum;\n\n                int x = 0;\n                for (int p = l; p <= r; p++) {\n                    int w = widths[p - l];\n                    int k = ord[p];\n                    sol[d][k] = {y, x, y + h, x + w};\n                    x += w;\n                }\n            }\n        }\n\n        y += h;\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> day_shelf_solution_order(const vector<int>& ord) {\n    vector<vector<int>> B(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int p = 0; p < N; p++) B[d][p] = A[d][ord[p]];\n    }\n\n    int K = N + 1;\n    int HD = 1001;\n\n    vector<int> pref(HD * D * K, 0);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) {\n                P(h, d, k + 1) = P(h, d, k) + ceil_div(B[d][k], h);\n            }\n        }\n    }\n\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        vector<vector<int>> hmin(N, vector<int>(N, -1));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l; r < N; r++) {\n                for (int h = 1; h <= 1000; h++) {\n                    int s = P(h, d, r + 1) - P(h, d, l);\n                    if (s <= W) {\n                        hmin[l][r] = h;\n                        break;\n                    }\n                }\n            }\n        }\n\n        const int INF = 1e9;\n        vector<int> dp(N + 1, INF), par(N + 1, -1);\n        dp[0] = 0;\n\n        for (int i = 0; i < N; i++) {\n            if (dp[i] == INF) continue;\n\n            for (int r = i; r < N; r++) {\n                int h = hmin[i][r];\n                if (h < 0) continue;\n\n                if (dp[i] + h < dp[r + 1]) {\n                    dp[r + 1] = dp[i] + h;\n                    par[r + 1] = i;\n                }\n            }\n        }\n\n        if (dp[N] > 1000) return {};\n\n        vector<pair<int,int>> rows;\n        int cur = N;\n\n        while (cur > 0) {\n            int p = par[cur];\n            if (p < 0) return {};\n            rows.push_back({p, cur - 1});\n            cur = p;\n        }\n\n        reverse(rows.begin(), rows.end());\n\n        int y = 0;\n        for (auto [l, r] : rows) {\n            int h = hmin[l][r];\n            int x = 0;\n\n            for (int p = l; p < r; p++) {\n                int w = ceil_div(B[d][p], h);\n                int k = ord[p];\n                sol[d][k] = {y, x, y + h, x + w};\n                x += w;\n            }\n\n            int k = ord[r];\n            sol[d][k] = {y, x, y + h, W};\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\n// ------------------------------------------------------------\n// Singleton strip fallback.\n// ------------------------------------------------------------\n\nvector<int> allocate_single_day_heights(int d) {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) -> int {\n        int rem = A[d][k] - h[k] * W;\n        if (rem <= 0) return 0;\n        return min(W, rem);\n    };\n\n    priority_queue<pair<int,int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n\n        if (b <= 0) break;\n\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<int> allocate_static_heights() {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) -> int {\n        int res = 0;\n        for (int d = 0; d < D; d++) {\n            int rem = A[d][k] - h[k] * W;\n            if (rem > 0) res += min(W, rem);\n        }\n        return res;\n    };\n\n    priority_queue<pair<int,int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n\n        if (b <= 0) break;\n\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<vector<Rect>> singleton_dynamic_solution() {\n    auto sol = make_empty_solution();\n\n    for (int d = 0; d < D; d++) {\n        vector<int> h = allocate_single_day_heights(d);\n        int y = 0;\n\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> singleton_static_solution() {\n    auto sol = make_empty_solution();\n    vector<int> h = allocate_static_heights();\n\n    for (int d = 0; d < D; d++) {\n        int y = 0;\n\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<int>> make_orders() {\n    vector<vector<int>> orders;\n\n    vector<int> id(N);\n    iota(id.begin(), id.end(), 0);\n    orders.push_back(id);\n\n    vector<int> rev = id;\n    reverse(rev.begin(), rev.end());\n    orders.push_back(rev);\n\n    vector<int> zig;\n    for (int l = 0, r = N - 1; l <= r; l++, r--) {\n        zig.push_back(l);\n        if (l != r) zig.push_back(r);\n    }\n    orders.push_back(zig);\n\n    vector<int> zag;\n    for (int l = 0, r = N - 1; l <= r; l++, r--) {\n        zag.push_back(r);\n        if (l != r) zag.push_back(l);\n    }\n    orders.push_back(zag);\n\n    return orders;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inputW;\n    cin >> inputW >> D >> N;\n\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    maxA.assign(N, 0);\n    for (int k = 0; k < N; k++) {\n        for (int d = 0; d < D; d++) {\n            maxA[k] = max(maxA[k], A[d][k]);\n        }\n    }\n\n    vector<vector<vector<Rect>>> candidates;\n\n    auto add_candidate = [&](vector<vector<Rect>> s) {\n        if (valid_solution(s)) candidates.push_back(move(s));\n    };\n\n    vector<int> avg = average_area_vector();\n    vector<int> p25 = percentile_area_vector(0.25);\n    vector<int> p50 = percentile_area_vector(0.50);\n    vector<int> p75 = percentile_area_vector(0.75);\n    vector<int> p90 = percentile_area_vector(0.90);\n\n    auto orders = make_orders();\n\n    // New: several reservation orders for contiguous shelf DP.\n    for (auto& ord : orders) {\n        add_candidate(stable_shelf_dp_order(ord));\n    }\n\n    // Per-day shelf is more expensive; use two most basic orders.\n    add_candidate(day_shelf_solution_order(orders[0]));\n    add_candidate(day_shelf_solution_order(orders[1]));\n\n    add_candidate(static_bfd_solution());\n    add_candidate(per_day_bfd_solution());\n\n    for (int h : promising_fixed_heights()) {\n        add_candidate(fixed_h_bfd_solution(h));\n    }\n\n    for (int mode = 0; mode <= 1; mode++) {\n        add_candidate(treemap_dynamic_solution(mode));\n        add_candidate(treemap_static_solution(maxA, mode));\n        add_candidate(treemap_static_solution(avg, mode));\n        add_candidate(treemap_static_solution(p75, mode));\n        add_candidate(treemap_static_solution(p90, mode));\n    }\n\n    add_candidate(fixed_guillotine_solution(avg, 0, 4));\n    add_candidate(fixed_guillotine_solution(avg, 1, 4));\n    add_candidate(fixed_guillotine_solution(avg, 2, 4));\n    add_candidate(fixed_guillotine_solution(avg, 3, 4));\n    add_candidate(fixed_guillotine_solution(avg, 4, 4));\n\n    add_candidate(fixed_guillotine_solution(maxA, 0, 4));\n    add_candidate(fixed_guillotine_solution(maxA, 1, 4));\n    add_candidate(fixed_guillotine_solution(maxA, 2, 4));\n    add_candidate(fixed_guillotine_solution(maxA, 4, 4));\n\n    add_candidate(fixed_guillotine_solution(p25, 2, 4));\n    add_candidate(fixed_guillotine_solution(p25, 4, 4));\n\n    add_candidate(fixed_guillotine_solution(p50, 1, 4));\n    add_candidate(fixed_guillotine_solution(p50, 2, 4));\n    add_candidate(fixed_guillotine_solution(p50, 3, 4));\n    add_candidate(fixed_guillotine_solution(p50, 4, 4));\n\n    add_candidate(fixed_guillotine_solution(p75, 1, 4));\n    add_candidate(fixed_guillotine_solution(p75, 2, 4));\n    add_candidate(fixed_guillotine_solution(p75, 4, 4));\n\n    add_candidate(fixed_guillotine_solution(p90, 1, 4));\n    add_candidate(fixed_guillotine_solution(p90, 2, 4));\n    add_candidate(fixed_guillotine_solution(p90, 4, 4));\n\n    add_candidate(singleton_dynamic_solution());\n    add_candidate(singleton_static_solution());\n\n    Scorer scorer;\n    ll bestScore = (1LL << 62);\n    int bestId = 0;\n\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        ll sc = scorer.score(candidates[i]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestId = i;\n        }\n    }\n\n    const auto& ans = candidates[bestId];\n\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            const Rect& r = ans[d][k];\n            cout << r.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 K = 81;\nstatic constexpr int MOD = 998244353;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int nextInt(int n) {\n        return int(next() % n);\n    }\n};\n\nstruct Action {\n    int m, p, q;\n    int cell[9];\n    int val[9];\n    long long sum;\n    int noise;\n    uint64_t lo, hi;\n};\n\nstruct State {\n    array<int, 81> board;\n    array<int, 81> seq;\n    long long score;\n};\n\nclass Solver {\nprivate:\n    int inN, M, inK;\n    int stamp[20][3][3];\n\n    vector<Action> actions;\n    vector<int> rawTopIds;\n\n    int DUMMY;\n\n    array<int, 81> initBoard;\n    long long initScore = 0;\n\n    chrono::steady_clock::time_point startTime;\n    static constexpr double TIME_LIMIT = 1.89;\n\n    XorShift rng;\n\n    inline double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    }\n\n    inline bool timeOver() const {\n        return elapsed() >= TIME_LIMIT;\n    }\n\n    inline bool overlapAction(int a, int b) const {\n        if (a == DUMMY || b == DUMMY) return false;\n        return ((actions[a].lo & actions[b].lo) | (actions[a].hi & actions[b].hi)) != 0;\n    }\n\n    inline long long rawKey(int id) const {\n        return actions[id].sum * 2048LL + actions[id].noise;\n    }\n\n    inline long long gainAdd(const array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long g = a.sum;\n\n        for (int k = 0; k < 9; k++) {\n            if (board[a.cell[k]] + a.val[k] >= MOD) {\n                g -= MOD;\n            }\n        }\n\n        return g;\n    }\n\n    inline long long gainRemove(const array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long g = -a.sum;\n\n        for (int k = 0; k < 9; k++) {\n            if (board[a.cell[k]] < a.val[k]) {\n                g += MOD;\n            }\n        }\n\n        return g;\n    }\n\n    inline long long applyAdd(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = a.sum;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int nv = board[c] + a.val[k];\n\n            if (nv >= MOD) {\n                nv -= MOD;\n                diff -= MOD;\n            }\n\n            board[c] = nv;\n        }\n\n        return diff;\n    }\n\n    inline long long applyRemove(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = -a.sum;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int nv = board[c] - a.val[k];\n\n            if (nv < 0) {\n                nv += MOD;\n                diff += MOD;\n            }\n\n            board[c] = nv;\n        }\n\n        return diff;\n    }\n\n    State emptyState() const {\n        State st;\n        st.board = initBoard;\n        st.seq.fill(DUMMY);\n        st.score = initScore;\n        return st;\n    }\n\n    template<int C>\n    inline void insertTop(array<int, C>& ids, array<long long, C>& gs, int id, long long g) {\n        if (g <= gs[C - 1]) return;\n\n        int pos = C - 1;\n\n        while (pos > 0 && g > gs[pos - 1]) {\n            ids[pos] = ids[pos - 1];\n            gs[pos] = gs[pos - 1];\n            pos--;\n        }\n\n        ids[pos] = id;\n        gs[pos] = g;\n    }\n\n    inline void addUnique(vector<int>& v, array<unsigned char, 1000>& used, int id) {\n        if (id < 0) return;\n\n        if (!used[id]) {\n            used[id] = 1;\n            v.push_back(id);\n        }\n    }\n\n    int bestAction(const array<int, 81>& board) const {\n        long long bestG = 0;\n        int bestId = DUMMY;\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(board, id);\n\n            if (g > bestG) {\n                bestG = g;\n                bestId = id;\n            }\n        }\n\n        return bestId;\n    }\n\n    State greedyState() {\n        State st = emptyState();\n\n        for (int t = 0; t < K; t++) {\n            int id = bestAction(st.board);\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    State randomizedGreedyState(int topC) {\n        State st = emptyState();\n        topC = min(topC, 32);\n\n        for (int t = 0; t < K; t++) {\n            array<int, 32> ids;\n            array<long long, 32> gs;\n\n            ids.fill(DUMMY);\n            gs.fill(LLONG_MIN / 4);\n\n            auto ins = [&](int id, long long g) {\n                if (g <= gs[topC - 1]) return;\n\n                int pos = topC - 1;\n\n                while (pos > 0 && g > gs[pos - 1]) {\n                    ids[pos] = ids[pos - 1];\n                    gs[pos] = gs[pos - 1];\n                    pos--;\n                }\n\n                ids[pos] = id;\n                gs[pos] = g;\n            };\n\n            ins(DUMMY, 0);\n\n            for (int id = 0; id < DUMMY; id++) {\n                ins(id, gainAdd(st.board, id));\n            }\n\n            int r;\n            int x = rng.nextInt(100);\n\n            if (x < 55) r = 0;\n            else if (x < 75) r = min(1, topC - 1);\n            else if (x < 88) r = min(2, topC - 1);\n            else r = rng.nextInt(topC);\n\n            int id = ids[r];\n            if (gs[r] < 0) id = DUMMY;\n\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    void shuffleOrder(array<int, 81>& ord) {\n        for (int i = K - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    void coordinateDescent(State& st, int maxPass) {\n        array<int, 81> ord;\n        for (int i = 0; i < K; i++) ord[i] = i;\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            if (timeOver()) return;\n\n            shuffleOrder(ord);\n            bool changed = false;\n\n            for (int oi = 0; oi < K; oi++) {\n                if ((oi & 7) == 0 && timeOver()) return;\n\n                int idx = ord[oi];\n                int oldId = st.seq[idx];\n\n                st.score += applyRemove(st.board, oldId);\n\n                long long bestG = 0;\n                int bestId = DUMMY;\n\n                for (int id = 0; id < DUMMY; id++) {\n                    long long g = gainAdd(st.board, id);\n\n                    if (g > bestG) {\n                        bestG = g;\n                        bestId = id;\n                    }\n                }\n\n                st.seq[idx] = bestId;\n                st.score += applyAdd(st.board, bestId);\n\n                if (bestId != oldId) changed = true;\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    int weakSlot(const State& st, int samples = 18) {\n        int bestIdx = rng.nextInt(K);\n        long long bestRemoveGain = gainRemove(st.board, st.seq[bestIdx]);\n\n        for (int t = 1; t < samples; t++) {\n            int idx = rng.nextInt(K);\n            long long g = gainRemove(st.board, st.seq[idx]);\n\n            if (g > bestRemoveGain) {\n                bestRemoveGain = g;\n                bestIdx = idx;\n            }\n        }\n\n        return bestIdx;\n    }\n\n    int weakSlotExcept(const State& st, int except, int refAction, int samples = 24) {\n        int bestIdx = -1;\n        long long bestValue = LLONG_MIN / 4;\n\n        for (int t = 0; t < samples; t++) {\n            int idx = rng.nextInt(K);\n            if (idx == except) continue;\n\n            long long v = gainRemove(st.board, st.seq[idx]);\n\n            if (overlapAction(refAction, st.seq[idx])) {\n                v += MOD / 2;\n            }\n\n            if (v > bestValue) {\n                bestValue = v;\n                bestIdx = idx;\n            }\n        }\n\n        if (bestIdx == -1) {\n            bestIdx = rng.nextInt(K - 1);\n            if (bestIdx >= except) bestIdx++;\n        }\n\n        return bestIdx;\n    }\n\n    void choosePairSlots(const State& st, int& x, int& y) {\n        int mode = rng.nextInt(100);\n\n        if (mode < 82) {\n            x = weakSlot(st, 16);\n            y = weakSlotExcept(st, x, st.seq[x], 26);\n        } else if (mode < 92) {\n            x = weakSlot(st, 12);\n            y = rng.nextInt(K - 1);\n            if (y >= x) y++;\n        } else {\n            x = rng.nextInt(K);\n            y = rng.nextInt(K - 1);\n            if (y >= x) y++;\n        }\n    }\n\n    void randomPerturb(State& st, int strength) {\n        for (int r = 0; r < strength; r++) {\n            int idx = rng.nextInt(K);\n            int oldId = st.seq[idx];\n\n            st.score += applyRemove(st.board, oldId);\n\n            int newId = rng.nextInt(DUMMY);\n            st.seq[idx] = newId;\n            st.score += applyAdd(st.board, newId);\n        }\n    }\n\n    void ruinRecreate(State& st, int strength, bool weak) {\n        bool used[81] = {};\n        vector<int> slots;\n        slots.reserve(strength);\n\n        while ((int)slots.size() < strength) {\n            int idx;\n\n            if (weak) {\n                idx = -1;\n                long long best = LLONG_MIN / 4;\n\n                for (int t = 0; t < 25; t++) {\n                    int cand = rng.nextInt(K);\n                    if (used[cand]) continue;\n\n                    long long g = gainRemove(st.board, st.seq[cand]);\n\n                    if (g > best) {\n                        best = g;\n                        idx = cand;\n                    }\n                }\n\n                if (idx == -1) idx = rng.nextInt(K);\n            } else {\n                idx = rng.nextInt(K);\n            }\n\n            if (!used[idx]) {\n                used[idx] = true;\n                slots.push_back(idx);\n\n                st.score += applyRemove(st.board, st.seq[idx]);\n                st.seq[idx] = DUMMY;\n            }\n        }\n\n        for (int i = (int)slots.size() - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(slots[i], slots[j]);\n        }\n\n        for (int idx : slots) {\n            int id = bestAction(st.board);\n            st.seq[idx] = id;\n            st.score += applyAdd(st.board, id);\n        }\n    }\n\n    vector<int> collectPairFirstCandidates(const array<int, 81>& board, int oldA, int oldB) {\n        static constexpr int CG = 26;\n\n        array<int, CG> gainIds;\n        array<long long, CG> gainKeys;\n\n        gainIds.fill(DUMMY);\n        gainKeys.fill(LLONG_MIN / 4);\n\n        insertTop<CG>(gainIds, gainKeys, DUMMY, 0);\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(board, id);\n            insertTop<CG>(gainIds, gainKeys, id, g);\n        }\n\n        vector<int> cand;\n        cand.reserve(48);\n        array<unsigned char, 1000> used{};\n\n        addUnique(cand, used, DUMMY);\n\n        for (int i = 0; i < CG; i++) {\n            addUnique(cand, used, gainIds[i]);\n        }\n\n        for (int i = 0; i < min<int>(8, rawTopIds.size()); i++) {\n            addUnique(cand, used, rawTopIds[i]);\n        }\n\n        addUnique(cand, used, oldA);\n        addUnique(cand, used, oldB);\n\n        for (int i = 0; i < 6; i++) {\n            addUnique(cand, used, rng.nextInt(DUMMY));\n        }\n\n        return cand;\n    }\n\n    bool pairAttempt(State& st) {\n        int x, y;\n        choosePairSlots(st, x, y);\n\n        int oldX = st.seq[x];\n        int oldY = st.seq[y];\n\n        long long originalScore = st.score;\n\n        st.score += applyRemove(st.board, oldX);\n        st.score += applyRemove(st.board, oldY);\n\n        long long baseScore = st.score;\n\n        vector<int> firstCand = collectPairFirstCandidates(st.board, oldX, oldY);\n\n        long long bestTotal = 0;\n        int bestA = DUMMY;\n        int bestB = DUMMY;\n\n        auto evalFirst = [&](int a) {\n            long long g1 = gainAdd(st.board, a);\n            applyAdd(st.board, a);\n\n            long long bestG2 = 0;\n            int b = DUMMY;\n\n            for (int id = 0; id < DUMMY; id++) {\n                long long g2 = gainAdd(st.board, id);\n\n                if (g2 > bestG2) {\n                    bestG2 = g2;\n                    b = id;\n                }\n            }\n\n            long long total = g1 + bestG2;\n\n            if (total > bestTotal) {\n                bestTotal = total;\n                bestA = a;\n                bestB = b;\n            }\n\n            applyRemove(st.board, a);\n        };\n\n        for (int a : firstCand) {\n            evalFirst(a);\n        }\n\n        if (baseScore + bestTotal > originalScore) {\n            st.seq[x] = bestA;\n            st.seq[y] = bestB;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, bestA);\n            st.score += applyAdd(st.board, bestB);\n\n            return true;\n        } else {\n            st.seq[x] = oldX;\n            st.seq[y] = oldY;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, oldX);\n            st.score += applyAdd(st.board, oldY);\n\n            return false;\n        }\n    }\n\n    vector<int> collectTripleFirstCandidates(const array<int, 81>& board, int oldA, int oldB, int oldC) {\n        static constexpr int CG = 10;\n\n        array<int, CG> gainIds;\n        array<long long, CG> gainKeys;\n\n        gainIds.fill(DUMMY);\n        gainKeys.fill(LLONG_MIN / 4);\n\n        insertTop<CG>(gainIds, gainKeys, DUMMY, 0);\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(board, id);\n            insertTop<CG>(gainIds, gainKeys, id, g);\n        }\n\n        vector<int> cand;\n        cand.reserve(24);\n        array<unsigned char, 1000> used{};\n\n        addUnique(cand, used, DUMMY);\n\n        for (int i = 0; i < CG; i++) {\n            addUnique(cand, used, gainIds[i]);\n        }\n\n        for (int i = 0; i < min<int>(4, rawTopIds.size()); i++) {\n            addUnique(cand, used, rawTopIds[i]);\n        }\n\n        addUnique(cand, used, oldA);\n        addUnique(cand, used, oldB);\n        addUnique(cand, used, oldC);\n\n        for (int i = 0; i < 3; i++) {\n            addUnique(cand, used, rng.nextInt(DUMMY));\n        }\n\n        return cand;\n    }\n\n    bool tripleAttempt(State& st) {\n        int x = weakSlot(st, 14);\n        int y = weakSlotExcept(st, x, st.seq[x], 20);\n\n        int z = -1;\n\n        for (int t = 0; t < 30; t++) {\n            int cand = rng.nextInt(K);\n\n            if (cand == x || cand == y) continue;\n\n            if (z == -1) {\n                z = cand;\n            } else {\n                long long vc = gainRemove(st.board, st.seq[cand]);\n                long long vz = gainRemove(st.board, st.seq[z]);\n\n                if (vc > vz) z = cand;\n            }\n        }\n\n        if (z == -1) {\n            z = rng.nextInt(K);\n            while (z == x || z == y) z = rng.nextInt(K);\n        }\n\n        int oldX = st.seq[x];\n        int oldY = st.seq[y];\n        int oldZ = st.seq[z];\n\n        long long originalScore = st.score;\n\n        st.score += applyRemove(st.board, oldX);\n        st.score += applyRemove(st.board, oldY);\n        st.score += applyRemove(st.board, oldZ);\n\n        long long baseScore = st.score;\n\n        static constexpr int C2 = 7;\n\n        vector<int> firstCand = collectTripleFirstCandidates(st.board, oldX, oldY, oldZ);\n\n        long long bestTotal = 0;\n        int bestA = DUMMY;\n        int bestB = DUMMY;\n        int bestC = DUMMY;\n\n        auto evalFirst = [&](int a) {\n            long long g1 = gainAdd(st.board, a);\n            applyAdd(st.board, a);\n\n            array<int, C2> secondIds;\n            array<long long, C2> secondGs;\n\n            secondIds.fill(DUMMY);\n            secondGs.fill(LLONG_MIN / 4);\n\n            insertTop<C2>(secondIds, secondGs, DUMMY, 0);\n\n            for (int id = 0; id < DUMMY; id++) {\n                insertTop<C2>(secondIds, secondGs, id, gainAdd(st.board, id));\n            }\n\n            for (int bi = 0; bi < C2; bi++) {\n                int b = secondIds[bi];\n\n                long long g2 = gainAdd(st.board, b);\n                applyAdd(st.board, b);\n\n                long long bestG3 = 0;\n                int c = DUMMY;\n\n                for (int id = 0; id < DUMMY; id++) {\n                    long long g3 = gainAdd(st.board, id);\n\n                    if (g3 > bestG3) {\n                        bestG3 = g3;\n                        c = id;\n                    }\n                }\n\n                long long total = g1 + g2 + bestG3;\n\n                if (total > bestTotal) {\n                    bestTotal = total;\n                    bestA = a;\n                    bestB = b;\n                    bestC = c;\n                }\n\n                applyRemove(st.board, b);\n            }\n\n            applyRemove(st.board, a);\n        };\n\n        for (int a : firstCand) {\n            evalFirst(a);\n        }\n\n        if (baseScore + bestTotal > originalScore) {\n            st.seq[x] = bestA;\n            st.seq[y] = bestB;\n            st.seq[z] = bestC;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, bestA);\n            st.score += applyAdd(st.board, bestB);\n            st.score += applyAdd(st.board, bestC);\n\n            return true;\n        } else {\n            st.seq[x] = oldX;\n            st.seq[y] = oldY;\n            st.seq[z] = oldZ;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, oldX);\n            st.score += applyAdd(st.board, oldY);\n            st.score += applyAdd(st.board, oldZ);\n\n            return false;\n        }\n    }\n\n    void pairLocalSearch(State& st, int attempts) {\n        int improved = 0;\n\n        for (int t = 0; t < attempts; t++) {\n            if ((t & 3) == 0 && timeOver()) return;\n\n            if (pairAttempt(st)) {\n                improved++;\n\n                if ((improved & 7) == 0) {\n                    coordinateDescent(st, 2);\n                }\n            }\n        }\n\n        if (improved > 0) coordinateDescent(st, 4);\n    }\n\n    void tripleLocalSearch(State& st, int attempts) {\n        int improved = 0;\n\n        for (int t = 0; t < attempts; t++) {\n            if (timeOver()) return;\n\n            if (tripleAttempt(st)) {\n                improved++;\n\n                if ((improved & 3) == 0) {\n                    coordinateDescent(st, 2);\n                }\n            }\n        }\n\n        if (improved > 0) coordinateDescent(st, 4);\n    }\n\npublic:\n    void readInput() {\n        cin >> inN >> M >> inK;\n\n        uint64_t seed = 123456789123ULL;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int x;\n                cin >> x;\n\n                initBoard[i * N + j] = x;\n                initScore += x;\n\n                seed ^= uint64_t(x + 1) * 1000003ULL;\n                seed = seed * 11995408973635179863ULL + 101;\n            }\n        }\n\n        for (int m = 0; m < M; m++) {\n            for (int i = 0; i < 3; i++) {\n                for (int j = 0; j < 3; j++) {\n                    cin >> stamp[m][i][j];\n\n                    seed ^= uint64_t(stamp[m][i][j] + 7) * 1000000007ULL;\n                    seed = seed * 1000003ULL + 97;\n                }\n            }\n        }\n\n        rng = XorShift(seed);\n    }\n\n    void buildActions() {\n        actions.clear();\n\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                for (int m = 0; m < M; m++) {\n                    Action a;\n                    a.m = m;\n                    a.p = p;\n                    a.q = q;\n                    a.sum = 0;\n                    a.lo = 0;\n                    a.hi = 0;\n\n                    uint64_t h = uint64_t(m + 1) * 1000003ULL\n                               ^ uint64_t(p + 11) * 10007ULL\n                               ^ uint64_t(q + 37) * 1009ULL;\n                    h ^= h >> 23;\n                    h *= 0x2127599bf4325c37ULL;\n                    h ^= h >> 47;\n                    a.noise = int(h & 2047);\n\n                    int idx = 0;\n\n                    for (int di = 0; di < 3; di++) {\n                        for (int dj = 0; dj < 3; dj++) {\n                            int c = (p + di) * N + (q + dj);\n\n                            a.cell[idx] = c;\n                            a.val[idx] = stamp[m][di][dj];\n                            a.sum += stamp[m][di][dj];\n\n                            if (c < 64) {\n                                a.lo |= 1ULL << c;\n                            } else {\n                                a.hi |= 1ULL << (c - 64);\n                            }\n\n                            idx++;\n                        }\n                    }\n\n                    actions.push_back(a);\n                }\n            }\n        }\n\n        DUMMY = (int)actions.size();\n\n        vector<pair<long long, int>> raw;\n        raw.reserve(DUMMY);\n\n        for (int id = 0; id < DUMMY; id++) {\n            raw.emplace_back(rawKey(id), id);\n        }\n\n        sort(raw.rbegin(), raw.rend());\n\n        rawTopIds.clear();\n        for (int i = 0; i < min<int>(80, raw.size()); i++) {\n            rawTopIds.push_back(raw[i].second);\n        }\n    }\n\n    void solve() {\n        startTime = chrono::steady_clock::now();\n\n        buildActions();\n\n        State best = greedyState();\n        coordinateDescent(best, 1000);\n\n        pairLocalSearch(best, 90);\n        tripleLocalSearch(best, 8);\n\n        int iter = 0;\n\n        while (!timeOver()) {\n            State cand;\n\n            int mode = iter % 10;\n\n            if (mode <= 3) {\n                cand = best;\n\n                int strength = 3 + rng.nextInt(10);\n                bool weak = (mode <= 1);\n\n                ruinRecreate(cand, strength, weak);\n                coordinateDescent(cand, 22);\n                pairLocalSearch(cand, 16);\n\n                if ((iter & 3) == 0) {\n                    tripleLocalSearch(cand, 2);\n                }\n            } else if (mode <= 6) {\n                cand = best;\n\n                int strength = 3 + rng.nextInt(12);\n\n                randomPerturb(cand, strength);\n                coordinateDescent(cand, 26);\n                pairLocalSearch(cand, 14);\n\n                if ((iter & 7) == 0) {\n                    tripleLocalSearch(cand, 2);\n                }\n            } else {\n                int topC = 6 + rng.nextInt(14);\n\n                cand = randomizedGreedyState(topC);\n                coordinateDescent(cand, 36);\n                pairLocalSearch(cand, 14);\n\n                if ((iter & 7) == 1) {\n                    tripleLocalSearch(cand, 2);\n                }\n            }\n\n            if (cand.score > best.score) {\n                best = cand;\n                coordinateDescent(best, 6);\n                pairLocalSearch(best, 8);\n            }\n\n            iter++;\n        }\n\n        vector<tuple<int, int, int>> ans;\n\n        for (int i = 0; i < K; i++) {\n            int id = best.seq[i];\n            if (id == DUMMY) continue;\n\n            const Action& a = actions[id];\n            ans.emplace_back(a.m, a.p, a.q);\n        }\n\n        cout << ans.size() << '\\n';\n\n        for (auto [m, p, q] : ans) {\n            cout << m << ' ' << p << ' ' << q << '\\n';\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\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int V = 25;\n\nstruct Param {\n    int deliverMode;\n    int digMode;\n    int storeMode;\n};\n\nint outputLength(const vector<string>& s) {\n    int t = 0;\n    for (auto &x : s) t = max(t, (int)x.size());\n    return t;\n}\n\nint mdist(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\n/* -------------------- Full local validator -------------------- */\n\nbool validateOutput(vector<string> S, const vector<vector<int>>& A) {\n    int T = outputLength(S);\n    if (T <= 0 || T > 10000) return false;\n\n    for (auto &s : S) {\n        if (s.empty() || (int)s.size() > 10000) return false;\n        while ((int)s.size() < T) s.push_back('.');\n    }\n\n    int grid[N][N];\n    int idx[N];\n    memset(grid, -1, sizeof(grid));\n    memset(idx, 0, sizeof(idx));\n\n    struct Crane {\n        int r, c;\n        int hold;\n        bool alive;\n    };\n\n    Crane cr[N];\n    for (int i = 0; i < N; i++) cr[i] = {i, 0, -1, true};\n\n    auto inside = [&](int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    };\n\n    for (int t = 0; t < T; t++) {\n        // 1. arrivals\n        for (int r = 0; r < N; r++) {\n            bool blockedByHolding = false;\n            for (int k = 0; k < N; k++) {\n                if (cr[k].alive && cr[k].hold != -1 && cr[k].r == r && cr[k].c == 0) {\n                    blockedByHolding = true;\n                }\n            }\n\n            if (idx[r] < N && grid[r][0] == -1 && !blockedByHolding) {\n                grid[r][0] = A[r][idx[r]];\n                idx[r]++;\n            }\n        }\n\n        vector<pair<int,int>> oldPos(N), newPos(N);\n        vector<bool> aliveAfter(N);\n        vector<char> act(N);\n\n        for (int i = 0; i < N; i++) {\n            act[i] = S[i][t];\n            if (string(\"PQUDLR.B\").find(act[i]) == string::npos) return false;\n\n            oldPos[i] = {cr[i].r, cr[i].c};\n            newPos[i] = oldPos[i];\n            aliveAfter[i] = cr[i].alive;\n\n            if (!cr[i].alive) {\n                if (act[i] != '.') return false;\n                continue;\n            }\n\n            char a = act[i];\n\n            if (a == 'P') {\n                if (cr[i].hold != -1 || grid[cr[i].r][cr[i].c] == -1) return false;\n            } else if (a == 'Q') {\n                if (cr[i].hold == -1 || grid[cr[i].r][cr[i].c] != -1) return false;\n            } else if (a == 'B') {\n                if (cr[i].hold != -1) return false;\n                aliveAfter[i] = false;\n            } else if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                int nr = cr[i].r;\n                int nc = cr[i].c;\n\n                if (a == 'U') nr--;\n                if (a == 'D') nr++;\n                if (a == 'L') nc--;\n                if (a == 'R') nc++;\n\n                if (!inside(nr, nc)) return false;\n\n                if (i != 0 && cr[i].hold != -1 && grid[nr][nc] != -1) return false;\n\n                newPos[i] = {nr, nc};\n            }\n        }\n\n        // collision\n        for (int i = 0; i < N; i++) {\n            if (!aliveAfter[i]) continue;\n            for (int j = i + 1; j < N; j++) {\n                if (!aliveAfter[j]) continue;\n                if (newPos[i] == newPos[j]) return false;\n            }\n        }\n\n        // swap\n        for (int i = 0; i < N; i++) {\n            if (!cr[i].alive || !aliveAfter[i]) continue;\n            for (int j = i + 1; j < N; j++) {\n                if (!cr[j].alive || !aliveAfter[j]) continue;\n                if (newPos[i] == oldPos[j] && newPos[j] == oldPos[i]) return false;\n            }\n        }\n\n        // apply P/Q\n        for (int i = 0; i < N; i++) {\n            if (!cr[i].alive) continue;\n\n            char a = act[i];\n\n            if (a == 'P') {\n                cr[i].hold = grid[cr[i].r][cr[i].c];\n                grid[cr[i].r][cr[i].c] = -1;\n            } else if (a == 'Q') {\n                grid[cr[i].r][cr[i].c] = cr[i].hold;\n                cr[i].hold = -1;\n            }\n        }\n\n        // apply movement / bomb\n        for (int i = 0; i < N; i++) {\n            if (!cr[i].alive) continue;\n\n            if (act[i] == 'B') {\n                cr[i].alive = false;\n            } else {\n                cr[i].r = newPos[i].first;\n                cr[i].c = newPos[i].second;\n            }\n        }\n\n        // 3. dispatch\n        for (int r = 0; r < N; r++) {\n            if (grid[r][N - 1] != -1) grid[r][N - 1] = -1;\n        }\n    }\n\n    return true;\n}\n\n/* -------------------- Large crane only greedy -------------------- */\n\nstruct GreedySolver {\n    vector<vector<int>> A;\n    Param param;\n\n    int grid[N][N];\n    int idx[N];\n\n    int cr = 0, cc = 0;\n    int hold = -1;\n\n    vector<string> S;\n    bool firstStep = true;\n\n    vector<int> nextNeed;\n    vector<int> delivered;\n    int deliveredCnt = 0;\n\n    GreedySolver(const vector<vector<int>>& A_, Param p) : A(A_), param(p) {\n        memset(grid, -1, sizeof(grid));\n        memset(idx, 0, sizeof(idx));\n        S.assign(N, \"\");\n        nextNeed.resize(N);\n        delivered.assign(V, 0);\n        for (int g = 0; g < N; g++) nextNeed[g] = g * N;\n    }\n\n    void step(char act) {\n        for (int r = 0; r < N; r++) {\n            bool blockedByHolding = (hold != -1 && cr == r && cc == 0);\n            if (idx[r] < N && grid[r][0] == -1 && !blockedByHolding) {\n                grid[r][0] = A[r][idx[r]];\n                idx[r]++;\n            }\n        }\n\n        S[0].push_back(act);\n        for (int i = 1; i < N; i++) {\n            if (firstStep) S[i].push_back('B');\n            else S[i].push_back('.');\n        }\n        firstStep = false;\n\n        if (act == 'P') {\n            hold = grid[cr][cc];\n            grid[cr][cc] = -1;\n        } else if (act == 'Q') {\n            grid[cr][cc] = hold;\n            hold = -1;\n        } else if (act == 'U') cr--;\n        else if (act == 'D') cr++;\n        else if (act == 'L') cc--;\n        else if (act == 'R') cc++;\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][N - 1] != -1) grid[r][N - 1] = -1;\n        }\n    }\n\n    void moveTo(int r, int c) {\n        while (cr < r) step('D');\n        while (cr > r) step('U');\n        while (cc < c) step('R');\n        while (cc > c) step('L');\n    }\n\n    void pickAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('P');\n    }\n\n    void releaseAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('Q');\n    }\n\n    void markDelivered(int id) {\n        if (!delivered[id]) {\n            delivered[id] = 1;\n            deliveredCnt++;\n        }\n\n        int g = id / N;\n        while (nextNeed[g] < (g + 1) * N && delivered[nextNeed[g]]) nextNeed[g]++;\n    }\n\n    optional<pair<int,int>> findAccessible(int id) {\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (grid[r][c] == id) return pair<int,int>{r, c};\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == id) {\n                return pair<int,int>{r, 0};\n            }\n        }\n\n        return nullopt;\n    }\n\n    int frontId(int r) const {\n        if (grid[r][0] != -1) return grid[r][0];\n        if (idx[r] < N) return A[r][idx[r]];\n        return -1;\n    }\n\n    vector<pair<int,int>> freeStorageCells() const {\n        vector<pair<int,int>> res;\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 1; c <= 3; c++) {\n                if (grid[r][c] == -1) res.push_back({r, c});\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (idx[r] >= N && grid[r][0] == -1) {\n                res.push_back({r, 0});\n            }\n        }\n\n        return res;\n    }\n\n    int estimateNextAfterDeliver(int deliveredId) {\n        int g0 = deliveredId / N;\n        int best = 20;\n\n        for (int g = 0; g < N; g++) {\n            int target = nextNeed[g];\n            if (g == g0) target++;\n            if (target >= (g + 1) * N) continue;\n\n            optional<pair<int,int>> pos;\n\n            for (int r = 0; r < N; r++) {\n                for (int c = 0; c < N; c++) {\n                    if (grid[r][c] == target && target != deliveredId) {\n                        pos = {r, c};\n                    }\n                }\n            }\n\n            for (int r = 0; r < N; r++) {\n                if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == target) {\n                    pos = {r, 0};\n                }\n            }\n\n            if (pos) {\n                best = min(best, mdist({g0, N - 1}, *pos) + mdist(*pos, {g, N - 1}));\n            }\n        }\n\n        return best;\n    }\n\n    int dispatchScore(int id, pair<int,int> src) {\n        int g = id / N;\n        int base = mdist({cr, cc}, src) + mdist(src, {g, N - 1});\n\n        if (param.deliverMode == 0) return base * 10;\n        if (param.deliverMode == 1) return mdist({cr, cc}, src) * 15 + mdist(src, {g, N - 1}) * 5;\n        if (param.deliverMode == 2) return base * 10 + estimateNextAfterDeliver(id) * 3;\n        return base * 10 - src.second * 2;\n    }\n\n    int depthToNeeded(int r) {\n        bool need[V] = {};\n\n        for (int g = 0; g < N; g++) {\n            if (nextNeed[g] < (g + 1) * N) need[nextNeed[g]] = true;\n        }\n\n        int d = 0;\n\n        if (grid[r][0] != -1) {\n            if (need[grid[r][0]]) return 0;\n            d = 1;\n        }\n\n        for (int k = idx[r]; k < N; k++, d++) {\n            if (need[A[r][k]]) return d;\n        }\n\n        return 100;\n    }\n\n    int digScore(int r) {\n        int f = frontId(r);\n        int dep = depthToNeeded(r);\n        int dcur = abs(cr - r) + cc;\n\n        int future = 0;\n        if (f != -1) {\n            int g = f / N;\n            future = abs(r - g) + 4;\n        }\n\n        if (param.digMode == 0) return dep * 100 + dcur * 5;\n        if (param.digMode == 1) return dep * 35 + dcur * 8 + future * 2;\n        if (param.digMode == 2) return dep * 25 + dcur * 15;\n        if (param.digMode == 3) return dep * 50 + dcur * 3 + future * 5;\n        return dep * 20 + dcur * 20 + r;\n    }\n\n    int chooseRowToDig() {\n        int bestRow = -1;\n        int bestScore = 1e9;\n\n        for (int r = 0; r < N; r++) {\n            int f = frontId(r);\n            if (f == -1) continue;\n            if (idx[r] >= N && grid[r][0] != -1) continue;\n\n            int sc = digScore(r);\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestRow = r;\n            }\n        }\n\n        if (bestRow != -1) return bestRow;\n\n        for (int r = 0; r < N; r++) {\n            if (frontId(r) != -1) return r;\n        }\n\n        return -1;\n    }\n\n    int storageScore(pair<int,int> from, pair<int,int> p, int id) {\n        int g = id / N;\n        int a = mdist(from, p);\n        int b = mdist(p, {g, N - 1});\n\n        if (param.storeMode == 0) return a * 10 + b * 10;\n        if (param.storeMode == 1) return a * 18 + b * 7;\n        if (param.storeMode == 2) return a * 7 + b * 18;\n        if (param.storeMode == 3) return a * 10 + b * 10 - p.second * 3;\n        return a * 10 + b * 10 + abs(p.first - g) * 5 - p.second;\n    }\n\n    pair<int,int> chooseStorageCell(pair<int,int> from, int id) {\n        auto cells = freeStorageCells();\n\n        pair<int,int> best = cells[0];\n        int bestCost = 1e9;\n\n        for (auto p : cells) {\n            int cost = storageScore(from, p, id);\n            if (cost < bestCost) {\n                bestCost = cost;\n                best = p;\n            }\n        }\n\n        return best;\n    }\n\n    void dispatchContainer(int id) {\n        auto srcOpt = findAccessible(id);\n        if (!srcOpt) return;\n\n        auto src = *srcOpt;\n        pickAt(src);\n\n        int g = id / N;\n        releaseAt({g, N - 1});\n\n        markDelivered(id);\n    }\n\n    void storeFrontContainer(int r) {\n        int id = frontId(r);\n        if (id == -1) return;\n\n        pair<int,int> src = {r, 0};\n        auto dst = chooseStorageCell(src, id);\n\n        pickAt(src);\n        releaseAt(dst);\n    }\n\n    void solve() {\n        while (deliveredCnt < V && (int)S[0].size() < 9500) {\n            int bestId = -1;\n            int bestScore = 1e9;\n\n            for (int g = 0; g < N; g++) {\n                if (nextNeed[g] >= (g + 1) * N) continue;\n\n                int id = nextNeed[g];\n                auto srcOpt = findAccessible(id);\n                if (!srcOpt) continue;\n\n                int sc = dispatchScore(id, *srcOpt);\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != -1) {\n                dispatchContainer(bestId);\n                continue;\n            }\n\n            auto cells = freeStorageCells();\n            if (!cells.empty()) {\n                int r = chooseRowToDig();\n                if (r != -1) {\n                    storeFrontContainer(r);\n                    continue;\n                }\n            }\n\n            step('.');\n        }\n\n        if (S[0].empty()) step('.');\n    }\n\n    vector<string> outputStrings() {\n        int T = outputLength(S);\n        for (auto &s : S) {\n            while ((int)s.size() < T) s.push_back('.');\n        }\n        return S;\n    }\n};\n\n/* -------------------- Small-assist subset solver -------------------- */\n\nstruct SmallAssistSolver {\n    vector<vector<int>> A;\n    Param param;\n    int mask;       // bit 0..3 correspond to rows 1..4\n    int stageCol;   // 2 or 3\n    int setupWait;  // 0..4\n\n    int grid[N][N];\n    int idx[N];\n\n    int lr = 0, lc = 0;\n    int lhold = -1;\n\n    int scol[N];\n    int shold[N];\n    bool salive[N];\n\n    vector<string> S;\n\n    vector<int> nextNeed;\n    vector<int> delivered;\n    int deliveredCnt = 0;\n    bool valid = true;\n\n    SmallAssistSolver(const vector<vector<int>>& A_, Param p, int mask_, int stageCol_, int setupWait_)\n        : A(A_), param(p), mask(mask_), stageCol(stageCol_), setupWait(setupWait_) {\n        memset(grid, -1, sizeof(grid));\n        memset(idx, 0, sizeof(idx));\n        S.assign(N, \"\");\n\n        for (int i = 0; i < N; i++) {\n            scol[i] = 0;\n            shold[i] = -1;\n            salive[i] = (i >= 1 && assisted(i));\n        }\n\n        nextNeed.resize(N);\n        delivered.assign(V, 0);\n        for (int g = 0; g < N; g++) nextNeed[g] = g * N;\n    }\n\n    bool assisted(int r) const {\n        if (r == 0) return false;\n        return (mask >> (r - 1)) & 1;\n    }\n\n    pair<int,int> deliveryTarget(int id) const {\n        int g = id / N;\n        if (assisted(g)) return {g, stageCol};\n        return {g, 4};\n    }\n\n    bool shuttlePathEmpty(int r) const {\n        if (!assisted(r)) return true;\n        for (int c = stageCol + 1; c <= 3; c++) {\n            if (grid[r][c] != -1) return false;\n        }\n        return true;\n    }\n\n    void step(char largeAct) {\n        if (!valid) return;\n\n        for (int r = 0; r < N; r++) {\n            bool blockedByLargeHolding = (lhold != -1 && lr == r && lc == 0);\n            bool blockedBySmallHolding =\n                (r >= 1 && salive[r] && shold[r] != -1 && scol[r] == 0);\n\n            if (idx[r] < N && grid[r][0] == -1 && !blockedByLargeHolding && !blockedBySmallHolding) {\n                grid[r][0] = A[r][idx[r]];\n                idx[r]++;\n            }\n        }\n\n        char acts[N];\n        acts[0] = largeAct;\n\n        int turn = (int)S[0].size();\n\n        for (int r = 1; r < N; r++) {\n            acts[r] = '.';\n\n            if (!assisted(r)) {\n                if (turn == 0) acts[r] = 'B';\n                continue;\n            }\n\n            if (!salive[r]) continue;\n\n            if (shold[r] != -1) {\n                if (scol[r] < 4) acts[r] = 'R';\n                else acts[r] = 'Q';\n            } else {\n                if (turn < 4 && scol[r] < 4) {\n                    acts[r] = 'R';\n                } else if (grid[r][stageCol] != -1) {\n                    if (scol[r] > stageCol) acts[r] = 'L';\n                    else if (scol[r] < stageCol) acts[r] = 'R';\n                    else acts[r] = 'P';\n                } else {\n                    if (scol[r] < 4) acts[r] = 'R';\n                }\n            }\n        }\n\n        for (int i = 0; i < N; i++) S[i].push_back(acts[i]);\n\n        if (largeAct == 'P') {\n            if (lhold != -1 || grid[lr][lc] == -1) valid = false;\n            else {\n                lhold = grid[lr][lc];\n                grid[lr][lc] = -1;\n            }\n        } else if (largeAct == 'Q') {\n            if (lhold == -1 || grid[lr][lc] != -1) valid = false;\n            else {\n                grid[lr][lc] = lhold;\n                lhold = -1;\n            }\n        } else if (largeAct == 'U') {\n            if (lr == 0) valid = false;\n            else lr--;\n        } else if (largeAct == 'D') {\n            if (lr == N - 1) valid = false;\n            else lr++;\n        } else if (largeAct == 'L') {\n            if (lc == 0) valid = false;\n            else lc--;\n        } else if (largeAct == 'R') {\n            if (lc == N - 1) valid = false;\n            else lc++;\n        }\n\n        for (int r = 1; r < N; r++) {\n            char a = acts[r];\n\n            if (a == 'B') {\n                salive[r] = false;\n            } else if (!salive[r]) {\n                // do nothing\n            } else if (a == 'L') {\n                if (scol[r] == 0) valid = false;\n                else scol[r]--;\n            } else if (a == 'R') {\n                if (scol[r] == 4) valid = false;\n                else {\n                    if (shold[r] != -1 && grid[r][scol[r] + 1] != -1) valid = false;\n                    scol[r]++;\n                }\n            } else if (a == 'P') {\n                if (shold[r] != -1 || grid[r][scol[r]] == -1) valid = false;\n                else {\n                    shold[r] = grid[r][scol[r]];\n                    grid[r][scol[r]] = -1;\n                }\n            } else if (a == 'Q') {\n                if (shold[r] == -1 || grid[r][scol[r]] != -1) valid = false;\n                else {\n                    grid[r][scol[r]] = shold[r];\n                    shold[r] = -1;\n                }\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][4] != -1) grid[r][4] = -1;\n        }\n    }\n\n    void waitSmallReadyForStage(int r) {\n        if (!assisted(r)) return;\n\n        int guard = 0;\n        while (valid &&\n               (grid[r][stageCol] != -1 || !shuttlePathEmpty(r) ||\n                shold[r] != -1 || scol[r] != 4) &&\n               guard++ < 100) {\n            step('.');\n        }\n    }\n\n    void moveTo(int r, int c) {\n        if (!valid) return;\n\n        if (assisted(r) && c == stageCol) {\n            moveTo(r, stageCol - 1);\n            waitSmallReadyForStage(r);\n            if (lc < stageCol) step('R');\n            return;\n        }\n\n        // Avoid travelling vertically through active shuttle lanes.\n        int safeCol = stageCol - 1;\n        if (lr != r && lc > safeCol) {\n            while (valid && lc > safeCol) step('L');\n        }\n\n        while (valid && lr < r) step('D');\n        while (valid && lr > r) step('U');\n        while (valid && lc < c) step('R');\n        while (valid && lc > c) step('L');\n    }\n\n    void pickAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('P');\n    }\n\n    void releaseAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('Q');\n    }\n\n    void markDelivered(int id) {\n        if (!delivered[id]) {\n            delivered[id] = 1;\n            deliveredCnt++;\n        }\n\n        int g = id / N;\n        while (nextNeed[g] < (g + 1) * N && delivered[nextNeed[g]]) nextNeed[g]++;\n    }\n\n    optional<pair<int,int>> findAccessible(int id) {\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (grid[r][c] == id) return pair<int,int>{r, c};\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == id) {\n                return pair<int,int>{r, 0};\n            }\n        }\n\n        return nullopt;\n    }\n\n    int frontId(int r) const {\n        if (grid[r][0] != -1) return grid[r][0];\n        if (idx[r] < N) return A[r][idx[r]];\n        return -1;\n    }\n\n    vector<pair<int,int>> freeStorageCells() const {\n        vector<pair<int,int>> res;\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 1; c <= 3; c++) {\n                if (grid[r][c] != -1) continue;\n\n                if (assisted(r)) {\n                    // Do not block shuttle stage or its carrying path.\n                    if (c >= stageCol) continue;\n                }\n\n                res.push_back({r, c});\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (idx[r] >= N && grid[r][0] == -1) {\n                res.push_back({r, 0});\n            }\n        }\n\n        return res;\n    }\n\n    int dispatchScore(int id, pair<int,int> src) {\n        auto dst = deliveryTarget(id);\n        int base = mdist({lr, lc}, src) + mdist(src, dst);\n\n        if (param.deliverMode == 0) return base * 10;\n        if (param.deliverMode == 1) return mdist({lr, lc}, src) * 15 + mdist(src, dst) * 5;\n        if (param.deliverMode == 2) return base * 10 + abs(dst.first - lr) * 2;\n        return base * 10 - src.second * 2;\n    }\n\n    int depthToNeeded(int r) {\n        bool need[V] = {};\n\n        for (int g = 0; g < N; g++) {\n            if (nextNeed[g] < (g + 1) * N) need[nextNeed[g]] = true;\n        }\n\n        int d = 0;\n\n        if (grid[r][0] != -1) {\n            if (need[grid[r][0]]) return 0;\n            d = 1;\n        }\n\n        for (int k = idx[r]; k < N; k++, d++) {\n            if (need[A[r][k]]) return d;\n        }\n\n        return 100;\n    }\n\n    int digScore(int r) {\n        int f = frontId(r);\n        int dep = depthToNeeded(r);\n        int dcur = abs(lr - r) + lc;\n\n        int future = 0;\n        if (f != -1) {\n            auto dst = deliveryTarget(f);\n            future = abs(r - dst.first) + dst.second;\n        }\n\n        if (param.digMode == 0) return dep * 100 + dcur * 5;\n        if (param.digMode == 1) return dep * 35 + dcur * 8 + future * 2;\n        if (param.digMode == 2) return dep * 25 + dcur * 15;\n        if (param.digMode == 3) return dep * 50 + dcur * 3 + future * 5;\n        return dep * 20 + dcur * 20 + r;\n    }\n\n    int chooseRowToDig() {\n        int bestRow = -1;\n        int bestScore = 1e9;\n\n        for (int r = 0; r < N; r++) {\n            int f = frontId(r);\n            if (f == -1) continue;\n            if (idx[r] >= N && grid[r][0] != -1) continue;\n\n            int sc = digScore(r);\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestRow = r;\n            }\n        }\n\n        if (bestRow != -1) return bestRow;\n\n        for (int r = 0; r < N; r++) {\n            if (frontId(r) != -1) return r;\n        }\n\n        return -1;\n    }\n\n    int storageScore(pair<int,int> from, pair<int,int> p, int id) {\n        auto dst = deliveryTarget(id);\n\n        int a = mdist(from, p);\n        int b = mdist(p, dst);\n\n        if (param.storeMode == 0) return a * 10 + b * 10;\n        if (param.storeMode == 1) return a * 18 + b * 7;\n        if (param.storeMode == 2) return a * 7 + b * 18;\n        if (param.storeMode == 3) return a * 10 + b * 10 - p.second * 3;\n        return a * 10 + b * 10 + abs(p.first - dst.first) * 5 - p.second;\n    }\n\n    pair<int,int> chooseStorageCell(pair<int,int> from, int id) {\n        auto cells = freeStorageCells();\n\n        pair<int,int> best = cells[0];\n        int bestCost = 1e9;\n\n        for (auto p : cells) {\n            int cost = storageScore(from, p, id);\n            if (cost < bestCost) {\n                bestCost = cost;\n                best = p;\n            }\n        }\n\n        return best;\n    }\n\n    void dispatchContainer(int id) {\n        auto srcOpt = findAccessible(id);\n        if (!srcOpt) return;\n\n        auto src = *srcOpt;\n        pickAt(src);\n\n        auto dst = deliveryTarget(id);\n        releaseAt(dst);\n\n        markDelivered(id);\n    }\n\n    void storeFrontContainer(int r) {\n        int id = frontId(r);\n        if (id == -1) return;\n\n        auto cells = freeStorageCells();\n        if (cells.empty()) return;\n\n        pair<int,int> src = {r, 0};\n        auto dst = chooseStorageCell(src, id);\n\n        pickAt(src);\n        releaseAt(dst);\n    }\n\n    void solve() {\n        for (int t = 0; t < setupWait; t++) step('.');\n\n        while (valid && deliveredCnt < V && (int)S[0].size() < 9500) {\n            int bestId = -1;\n            int bestScore = 1e9;\n\n            for (int g = 0; g < N; g++) {\n                if (nextNeed[g] >= (g + 1) * N) continue;\n\n                int id = nextNeed[g];\n                auto srcOpt = findAccessible(id);\n                if (!srcOpt) continue;\n\n                int sc = dispatchScore(id, *srcOpt);\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != -1) {\n                dispatchContainer(bestId);\n                continue;\n            }\n\n            auto cells = freeStorageCells();\n            if (!cells.empty()) {\n                int r = chooseRowToDig();\n                if (r != -1) {\n                    storeFrontContainer(r);\n                    continue;\n                }\n            }\n\n            step('.');\n        }\n\n        // Flush shuttle containers.\n        for (int t = 0; t < 120; t++) {\n            bool busy = false;\n\n            for (int r = 1; r < N; r++) {\n                if (!assisted(r)) continue;\n\n                if (grid[r][stageCol] != -1 || !shuttlePathEmpty(r) ||\n                    shold[r] != -1 || scol[r] != 4) {\n                    busy = true;\n                }\n            }\n\n            if (!busy) break;\n            step('.');\n        }\n\n        if (S[0].empty()) step('.');\n    }\n\n    vector<string> outputStrings() {\n        int T = outputLength(S);\n        for (auto &s : S) {\n            while ((int)s.size() < T) s.push_back('.');\n        }\n        return S;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    auto elapsedMs = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - startTime\n        ).count();\n    };\n\n    int inputN;\n    cin >> inputN;\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<Param> allParams;\n    for (int dm = 0; dm < 4; dm++) {\n        for (int dig = 0; dig < 5; dig++) {\n            for (int sm = 0; sm < 5; sm++) {\n                allParams.push_back({dm, dig, sm});\n            }\n        }\n    }\n\n    vector<Param> coreParams = {\n        {0,0,0}, {0,0,4}, {2,1,4},\n        {0,1,4}, {0,2,4}, {0,3,4}, {0,4,4},\n        {1,0,4}, {1,1,4}, {1,2,4},\n        {2,0,4}, {2,2,4}, {2,3,4},\n        {3,0,4}, {3,1,4}, {3,2,4},\n        {0,0,0}, {1,0,0}, {2,0,0}, {3,0,0},\n        {0,1,0}, {0,2,0}, {0,3,0}, {0,4,0},\n        {0,0,1}, {0,0,2}, {0,0,3}\n    };\n\n    // Strong default-like settings first.\n    allParams.insert(allParams.begin(), {0,0,0});\n    allParams.insert(allParams.begin(), {0,0,4});\n    allParams.insert(allParams.begin(), {2,1,4});\n\n    vector<string> best;\n    int bestLen = INT_MAX;\n\n    auto tryCandidate = [&](const vector<string>& cand) {\n        int len = outputLength(cand);\n        if (len >= bestLen) return;\n\n        if (validateOutput(cand, A)) {\n            bestLen = len;\n            best = cand;\n        }\n    };\n\n    // Safe large-crane-only variants.\n    for (auto p : allParams) {\n        GreedySolver solver(A, p);\n        solver.solve();\n\n        if (solver.deliveredCnt != V) continue;\n\n        auto cand = solver.outputStrings();\n        tryCandidate(cand);\n    }\n\n    // Previous robust style: all rows assisted, stage at column 3.\n    for (auto p : allParams) {\n        if (elapsedMs() > 2500) break;\n\n        SmallAssistSolver solver(A, p, 15, 3, 4);\n        solver.solve();\n\n        if (!solver.valid || solver.deliveredCnt != V) continue;\n\n        auto cand = solver.outputStrings();\n        tryCandidate(cand);\n    }\n\n    // Refinement 1: start large crane earlier while shuttles are still moving.\n    for (int wait : {0, 1, 2, 3}) {\n        for (auto p : coreParams) {\n            if (elapsedMs() > 2600) break;\n\n            SmallAssistSolver solver(A, p, 15, 3, wait);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n\n            auto cand = solver.outputStrings();\n            tryCandidate(cand);\n        }\n    }\n\n    // Refinement 2: drop at column 2 instead of 3. This saves large-crane travel\n    // if the small shuttle can absorb the extra work.\n    for (int wait : {0, 1, 2, 3, 4}) {\n        for (auto p : coreParams) {\n            if (elapsedMs() > 2650) break;\n\n            SmallAssistSolver solver(A, p, 15, 2, wait);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n\n            auto cand = solver.outputStrings();\n            tryCandidate(cand);\n        }\n    }\n\n    // Subsets of assisted rows, stage column 3.\n    for (int mask = 1; mask < 16; mask++) {\n        if (mask == 15) continue;\n\n        for (auto p : coreParams) {\n            if (elapsedMs() > 2700) break;\n\n            SmallAssistSolver solver(A, p, mask, 3, 4);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n\n            auto cand = solver.outputStrings();\n            tryCandidate(cand);\n        }\n    }\n\n    // Subsets with early start.\n    for (int mask = 1; mask < 16; mask++) {\n        if (mask == 15) continue;\n\n        for (int wait : {0, 2}) {\n            for (auto p : coreParams) {\n                if (elapsedMs() > 2750) break;\n\n                SmallAssistSolver solver(A, p, mask, 3, wait);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n\n                auto cand = solver.outputStrings();\n                tryCandidate(cand);\n            }\n        }\n    }\n\n    // Subsets with column-2 staging. A smaller sweep to stay safely under TL.\n    vector<Param> smallCore = {\n        {0,0,0}, {0,0,4}, {2,1,4},\n        {0,1,4}, {1,0,4}, {2,0,4}, {3,0,4},\n        {0,0,1}, {0,0,2}, {0,0,3}\n    };\n\n    for (int mask = 1; mask < 16; mask++) {\n        if (mask == 15) continue;\n\n        for (int wait : {0, 2, 4}) {\n            for (auto p : smallCore) {\n                if (elapsedMs() > 2800) break;\n\n                SmallAssistSolver solver(A, p, mask, 2, wait);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n\n                auto cand = solver.outputStrings();\n                tryCandidate(cand);\n            }\n        }\n    }\n\n    // Emergency fallback.\n    if (best.empty()) {\n        GreedySolver solver(A, {0,0,0});\n        solver.solve();\n        best = solver.outputStrings();\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int B = 10;\nstatic const int V = N * N;\nstatic const long long INF = (1LL << 60);\n\nint hval[V];\nlong long base_cost = 0;\n\nint dr[4] = {-1, 0, 1, 0};\nint dc[4] = {0, 1, 0, -1};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n\n    DSU(int n = 0) { init(n); }\n\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n\n        if (a == b) return false;\n\n        if (sz[a] < sz[b]) swap(a, b);\n\n        p[b] = a;\n        sz[a] += sz[b];\n\n        return true;\n    }\n};\n\nstruct Edge {\n    int a, b;\n};\n\nstruct EvalResult {\n    long long cost = INF;\n    vector<int> order; // nonzero cells only\n};\n\nint id20(int r, int c) {\n    return r * N + c;\n}\n\nint manhattan20(int a, int b) {\n    return abs(a / N - b / N) + abs(a % N - b % N);\n}\n\nint dir_between(int a, int b) {\n    int ar = a / N;\n    int ac = a % N;\n    int br = b / N;\n    int bc = b % N;\n\n    for (int d = 0; d < 4; d++) {\n        if (ar + dr[d] == br && ac + dc[d] == bc) return d;\n    }\n\n    return -1;\n}\n\nvoid add_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n\n    if (d < 0 || e < 0) return;\n\n    mask[a] |= (1u << d);\n    mask[b] |= (1u << e);\n}\n\nvoid remove_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n\n    if (d < 0 || e < 0) return;\n\n    mask[a] &= ~(1u << d);\n    mask[b] &= ~(1u << e);\n}\n\nvoid eval_order_direction(const vector<int>& seq, EvalResult& res, bool store_order) {\n    int M = (int)seq.size();\n\n    if (M == 0) {\n        if (0 < res.cost) {\n            res.cost = 0;\n            if (store_order) res.order.clear();\n        }\n        return;\n    }\n\n    static int pref[V + 1];\n\n    pref[0] = 0;\n\n    for (int i = 0; i < M; i++) {\n        pref[i + 1] = pref[i] + hval[seq[i]];\n    }\n\n    int mn = pref[0];\n\n    for (int i = 0; i < M; i++) {\n        mn = min(mn, pref[i]);\n    }\n\n    for (int k = 0; k < M; k++) {\n        if (pref[k] != mn) continue;\n\n        long long load = 0;\n        long long move_cost = 0;\n        bool ok = true;\n\n        int start = seq[k];\n\n        move_cost += 100LL * (start / N + start % N);\n\n        for (int t = 0; t < M; t++) {\n            int id = seq[(k + t) % M];\n\n            load += hval[id];\n\n            if (load < 0) {\n                ok = false;\n                break;\n            }\n\n            if (t + 1 < M) {\n                int nxt = seq[(k + t + 1) % M];\n                int dist = manhattan20(id, nxt);\n                move_cost += (100LL + load) * dist;\n            }\n        }\n\n        if (!ok || load != 0) continue;\n\n        long long cost = base_cost + move_cost;\n\n        if (cost < res.cost) {\n            res.cost = cost;\n\n            if (store_order) {\n                res.order.clear();\n                res.order.reserve(M);\n\n                for (int t = 0; t < M; t++) {\n                    res.order.push_back(seq[(k + t) % M]);\n                }\n            }\n        }\n    }\n}\n\nEvalResult evaluate_order_cycle(const vector<int>& seq, bool store_order) {\n    EvalResult res;\n\n    eval_order_direction(seq, res, store_order);\n\n    vector<int> rev = seq;\n    reverse(rev.begin(), rev.end());\n\n    eval_order_direction(rev, res, store_order);\n\n    return res;\n}\n\nEvalResult evaluate_hamiltonian_cycle_skip_zero(const vector<int>& cyc, bool store_order) {\n    vector<int> seq;\n    seq.reserve(V);\n\n    for (int x : cyc) {\n        if (hval[x] != 0) seq.push_back(x);\n    }\n\n    return evaluate_order_cycle(seq, store_order);\n}\n\nbool build_cycle_from_tree_edges(const vector<Edge>& tree_edges, vector<int>& cyc) {\n    array<unsigned char, V> mask;\n    mask.fill(0);\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int a = id20(2 * r, 2 * c);\n            int b = id20(2 * r, 2 * c + 1);\n            int e = id20(2 * r + 1, 2 * c + 1);\n            int d = id20(2 * r + 1, 2 * c);\n\n            add_edge_cell(mask, a, b);\n            add_edge_cell(mask, b, e);\n            add_edge_cell(mask, e, d);\n            add_edge_cell(mask, d, a);\n        }\n    }\n\n    for (auto ed : tree_edges) {\n        int ar = ed.a / B;\n        int ac = ed.a % B;\n        int br = ed.b / B;\n        int bc = ed.b % B;\n\n        if (ar == br) {\n            int r = ar;\n            int c = min(ac, bc);\n\n            int a1 = id20(2 * r, 2 * c + 1);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r, 2 * c + 2);\n            int b2 = id20(2 * r + 1, 2 * c + 2);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        } else {\n            int r = min(ar, br);\n            int c = ac;\n\n            int a1 = id20(2 * r + 1, 2 * c);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r + 2, 2 * c);\n            int b2 = id20(2 * r + 2, 2 * c + 1);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        }\n    }\n\n    for (int i = 0; i < V; i++) {\n        if (__builtin_popcount((int)mask[i]) != 2) return false;\n    }\n\n    cyc.clear();\n\n    int start = 0;\n    int cur = start;\n    int prev = -1;\n\n    while (true) {\n        cyc.push_back(cur);\n\n        int nxt = -1;\n\n        for (int d = 0; d < 4; d++) {\n            if (!(mask[cur] & (1u << d))) continue;\n\n            int r = cur / N + dr[d];\n            int c = cur % N + dc[d];\n            int nb = id20(r, c);\n\n            if (nb != prev) {\n                nxt = nb;\n                break;\n            }\n        }\n\n        if (nxt < 0) return false;\n\n        prev = cur;\n        cur = nxt;\n\n        if (cur == start) break;\n        if ((int)cyc.size() > V) return false;\n    }\n\n    return (int)cyc.size() == V;\n}\n\nvector<Edge> all_edges;\nint edge_id[100][100];\n\nvector<char> tree_to_mask(const vector<Edge>& tr) {\n    vector<char> in(all_edges.size(), 0);\n\n    for (auto e : tr) {\n        int id = edge_id[e.a][e.b];\n\n        if (id >= 0) {\n            in[id] = 1;\n        }\n    }\n\n    return in;\n}\n\nvector<Edge> mask_to_tree_edges(const vector<char>& in) {\n    vector<Edge> tr;\n    tr.reserve(B * B - 1);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        if (in[i]) tr.push_back(all_edges[i]);\n    }\n\n    return tr;\n}\n\nEvalResult evaluate_tree_mask(const vector<char>& in, bool store_order) {\n    vector<Edge> tr = mask_to_tree_edges(in);\n    vector<int> cyc;\n\n    if ((int)tr.size() != B * B - 1) return EvalResult();\n\n    if (!build_cycle_from_tree_edges(tr, cyc)) return EvalResult();\n\n    return evaluate_hamiltonian_cycle_skip_zero(cyc, store_order);\n}\n\nvector<Edge> make_row_tree(int col) {\n    vector<Edge> res;\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c + 1 < B; c++) {\n            res.push_back({r * B + c, r * B + c + 1});\n        }\n    }\n\n    for (int r = 0; r + 1 < B; r++) {\n        res.push_back({r * B + col, (r + 1) * B + col});\n    }\n\n    return res;\n}\n\nvector<Edge> make_col_tree(int row) {\n    vector<Edge> res;\n\n    for (int c = 0; c < B; c++) {\n        for (int r = 0; r + 1 < B; r++) {\n            res.push_back({r * B + c, (r + 1) * B + c});\n        }\n    }\n\n    for (int c = 0; c + 1 < B; c++) {\n        res.push_back({row * B + c, row * B + c + 1});\n    }\n\n    return res;\n}\n\nvector<char> random_kruskal_tree(mt19937& rng) {\n    vector<int> perm(all_edges.size());\n    iota(perm.begin(), perm.end(), 0);\n\n    shuffle(perm.begin(), perm.end(), rng);\n\n    DSU dsu(B * B);\n    vector<char> in(all_edges.size(), 0);\n\n    int cnt = 0;\n\n    for (int id : perm) {\n        auto e = all_edges[id];\n\n        if (dsu.unite(e.a, e.b)) {\n            in[id] = 1;\n            cnt++;\n\n            if (cnt == B * B - 1) break;\n        }\n    }\n\n    return in;\n}\n\nvector<char> random_prim_tree(mt19937& rng) {\n    vector<vector<pair<int, int>>> g(B * B);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        auto e = all_edges[i];\n\n        g[e.a].push_back({e.b, i});\n        g[e.b].push_back({e.a, i});\n    }\n\n    vector<char> used(B * B, 0);\n    vector<char> in(all_edges.size(), 0);\n\n    int st = uniform_int_distribution<int>(0, B * B - 1)(rng);\n\n    used[st] = 1;\n\n    vector<pair<int, int>> frontier;\n\n    for (auto p : g[st]) {\n        frontier.push_back({p.first, p.second});\n    }\n\n    int cnt = 0;\n\n    while (cnt < B * B - 1 && !frontier.empty()) {\n        int k = uniform_int_distribution<int>(0, (int)frontier.size() - 1)(rng);\n\n        auto [to, eid] = frontier[k];\n\n        frontier[k] = frontier.back();\n        frontier.pop_back();\n\n        auto e = all_edges[eid];\n\n        int a = e.a;\n        int b = e.b;\n        int nxt = -1;\n\n        if (used[a] && !used[b]) {\n            nxt = b;\n        } else if (used[b] && !used[a]) {\n            nxt = a;\n        } else {\n            continue;\n        }\n\n        used[nxt] = 1;\n        in[eid] = 1;\n        cnt++;\n\n        for (auto p : g[nxt]) {\n            if (!used[p.first]) {\n                frontier.push_back({p.first, p.second});\n            }\n        }\n    }\n\n    return in;\n}\n\nvector<int> get_path_edges_in_tree(const vector<char>& in, int s, int t) {\n    vector<vector<pair<int, int>>> g(B * B);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        if (!in[i]) continue;\n\n        auto e = all_edges[i];\n\n        g[e.a].push_back({e.b, i});\n        g[e.b].push_back({e.a, i});\n    }\n\n    vector<int> par(B * B, -1);\n    vector<int> pedge(B * B, -1);\n\n    queue<int> q;\n\n    par[s] = s;\n    q.push(s);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        if (v == t) break;\n\n        for (auto [to, eid] : g[v]) {\n            if (par[to] != -1) continue;\n\n            par[to] = v;\n            pedge[to] = eid;\n            q.push(to);\n        }\n    }\n\n    vector<int> path;\n\n    if (par[t] == -1) return path;\n\n    int cur = t;\n\n    while (cur != s) {\n        path.push_back(pedge[cur]);\n        cur = par[cur];\n    }\n\n    return path;\n}\n\nvoid local_search(vector<char>& cur_tree, EvalResult& global_best, const Timer& timer) {\n    EvalResult cur_eval = evaluate_tree_mask(cur_tree, false);\n    long long cur_cost = cur_eval.cost;\n\n    if (cur_cost >= INF) return;\n\n    bool improved = true;\n\n    while (timer.elapsed() < 1.85 && improved) {\n        improved = false;\n\n        long long best_cost = cur_cost;\n        int best_add = -1;\n        int best_rem = -1;\n\n        vector<int> non_edges;\n\n        for (int i = 0; i < (int)all_edges.size(); i++) {\n            if (!cur_tree[i]) {\n                non_edges.push_back(i);\n            }\n        }\n\n        for (int eid : non_edges) {\n            if (timer.elapsed() > 1.85) break;\n\n            auto e = all_edges[eid];\n            vector<int> path = get_path_edges_in_tree(cur_tree, e.a, e.b);\n\n            for (int rem : path) {\n                cur_tree[eid] = 1;\n                cur_tree[rem] = 0;\n\n                EvalResult ev = evaluate_tree_mask(cur_tree, false);\n\n                cur_tree[eid] = 0;\n                cur_tree[rem] = 1;\n\n                if (ev.cost < best_cost) {\n                    best_cost = ev.cost;\n                    best_add = eid;\n                    best_rem = rem;\n                }\n            }\n        }\n\n        if (best_add != -1) {\n            cur_tree[best_add] = 1;\n            cur_tree[best_rem] = 0;\n\n            cur_cost = best_cost;\n            improved = true;\n\n            EvalResult stored = evaluate_tree_mask(cur_tree, true);\n\n            if (stored.cost < global_best.cost) {\n                global_best = stored;\n            }\n        }\n    }\n}\n\nvoid try_order_candidate(EvalResult& best, const vector<int>& seq) {\n    EvalResult ev = evaluate_order_cycle(seq, true);\n\n    if (ev.cost < best.cost) {\n        best = ev;\n    }\n}\n\nvector<int> make_row_snake_order() {\n    vector<int> seq;\n\n    for (int r = 0; r < N; r++) {\n        if (r % 2 == 0) {\n            for (int c = 0; c < N; c++) {\n                int id = id20(r, c);\n                if (hval[id] != 0) seq.push_back(id);\n            }\n        } else {\n            for (int c = N - 1; c >= 0; c--) {\n                int id = id20(r, c);\n                if (hval[id] != 0) seq.push_back(id);\n            }\n        }\n    }\n\n    return seq;\n}\n\nvector<int> make_col_snake_order() {\n    vector<int> seq;\n\n    for (int c = 0; c < N; c++) {\n        if (c % 2 == 0) {\n            for (int r = 0; r < N; r++) {\n                int id = id20(r, c);\n                if (hval[id] != 0) seq.push_back(id);\n            }\n        } else {\n            for (int r = N - 1; r >= 0; r--) {\n                int id = id20(r, c);\n                if (hval[id] != 0) seq.push_back(id);\n            }\n        }\n    }\n\n    return seq;\n}\n\nvector<int> make_nearest_neighbor_order(int start_cell) {\n    vector<int> cells;\n\n    for (int i = 0; i < V; i++) {\n        if (hval[i] != 0) cells.push_back(i);\n    }\n\n    int M = (int)cells.size();\n\n    if (M == 0) return {};\n\n    vector<char> used(V, 0);\n    vector<int> seq;\n    seq.reserve(M);\n\n    int cur = cells[0];\n    int bestd = INF;\n\n    for (int x : cells) {\n        int d = manhattan20(start_cell, x);\n\n        if (d < bestd) {\n            bestd = d;\n            cur = x;\n        }\n    }\n\n    for (int step = 0; step < M; step++) {\n        seq.push_back(cur);\n        used[cur] = 1;\n\n        int nxt = -1;\n        int nd = 1e9;\n\n        for (int x : cells) {\n            if (used[x]) continue;\n\n            int d = manhattan20(cur, x);\n\n            if (d < nd) {\n                nd = d;\n                nxt = x;\n            }\n        }\n\n        if (nxt == -1) break;\n\n        cur = nxt;\n    }\n\n    return seq;\n}\n\nvoid optimize_order_directly(EvalResult& global_best, const Timer& timer, mt19937& rng) {\n    if (global_best.order.empty()) return;\n\n    vector<int> seq = global_best.order;\n\n    EvalResult cur_eval = evaluate_order_cycle(seq, true);\n\n    if (cur_eval.cost < global_best.cost) {\n        global_best = cur_eval;\n    }\n\n    seq = global_best.order;\n\n    long long cur_cost = global_best.cost;\n    int M = (int)seq.size();\n\n    auto accept_current = [&]() {\n        EvalResult stored = evaluate_order_cycle(seq, true);\n\n        cur_cost = stored.cost;\n        seq = stored.order;\n        M = (int)seq.size();\n\n        if (stored.cost < global_best.cost) {\n            global_best = stored;\n        }\n    };\n\n    while (timer.elapsed() < 1.94) {\n        bool found = false;\n\n        // 2-opt style reversal\n        for (int i = 0; i < M && !found; i++) {\n            if ((i & 7) == 0 && timer.elapsed() > 1.94) break;\n\n            for (int j = i + 2; j < M; j++) {\n                if (i == 0 && j == M - 1) continue;\n\n                reverse(seq.begin() + i + 1, seq.begin() + j + 1);\n\n                EvalResult ev = evaluate_order_cycle(seq, false);\n\n                if (ev.cost < cur_cost) {\n                    accept_current();\n                    found = true;\n                    break;\n                }\n\n                reverse(seq.begin() + i + 1, seq.begin() + j + 1);\n            }\n        }\n\n        if (found) continue;\n\n        // Relocation: remove one node and insert elsewhere.\n        for (int i = 0; i < M && !found; i++) {\n            if ((i & 7) == 0 && timer.elapsed() > 1.94) break;\n\n            int x = seq[i];\n            seq.erase(seq.begin() + i);\n\n            for (int j = 0; j < M - 1; j++) {\n                if (j == i || j == i - 1) continue;\n\n                seq.insert(seq.begin() + j, x);\n\n                EvalResult ev = evaluate_order_cycle(seq, false);\n\n                if (ev.cost < cur_cost) {\n                    accept_current();\n                    found = true;\n                    break;\n                }\n\n                seq.erase(seq.begin() + j);\n            }\n\n            if (!found) {\n                seq.insert(seq.begin() + i, x);\n            }\n        }\n\n        if (found) continue;\n\n        // Swap two nodes.\n        for (int i = 0; i < M && !found; i++) {\n            if ((i & 7) == 0 && timer.elapsed() > 1.94) break;\n\n            for (int j = i + 1; j < M; j++) {\n                swap(seq[i], seq[j]);\n\n                EvalResult ev = evaluate_order_cycle(seq, false);\n\n                if (ev.cost < cur_cost) {\n                    accept_current();\n                    found = true;\n                    break;\n                }\n\n                swap(seq[i], seq[j]);\n            }\n        }\n\n        if (!found) break;\n    }\n\n    // Small randomized improvement phase.\n    while (timer.elapsed() < 1.965) {\n        if (M <= 2) break;\n\n        int type = uniform_int_distribution<int>(0, 2)(rng);\n\n        if (type == 0) {\n            int i = uniform_int_distribution<int>(0, M - 2)(rng);\n            int j = uniform_int_distribution<int>(i + 1, M - 1)(rng);\n\n            if (i == 0 && j == M - 1) continue;\n\n            reverse(seq.begin() + i, seq.begin() + j + 1);\n\n            EvalResult ev = evaluate_order_cycle(seq, false);\n\n            if (ev.cost < cur_cost) {\n                accept_current();\n            } else {\n                reverse(seq.begin() + i, seq.begin() + j + 1);\n            }\n        } else if (type == 1) {\n            int i = uniform_int_distribution<int>(0, M - 1)(rng);\n            int j = uniform_int_distribution<int>(0, M - 1)(rng);\n\n            if (i == j) continue;\n\n            swap(seq[i], seq[j]);\n\n            EvalResult ev = evaluate_order_cycle(seq, false);\n\n            if (ev.cost < cur_cost) {\n                accept_current();\n            } else {\n                swap(seq[i], seq[j]);\n            }\n        } else {\n            int i = uniform_int_distribution<int>(0, M - 1)(rng);\n            int j = uniform_int_distribution<int>(0, M - 1)(rng);\n\n            if (i == j) continue;\n\n            int x = seq[i];\n\n            seq.erase(seq.begin() + i);\n\n            if (j > i) j--;\n\n            seq.insert(seq.begin() + j, x);\n\n            EvalResult ev = evaluate_order_cycle(seq, false);\n\n            if (ev.cost < cur_cost) {\n                accept_current();\n            } else {\n                seq.erase(seq.begin() + j);\n                seq.insert(seq.begin() + i, x);\n            }\n        }\n    }\n}\n\nvoid append_manhattan_moves(vector<string>& ans, int from, int to) {\n    int r = from / N;\n    int c = from % N;\n    int tr = to / N;\n    int tc = to % N;\n\n    while (r < tr) {\n        ans.push_back(\"D\");\n        r++;\n    }\n\n    while (r > tr) {\n        ans.push_back(\"U\");\n        r--;\n    }\n\n    while (c < tc) {\n        ans.push_back(\"R\");\n        c++;\n    }\n\n    while (c > tc) {\n        ans.push_back(\"L\");\n        c--;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int n;\n    cin >> n;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n\n            hval[id20(i, j)] = x;\n            base_cost += abs(x);\n        }\n    }\n\n    if (base_cost == 0) {\n        return 0;\n    }\n\n    memset(edge_id, -1, sizeof(edge_id));\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int v = r * B + c;\n\n            if (r + 1 < B) {\n                int u = (r + 1) * B + c;\n                int id = all_edges.size();\n\n                all_edges.push_back({v, u});\n\n                edge_id[v][u] = edge_id[u][v] = id;\n            }\n\n            if (c + 1 < B) {\n                int u = r * B + c + 1;\n                int id = all_edges.size();\n\n                all_edges.push_back({v, u});\n\n                edge_id[v][u] = edge_id[u][v] = id;\n            }\n        }\n    }\n\n    mt19937 rng(123456789);\n\n    EvalResult best;\n    vector<char> best_tree;\n\n    // Extra order candidates.\n    try_order_candidate(best, make_row_snake_order());\n    try_order_candidate(best, make_col_snake_order());\n\n    {\n        vector<int> rev = make_row_snake_order();\n        reverse(rev.begin(), rev.end());\n        try_order_candidate(best, rev);\n    }\n\n    {\n        vector<int> rev = make_col_snake_order();\n        reverse(rev.begin(), rev.end());\n        try_order_candidate(best, rev);\n    }\n\n    try_order_candidate(best, make_nearest_neighbor_order(id20(0, 0)));\n    try_order_candidate(best, make_nearest_neighbor_order(id20(0, N - 1)));\n    try_order_candidate(best, make_nearest_neighbor_order(id20(N - 1, 0)));\n    try_order_candidate(best, make_nearest_neighbor_order(id20(N - 1, N - 1)));\n\n    auto try_tree = [&](const vector<char>& in) {\n        EvalResult ev = evaluate_tree_mask(in, true);\n\n        if (ev.cost < best.cost) {\n            best = ev;\n            best_tree = in;\n        }\n    };\n\n    for (int c = 0; c < B; c++) {\n        try_tree(tree_to_mask(make_row_tree(c)));\n    }\n\n    for (int r = 0; r < B; r++) {\n        try_tree(tree_to_mask(make_col_tree(r)));\n    }\n\n    int iter = 0;\n\n    while (timer.elapsed() < 0.95) {\n        vector<char> tr;\n\n        if (iter & 1) {\n            tr = random_kruskal_tree(rng);\n        } else {\n            tr = random_prim_tree(rng);\n        }\n\n        try_tree(tr);\n\n        iter++;\n    }\n\n    if (!best_tree.empty()) {\n        vector<char> cur = best_tree;\n\n        local_search(cur, best, timer);\n\n        best_tree = cur;\n    }\n\n    while (timer.elapsed() < 1.83) {\n        vector<char> tr;\n\n        if (iter & 1) {\n            tr = random_kruskal_tree(rng);\n        } else {\n            tr = random_prim_tree(rng);\n        }\n\n        EvalResult ev = evaluate_tree_mask(tr, true);\n\n        if (ev.cost < best.cost) {\n            best = ev;\n            best_tree = tr;\n\n            vector<char> cur = best_tree;\n\n            local_search(cur, best, timer);\n\n            best_tree = cur;\n        }\n\n        iter++;\n    }\n\n    optimize_order_directly(best, timer, rng);\n\n    if (best.order.empty()) {\n        return 0;\n    }\n\n    vector<string> ans;\n\n    int cur = 0;\n\n    append_manhattan_moves(ans, cur, best.order[0]);\n    cur = best.order[0];\n\n    long long load = 0;\n\n    for (int idx = 0; idx < (int)best.order.size(); idx++) {\n        int id = best.order[idx];\n        int v = hval[id];\n\n        if (v > 0) {\n            ans.push_back(\"+\" + to_string(v));\n            load += v;\n        } else if (v < 0) {\n            ans.push_back(\"-\" + to_string(-v));\n            load += v;\n        }\n\n        if (idx + 1 < (int)best.order.size()) {\n            int nxt = best.order[idx + 1];\n\n            append_manhattan_moves(ans, id, nxt);\n\n            cur = nxt;\n        }\n    }\n\n    for (const string& s : ans) {\n        cout << s << '\\n';\n    }\n\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    int randint(int n) {\n        return (int)(next_u32() % n);\n    }\n\n    double uniform01() {\n        return (next_u32() >> 8) * (1.0 / 16777216.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int G = N * N;\n    const int K = 2 * N * (N - 1);\n    const int MAXS = 1500;\n    const int TOTAL = 1 << 15;\n\n    vector<vector<int>> X(K, vector<int>(M));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    XorShift rng;\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) {\n            rng.x ^= (uint64_t)(X[i][j] + 1009) * 11995408973635179863ULL;\n            rng.x ^= rng.x << 7;\n            rng.x ^= rng.x >> 9;\n        }\n    }\n\n    vector<int> initialMax(M, 0);\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) {\n            initialMax[j] = max(initialMax[j], X[i][j]);\n        }\n    }\n\n    vector<pair<int, int>> edges;\n    vector<vector<int>> incident(G);\n    vector<vector<int>> neigh(G);\n\n    auto gid = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j + 1 < N; j++) {\n            int a = gid(i, j);\n            int b = gid(i, j + 1);\n            int e = edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n            neigh[a].push_back(b);\n            neigh[b].push_back(a);\n        }\n    }\n\n    for (int i = 0; i + 1 < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = gid(i, j);\n            int b = gid(i + 1, j);\n            int e = edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n            neigh[a].push_back(b);\n            neigh[b].push_back(a);\n        }\n    }\n\n    vector<int> posOrder(G);\n    iota(posOrder.begin(), posOrder.end(), 0);\n\n    sort(posOrder.begin(), posOrder.end(), [&](int a, int b) {\n        int da = incident[a].size();\n        int db = incident[b].size();\n        if (da != db) return da > db;\n\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n        double ca = abs(ai - (N - 1) / 2.0) + abs(aj - (N - 1) / 2.0);\n        double cb = abs(bi - (N - 1) / 2.0) + abs(bj - (N - 1) / 2.0);\n        return ca < cb;\n    });\n\n    vector<double> logVal(TOTAL + 1, -1e100);\n    for (int i = 1; i <= TOTAL; i++) {\n        logVal[i] = log((double)i / TOTAL);\n    }\n\n    auto calc_delta_pair_score = [&](const vector<int>& slots,\n                                     const vector<vector<double>>& W,\n                                     int a,\n                                     int b) -> double {\n        if (a == b) return 0.0;\n        if (a >= G && b >= G) return 0.0;\n\n        double delta = 0.0;\n\n        for (auto [u, v] : edges) {\n            if (u != a && u != b && v != a && v != b) continue;\n\n            int su = slots[u];\n            int sv = slots[v];\n\n            int nsu = su;\n            int nsv = sv;\n\n            if (u == a) nsu = slots[b];\n            else if (u == b) nsu = slots[a];\n\n            if (v == a) nsv = slots[b];\n            else if (v == b) nsv = slots[a];\n\n            delta += W[nsu][nsv] - W[su][sv];\n        }\n\n        return delta;\n    };\n\n    auto total_pair_score = [&](const vector<int>& slots,\n                                const vector<vector<double>>& W) -> double {\n        double s = 0.0;\n        for (auto [u, v] : edges) {\n            s += W[slots[u]][slots[v]];\n        }\n        return s;\n    };\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> sumValue(K, 0);\n        for (int i = 0; i < K; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) s += X[i][j];\n            sumValue[i] = s;\n        }\n\n        double progress = (T == 1 ? 1.0 : (double)turn / (T - 1));\n\n        bool useExactQuantile = (turn >= 4);\n        bool finalTurn = (turn == T - 1);\n\n        vector<vector<int>> q950(K, vector<int>(K, 0));\n        vector<vector<int>> q985(K, vector<int>(K, 0));\n        vector<vector<int>> q995(K, vector<int>(K, 0));\n\n        vector<unsigned short> cdf;\n        if (finalTurn) {\n            cdf.assign(K * K * (MAXS + 1), 0);\n        }\n\n        if (useExactQuantile || finalTurn) {\n            vector<int> cnt(MAXS + 1, 0), nxt(MAXS + 1, 0);\n            vector<int> active, nactive;\n\n            int target950 = (950 * TOTAL + 999) / 1000;\n            int target985 = (985 * TOTAL + 999) / 1000;\n            int target995 = (995 * TOTAL + 999) / 1000;\n\n            for (int i = 0; i < K; i++) {\n                for (int j = i + 1; j < K; j++) {\n                    fill(cnt.begin(), cnt.end(), 0);\n                    fill(nxt.begin(), nxt.end(), 0);\n\n                    active.clear();\n                    active.push_back(0);\n                    cnt[0] = 1;\n\n                    for (int l = 0; l < M; l++) {\n                        nactive.clear();\n\n                        int a = X[i][l];\n                        int b = X[j][l];\n\n                        for (int s : active) {\n                            int c = cnt[s];\n\n                            int s1 = s + a;\n                            if (nxt[s1] == 0) nactive.push_back(s1);\n                            nxt[s1] += c;\n\n                            int s2 = s + b;\n                            if (nxt[s2] == 0) nactive.push_back(s2);\n                            nxt[s2] += c;\n                        }\n\n                        for (int s : active) cnt[s] = 0;\n\n                        for (int s : nactive) {\n                            cnt[s] = nxt[s];\n                            nxt[s] = 0;\n                        }\n\n                        active.swap(nactive);\n                    }\n\n                    int cum = 0;\n                    int qq950 = MAXS;\n                    int qq985 = MAXS;\n                    int qq995 = MAXS;\n                    bool f950 = false, f985 = false, f995 = false;\n\n                    int base1 = (i * K + j) * (MAXS + 1);\n                    int base2 = (j * K + i) * (MAXS + 1);\n\n                    for (int s = 0; s <= MAXS; s++) {\n                        cum += cnt[s];\n\n                        if (!f950 && cum >= target950) {\n                            qq950 = s;\n                            f950 = true;\n                        }\n\n                        if (!f985 && cum >= target985) {\n                            qq985 = s;\n                            f985 = true;\n                        }\n\n                        if (!f995 && cum >= target995) {\n                            qq995 = s;\n                            f995 = true;\n                        }\n\n                        if (finalTurn) {\n                            cdf[base1 + s] = (unsigned short)cum;\n                            cdf[base2 + s] = (unsigned short)cum;\n                        }\n                    }\n\n                    q950[i][j] = q950[j][i] = qq950;\n                    q985[i][j] = q985[j][i] = qq985;\n                    q995[i][j] = q995[j][i] = qq995;\n                }\n            }\n        }\n\n        double alpha = 0.45 * (1.0 - progress) + 0.08 * progress;\n        double tailCoef = 0.55 * (1.0 - progress) + 1.30 * progress;\n        double geneCoef = 0.08 * (1.0 - progress) + 0.02 * progress;\n\n        vector<vector<double>> W(K, vector<double>(K, 0.0));\n\n        for (int i = 0; i < K; i++) {\n            for (int j = i + 1; j < K; j++) {\n                double mu = 0.5 * (sumValue[i] + sumValue[j]);\n\n                double cmax = 0.0;\n                double diff2 = 0.0;\n                double gene = 0.0;\n\n                for (int l = 0; l < M; l++) {\n                    int a = X[i][l];\n                    int b = X[j][l];\n                    int mx = max(a, b);\n                    int d = a - b;\n\n                    cmax += mx;\n                    diff2 += (double)d * d;\n\n                    int den = max(1, initialMax[l]);\n                    gene += (double)mx * mx / den;\n                }\n\n                double sigma = 0.5 * sqrt(diff2);\n\n                double baseScore = mu;\n                baseScore += alpha * (cmax - mu);\n                baseScore += tailCoef * sigma;\n                baseScore += geneCoef * gene;\n\n                double score = baseScore;\n\n                if (useExactQuantile) {\n                    double exactScore =\n                        0.20 * q950[i][j] +\n                        0.55 * q985[i][j] +\n                        0.18 * q995[i][j] +\n                        0.07 * cmax;\n\n                    double blend = min(1.0, progress * progress * 1.15);\n                    score = (1.0 - blend) * baseScore + blend * exactScore;\n                }\n\n                W[i][j] = W[j][i] = score;\n            }\n        }\n\n        vector<double> potBySeed(K, 0.0);\n        vector<pair<double, int>> potential;\n        potential.reserve(K);\n\n        for (int i = 0; i < K; i++) {\n            vector<double> v;\n            v.reserve(K - 1);\n\n            for (int j = 0; j < K; j++) {\n                if (i != j) v.push_back(W[i][j]);\n            }\n\n            nth_element(v.begin(), v.begin() + 8, v.end(), greater<double>());\n\n            double p = 0.0;\n            for (int k = 0; k < 8; k++) p += v[k];\n\n            p += 0.16 * sumValue[i];\n\n            double soloGene = 0.0;\n            for (int l = 0; l < M; l++) {\n                int den = max(1, initialMax[l]);\n                double r = (double)X[i][l] / den;\n                soloGene += X[i][l] * r * r;\n            }\n\n            p += (0.85 * (1.0 - progress) + 0.25 * progress) * soloGene;\n\n            potBySeed[i] = p;\n            potential.push_back({p, i});\n        }\n\n        sort(potential.begin(), potential.end(), greater<pair<double, int>>());\n\n        vector<int> slots(K, -1);\n        vector<int> usedSeed(K, 0);\n        vector<int> selected;\n        selected.reserve(G);\n\n        for (int k = 0; k < G; k++) {\n            selected.push_back(potential[k].second);\n            usedSeed[potential[k].second] = 1;\n        }\n\n        // Greedy constructive initial layout.\n        vector<int> placedSeed(K, 0);\n        vector<int> filledPos(G, 0);\n\n        int firstPos = posOrder[0];\n        int firstSeed = selected[0];\n\n        slots[firstPos] = firstSeed;\n        filledPos[firstPos] = 1;\n        placedSeed[firstSeed] = 1;\n\n        for (int step = 1; step < G; step++) {\n            int bestPos = -1;\n            tuple<int, int, double> bestPosKey(-1, -1, 1e100);\n\n            for (int p = 0; p < G; p++) {\n                if (filledPos[p]) continue;\n\n                int cnt = 0;\n                for (int nb : neigh[p]) {\n                    if (filledPos[nb]) cnt++;\n                }\n\n                int deg = incident[p].size();\n                int pi = p / N, pj = p % N;\n                double centerDist = abs(pi - (N - 1) / 2.0) + abs(pj - (N - 1) / 2.0);\n\n                auto key = make_tuple(cnt, deg, -centerDist);\n                if (key > bestPosKey) {\n                    bestPosKey = key;\n                    bestPos = p;\n                }\n            }\n\n            int bestSeed = -1;\n            double bestScore = -1e100;\n\n            for (int s : selected) {\n                if (placedSeed[s]) continue;\n\n                double sc = 0.025 * potBySeed[s];\n\n                for (int nb : neigh[bestPos]) {\n                    if (filledPos[nb]) {\n                        sc += W[s][slots[nb]];\n                    }\n                }\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestSeed = s;\n                }\n            }\n\n            slots[bestPos] = bestSeed;\n            filledPos[bestPos] = 1;\n            placedSeed[bestSeed] = 1;\n        }\n\n        int ptr = G;\n        for (int i = 0; i < K; i++) {\n            if (!usedSeed[i]) {\n                slots[ptr++] = i;\n            }\n        }\n\n        double curScore = total_pair_score(slots, W);\n\n        int ITER = finalTurn ? 75000 : 92000;\n        double T0 = finalTurn ? 60.0 : 82.0;\n        double T1 = 0.05;\n\n        for (int it = 0; it < ITER; it++) {\n            int a, b;\n\n            if (rng.randint(100) < 67) {\n                a = rng.randint(G);\n                b = rng.randint(K);\n            } else {\n                a = rng.randint(K);\n                b = rng.randint(K);\n            }\n\n            if (a == b) continue;\n            if (a >= G && b >= G) continue;\n\n            double delta = calc_delta_pair_score(slots, W, a, b);\n\n            double ratio = (double)it / ITER;\n            double temp = T0 * (1.0 - ratio) + T1 * ratio;\n\n            bool accept = false;\n            if (delta >= 0.0) {\n                accept = true;\n            } else {\n                double prob = exp(delta / temp);\n                if (rng.uniform01() < prob) accept = true;\n            }\n\n            if (accept) {\n                swap(slots[a], slots[b]);\n                curScore += delta;\n            }\n        }\n\n        for (int pass = 0; pass < 3; pass++) {\n            bool improved = false;\n\n            for (int a = 0; a < K; a++) {\n                for (int b = a + 1; b < K; b++) {\n                    if (a >= G && b >= G) continue;\n\n                    double delta = calc_delta_pair_score(slots, W, a, b);\n                    if (delta > 1e-9) {\n                        swap(slots[a], slots[b]);\n                        curScore += delta;\n                        improved = true;\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n\n        if (finalTurn) {\n            vector<double> sumLog(MAXS + 1, 0.0), tmpLog(MAXS + 1);\n            vector<int> zeroCnt(MAXS + 1, 0), tmpZero(MAXS + 1);\n\n            auto addPair = [&](vector<double>& sl,\n                               vector<int>& zc,\n                               int a,\n                               int b,\n                               int coef) {\n                int base = (a * K + b) * (MAXS + 1);\n                for (int s = 0; s <= MAXS; s++) {\n                    int c = cdf[base + s];\n                    if (c == 0) {\n                        zc[s] += coef;\n                    } else {\n                        sl[s] += coef * logVal[c];\n                    }\n                }\n            };\n\n            auto exactScoreFromState = [&](const vector<double>& sl,\n                                           const vector<int>& zc) {\n                double res = 0.0;\n                for (int s = 0; s < MAXS; s++) {\n                    double prod = (zc[s] > 0 ? 0.0 : exp(sl[s]));\n                    res += 1.0 - prod;\n                }\n                return res;\n            };\n\n            for (auto [u, v] : edges) {\n                addPair(sumLog, zeroCnt, slots[u], slots[v], +1);\n            }\n\n            double exactCur = exactScoreFromState(sumLog, zeroCnt);\n            double bestExact = exactCur;\n            vector<int> bestExactSlots = slots;\n            vector<double> bestLog = sumLog;\n            vector<int> bestZero = zeroCnt;\n\n            auto evalExactSwap = [&](int a, int b) -> double {\n                tmpLog = sumLog;\n                tmpZero = zeroCnt;\n\n                vector<int> aff;\n\n                if (a < G) {\n                    for (int e : incident[a]) aff.push_back(e);\n                }\n                if (b < G) {\n                    for (int e : incident[b]) aff.push_back(e);\n                }\n\n                sort(aff.begin(), aff.end());\n                aff.erase(unique(aff.begin(), aff.end()), aff.end());\n\n                for (int e : aff) {\n                    auto [u, v] = edges[e];\n\n                    int oldU = slots[u];\n                    int oldV = slots[v];\n\n                    int newU = oldU;\n                    int newV = oldV;\n\n                    if (u == a) newU = slots[b];\n                    else if (u == b) newU = slots[a];\n\n                    if (v == a) newV = slots[b];\n                    else if (v == b) newV = slots[a];\n\n                    addPair(tmpLog, tmpZero, oldU, oldV, -1);\n                    addPair(tmpLog, tmpZero, newU, newV, +1);\n                }\n\n                return exactScoreFromState(tmpLog, tmpZero);\n            };\n\n            const int EXACT_ITER = 16000;\n\n            for (int it = 0; it < EXACT_ITER; it++) {\n                int a, b;\n\n                if (rng.randint(100) < 72) {\n                    a = rng.randint(G);\n                    b = rng.randint(K);\n                } else {\n                    a = rng.randint(K);\n                    b = rng.randint(K);\n                }\n\n                if (a == b) continue;\n                if (a >= G && b >= G) continue;\n\n                double nxtScore = evalExactSwap(a, b);\n                double delta = nxtScore - exactCur;\n\n                double ratio = (double)it / EXACT_ITER;\n                double temp = 3.2 * (1.0 - ratio) + 0.01 * ratio;\n\n                bool accept = false;\n                if (delta >= 0.0) {\n                    accept = true;\n                } else {\n                    if (rng.uniform01() < exp(delta / temp)) accept = true;\n                }\n\n                if (accept) {\n                    swap(slots[a], slots[b]);\n                    sumLog.swap(tmpLog);\n                    zeroCnt.swap(tmpZero);\n                    exactCur = nxtScore;\n\n                    if (exactCur > bestExact) {\n                        bestExact = exactCur;\n                        bestExactSlots = slots;\n                        bestLog = sumLog;\n                        bestZero = zeroCnt;\n                    }\n                }\n            }\n\n            slots = bestExactSlots;\n            sumLog = bestLog;\n            zeroCnt = bestZero;\n            exactCur = bestExact;\n\n            for (int pass = 0; pass < 2; pass++) {\n                bool improved = false;\n\n                for (int a = 0; a < K; a++) {\n                    for (int b = a + 1; b < K; b++) {\n                        if (a >= G && b >= G) continue;\n\n                        double nxtScore = evalExactSwap(a, b);\n                        if (nxtScore > exactCur + 1e-9) {\n                            swap(slots[a], slots[b]);\n                            sumLog.swap(tmpLog);\n                            zeroCnt.swap(tmpZero);\n                            exactCur = nxtScore;\n                            improved = true;\n                        }\n                    }\n                }\n\n                if (!improved) break;\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << slots[gid(i, j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < M; j++) {\n                if (!(cin >> X[i][j])) return 0;\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing Clock = chrono::steady_clock;\nClock::time_point START_TIME;\n\nbool time_ok(double limit = 2.72) {\n    return chrono::duration<double>(Clock::now() - START_TIME).count() < limit;\n}\n\nstruct Pos {\n    int x, y;\n};\n\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\n\nint manhattan(const Pos& a, const Pos& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nbool inside(int N, int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\nstruct Solution {\n    int Vp = 1;\n    vector<pair<int, int>> edges;\n    Pos init{0, 0};\n    vector<string> ops;\n};\n\nchar move_char(Pos& cur, const Pos& to) {\n    if (cur.x < to.x) {\n        cur.x++;\n        return 'D';\n    }\n    if (cur.x > to.x) {\n        cur.x--;\n        return 'U';\n    }\n    if (cur.y < to.y) {\n        cur.y++;\n        return 'R';\n    }\n    if (cur.y > to.y) {\n        cur.y--;\n        return 'L';\n    }\n    return '.';\n}\n\nbool better_choice(int mode, int k, int cost, int bestK, int bestCost, long long score, long long bestScore) {\n    if (mode == 0) {\n        return k > bestK || (k == bestK && cost < bestCost);\n    } else if (mode == 1) {\n        return score > bestScore || (score == bestScore && (k > bestK || (k == bestK && cost < bestCost)));\n    } else {\n        if (bestK < 0) return true;\n        long long lhs = 1LL * k * (bestCost + 8);\n        long long rhs = 1LL * bestK * (cost + 8);\n        return lhs > rhs || (lhs == rhs && cost < bestCost);\n    }\n}\n\n/* ---------- one-finger fallback ---------- */\n\nvoid append_single_move(vector<string>& ops, Pos& cur, const Pos& to, bool action) {\n    vector<char> mv;\n\n    while (cur.x < to.x) {\n        mv.push_back('D');\n        cur.x++;\n    }\n    while (cur.x > to.x) {\n        mv.push_back('U');\n        cur.x--;\n    }\n    while (cur.y < to.y) {\n        mv.push_back('R');\n        cur.y++;\n    }\n    while (cur.y > to.y) {\n        mv.push_back('L');\n        cur.y--;\n    }\n\n    if (mv.empty()) {\n        if (action) ops.push_back(\".P\");\n        return;\n    }\n\n    for (int i = 0; i < (int)mv.size(); i++) {\n        string op = \"..\";\n        op[0] = mv[i];\n        if (i + 1 == (int)mv.size() && action) op[1] = 'P';\n        ops.push_back(op);\n    }\n}\n\nSolution make_single_solution(const vector<Pos>& src, const vector<Pos>& dst) {\n    int D = src.size();\n\n    Solution sol;\n    sol.Vp = 1;\n    sol.init = {0, 0};\n\n    if (D == 0) return sol;\n\n    vector<int> remS(D), remT(D);\n    iota(remS.begin(), remS.end(), 0);\n    iota(remT.begin(), remT.end(), 0);\n\n    vector<pair<int, int>> plan;\n    Pos cur{0, 0};\n    bool hasCur = false;\n\n    while (!remS.empty()) {\n        int bestSI = -1;\n        int bestTI = -1;\n        int bestScore = INT_MAX;\n\n        for (int ai = 0; ai < (int)remS.size(); ai++) {\n            int si = remS[ai];\n            int dcur = hasCur ? manhattan(cur, src[si]) : 0;\n\n            for (int bi = 0; bi < (int)remT.size(); bi++) {\n                int ti = remT[bi];\n                int score = dcur + 2 * manhattan(src[si], dst[ti]);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    bestSI = ai;\n                    bestTI = bi;\n                }\n            }\n        }\n\n        int si = remS[bestSI];\n        int ti = remT[bestTI];\n\n        plan.push_back({si, ti});\n        cur = dst[ti];\n        hasCur = true;\n\n        remS[bestSI] = remS.back();\n        remS.pop_back();\n\n        remT[bestTI] = remT.back();\n        remT.pop_back();\n    }\n\n    sol.init = src[plan[0].first];\n    cur = sol.init;\n    sol.ops.push_back(\".P\");\n\n    for (int i = 0; i < D; i++) {\n        int si = plan[i].first;\n        int ti = plan[i].second;\n\n        if (i > 0) append_single_move(sol.ops, cur, src[si], true);\n        append_single_move(sol.ops, cur, dst[ti], true);\n    }\n\n    return sol;\n}\n\n/* ---------- star arm ---------- */\n\nstruct StarState {\n    int Vp;\n    Pos root;\n    vector<int> dir;\n    vector<int> holding;\n    vector<string> ops;\n};\n\nvoid star_move_rotate_action(\n    StarState& st,\n    const Pos& to,\n    const vector<int>& desired,\n    const vector<int>& actionLeaves\n) {\n    vector<int> act(st.Vp, 0);\n    for (int leaf : actionLeaves) act[leaf] = 1;\n\n    auto ready = [&]() {\n        if (st.root.x != to.x || st.root.y != to.y) return false;\n        for (int i = 1; i < st.Vp; i++) {\n            if (desired[i] != -1 && st.dir[i] != desired[i]) return false;\n        }\n        return true;\n    };\n\n    while (true) {\n        if (ready()) {\n            string op(2 * st.Vp, '.');\n            bool any = false;\n\n            for (int i = 1; i < st.Vp; i++) {\n                if (act[i]) {\n                    op[st.Vp + i] = 'P';\n                    st.holding[i] ^= 1;\n                    any = true;\n                }\n            }\n\n            if (any) st.ops.push_back(op);\n            return;\n        }\n\n        string op(2 * st.Vp, '.');\n        op[0] = move_char(st.root, to);\n\n        for (int i = 1; i < st.Vp; i++) {\n            if (desired[i] == -1 || st.dir[i] == desired[i]) continue;\n\n            int diff = (desired[i] - st.dir[i] + 4) % 4;\n\n            if (diff == 1 || diff == 2) {\n                op[i] = 'R';\n                st.dir[i] = (st.dir[i] + 1) % 4;\n            } else {\n                op[i] = 'L';\n                st.dir[i] = (st.dir[i] + 3) % 4;\n            }\n        }\n\n        if (ready()) {\n            for (int i = 1; i < st.Vp; i++) {\n                if (act[i]) {\n                    op[st.Vp + i] = 'P';\n                    st.holding[i] ^= 1;\n                }\n            }\n            st.ops.push_back(op);\n            return;\n        }\n\n        st.ops.push_back(op);\n    }\n}\n\nSolution make_star_solution(\n    int N,\n    int V,\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    const vector<int>& inputLengths,\n    int mode\n) {\n    int D = src.size();\n\n    Solution sol;\n    sol.Vp = min(V, 1 + (int)inputLengths.size());\n    sol.init = {0, 0};\n\n    int F = sol.Vp - 1;\n\n    if (F <= 0 || D == 0) {\n        sol.Vp = 1;\n        return sol;\n    }\n\n    vector<int> leafLen(sol.Vp);\n    vector<int> uniqueLens;\n\n    for (int i = 1; i < sol.Vp; i++) {\n        int L = max(1, min(inputLengths[i - 1], N - 1));\n        leafLen[i] = L;\n        uniqueLens.push_back(L);\n        sol.edges.push_back({0, L});\n    }\n\n    sort(uniqueLens.begin(), uniqueLens.end());\n    uniqueLens.erase(unique(uniqueLens.begin(), uniqueLens.end()), uniqueLens.end());\n\n    int Lcnt = uniqueLens.size();\n\n    unordered_map<int, int> lenIndex;\n    for (int i = 0; i < Lcnt; i++) lenIndex[uniqueLens[i]] = i;\n\n    vector<vector<int>> leavesByLen(Lcnt);\n\n    for (int i = 1; i < sol.Vp; i++) {\n        leavesByLen[lenIndex[leafLen[i]]].push_back(i);\n    }\n\n    vector<vector<int>> sid(N, vector<int>(N, -1));\n    vector<vector<int>> tid(N, vector<int>(N, -1));\n\n    for (int i = 0; i < D; i++) {\n        sid[src[i].x][src[i].y] = i;\n        tid[dst[i].x][dst[i].y] = i;\n    }\n\n    vector<char> remS(D, 1), remT(D, 1);\n\n    auto count_center = [&](const Pos& c, const vector<vector<int>>& id, const vector<char>& rem) {\n        vector<int> cnt(Lcnt, 0);\n\n        for (int li = 0; li < Lcnt; li++) {\n            int L = uniqueLens[li];\n\n            for (int d = 0; d < 4; d++) {\n                int x = c.x + DX[d] * L;\n                int y = c.y + DY[d] * L;\n\n                if (!inside(N, x, y)) continue;\n\n                int idx = id[x][y];\n                if (idx != -1 && rem[idx]) cnt[li]++;\n            }\n\n            cnt[li] = min(cnt[li], (int)leavesByLen[li].size());\n        }\n\n        return cnt;\n    };\n\n    auto dirs_center = [&](const Pos& c, int li, const vector<vector<int>>& id, const vector<char>& rem) {\n        vector<int> dirs;\n        int L = uniqueLens[li];\n\n        for (int d = 0; d < 4; d++) {\n            int x = c.x + DX[d] * L;\n            int y = c.y + DY[d] * L;\n\n            if (!inside(N, x, y)) continue;\n\n            int idx = id[x][y];\n            if (idx != -1 && rem[idx]) dirs.push_back(d);\n        }\n\n        return dirs;\n    };\n\n    StarState st;\n    st.Vp = sol.Vp;\n    st.root = {0, 0};\n    st.dir.assign(sol.Vp, 0);\n    st.holding.assign(sol.Vp, 0);\n\n    bool initialized = false;\n    Pos curRoot{0, 0};\n    int remaining = D;\n\n    while (remaining > 0) {\n        if (!time_ok()) break;\n\n        vector<vector<int>> sCnt(N * N), tCnt(N * N);\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                int idc = x * N + y;\n                Pos c{x, y};\n\n                sCnt[idc] = count_center(c, sid, remS);\n                tCnt[idc] = count_center(c, tid, remT);\n            }\n        }\n\n        int bestK = -1;\n        int bestCost = 1e9;\n        long long bestScore = LLONG_MIN;\n        Pos bestS{0, 0}, bestT{0, 0};\n\n        for (int sx = 0; sx < N; sx++) {\n            for (int sy = 0; sy < N; sy++) {\n                int si = sx * N + sy;\n\n                int sTotal = 0;\n                for (int v : sCnt[si]) sTotal += v;\n                if (sTotal == 0) continue;\n\n                Pos sc{sx, sy};\n\n                for (int tx = 0; tx < N; tx++) {\n                    for (int ty = 0; ty < N; ty++) {\n                        int ti = tx * N + ty;\n\n                        int k = 0;\n                        for (int li = 0; li < Lcnt; li++) {\n                            k += min(sCnt[si][li], tCnt[ti][li]);\n                        }\n\n                        if (k <= 0) continue;\n\n                        Pos tc{tx, ty};\n                        int cost = (initialized ? manhattan(curRoot, sc) : 0) + manhattan(sc, tc);\n                        long long score = 90LL * k - cost;\n\n                        if (better_choice(mode, k, cost, bestK, bestCost, score, bestScore)) {\n                            bestK = k;\n                            bestCost = cost;\n                            bestScore = score;\n                            bestS = sc;\n                            bestT = tc;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (bestK <= 0) break;\n\n        if (!initialized) {\n            sol.init = bestS;\n            st.root = bestS;\n            curRoot = bestS;\n            initialized = true;\n        }\n\n        vector<int> pickupDesired(sol.Vp, -1);\n        vector<int> releaseDesired(sol.Vp, -1);\n        vector<int> actionLeaves;\n\n        for (int li = 0; li < Lcnt; li++) {\n            vector<int> sd = dirs_center(bestS, li, sid, remS);\n            vector<int> td = dirs_center(bestT, li, tid, remT);\n\n            int q = min({(int)sd.size(), (int)td.size(), (int)leavesByLen[li].size()});\n\n            for (int z = 0; z < q; z++) {\n                int leaf = leavesByLen[li][z];\n                int sdir = sd[z];\n                int tdir = td[z];\n                int L = uniqueLens[li];\n\n                pickupDesired[leaf] = sdir;\n                releaseDesired[leaf] = tdir;\n                actionLeaves.push_back(leaf);\n\n                int sx = bestS.x + DX[sdir] * L;\n                int sy = bestS.y + DY[sdir] * L;\n                int tx = bestT.x + DX[tdir] * L;\n                int ty = bestT.y + DY[tdir] * L;\n\n                int si = sid[sx][sy];\n                int ti = tid[tx][ty];\n\n                if (si != -1 && remS[si]) {\n                    remS[si] = 0;\n                    remaining--;\n                }\n\n                if (ti != -1 && remT[ti]) {\n                    remT[ti] = 0;\n                }\n            }\n        }\n\n        if (actionLeaves.empty()) break;\n\n        star_move_rotate_action(st, bestS, pickupDesired, actionLeaves);\n        star_move_rotate_action(st, bestT, releaseDesired, actionLeaves);\n\n        curRoot = bestT;\n\n        if ((int)st.ops.size() > 100000) break;\n    }\n\n    if (remaining != 0 || !initialized || (int)st.ops.size() > 100000) {\n        sol.Vp = 1;\n        sol.edges.clear();\n        sol.init = {0, 0};\n        sol.ops.clear();\n        return sol;\n    }\n\n    sol.ops = move(st.ops);\n    return sol;\n}\n\n/* ---------- two-link arm ---------- */\n\nstruct Option {\n    int dx, dy;\n    int d1, d2;\n};\n\nstruct TwoState {\n    int Vp;\n    int F;\n    Pos root;\n    vector<int> d1;\n    vector<int> d2;\n    vector<string> ops;\n};\n\nvoid two_move_rotate_action(\n    TwoState& st,\n    const Pos& to,\n    const vector<int>& desired1,\n    const vector<int>& desired2,\n    const vector<int>& actionLeaves\n) {\n    vector<int> act(st.Vp, 0);\n    for (int leaf : actionLeaves) act[leaf] = 1;\n\n    auto ready = [&]() {\n        if (st.root.x != to.x || st.root.y != to.y) return false;\n\n        for (int f = 0; f < st.F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            if (desired1[j] != -1 && st.d1[f] != desired1[j]) return false;\n            if (desired2[l] != -1 && st.d2[f] != desired2[l]) return false;\n        }\n\n        return true;\n    };\n\n    while (true) {\n        if (ready()) {\n            string op(2 * st.Vp, '.');\n            bool any = false;\n\n            for (int leaf : actionLeaves) {\n                op[st.Vp + leaf] = 'P';\n                any = true;\n            }\n\n            if (any) st.ops.push_back(op);\n            return;\n        }\n\n        string op(2 * st.Vp, '.');\n        op[0] = move_char(st.root, to);\n\n        for (int f = 0; f < st.F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            if (desired1[j] != -1 && st.d1[f] != desired1[j]) {\n                int diff = (desired1[j] - st.d1[f] + 4) % 4;\n\n                if (diff == 1 || diff == 2) {\n                    op[j] = 'R';\n                    st.d1[f] = (st.d1[f] + 1) % 4;\n                    st.d2[f] = (st.d2[f] + 1) % 4;\n                } else {\n                    op[j] = 'L';\n                    st.d1[f] = (st.d1[f] + 3) % 4;\n                    st.d2[f] = (st.d2[f] + 3) % 4;\n                }\n            }\n\n            if (desired2[l] != -1 && st.d2[f] != desired2[l]) {\n                int diff = (desired2[l] - st.d2[f] + 4) % 4;\n\n                if (diff == 1 || diff == 2) {\n                    op[l] = 'R';\n                    st.d2[f] = (st.d2[f] + 1) % 4;\n                } else {\n                    op[l] = 'L';\n                    st.d2[f] = (st.d2[f] + 3) % 4;\n                }\n            }\n        }\n\n        if (ready()) {\n            for (int leaf : actionLeaves) op[st.Vp + leaf] = 'P';\n            st.ops.push_back(op);\n            return;\n        }\n\n        st.ops.push_back(op);\n    }\n}\n\nSolution make_two_link_solution(\n    int N,\n    int V,\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    const vector<pair<int, int>>& typeInput,\n    int mode\n) {\n    int D = src.size();\n\n    Solution sol;\n\n    int F = min((V - 1) / 2, (int)typeInput.size());\n\n    if (F <= 0 || D == 0) {\n        sol.Vp = 1;\n        return sol;\n    }\n\n    sol.Vp = 1 + 2 * F;\n\n    vector<int> A(F), B(F);\n\n    for (int f = 0; f < F; f++) {\n        A[f] = max(1, min(typeInput[f].first, N - 1));\n        B[f] = max(1, min(typeInput[f].second, N - 1));\n\n        int j = 1 + 2 * f;\n\n        sol.edges.push_back({0, A[f]});\n        sol.edges.push_back({j, B[f]});\n    }\n\n    vector<vector<Option>> opts(F);\n\n    for (int f = 0; f < F; f++) {\n        map<pair<int, int>, Option> mp;\n\n        for (int d1 = 0; d1 < 4; d1++) {\n            for (int d2 = 0; d2 < 4; d2++) {\n                int ox = DX[d1] * A[f] + DX[d2] * B[f];\n                int oy = DY[d1] * A[f] + DY[d2] * B[f];\n\n                pair<int, int> key{ox, oy};\n                if (!mp.count(key)) {\n                    mp[key] = {ox, oy, d1, d2};\n                }\n            }\n        }\n\n        for (auto& kv : mp) opts[f].push_back(kv.second);\n    }\n\n    vector<vector<int>> sid(N, vector<int>(N, -1));\n    vector<vector<int>> tid(N, vector<int>(N, -1));\n\n    for (int i = 0; i < D; i++) {\n        sid[src[i].x][src[i].y] = i;\n        tid[dst[i].x][dst[i].y] = i;\n    }\n\n    vector<char> remS(D, 1), remT(D, 1);\n\n    TwoState st;\n    st.Vp = sol.Vp;\n    st.F = F;\n    st.root = {0, 0};\n    st.d1.assign(F, 0);\n    st.d2.assign(F, 0);\n\n    bool initialized = false;\n    Pos curRoot{0, 0};\n    int remaining = D;\n\n    vector<int> stamp(N * N, 0);\n    int stampId = 1;\n\n    auto compute_data = [&](const vector<vector<int>>& id, const vector<char>& rem) {\n        vector<int> mask(N * N, 0), cnt(N * N, 0);\n\n        for (int cx = 0; cx < N; cx++) {\n            for (int cy = 0; cy < N; cy++) {\n                int cid = cx * N + cy;\n                ++stampId;\n\n                for (int f = 0; f < F; f++) {\n                    bool okLeaf = false;\n\n                    for (const auto& op : opts[f]) {\n                        int x = cx + op.dx;\n                        int y = cy + op.dy;\n\n                        if (!inside(N, x, y)) continue;\n\n                        int idx = id[x][y];\n                        if (idx == -1 || !rem[idx]) continue;\n\n                        okLeaf = true;\n\n                        int cell = x * N + y;\n                        if (stamp[cell] != stampId) {\n                            stamp[cell] = stampId;\n                            cnt[cid]++;\n                        }\n                    }\n\n                    if (okLeaf) mask[cid] |= (1 << f);\n                }\n            }\n        }\n\n        return pair<vector<int>, vector<int>>(move(mask), move(cnt));\n    };\n\n    auto collect_options = [&](const Pos& c, int f, const vector<vector<int>>& id, const vector<char>& rem) {\n        vector<pair<int, Option>> res;\n\n        for (const auto& op : opts[f]) {\n            int x = c.x + op.dx;\n            int y = c.y + op.dy;\n\n            if (!inside(N, x, y)) continue;\n\n            int idx = id[x][y];\n            if (idx != -1 && rem[idx]) {\n                res.push_back({idx, op});\n            }\n        }\n\n        return res;\n    };\n\n    while (remaining > 0) {\n        if (!time_ok()) break;\n\n        auto [sMask, sCnt] = compute_data(sid, remS);\n        auto [tMask, tCnt] = compute_data(tid, remT);\n\n        int bestK = -1;\n        int bestCost = 1e9;\n        long long bestScore = LLONG_MIN;\n        Pos bestS{0, 0}, bestT{0, 0};\n\n        for (int si = 0; si < N * N; si++) {\n            if (sCnt[si] == 0) continue;\n\n            Pos sc{si / N, si % N};\n\n            for (int ti = 0; ti < N * N; ti++) {\n                if (tCnt[ti] == 0) continue;\n\n                int common = __builtin_popcount((unsigned)(sMask[si] & tMask[ti]));\n                int k = min({common, sCnt[si], tCnt[ti]});\n\n                if (k <= 0) continue;\n\n                Pos tc{ti / N, ti % N};\n\n                int cost = (initialized ? manhattan(curRoot, sc) : 0) + manhattan(sc, tc);\n                long long score = 90LL * k - cost;\n\n                if (better_choice(mode, k, cost, bestK, bestCost, score, bestScore)) {\n                    bestK = k;\n                    bestCost = cost;\n                    bestScore = score;\n                    bestS = sc;\n                    bestT = tc;\n                }\n            }\n        }\n\n        if (bestK <= 0) break;\n\n        if (!initialized) {\n            sol.init = bestS;\n            st.root = bestS;\n            curRoot = bestS;\n            initialized = true;\n        }\n\n        vector<int> desired1(sol.Vp, -1);\n        vector<int> desired2(sol.Vp, -1);\n        vector<int> releaseDesired1(sol.Vp, -1);\n        vector<int> releaseDesired2(sol.Vp, -1);\n        vector<int> actionLeaves;\n\n        vector<char> usedS(D, 0), usedT(D, 0);\n\n        for (int f = 0; f < F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            auto so = collect_options(bestS, f, sid, remS);\n            auto to = collect_options(bestT, f, tid, remT);\n\n            bool assigned = false;\n\n            for (auto [si, sop] : so) {\n                if (usedS[si]) continue;\n\n                for (auto [ti, top] : to) {\n                    if (usedT[ti]) continue;\n\n                    usedS[si] = 1;\n                    usedT[ti] = 1;\n\n                    desired1[j] = sop.d1;\n                    desired2[l] = sop.d2;\n                    releaseDesired1[j] = top.d1;\n                    releaseDesired2[l] = top.d2;\n                    actionLeaves.push_back(l);\n\n                    remS[si] = 0;\n                    remT[ti] = 0;\n                    remaining--;\n\n                    assigned = true;\n                    break;\n                }\n\n                if (assigned) break;\n            }\n        }\n\n        if (actionLeaves.empty()) break;\n\n        two_move_rotate_action(st, bestS, desired1, desired2, actionLeaves);\n        two_move_rotate_action(st, bestT, releaseDesired1, releaseDesired2, actionLeaves);\n\n        curRoot = bestT;\n\n        if ((int)st.ops.size() > 100000) break;\n    }\n\n    if (remaining != 0 || !initialized || (int)st.ops.size() > 100000) {\n        sol.Vp = 1;\n        sol.edges.clear();\n        sol.init = {0, 0};\n        sol.ops.clear();\n        return sol;\n    }\n\n    sol.ops = move(st.ops);\n    return sol;\n}\n\n/* ---------- main ---------- */\n\nint main() {\n    START_TIME = Clock::now();\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<Pos> src, dst;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                src.push_back({i, j});\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    Solution best = make_single_solution(src, dst);\n\n    auto consider = [&](Solution sol) {\n        if (!src.empty() && sol.ops.empty()) return;\n        if (sol.ops.size() < best.ops.size()) best = move(sol);\n    };\n\n    int Fstar = max(0, V - 1);\n\n    vector<int> len1, len2, len3, len4, len5;\n\n    for (int i = 0; i < Fstar; i++) len1.push_back(1 + i / 4);\n    for (int i = 0; i < Fstar; i++) len2.push_back(1 + i / 2);\n    for (int i = 0; i < Fstar; i++) len3.push_back(1 + (i % 7));\n    for (int i = 0; i < Fstar; i++) len4.push_back(2 + (i % 6));\n    for (int i = 0; i < Fstar; i++) len5.push_back(1 + (i % 10));\n\n    if (time_ok(2.40)) consider(make_star_solution(N, V, src, dst, len1, 0));\n    if (time_ok(2.40)) consider(make_star_solution(N, V, src, dst, len2, 0));\n    if (time_ok(2.40)) consider(make_star_solution(N, V, src, dst, len3, 0));\n    if (time_ok(2.25)) consider(make_star_solution(N, V, src, dst, len1, 1));\n    if (time_ok(2.20)) consider(make_star_solution(N, V, src, dst, len4, 0));\n    if (time_ok(2.10)) consider(make_star_solution(N, V, src, dst, len5, 2));\n\n    int Ftwo = max(0, (V - 1) / 2);\n\n    auto repeated = [&](pair<int, int> p) {\n        vector<pair<int, int>> res;\n        for (int i = 0; i < Ftwo; i++) res.push_back(p);\n        return res;\n    };\n\n    vector<pair<int, int>> twoTypes1 = repeated({1, 2});\n\n    vector<pair<int, int>> twoTypes2;\n    for (int i = 0; i < Ftwo; i++) {\n        if (i % 3 == 0) twoTypes2.push_back({1, 1});\n        else if (i % 3 == 1) twoTypes2.push_back({1, 2});\n        else twoTypes2.push_back({2, 3});\n    }\n\n    vector<pair<int, int>> twoTypes3;\n    vector<pair<int, int>> cyc3 = {\n        {1, 1}, {1, 2}, {1, 3}, {2, 2}, {2, 3}, {3, 3}, {1, 4}\n    };\n    for (int i = 0; i < Ftwo; i++) twoTypes3.push_back(cyc3[i % cyc3.size()]);\n\n    vector<pair<int, int>> twoTypes4;\n    vector<pair<int, int>> cyc4 = {\n        {1, 2}, {2, 1}, {1, 3}, {3, 1}, {2, 2}, {2, 4}, {4, 2}\n    };\n    for (int i = 0; i < Ftwo; i++) twoTypes4.push_back(cyc4[i % cyc4.size()]);\n\n    if (time_ok(2.35)) consider(make_two_link_solution(N, V, src, dst, twoTypes1, 0));\n    if (time_ok(2.35)) consider(make_two_link_solution(N, V, src, dst, twoTypes2, 0));\n\n    if (time_ok(2.18)) consider(make_two_link_solution(N, V, src, dst, repeated({1, 1}), 0));\n    if (time_ok(2.18)) consider(make_two_link_solution(N, V, src, dst, repeated({2, 2}), 0));\n    if (time_ok(2.18)) consider(make_two_link_solution(N, V, src, dst, repeated({2, 3}), 0));\n    if (time_ok(2.18)) consider(make_two_link_solution(N, V, src, dst, repeated({1, 3}), 0));\n\n    if (time_ok(2.08)) consider(make_two_link_solution(N, V, src, dst, twoTypes1, 1));\n    if (time_ok(2.08)) consider(make_two_link_solution(N, V, src, dst, twoTypes2, 1));\n    if (time_ok(2.08)) consider(make_two_link_solution(N, V, src, dst, twoTypes2, 2));\n\n    // New cheap mixed candidates.\n    if (time_ok(2.00)) consider(make_two_link_solution(N, V, src, dst, twoTypes3, 0));\n    if (time_ok(1.94)) consider(make_two_link_solution(N, V, src, dst, twoTypes4, 0));\n    if (time_ok(1.88)) consider(make_two_link_solution(N, V, src, dst, repeated({3, 3}), 0));\n    if (time_ok(1.82)) consider(make_two_link_solution(N, V, src, dst, repeated({2, 4}), 0));\n    if (time_ok(1.76)) consider(make_two_link_solution(N, V, src, dst, twoTypes3, 1));\n\n    cout << best.Vp << '\\n';\n\n    for (auto [p, L] : best.edges) {\n        cout << p << ' ' << L << '\\n';\n    }\n\n    cout << best.init.x << ' ' << best.init.y << '\\n';\n\n    for (const string& op : best.ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Fish {\n    int x, y, w;\n};\n\nstruct PolyCand {\n    int diff = -1000000000;\n    vector<pair<int,int>> poly;\n};\n\nstruct EvalResult {\n    bool ok = false;\n    int diff = -1000000000;\n    vector<char> mask;\n    vector<pair<int,int>> poly;\n};\n\nstatic const int LIM = 100000;\nstatic const int MAX_PERIM = 400000;\nstatic const int MAX_VERT = 1000;\n\nint N;\nvector<Fish> fishes;\nPolyCand bestAns;\nTimer timer;\n\nstatic inline int id(int x, int y, int G) {\n    return y * G + x;\n}\n\nint exactDiffRect(int x1, int y1, int x2, int y2) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) s += p.w;\n    }\n    return s;\n}\n\nvoid updateBest(const vector<pair<int,int>>& poly, int diff) {\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return;\n    if (diff > bestAns.diff) {\n        bestAns.diff = diff;\n        bestAns.poly = poly;\n    }\n}\n\nbool pointInsideMask(const vector<char>& mask, int G, int L, int px, int py) {\n    int xs[2], ys[2];\n    int nx = 0, ny = 0;\n\n    if (px == LIM) xs[nx++] = G - 1;\n    else xs[nx++] = px / L;\n    if (px > 0 && px % L == 0) xs[nx++] = px / L - 1;\n\n    if (py == LIM) ys[ny++] = G - 1;\n    else ys[ny++] = py / L;\n    if (py > 0 && py % L == 0) ys[ny++] = py / L - 1;\n\n    for (int i = 0; i < nx; i++) {\n        for (int j = 0; j < ny; j++) {\n            int x = xs[i], y = ys[j];\n            if (0 <= x && x < G && 0 <= y && y < G && mask[id(x,y,G)]) return true;\n        }\n    }\n    return false;\n}\n\nint exactDiffMask(const vector<char>& mask, int G, int L) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (pointInsideMask(mask, G, L, p.x, p.y)) s += p.w;\n    }\n    return s;\n}\n\nbool isConnected(const vector<char>& mask, int G) {\n    int st = -1, cnt = 0;\n    for (int i = 0; i < G * G; i++) {\n        if (mask[i]) {\n            cnt++;\n            if (st == -1) st = i;\n        }\n    }\n    if (cnt == 0) return false;\n\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    q.push(st);\n    vis[st] = 1;\n    int got = 0;\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        got++;\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n            int ni = id(nx,ny,G);\n            if (!mask[ni] || vis[ni]) continue;\n            vis[ni] = 1;\n            q.push(ni);\n        }\n    }\n    return got == cnt;\n}\n\nvoid fillHoles(vector<char>& mask, int G) {\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n\n    auto push_empty = [&](int x, int y) {\n        if (x < 0 || x >= G || y < 0 || y >= G) return;\n        int v = id(x,y,G);\n        if (!mask[v] && !vis[v]) {\n            vis[v] = 1;\n            q.push(v);\n        }\n    };\n\n    for (int i = 0; i < G; i++) {\n        push_empty(i, 0);\n        push_empty(i, G - 1);\n        push_empty(0, i);\n        push_empty(G - 1, i);\n    }\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            push_empty(x + dx[d], y + dy[d]);\n        }\n    }\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] && !vis[i]) mask[i] = 1;\n    }\n}\n\nvoid normalizeMask(vector<char>& mask, int G, const vector<int>& cellW) {\n    fillHoles(mask, G);\n\n    for (int iter = 0; iter < G * G; iter++) {\n        bool changed = false;\n        for (int y = 0; y + 1 < G; y++) {\n            for (int x = 0; x + 1 < G; x++) {\n                int a = id(x,y,G);\n                int b = id(x+1,y,G);\n                int c = id(x,y+1,G);\n                int d = id(x+1,y+1,G);\n\n                if (mask[a] && mask[d] && !mask[b] && !mask[c]) {\n                    if (cellW[b] >= cellW[c]) mask[b] = 1;\n                    else mask[c] = 1;\n                    changed = true;\n                }\n                if (mask[b] && mask[c] && !mask[a] && !mask[d]) {\n                    if (cellW[a] >= cellW[d]) mask[a] = 1;\n                    else mask[d] = 1;\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n        fillHoles(mask, G);\n    }\n}\n\nint calcPerimCells(const vector<char>& mask, int G) {\n    int per = 0;\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n            if (x == 0 || !mask[id(x-1,y,G)]) per++;\n            if (x == G-1 || !mask[id(x+1,y,G)]) per++;\n            if (y == 0 || !mask[id(x,y-1,G)]) per++;\n            if (y == G-1 || !mask[id(x,y+1,G)]) per++;\n        }\n    }\n    return per;\n}\n\nvector<pair<int,int>> extractPolygon(const vector<char>& mask, int G, int L) {\n    int V = (G + 1) * (G + 1);\n    vector<int> nxt(V, -1), indeg(V, 0);\n    bool bad = false;\n    int edgeCnt = 0;\n\n    auto vid = [&](int x, int y) {\n        return y * (G + 1) + x;\n    };\n\n    auto addEdge = [&](int x1, int y1, int x2, int y2) {\n        int u = vid(x1,y1), v = vid(x2,y2);\n        if (nxt[u] != -1) bad = true;\n        nxt[u] = v;\n        indeg[v]++;\n        if (indeg[v] > 1) bad = true;\n        edgeCnt++;\n    };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n\n            if (y == 0 || !mask[id(x,y-1,G)]) addEdge(x, y, x+1, y);\n            if (x == G-1 || !mask[id(x+1,y,G)]) addEdge(x+1, y, x+1, y+1);\n            if (y == G-1 || !mask[id(x,y+1,G)]) addEdge(x+1, y+1, x, y+1);\n            if (x == 0 || !mask[id(x-1,y,G)]) addEdge(x, y+1, x, y);\n        }\n    }\n\n    if (bad || edgeCnt == 0) return {};\n\n    int st = -1;\n    for (int i = 0; i < V; i++) {\n        if (nxt[i] != -1) {\n            st = i;\n            break;\n        }\n    }\n\n    vector<char> used(V, 0);\n    vector<pair<int,int>> poly;\n    int cur = st;\n\n    for (int step = 0; step <= edgeCnt; step++) {\n        if (cur == -1) return {};\n        if (cur == st && step > 0) break;\n        if (used[cur]) return {};\n        used[cur] = 1;\n\n        int gx = cur % (G + 1);\n        int gy = cur / (G + 1);\n        poly.push_back({gx * L, gy * L});\n        cur = nxt[cur];\n    }\n\n    if (cur != st) return {};\n    if ((int)poly.size() != edgeCnt) return {};\n\n    auto collinear = [](pair<int,int> a, pair<int,int> b, pair<int,int> c) {\n        return (a.first == b.first && b.first == c.first) ||\n               (a.second == b.second && b.second == c.second);\n    };\n\n    bool changed = true;\n    while (changed && poly.size() >= 4) {\n        changed = false;\n        vector<pair<int,int>> np;\n        int m = (int)poly.size();\n        for (int i = 0; i < m; i++) {\n            auto a = poly[(i - 1 + m) % m];\n            auto b = poly[i];\n            auto c = poly[(i + 1) % m];\n            if (collinear(a,b,c)) changed = true;\n            else np.push_back(b);\n        }\n        poly.swap(np);\n    }\n\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return {};\n\n    set<pair<int,int>> ss(poly.begin(), poly.end());\n    if (ss.size() != poly.size()) return {};\n\n    return poly;\n}\n\nEvalResult evalMask(vector<char> mask, int G, int L, const vector<int>& cellW) {\n    EvalResult res;\n    normalizeMask(mask, G, cellW);\n\n    if (!isConnected(mask, G)) return res;\n\n    int perCells = calcPerimCells(mask, G);\n    if (perCells * L > MAX_PERIM) return res;\n\n    auto poly = extractPolygon(mask, G, L);\n    if (poly.empty()) return res;\n\n    int diff = exactDiffMask(mask, G, L);\n\n    res.ok = true;\n    res.diff = diff;\n    res.mask = std::move(mask);\n    res.poly = std::move(poly);\n    return res;\n}\n\nvector<int> buildGridWeight(int G, int L) {\n    vector<int> w(G * G, 0);\n    for (auto &p : fishes) {\n        int x = min(G - 1, p.x / L);\n        int y = min(G - 1, p.y / L);\n        w[id(x,y,G)] += p.w;\n    }\n    return w;\n}\n\nvoid tryTinyBaseline() {\n    for (int i = 0; i < N; i++) {\n        int x = fishes[i].x;\n        int y = fishes[i].y;\n        int x1, x2, y1, y2;\n\n        if (x < LIM) x1 = x, x2 = x + 1;\n        else x1 = x - 1, x2 = x;\n\n        if (y < LIM) y1 = y, y2 = y + 1;\n        else y1 = y - 1, y2 = y;\n\n        int diff = exactDiffRect(x1,y1,x2,y2);\n        vector<pair<int,int>> poly = {\n            {x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}\n        };\n        updateBest(poly, diff);\n    }\n}\n\nvoid tryBestRectangle(int G, int L, const vector<int>& cellW) {\n    int maxSideSum = MAX_PERIM / (2 * L);\n\n    int bestVal = -1000000000;\n    int bx1 = 0, by1 = 0, bx2 = 1, by2 = 1;\n\n    vector<int> arr(G), pref(G + 1);\n\n    for (int xl = 0; xl < G; xl++) {\n        fill(arr.begin(), arr.end(), 0);\n\n        for (int xr = xl; xr < G; xr++) {\n            for (int y = 0; y < G; y++) {\n                arr[y] += cellW[id(xr,y,G)];\n            }\n\n            int width = xr - xl + 1;\n            int maxH = maxSideSum - width;\n            if (maxH <= 0) continue;\n            maxH = min(maxH, G);\n\n            pref[0] = 0;\n            for (int y = 0; y < G; y++) pref[y+1] = pref[y] + arr[y];\n\n            deque<int> dq;\n            for (int e = 1; e <= G; e++) {\n                int sNew = e - 1;\n                while (!dq.empty() && pref[dq.back()] >= pref[sNew]) dq.pop_back();\n                dq.push_back(sNew);\n\n                while (!dq.empty() && dq.front() < e - maxH) dq.pop_front();\n\n                int s = dq.front();\n                int val = pref[e] - pref[s];\n                if (val > bestVal) {\n                    bestVal = val;\n                    bx1 = xl;\n                    bx2 = xr + 1;\n                    by1 = s;\n                    by2 = e;\n                }\n            }\n        }\n    }\n\n    int x1 = bx1 * L;\n    int x2 = bx2 * L;\n    int y1 = by1 * L;\n    int y2 = by2 * L;\n\n    int diff = exactDiffRect(x1,y1,x2,y2);\n    vector<pair<int,int>> poly = {\n        {x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}\n    };\n    updateBest(poly, diff);\n}\n\nstruct Comp {\n    int score = 0;\n    int size = 0;\n    long long sx = 0, sy = 0;\n    vector<int> cells;\n};\n\nvector<Comp> getComponents(const vector<char>& mask, int G, const vector<int>& cellW) {\n    vector<Comp> comps;\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] || vis[i]) continue;\n\n        Comp c;\n        vis[i] = 1;\n        q.push(i);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            int x = v % G, y = v / G;\n\n            c.cells.push_back(v);\n            c.score += cellW[v];\n            c.size++;\n            c.sx += x;\n            c.sy += y;\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n                int ni = id(nx,ny,G);\n                if (!mask[ni] || vis[ni]) continue;\n                vis[ni] = 1;\n                q.push(ni);\n            }\n        }\n\n        if (c.size > 0) comps.push_back(std::move(c));\n    }\n\n    sort(comps.begin(), comps.end(), [](const Comp& a, const Comp& b) {\n        return a.score > b.score;\n    });\n\n    return comps;\n}\n\nvector<char> makeCompMask(const Comp& c, int G) {\n    vector<char> m(G * G, 0);\n    for (int v : c.cells) m[v] = 1;\n    return m;\n}\n\nvoid addPath(vector<char>& m, int G, int x1, int y1, int x2, int y2, bool hv) {\n    if (hv) {\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y1,G)] = 1;\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x2,y,G)] = 1;\n    } else {\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x1,y,G)] = 1;\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y2,G)] = 1;\n    }\n}\n\nvoid tryGreedyUnion(vector<Comp>& comps, int G, int L, const vector<int>& cellW) {\n    vector<Comp> pos;\n    for (auto &c : comps) {\n        if (c.score > 0) pos.push_back(c);\n        if ((int)pos.size() >= 20) break;\n    }\n    if (pos.empty()) return;\n\n    vector<char> cur = makeCompMask(pos[0], G);\n    auto er0 = evalMask(cur, G, L, cellW);\n    if (!er0.ok) return;\n\n    updateBest(er0.poly, er0.diff);\n    cur = er0.mask;\n    int curDiff = er0.diff;\n\n    for (int ci = 1; ci < (int)pos.size(); ci++) {\n        const Comp& c = pos[ci];\n\n        int cx = (int)(c.sx / max(1, c.size));\n        int cy = (int)(c.sy / max(1, c.size));\n\n        int ax = -1, ay = -1, bestD = INT_MAX;\n        for (int y = 0; y < G; y++) {\n            for (int x = 0; x < G; x++) {\n                if (!cur[id(x,y,G)]) continue;\n                int d = abs(x - cx) + abs(y - cy);\n                if (d < bestD) {\n                    bestD = d;\n                    ax = x;\n                    ay = y;\n                }\n            }\n        }\n\n        int bx = -1, by = -1;\n        bestD = INT_MAX;\n        for (int v : c.cells) {\n            int x = v % G, y = v / G;\n            int d = abs(x - ax) + abs(y - ay);\n            if (d < bestD) {\n                bestD = d;\n                bx = x;\n                by = y;\n            }\n        }\n\n        vector<char> base = cur;\n        for (int v : c.cells) base[v] = 1;\n\n        vector<char> m1 = base, m2 = base;\n        addPath(m1, G, ax, ay, bx, by, true);\n        addPath(m2, G, ax, ay, bx, by, false);\n\n        auto e1 = evalMask(m1, G, L, cellW);\n        auto e2 = evalMask(m2, G, L, cellW);\n\n        EvalResult bestE;\n        if (e1.ok) bestE = e1;\n        if (e2.ok && (!bestE.ok || e2.diff > bestE.diff)) bestE = e2;\n\n        if (bestE.ok) {\n            updateBest(bestE.poly, bestE.diff);\n            if (bestE.diff > curDiff) {\n                curDiff = bestE.diff;\n                cur = bestE.mask;\n            }\n        }\n    }\n}\n\nvector<int> boxSmooth(const vector<int>& w, int G, int r) {\n    vector<int> pref((G+1)*(G+1), 0);\n    auto pid = [&](int x, int y) { return y * (G + 1) + x; };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            pref[pid(x+1,y+1)] =\n                pref[pid(x+1,y)] + pref[pid(x,y+1)] - pref[pid(x,y)] + w[id(x,y,G)];\n        }\n    }\n\n    vector<int> sm(G * G, 0);\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            int x1 = max(0, x - r);\n            int y1 = max(0, y - r);\n            int x2 = min(G, x + r + 1);\n            int y2 = min(G, y + r + 1);\n            int val =\n                pref[pid(x2,y2)] - pref[pid(x1,y2)] -\n                pref[pid(x2,y1)] + pref[pid(x1,y1)];\n            sm[id(x,y,G)] = val;\n        }\n    }\n    return sm;\n}\n\nvoid processGrid(int L) {\n    int G = LIM / L;\n    vector<int> cellW = buildGridWeight(G, L);\n\n    tryBestRectangle(G, L, cellW);\n\n    vector<int> radii;\n    if (L == 500) radii = {0,1,2,3,5,8,12};\n    else if (L == 1000) radii = {0,1,2,3,5,8};\n    else if (L == 2000) radii = {0,1,2,3,4};\n    else radii = {0,1,2,3};\n\n    for (int r : radii) {\n        vector<int> sm = boxSmooth(cellW, G, r);\n\n        vector<int> thresholds;\n        if (r == 0) thresholds = {0};\n        else thresholds = {-1, 0, 1, 2, 4};\n\n        for (int th : thresholds) {\n            vector<char> mask(G * G, 0);\n            for (int i = 0; i < G * G; i++) {\n                if (sm[i] > th) mask[i] = 1;\n            }\n\n            auto comps = getComponents(mask, G, cellW);\n\n            int cnt = 0;\n            for (auto &c : comps) {\n                if (c.score <= 0) continue;\n                auto cm = makeCompMask(c, G);\n                auto er = evalMask(cm, G, L, cellW);\n                if (er.ok) updateBest(er.poly, er.diff);\n\n                cnt++;\n                if (cnt >= 30) break;\n            }\n\n            tryGreedyUnion(comps, G, L, cellW);\n        }\n    }\n}\n\nlong long twiceArea(const vector<pair<int,int>>& p) {\n    long long a = 0;\n    int m = (int)p.size();\n    for (int i = 0; i < m; i++) {\n        auto [x1,y1] = p[i];\n        auto [x2,y2] = p[(i+1)%m];\n        a += 1LL * x1 * y2 - 1LL * y1 * x2;\n    }\n    return a;\n}\n\nlong long polygonPerimeter(const vector<pair<int,int>>& p) {\n    long long per = 0;\n    int m = (int)p.size();\n    for (int i = 0; i < m; i++) {\n        auto [x1,y1] = p[i];\n        auto [x2,y2] = p[(i+1)%m];\n        per += abs(x1 - x2) + abs(y1 - y2);\n    }\n    return per;\n}\n\nbool betweenLL(long long a, long long b, long long c) {\n    return min(a,b) <= c && c <= max(a,b);\n}\n\nbool segIntersect(pair<int,int> a, pair<int,int> b, pair<int,int> c, pair<int,int> d) {\n    if (a.first == b.first && c.first == d.first) {\n        if (a.first != c.first) return false;\n        return max(min(a.second,b.second), min(c.second,d.second)) <=\n               min(max(a.second,b.second), max(c.second,d.second));\n    }\n    if (a.second == b.second && c.second == d.second) {\n        if (a.second != c.second) return false;\n        return max(min(a.first,b.first), min(c.first,d.first)) <=\n               min(max(a.first,b.first), max(c.first,d.first));\n    }\n\n    if (a.second == b.second) {\n        swap(a,c);\n        swap(b,d);\n    }\n\n    int vx = a.first;\n    int hy = c.second;\n    return betweenLL(a.second,b.second,hy) && betweenLL(c.first,d.first,vx);\n}\n\nbool validPolygon(const vector<pair<int,int>>& p) {\n    int m = (int)p.size();\n    if (m < 4 || m > MAX_VERT) return false;\n\n    set<pair<int,int>> st(p.begin(), p.end());\n    if ((int)st.size() != m) return false;\n\n    for (int i = 0; i < m; i++) {\n        auto a = p[i], b = p[(i+1)%m];\n        if (a == b) return false;\n        if (!(a.first == b.first || a.second == b.second)) return false;\n        if (a.first < 0 || a.first > LIM || a.second < 0 || a.second > LIM) return false;\n    }\n\n    if (polygonPerimeter(p) > MAX_PERIM) return false;\n\n    for (int i = 0; i < m; i++) {\n        auto a = p[i], b = p[(i+1)%m];\n        for (int j = i + 1; j < m; j++) {\n            if ((i + 1) % m == j) continue;\n            if ((j + 1) % m == i) continue;\n\n            auto c = p[j], d = p[(j+1)%m];\n            if (segIntersect(a,b,c,d)) return false;\n        }\n    }\n    return true;\n}\n\nbool onSegmentPoint(pair<int,int> a, pair<int,int> b, int x, int y) {\n    if (a.first == b.first) {\n        return x == a.first && min(a.second,b.second) <= y && y <= max(a.second,b.second);\n    } else {\n        return y == a.second && min(a.first,b.first) <= x && x <= max(a.first,b.first);\n    }\n}\n\nbool pointInPolygon(const vector<pair<int,int>>& p, int x, int y) {\n    int m = (int)p.size();\n\n    for (int i = 0; i < m; i++) {\n        if (onSegmentPoint(p[i], p[(i+1)%m], x, y)) return true;\n    }\n\n    bool inside = false;\n    for (int i = 0; i < m; i++) {\n        auto [x1,y1] = p[i];\n        auto [x2,y2] = p[(i+1)%m];\n\n        if (x1 == x2) {\n            if ((y1 > y) != (y2 > y)) {\n                if (x < x1) inside = !inside;\n            }\n        }\n    }\n    return inside;\n}\n\nint exactDiffPolygon(const vector<pair<int,int>>& p) {\n    int s = 0;\n    for (auto &f : fishes) {\n        if (pointInPolygon(p, f.x, f.y)) s += f.w;\n    }\n    return s;\n}\n\nint rangeSumInclusive(const vector<pair<int,int>>& xs, const vector<int>& pref, int l, int r) {\n    if (l > r) return 0;\n    int L = lower_bound(xs.begin(), xs.end(), make_pair(l, -1000000000)) - xs.begin();\n    int R = upper_bound(xs.begin(), xs.end(), make_pair(r,  1000000000)) - xs.begin();\n    return pref[R] - pref[L];\n}\n\nvoid tryEdgeShiftRefine(int SHIFT, int passes) {\n    if (bestAns.poly.empty()) return;\n    if (timer.sec() > 1.75) return;\n\n    vector<pair<int,int>> p = bestAns.poly;\n    if (!validPolygon(p)) return;\n\n    int m = (int)p.size();\n    bool ccw = twiceArea(p) > 0;\n\n    for (int pass = 0; pass < passes; pass++) {\n        if (timer.sec() > 1.90) break;\n\n        for (int i = 0; i < m; i++) {\n            if (timer.sec() > 1.90) break;\n\n            int j = (i + 1) % m;\n            int im = (i - 1 + m) % m;\n            int j2 = (i + 2) % m;\n\n            auto a = p[i], b = p[j];\n\n            if (a.first == b.first) {\n                int x = a.first;\n                int y1 = min(a.second, b.second);\n                int y2 = max(a.second, b.second);\n\n                int lo = max(0, x - SHIFT);\n                int hi = min(LIM, x + SHIFT);\n\n                int xp = p[im].first;\n                int xn = p[j2].first;\n\n                if (x > xp) lo = max(lo, xp + 1);\n                else hi = min(hi, xp - 1);\n\n                if (x > xn) lo = max(lo, xn + 1);\n                else hi = min(hi, xn - 1);\n\n                if (lo > hi) continue;\n\n                vector<pair<int,int>> xs;\n                vector<int> cand;\n                cand.push_back(x);\n\n                for (auto &f : fishes) {\n                    if (y1 <= f.y && f.y <= y2 && lo <= f.x && f.x <= hi) {\n                        xs.push_back({f.x, f.w});\n                        cand.push_back(f.x);\n                        if (f.x + 1 <= hi) cand.push_back(f.x + 1);\n                        if (f.x - 1 >= lo) cand.push_back(f.x - 1);\n                    }\n                }\n\n                if (xs.empty()) continue;\n\n                sort(xs.begin(), xs.end());\n                vector<int> pref(xs.size() + 1, 0);\n                for (int k = 0; k < (int)xs.size(); k++) pref[k+1] = pref[k] + xs[k].second;\n\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n                int dy = b.second - a.second;\n                int leftSign = (dy > 0 ? -1 : +1);\n                int insideSign = ccw ? leftSign : -leftSign;\n\n                int bestX = x;\n                int bestDelta = 0;\n\n                for (int nx : cand) {\n                    if (nx == x || nx < lo || nx > hi) continue;\n\n                    int sum = rangeSumInclusive(xs, pref, min(x,nx), max(x,nx));\n                    int dx = nx - x;\n\n                    int delta;\n                    if (insideSign * dx < 0) delta = sum;\n                    else delta = -sum;\n\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestX = nx;\n                    }\n                }\n\n                if (bestDelta > 0 && bestX != x) {\n                    p[i].first = bestX;\n                    p[j].first = bestX;\n                    if (polygonPerimeter(p) > MAX_PERIM) {\n                        p[i].first = x;\n                        p[j].first = x;\n                    }\n                }\n            } else if (a.second == b.second) {\n                int y = a.second;\n                int x1 = min(a.first, b.first);\n                int x2 = max(a.first, b.first);\n\n                int lo = max(0, y - SHIFT);\n                int hi = min(LIM, y + SHIFT);\n\n                int yp = p[im].second;\n                int yn = p[j2].second;\n\n                if (y > yp) lo = max(lo, yp + 1);\n                else hi = min(hi, yp - 1);\n\n                if (y > yn) lo = max(lo, yn + 1);\n                else hi = min(hi, yn - 1);\n\n                if (lo > hi) continue;\n\n                vector<pair<int,int>> ys;\n                vector<int> cand;\n                cand.push_back(y);\n\n                for (auto &f : fishes) {\n                    if (x1 <= f.x && f.x <= x2 && lo <= f.y && f.y <= hi) {\n                        ys.push_back({f.y, f.w});\n                        cand.push_back(f.y);\n                        if (f.y + 1 <= hi) cand.push_back(f.y + 1);\n                        if (f.y - 1 >= lo) cand.push_back(f.y - 1);\n                    }\n                }\n\n                if (ys.empty()) continue;\n\n                sort(ys.begin(), ys.end());\n                vector<int> pref(ys.size() + 1, 0);\n                for (int k = 0; k < (int)ys.size(); k++) pref[k+1] = pref[k] + ys[k].second;\n\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n                int dx = b.first - a.first;\n                int leftSign = (dx > 0 ? +1 : -1);\n                int insideSign = ccw ? leftSign : -leftSign;\n\n                int bestY = y;\n                int bestDelta = 0;\n\n                for (int ny : cand) {\n                    if (ny == y || ny < lo || ny > hi) continue;\n\n                    int sum = rangeSumInclusive(ys, pref, min(y,ny), max(y,ny));\n                    int dy = ny - y;\n\n                    int delta;\n                    if (insideSign * dy < 0) delta = sum;\n                    else delta = -sum;\n\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestY = ny;\n                    }\n                }\n\n                if (bestDelta > 0 && bestY != y) {\n                    p[i].second = bestY;\n                    p[j].second = bestY;\n                    if (polygonPerimeter(p) > MAX_PERIM) {\n                        p[i].second = y;\n                        p[j].second = y;\n                    }\n                }\n            }\n        }\n\n        if (validPolygon(p)) {\n            int diff = exactDiffPolygon(p);\n            updateBest(p, diff);\n        }\n    }\n}\n\nstruct NotchCand {\n    int approx;\n    int edge;\n    int t1, t2;\n    int nx, ny;\n    int depth;\n};\n\nvector<pair<int,int>> applyNotch(const vector<pair<int,int>>& p, const NotchCand& c) {\n    int m = (int)p.size();\n    if (m + 4 > MAX_VERT) return {};\n\n    int i = c.edge;\n    int j = (i + 1) % m;\n    auto A = p[i];\n    auto B = p[j];\n\n    int vx = (B.first > A.first) ? 1 : (B.first < A.first ? -1 : 0);\n    int vy = (B.second > A.second) ? 1 : (B.second < A.second ? -1 : 0);\n\n    pair<int,int> P1 = {A.first + vx * c.t1, A.second + vy * c.t1};\n    pair<int,int> P2 = {A.first + vx * c.t2, A.second + vy * c.t2};\n    pair<int,int> Q1 = {P1.first + c.nx * c.depth, P1.second + c.ny * c.depth};\n    pair<int,int> Q2 = {P2.first + c.nx * c.depth, P2.second + c.ny * c.depth};\n\n    if (P1 == A || P2 == B || P1 == P2 || Q1 == Q2) return {};\n    if (Q1.first < 0 || Q1.first > LIM || Q1.second < 0 || Q1.second > LIM) return {};\n    if (Q2.first < 0 || Q2.first > LIM || Q2.second < 0 || Q2.second > LIM) return {};\n\n    vector<pair<int,int>> np;\n    np.reserve(m + 4);\n\n    for (int k = 0; k < m; k++) {\n        np.push_back(p[k]);\n        if (k == i) {\n            np.push_back(P1);\n            np.push_back(Q1);\n            np.push_back(Q2);\n            np.push_back(P2);\n        }\n    }\n\n    return np;\n}\n\nbool tryOneNotchIteration(int candLimit) {\n    if (bestAns.poly.empty()) return false;\n    if (timer.sec() > 1.83) return false;\n\n    vector<pair<int,int>> base = bestAns.poly;\n    if (!validPolygon(base)) return false;\n    if ((int)base.size() + 4 > MAX_VERT) return false;\n\n    bool ccw = twiceArea(base) > 0;\n    int m = (int)base.size();\n    long long basePer = polygonPerimeter(base);\n\n    const int MAX_D = 320;\n    vector<int> widths = {70, 140, 260, 520, 900, 1500};\n    vector<NotchCand> cands;\n\n    for (int i = 0; i < m; i++) {\n        if (timer.sec() > 1.87) break;\n\n        int j = (i + 1) % m;\n        auto A = base[i];\n        auto B = base[j];\n\n        int vx = (B.first > A.first) ? 1 : (B.first < A.first ? -1 : 0);\n        int vy = (B.second > A.second) ? 1 : (B.second < A.second ? -1 : 0);\n        int len = abs(B.first - A.first) + abs(B.second - A.second);\n        if (len < 20) continue;\n\n        int leftNx = -vy;\n        int leftNy = vx;\n        int inNx = ccw ? leftNx : -leftNx;\n        int inNy = ccw ? leftNy : -leftNy;\n        int outNx = -inNx;\n        int outNy = -inNy;\n\n        struct Near {\n            int t;\n            int din;\n            int dout;\n            int w;\n        };\n        vector<Near> near;\n\n        for (auto &f : fishes) {\n            int t;\n            if (vx != 0) t = (f.x - A.first) * vx;\n            else t = (f.y - A.second) * vy;\n\n            if (t <= 0 || t >= len) continue;\n\n            int dx = f.x - A.first;\n            int dy = f.y - A.second;\n            int din = dx * inNx + dy * inNy;\n            int dout = dx * outNx + dy * outNy;\n\n            if ((din > 0 && din <= MAX_D) || (dout > 0 && dout <= MAX_D)) {\n                near.push_back({t, din, dout, f.w});\n            }\n        }\n\n        if (near.empty()) continue;\n\n        int anchorCount = 0;\n        for (auto &anchor : near) {\n            if (++anchorCount > 80) break;\n\n            for (int mode = 0; mode < 2; mode++) {\n                if (mode == 0 && !(anchor.dout > 0 && anchor.w > 0)) continue;\n                if (mode == 1 && !(anchor.din > 0 && anchor.w < 0)) continue;\n\n                int nx = (mode == 0 ? outNx : inNx);\n                int ny = (mode == 0 ? outNy : inNy);\n                int dist = (mode == 0 ? anchor.dout : anchor.din);\n                int depth = min(MAX_D, dist + 35);\n\n                if (basePer + 2LL * depth > MAX_PERIM) continue;\n\n                for (int W : widths) {\n                    int t1 = max(1, anchor.t - W);\n                    int t2 = min(len - 1, anchor.t + W);\n                    if (t2 - t1 < 2) continue;\n\n                    int approx = 0;\n                    for (auto &q : near) {\n                        if (q.t < t1 || q.t > t2) continue;\n                        if (mode == 0) {\n                            if (q.dout > 0 && q.dout <= depth) approx += q.w;\n                        } else {\n                            if (q.din > 0 && q.din <= depth) approx -= q.w;\n                        }\n                    }\n\n                    if (approx > 0) {\n                        cands.push_back({approx, i, t1, t2, nx, ny, depth});\n                    }\n                }\n            }\n        }\n    }\n\n    if (cands.empty()) return false;\n\n    sort(cands.begin(), cands.end(), [](const NotchCand& a, const NotchCand& b) {\n        return a.approx > b.approx;\n    });\n\n    int limit = min<int>(candLimit, cands.size());\n    int bestDiff = bestAns.diff;\n    vector<pair<int,int>> bestPoly;\n\n    for (int idx = 0; idx < limit; idx++) {\n        if (timer.sec() > 1.92) break;\n\n        auto np = applyNotch(base, cands[idx]);\n        if (np.empty()) continue;\n        if (!validPolygon(np)) continue;\n\n        int diff = exactDiffPolygon(np);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly = std::move(np);\n        }\n    }\n\n    if (!bestPoly.empty()) {\n        updateBest(bestPoly, bestDiff);\n        return true;\n    }\n    return false;\n}\n\nvoid tryNotchRefineIterative() {\n    if (timer.sec() > 1.82) return;\n\n    for (int iter = 0; iter < 3; iter++) {\n        if (timer.sec() > 1.86) break;\n        int limit = (iter == 0 ? 90 : 45);\n        bool improved = tryOneNotchIteration(limit);\n        if (!improved) break;\n\n        if (timer.sec() < 1.88) {\n            tryEdgeShiftRefine(120, 1);\n        }\n    }\n}\n\nstruct CornerCand {\n    int approx;\n    int vertex;\n    int d1, d2;\n};\n\nvector<pair<int,int>> applyCornerCut(const vector<pair<int,int>>& p, const CornerCand& c) {\n    int m = (int)p.size();\n    if (m + 2 > MAX_VERT) return {};\n\n    int i = c.vertex;\n    int pi = (i - 1 + m) % m;\n    int ni = (i + 1) % m;\n\n    auto A = p[pi];\n    auto B = p[i];\n    auto C = p[ni];\n\n    int e1x = (B.first > A.first) ? 1 : (B.first < A.first ? -1 : 0);\n    int e1y = (B.second > A.second) ? 1 : (B.second < A.second ? -1 : 0);\n    int e2x = (C.first > B.first) ? 1 : (C.first < B.first ? -1 : 0);\n    int e2y = (C.second > B.second) ? 1 : (C.second < B.second ? -1 : 0);\n\n    int len1 = abs(B.first - A.first) + abs(B.second - A.second);\n    int len2 = abs(C.first - B.first) + abs(C.second - B.second);\n\n    if (c.d1 <= 0 || c.d2 <= 0 || c.d1 >= len1 || c.d2 >= len2) return {};\n\n    pair<int,int> R1 = {B.first - e1x * c.d1, B.second - e1y * c.d1};\n    pair<int,int> R2 = {B.first + e2x * c.d2, B.second + e2y * c.d2};\n    pair<int,int> Q  = {R1.first + e2x * c.d2, R1.second + e2y * c.d2};\n\n    if (Q.first < 0 || Q.first > LIM || Q.second < 0 || Q.second > LIM) return {};\n    if (R1 == Q || R2 == Q || R1 == R2) return {};\n\n    vector<pair<int,int>> np;\n    np.reserve(m + 2);\n\n    for (int k = 0; k < m; k++) {\n        if (k == i) {\n            np.push_back(R1);\n            np.push_back(Q);\n            np.push_back(R2);\n        } else {\n            np.push_back(p[k]);\n        }\n    }\n\n    return np;\n}\n\nbool tryOneCornerCutIteration(int candLimit) {\n    if (bestAns.poly.empty()) return false;\n    if (timer.sec() > 1.84) return false;\n\n    vector<pair<int,int>> base = bestAns.poly;\n    if (!validPolygon(base)) return false;\n    if ((int)base.size() + 2 > MAX_VERT) return false;\n\n    bool ccw = twiceArea(base) > 0;\n    int m = (int)base.size();\n\n    const int MAX_D = 520;\n    vector<CornerCand> cands;\n\n    for (int i = 0; i < m; i++) {\n        if (timer.sec() > 1.88) break;\n\n        int pi = (i - 1 + m) % m;\n        int ni = (i + 1) % m;\n\n        auto A = base[pi];\n        auto B = base[i];\n        auto C = base[ni];\n\n        int e1x = (B.first > A.first) ? 1 : (B.first < A.first ? -1 : 0);\n        int e1y = (B.second > A.second) ? 1 : (B.second < A.second ? -1 : 0);\n        int e2x = (C.first > B.first) ? 1 : (C.first < B.first ? -1 : 0);\n        int e2y = (C.second > B.second) ? 1 : (C.second < B.second ? -1 : 0);\n\n        if (e1x * e2x + e1y * e2y != 0) continue;\n\n        int len1 = abs(B.first - A.first) + abs(B.second - A.second);\n        int len2 = abs(C.first - B.first) + abs(C.second - B.second);\n        if (len1 < 40 || len2 < 40) continue;\n\n        int cross = e1x * e2y - e1y * e2x;\n        bool convex = ccw ? (cross > 0) : (cross < 0);\n\n        struct Near {\n            int a, b, w;\n        };\n        vector<Near> near;\n\n        vector<int> d1s = {40, 80, 140, 240, 380, 520};\n        vector<int> d2s = {40, 80, 140, 240, 380, 520};\n\n        for (auto &f : fishes) {\n            int dx = f.x - B.first;\n            int dy = f.y - B.second;\n\n            int a = dx * (-e1x) + dy * (-e1y);\n            int b = dx * e2x + dy * e2y;\n\n            if (a > 0 && b > 0 && a < len1 && b < len2 && a <= MAX_D && b <= MAX_D) {\n                near.push_back({a,b,f.w});\n\n                int aa1 = min(len1 - 1, a + 25);\n                int bb1 = min(len2 - 1, b + 25);\n                int aa2 = min(len1 - 1, a + 80);\n                int bb2 = min(len2 - 1, b + 80);\n\n                if (aa1 > 0) d1s.push_back(aa1);\n                if (aa2 > 0) d1s.push_back(aa2);\n                if (bb1 > 0) d2s.push_back(bb1);\n                if (bb2 > 0) d2s.push_back(bb2);\n            }\n        }\n\n        if (near.empty()) continue;\n\n        sort(d1s.begin(), d1s.end());\n        d1s.erase(unique(d1s.begin(), d1s.end()), d1s.end());\n        sort(d2s.begin(), d2s.end());\n        d2s.erase(unique(d2s.begin(), d2s.end()), d2s.end());\n\n        if ((int)d1s.size() > 22) d1s.resize(22);\n        if ((int)d2s.size() > 22) d2s.resize(22);\n\n        for (int d1 : d1s) {\n            if (d1 <= 0 || d1 >= len1) continue;\n            for (int d2 : d2s) {\n                if (d2 <= 0 || d2 >= len2) continue;\n\n                int sum = 0;\n                for (auto &q : near) {\n                    if (q.a <= d1 && q.b <= d2) sum += q.w;\n                }\n\n                int approx = convex ? -sum : sum;\n                if (approx > 0) {\n                    cands.push_back({approx, i, d1, d2});\n                }\n            }\n        }\n    }\n\n    if (cands.empty()) return false;\n\n    sort(cands.begin(), cands.end(), [](const CornerCand& a, const CornerCand& b) {\n        return a.approx > b.approx;\n    });\n\n    int limit = min<int>(candLimit, cands.size());\n    int bestDiff = bestAns.diff;\n    vector<pair<int,int>> bestPoly;\n\n    for (int idx = 0; idx < limit; idx++) {\n        if (timer.sec() > 1.93) break;\n\n        auto np = applyCornerCut(base, cands[idx]);\n        if (np.empty()) continue;\n        if (!validPolygon(np)) continue;\n\n        int diff = exactDiffPolygon(np);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly = std::move(np);\n        }\n    }\n\n    if (!bestPoly.empty()) {\n        updateBest(bestPoly, bestDiff);\n        return true;\n    }\n    return false;\n}\n\nvoid tryCornerCutRefine() {\n    if (timer.sec() > 1.84) return;\n\n    for (int iter = 0; iter < 2; iter++) {\n        if (timer.sec() > 1.88) break;\n\n        int limit = (iter == 0 ? 70 : 35);\n        bool improved = tryOneCornerCutIteration(limit);\n        if (!improved) break;\n\n        if (timer.sec() < 1.89) {\n            tryEdgeShiftRefine(120, 1);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    fishes.reserve(2 * N);\n\n    for (int i = 0; i < 2 * N; i++) {\n        int x, y;\n        cin >> x >> y;\n        int w = (i < N ? 1 : -1);\n        fishes.push_back({x,y,w});\n    }\n\n    tryTinyBaseline();\n\n    vector<int> Ls = {500, 1000, 2000, 2500, 4000, 5000};\n    for (int L : Ls) {\n        processGrid(L);\n    }\n\n    tryEdgeShiftRefine(120, 2);\n    tryEdgeShiftRefine(240, 1);\n\n    tryNotchRefineIterative();\n\n    // New corner-local refinement.\n    tryCornerCutRefine();\n\n    tryEdgeShiftRefine(120, 1);\n\n    if (bestAns.poly.empty()) {\n        cout << 4 << '\\n';\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << bestAns.poly.size() << '\\n';\n    for (auto [x,y] : bestAns.poly) {\n        x = max(0, min(LIM, x));\n        y = max(0, min(LIM, y));\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Op {\n    int p, r;\n    char d;\n    int b;\n};\n\nstruct Solution {\n    vector<Op> ops;\n    ll estScore;\n};\n\nstatic inline bool overlap(ll l1, ll r1, ll l2, ll r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstruct Solver {\n    int N, T;\n    ll sigma;\n\n    vector<ll> w, h;\n    vector<ll> rawW, rawH;\n    vector<ll> obsW, obsH;\n    vector<ll> adjW, adjH;\n\n    vector<Solution> sols;\n    unordered_set<string> seen;\n\n    chrono::steady_clock::time_point st;\n    mt19937 rng;\n\n    Solver() : rng(1234567) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    pair<ll, ll> simulateWith(const vector<Op>& ops, const vector<ll>& W0, const vector<ll>& H0) const {\n        vector<ll> X(N), Y(N), W(N), H(N);\n        vector<char> used(N, 0);\n        ll BW = 0, BH = 0;\n\n        for (auto &op : ops) {\n            int p = op.p;\n            ll rw = op.r ? H0[p] : W0[p];\n            ll rh = op.r ? W0[p] : H0[p];\n            ll x = 0, y = 0;\n\n            if (op.d == 'U') {\n                x = (op.b == -1 ? 0 : X[op.b] + W[op.b]);\n                y = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap(x, x + rw, X[j], X[j] + W[j])) {\n                        y = max(y, Y[j] + H[j]);\n                    }\n                }\n            } else {\n                y = (op.b == -1 ? 0 : Y[op.b] + H[op.b]);\n                x = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap(y, y + rh, Y[j], Y[j] + H[j])) {\n                        x = max(x, X[j] + W[j]);\n                    }\n                }\n            }\n\n            X[p] = x;\n            Y[p] = y;\n            W[p] = rw;\n            H[p] = rh;\n            used[p] = 1;\n            BW = max(BW, x + rw);\n            BH = max(BH, y + rh);\n        }\n\n        return {BW, BH};\n    }\n\n    pair<ll, ll> simulate(const vector<Op>& ops) const {\n        return simulateWith(ops, w, h);\n    }\n\n    string makeKey(const vector<Op>& ops) const {\n        string s;\n        s.reserve(ops.size() * 3);\n        for (auto &op : ops) {\n            s.push_back(char(op.r));\n            s.push_back(op.d);\n            s.push_back(char(op.b + 1));\n        }\n        return s;\n    }\n\n    void addSolution(const vector<Op>& ops) {\n        if ((int)ops.size() != N) return;\n\n        string key = makeKey(ops);\n        if (seen.find(key) != seen.end()) return;\n        seen.insert(key);\n\n        auto [W0, H0] = simulate(ops);\n        sols.push_back({ops, W0 + H0});\n    }\n\n    void outputOps(const vector<Op>& ops) {\n        cout << ops.size() << '\\n';\n        for (auto &op : ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n    }\n\n    vector<Op> makeBlockRow(int l, int r, int rot) {\n        vector<Op> ops;\n        ops.reserve(r - l);\n        for (int i = l; i < r; i++) ops.push_back({i, rot, 'L', -1});\n        return ops;\n    }\n\n    vector<Op> makeBlockCol(int l, int r, int rot) {\n        vector<Op> ops;\n        ops.reserve(r - l);\n        for (int i = l; i < r; i++) ops.push_back({i, rot, 'U', -1});\n        return ops;\n    }\n\n    int performCalibration() {\n        int reserveTurns = max(20, N / 2);\n        int budget = T - reserveTurns;\n        int maxPairs = budget / 2;\n        int G = max(0, min(8, maxPairs));\n\n        if (G <= 0) return 0;\n\n        vector<int> L(G), R(G);\n        for (int g = 0; g < G; g++) {\n            L[g] = (long long)N * g / G;\n            R[g] = (long long)N * (g + 1) / G;\n        }\n\n        int extraBlocks = 0;\n        if (sigma >= 7000 && T >= 3 * N) {\n            int rem = budget - 2 * G;\n            if (rem >= 8) extraBlocks = min({4, G, rem / 2});\n        }\n\n        vector<double> sumDW(G, 0.0), sumDH(G, 0.0);\n        vector<int> cntW(G, 0), cntH(G, 0);\n\n        int usedTurns = 0;\n\n        for (int g = 0; g < G; g++) {\n            int l = L[g], r = R[g];\n            if (l >= r) continue;\n\n            {\n                vector<Op> ops = makeBlockRow(l, r, 0);\n                outputOps(ops);\n\n                ll Wobs, Hobs;\n                if (!(cin >> Wobs >> Hobs)) exit(0);\n                usedTurns++;\n\n                ll sumObs = 0;\n                for (int i = l; i < r; i++) sumObs += rawW[i];\n                sumDW[g] += (double)(Wobs - sumObs);\n                cntW[g]++;\n            }\n\n            {\n                vector<Op> ops = makeBlockCol(l, r, 0);\n                outputOps(ops);\n\n                ll Wobs, Hobs;\n                if (!(cin >> Wobs >> Hobs)) exit(0);\n                usedTurns++;\n\n                ll sumObs = 0;\n                for (int i = l; i < r; i++) sumObs += rawH[i];\n                sumDH[g] += (double)(Hobs - sumObs);\n                cntH[g]++;\n            }\n\n            if (g < extraBlocks) {\n                // Rotated horizontal row: observed width ~= sum of original heights.\n                {\n                    vector<Op> ops = makeBlockRow(l, r, 1);\n                    outputOps(ops);\n\n                    ll Wobs, Hobs;\n                    if (!(cin >> Wobs >> Hobs)) exit(0);\n                    usedTurns++;\n\n                    ll sumObs = 0;\n                    for (int i = l; i < r; i++) sumObs += rawH[i];\n                    sumDH[g] += (double)(Wobs - sumObs);\n                    cntH[g]++;\n                }\n\n                // Rotated vertical column: observed height ~= sum of original widths.\n                {\n                    vector<Op> ops = makeBlockCol(l, r, 1);\n                    outputOps(ops);\n\n                    ll Wobs, Hobs;\n                    if (!(cin >> Wobs >> Hobs)) exit(0);\n                    usedTurns++;\n\n                    ll sumObs = 0;\n                    for (int i = l; i < r; i++) sumObs += rawW[i];\n                    sumDW[g] += (double)(Hobs - sumObs);\n                    cntW[g]++;\n                }\n            }\n        }\n\n        w = rawW;\n        h = rawH;\n\n        for (int g = 0; g < G; g++) {\n            int l = L[g], r = R[g];\n            int k = r - l;\n            if (k <= 0) continue;\n\n            if (cntW[g] > 0) {\n                double delta = sumDW[g] / (1.0 + (double)cntW[g] * k);\n                for (int i = l; i < r; i++) {\n                    w[i] = max(1LL, (ll)llround((double)rawW[i] + delta));\n                }\n            }\n\n            if (cntH[g] > 0) {\n                double delta = sumDH[g] / (1.0 + (double)cntH[g] * k);\n                for (int i = l; i < r; i++) {\n                    h[i] = max(1LL, (ll)llround((double)rawH[i] + delta));\n                }\n            }\n        }\n\n        return usedTurns;\n    }\n\n    struct SegInfo {\n        bool ok = false;\n        ll rowH = 0;\n        ll rowW = 0;\n        vector<int> rot;\n    };\n\n    SegInfo calcRowSegment(int l, int r, ll limitW, bool needRot) const {\n        vector<ll> cand;\n        cand.reserve((r - l) * 2);\n\n        for (int i = l; i < r; i++) {\n            cand.push_back(h[i]);\n            cand.push_back(w[i]);\n        }\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        for (ll HH : cand) {\n            ll sumW = 0;\n            bool ok = true;\n            vector<int> rots;\n            if (needRot) rots.reserve(r - l);\n\n            for (int i = l; i < r; i++) {\n                const ll INF = (1LL << 60);\n                ll bw = INF;\n                int br = -1;\n\n                if (h[i] <= HH) {\n                    bw = w[i];\n                    br = 0;\n                }\n                if (w[i] <= HH && h[i] < bw) {\n                    bw = h[i];\n                    br = 1;\n                }\n\n                if (br == -1) {\n                    ok = false;\n                    break;\n                }\n\n                sumW += bw;\n                if (sumW > limitW) {\n                    ok = false;\n                    break;\n                }\n\n                if (needRot) rots.push_back(br);\n            }\n\n            if (ok) {\n                SegInfo res;\n                res.ok = true;\n                res.rowH = HH;\n                res.rowW = sumW;\n                if (needRot) res.rot = move(rots);\n                return res;\n            }\n        }\n\n        return {};\n    }\n\n    SegInfo calcColSegment(int l, int r, ll limitH, bool needRot) const {\n        vector<ll> cand;\n        cand.reserve((r - l) * 2);\n\n        for (int i = l; i < r; i++) {\n            cand.push_back(w[i]);\n            cand.push_back(h[i]);\n        }\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        for (ll WW : cand) {\n            ll sumH = 0;\n            bool ok = true;\n            vector<int> rots;\n            if (needRot) rots.reserve(r - l);\n\n            for (int i = l; i < r; i++) {\n                const ll INF = (1LL << 60);\n                ll bh = INF;\n                int br = -1;\n\n                if (w[i] <= WW) {\n                    bh = h[i];\n                    br = 0;\n                }\n                if (h[i] <= WW && w[i] < bh) {\n                    bh = w[i];\n                    br = 1;\n                }\n\n                if (br == -1) {\n                    ok = false;\n                    break;\n                }\n\n                sumH += bh;\n                if (sumH > limitH) {\n                    ok = false;\n                    break;\n                }\n\n                if (needRot) rots.push_back(br);\n            }\n\n            if (ok) {\n                SegInfo res;\n                res.ok = true;\n                res.rowH = sumH;\n                res.rowW = WW;\n                if (needRot) res.rot = move(rots);\n                return res;\n            }\n        }\n\n        return {};\n    }\n\n    void buildRowsFromPrev(const vector<int>& prv) {\n        if (prv[N] == -1) return;\n\n        vector<pair<int,int>> rows;\n        for (int cur = N; cur > 0; cur = prv[cur]) rows.push_back({prv[cur], cur});\n        reverse(rows.begin(), rows.end());\n\n        vector<int> rot(N, 0);\n        for (auto [l, r] : rows) {\n            // Reconstruct with effectively infinite limit.\n            SegInfo si = calcRowSegment(l, r, (1LL << 60), true);\n            if (!si.ok) return;\n            for (int k = l; k < r; k++) rot[k] = si.rot[k - l];\n        }\n\n        vector<Op> ops;\n        ops.reserve(N);\n\n        int prevAnchor = -1;\n\n        for (int row = 0; row < (int)rows.size(); row++) {\n            auto [l, r] = rows[row];\n            int b = (row == 0 ? -1 : prevAnchor);\n\n            for (int i = l; i < r; i++) ops.push_back({i, rot[i], 'L', b});\n\n            ll bestH = -1;\n            int anchor = l;\n            for (int i = l; i < r; i++) {\n                ll hh = rot[i] ? w[i] : h[i];\n                if (hh > bestH) {\n                    bestH = hh;\n                    anchor = i;\n                }\n            }\n            prevAnchor = anchor;\n        }\n\n        addSolution(ops);\n    }\n\n    void buildColsFromPrev(const vector<int>& prv) {\n        if (prv[N] == -1) return;\n\n        vector<pair<int,int>> cols;\n        for (int cur = N; cur > 0; cur = prv[cur]) cols.push_back({prv[cur], cur});\n        reverse(cols.begin(), cols.end());\n\n        vector<int> rot(N, 0);\n        for (auto [l, r] : cols) {\n            SegInfo si = calcColSegment(l, r, (1LL << 60), true);\n            if (!si.ok) return;\n            for (int k = l; k < r; k++) rot[k] = si.rot[k - l];\n        }\n\n        vector<Op> ops;\n        ops.reserve(N);\n\n        int prevAnchor = -1;\n\n        for (int col = 0; col < (int)cols.size(); col++) {\n            auto [l, r] = cols[col];\n            int b = (col == 0 ? -1 : prevAnchor);\n\n            for (int i = l; i < r; i++) ops.push_back({i, rot[i], 'U', b});\n\n            ll bestW = -1;\n            int anchor = l;\n            for (int i = l; i < r; i++) {\n                ll ww = rot[i] ? h[i] : w[i];\n                if (ww > bestW) {\n                    bestW = ww;\n                    anchor = i;\n                }\n            }\n            prevAnchor = anchor;\n        }\n\n        addSolution(ops);\n    }\n\n    void generateShelfRows(ll limitW) {\n        const ll INF = (1LL << 60);\n\n        vector<vector<ll>> segH(N, vector<ll>(N + 1, INF));\n        vector<vector<ll>> segW(N, vector<ll>(N + 1, INF));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l + 1; r <= N; r++) {\n                SegInfo si = calcRowSegment(l, r, limitW, false);\n                if (si.ok) {\n                    segH[l][r] = si.rowH;\n                    segW[l][r] = si.rowW;\n                }\n            }\n        }\n\n        // Original objective: minimize total height under width limit.\n        {\n            vector<ll> dpH(N + 1, INF), dpMaxW(N + 1, INF);\n            vector<int> prv(N + 1, -1);\n\n            dpH[0] = 0;\n            dpMaxW[0] = 0;\n\n            for (int i = 1; i <= N; i++) {\n                for (int l = 0; l < i; l++) {\n                    if (dpH[l] == INF || segH[l][i] == INF) continue;\n\n                    ll nh = dpH[l] + segH[l][i];\n                    ll nw = max(dpMaxW[l], segW[l][i]);\n\n                    if (nh < dpH[i] || (nh == dpH[i] && nw < dpMaxW[i])) {\n                        dpH[i] = nh;\n                        dpMaxW[i] = nw;\n                        prv[i] = l;\n                    }\n                }\n            }\n\n            buildRowsFromPrev(prv);\n        }\n\n        // Added objective: directly minimize estimated W + H.\n        {\n            vector<ll> dpH(N + 1, INF), dpMaxW(N + 1, INF);\n            vector<int> prv(N + 1, -1);\n\n            dpH[0] = 0;\n            dpMaxW[0] = 0;\n\n            for (int i = 1; i <= N; i++) {\n                for (int l = 0; l < i; l++) {\n                    if (dpH[l] == INF || segH[l][i] == INF) continue;\n\n                    ll nh = dpH[l] + segH[l][i];\n                    ll nw = max(dpMaxW[l], segW[l][i]);\n\n                    ll oldCost = (dpH[i] == INF ? INF : dpH[i] + dpMaxW[i]);\n                    ll newCost = nh + nw;\n\n                    if (newCost < oldCost || (newCost == oldCost && nh < dpH[i])) {\n                        dpH[i] = nh;\n                        dpMaxW[i] = nw;\n                        prv[i] = l;\n                    }\n                }\n            }\n\n            buildRowsFromPrev(prv);\n        }\n    }\n\n    void generateShelfCols(ll limitH) {\n        const ll INF = (1LL << 60);\n\n        vector<vector<ll>> segW(N, vector<ll>(N + 1, INF));\n        vector<vector<ll>> segH(N, vector<ll>(N + 1, INF));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l + 1; r <= N; r++) {\n                SegInfo si = calcColSegment(l, r, limitH, false);\n                if (si.ok) {\n                    segW[l][r] = si.rowW;\n                    segH[l][r] = si.rowH;\n                }\n            }\n        }\n\n        // Original objective: minimize total width under height limit.\n        {\n            vector<ll> dpW(N + 1, INF), dpMaxH(N + 1, INF);\n            vector<int> prv(N + 1, -1);\n\n            dpW[0] = 0;\n            dpMaxH[0] = 0;\n\n            for (int i = 1; i <= N; i++) {\n                for (int l = 0; l < i; l++) {\n                    if (dpW[l] == INF || segW[l][i] == INF) continue;\n\n                    ll nw = dpW[l] + segW[l][i];\n                    ll nh = max(dpMaxH[l], segH[l][i]);\n\n                    if (nw < dpW[i] || (nw == dpW[i] && nh < dpMaxH[i])) {\n                        dpW[i] = nw;\n                        dpMaxH[i] = nh;\n                        prv[i] = l;\n                    }\n                }\n            }\n\n            buildColsFromPrev(prv);\n        }\n\n        // Added objective: directly minimize estimated W + H.\n        {\n            vector<ll> dpW(N + 1, INF), dpMaxH(N + 1, INF);\n            vector<int> prv(N + 1, -1);\n\n            dpW[0] = 0;\n            dpMaxH[0] = 0;\n\n            for (int i = 1; i <= N; i++) {\n                for (int l = 0; l < i; l++) {\n                    if (dpW[l] == INF || segW[l][i] == INF) continue;\n\n                    ll nw = dpW[l] + segW[l][i];\n                    ll nh = max(dpMaxH[l], segH[l][i]);\n\n                    ll oldCost = (dpW[i] == INF ? INF : dpW[i] + dpMaxH[i]);\n                    ll newCost = nw + nh;\n\n                    if (newCost < oldCost || (newCost == oldCost && nw < dpW[i])) {\n                        dpW[i] = nw;\n                        dpMaxH[i] = nh;\n                        prv[i] = l;\n                    }\n                }\n            }\n\n            buildColsFromPrev(prv);\n        }\n    }\n\n    void generateSimpleRowsAndCols() {\n        for (int policy = 0; policy < 4; policy++) {\n            vector<Op> ops;\n            ops.reserve(N);\n\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (policy == 1) r = 1;\n                else if (policy == 2) r = (h[i] < w[i]);\n                else if (policy == 3) r = (w[i] < h[i]);\n\n                ops.push_back({i, r, 'L', -1});\n            }\n\n            addSolution(ops);\n        }\n\n        for (int policy = 0; policy < 4; policy++) {\n            vector<Op> ops;\n            ops.reserve(N);\n\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (policy == 1) r = 1;\n                else if (policy == 2) r = (h[i] < w[i]);\n                else if (policy == 3) r = (w[i] < h[i]);\n\n                ops.push_back({i, r, 'U', -1});\n            }\n\n            addSolution(ops);\n        }\n    }\n\n    void generateGreedy(double wp, double wa, double wb, double noiseCoef) {\n        vector<Op> ops;\n        ops.reserve(N);\n\n        vector<ll> X(N), Y(N), RW(N), RH(N);\n        vector<char> used(N, 0);\n        ll curW = 0, curH = 0;\n\n        long double area = 0;\n        for (int i = 0; i < N; i++) area += (long double)w[i] * h[i];\n\n        double scale = max(1.0, sqrt((double)area));\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        for (int i = 0; i < N; i++) {\n            double bestCost = 1e100;\n            Op bestOp{i, 0, 'L', -1};\n            ll bestX = 0, bestY = 0, bestRW = w[i], bestRH = h[i];\n            ll bestBW = 0, bestBH = 0;\n\n            for (int r = 0; r < 2; r++) {\n                ll rw = r ? h[i] : w[i];\n                ll rh = r ? w[i] : h[i];\n\n                for (int d0 = 0; d0 < 2; d0++) {\n                    char d = d0 ? 'L' : 'U';\n\n                    for (int b = -1; b < i; b++) {\n                        ll x = 0, y = 0;\n\n                        if (d == 'U') {\n                            x = (b == -1 ? 0 : X[b] + RW[b]);\n                            y = 0;\n\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (overlap(x, x + rw, X[j], X[j] + RW[j])) {\n                                    y = max(y, Y[j] + RH[j]);\n                                }\n                            }\n                        } else {\n                            y = (b == -1 ? 0 : Y[b] + RH[b]);\n                            x = 0;\n\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (overlap(y, y + rh, Y[j], Y[j] + RH[j])) {\n                                    x = max(x, X[j] + RW[j]);\n                                }\n                            }\n                        }\n\n                        ll BW = max(curW, x + rw);\n                        ll BH = max(curH, y + rh);\n\n                        double cost = 0.0;\n                        cost += wp * (double)(BW + BH);\n                        cost += wa * ((double)BW * (double)BH / scale);\n                        cost += wb * (double)llabs(BW - BH);\n                        cost += noiseCoef * scale * ud(rng);\n                        cost += 0.0001 * (double)(x + y);\n\n                        if (cost < bestCost) {\n                            bestCost = cost;\n                            bestOp = {i, r, d, b};\n                            bestX = x;\n                            bestY = y;\n                            bestRW = rw;\n                            bestRH = rh;\n                            bestBW = BW;\n                            bestBH = BH;\n                        }\n                    }\n                }\n            }\n\n            ops.push_back(bestOp);\n            X[i] = bestX;\n            Y[i] = bestY;\n            RW[i] = bestRW;\n            RH[i] = bestRH;\n            used[i] = 1;\n            curW = bestBW;\n            curH = bestBH;\n        }\n\n        addSolution(ops);\n    }\n\n    void makeAdjustedDimensions() {\n        vector<ll> vals;\n        vals.reserve(2 * N);\n        for (int i = 0; i < N; i++) {\n            vals.push_back(obsW[i]);\n            vals.push_back(obsH[i]);\n        }\n\n        sort(vals.begin(), vals.end());\n\n        int m = vals.size();\n        double q10 = vals[max(0, min(m - 1, m / 10))];\n\n        double Lhat = (q10 - 10000.0) / 0.9;\n        Lhat = min(50000.0, max(10000.0, Lhat));\n\n        double mean = (Lhat + 100000.0) * 0.5;\n        double var = (100000.0 - Lhat) * (100000.0 - Lhat) / 12.0;\n        double a = var / (var + (double)sigma * (double)sigma);\n\n        a = 1.0 - 1.15 * (1.0 - a);\n        a = min(1.0, max(0.55, a));\n\n        adjW.resize(N);\n        adjH.resize(N);\n\n        for (int i = 0; i < N; i++) {\n            adjW[i] = max(1LL, (ll)llround(a * obsW[i] + (1.0 - a) * mean));\n            adjH[i] = max(1LL, (ll)llround(a * obsH[i] + (1.0 - a) * mean));\n        }\n    }\n\n    vector<ll> makeLimits(int cnt, double lo, double hi) const {\n        long double area = 0;\n        ll minSingleSide = 1;\n\n        for (int i = 0; i < N; i++) {\n            area += (long double)w[i] * h[i];\n            minSingleSide = max(minSingleSide, min(w[i], h[i]));\n        }\n\n        double sqrtA = sqrt((double)area);\n        vector<ll> limits;\n\n        for (int k = 0; k < cnt; k++) {\n            double f = lo + (hi - lo) * k / max(1, cnt - 1);\n            limits.push_back(max<ll>(minSingleSide, (ll)llround(sqrtA * f)));\n        }\n\n        sort(limits.begin(), limits.end());\n        limits.erase(unique(limits.begin(), limits.end()), limits.end());\n        return limits;\n    }\n\n    void recomputeScoresWithCalibrated() {\n        for (auto &s : sols) {\n            auto [BWc, BHc] = simulateWith(s.ops, obsW, obsH);\n            auto [BWr, BHr] = simulateWith(s.ops, rawW, rawH);\n\n            ll sc = BWc + BHc;\n            ll sr = BWr + BHr;\n\n            s.estScore = (3 * sc + sr) / 4;\n        }\n    }\n\n    void generateCandidateSet(const vector<ll>& Wset, const vector<ll>& Hset,\n                              int shelfCnt, double shelfLo, double shelfHi,\n                              double timeLimit, int greedyLimit) {\n        w = Wset;\n        h = Hset;\n\n        generateSimpleRowsAndCols();\n\n        vector<ll> limits = makeLimits(shelfCnt, shelfLo, shelfHi);\n        for (ll L : limits) {\n            if (elapsed() > timeLimit) break;\n            generateShelfRows(L);\n            generateShelfCols(L);\n        }\n\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        int greedyTrials = 0;\n        while (elapsed() < timeLimit && greedyTrials < greedyLimit) {\n            greedyTrials++;\n\n            double wp = 1.0;\n            double wa = pow(10.0, -0.45 + 1.35 * ud(rng));\n            double wb = 0.03 + 1.50 * ud(rng);\n            double nz = 0.0;\n\n            if (greedyTrials % 3 == 0) nz = 0.01 * ud(rng);\n            if (greedyTrials % 7 == 0) nz = 0.05 * ud(rng);\n            if (greedyTrials % 19 == 0) nz = 0.10 * ud(rng);\n\n            generateGreedy(wp, wa, wb, nz);\n        }\n    }\n\n    void generateAll() {\n        st = chrono::steady_clock::now();\n\n        obsW = w;\n        obsH = h;\n        makeAdjustedDimensions();\n\n        generateCandidateSet(obsW, obsH, 55, 0.50, 2.65, 2.34, 680);\n\n        if (elapsed() < 2.52) {\n            generateCandidateSet(rawW, rawH, 22, 0.55, 2.45, 2.52, 120);\n        }\n\n        if (elapsed() < 2.66) {\n            generateCandidateSet(adjW, adjH, 16, 0.55, 2.45, 2.66, 70);\n        }\n\n        if (sols.empty()) {\n            w = obsW;\n            h = obsH;\n            vector<Op> ops;\n            for (int i = 0; i < N; i++) ops.push_back({i, 0, 'L', -1});\n            addSolution(ops);\n        }\n\n        recomputeScoresWithCalibrated();\n\n        sort(sols.begin(), sols.end(), [](const Solution& a, const Solution& b) {\n            return a.estScore < b.estScore;\n        });\n    }\n\n    void run() {\n        cin >> N >> T >> sigma;\n\n        w.resize(N);\n        h.resize(N);\n\n        for (int i = 0; i < N; i++) {\n            cin >> w[i] >> h[i];\n        }\n\n        rawW = w;\n        rawH = h;\n\n        int usedTurns = performCalibration();\n\n        generateAll();\n\n        for (int t = usedTurns; t < T; t++) {\n            const vector<Op>& ops = sols[(t - usedTurns) % sols.size()].ops;\n\n            outputOps(ops);\n\n            ll Wobs, Hobs;\n            if (!(cin >> Wobs >> Hobs)) return;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.run();\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 10;\nstatic constexpr int MAXN = 1000;\nstatic constexpr long long NEG = -(1LL << 60);\n\nstruct Edge {\n    int u, v;\n    long long len2;\n};\n\nstruct Solver {\n    int N, M, HH;\n    vector<int> A;\n    vector<Edge> edges;\n    vector<vector<int>> adj;\n    vector<int> xs, ys;\n    vector<bitset<MAXN>> con;\n\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n\n    vector<array<long long, 11>> dp_no, dp_need;\n    vector<vector<int>> children;\n\n    vector<int> orderHigh, orderLow;\n\n    Solver() : rng(1234567) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    long long scoreLabels(const vector<int>& d) const {\n        long long s = 0;\n        for (int i = 0; i < N; i++) s += 1LL * (d[i] + 1) * A[i];\n        return s;\n    }\n\n    long long keyPrim(int mode, int from, int to) {\n        long long noise = (long long)(rng() % 100000);\n        long long dx = xs[from] - xs[to];\n        long long dy = ys[from] - ys[to];\n        long long len2 = dx * dx + dy * dy;\n\n        if (mode == 0) return 1LL * A[to] * 100000 + noise;\n        if (mode == 1) return 1LL * (101 - A[to]) * 100000 + noise;\n        if (mode == 2) return (long long)(rng() & 0x7fffffff);\n        if (mode == 3) return len2 * 1000 + noise;\n        if (mode == 4) return (2000000LL - min(len2, 2000000LL)) * 1000 + noise;\n        return 1LL * A[to] * 50000 + len2 + noise;\n    }\n\n    vector<int> makePrimTree(int mode) {\n        vector<int> par(N, -2), used(N, 0);\n\n        int start = 0;\n        if (mode == 0 || mode == 5) start = min_element(A.begin(), A.end()) - A.begin();\n        else if (mode == 1) start = max_element(A.begin(), A.end()) - A.begin();\n        else start = rng() % N;\n\n        using T = tuple<long long, int, int>;\n        priority_queue<T, vector<T>, greater<T>> pq;\n\n        used[start] = 1;\n        par[start] = -1;\n        int cnt = 1;\n\n        for (int to : adj[start]) pq.emplace(keyPrim(mode, start, to), start, to);\n\n        while (cnt < N && !pq.empty()) {\n            auto [key, from, v] = pq.top();\n            pq.pop();\n            if (used[v]) continue;\n\n            used[v] = 1;\n            par[v] = from;\n            cnt++;\n\n            for (int to : adj[v]) {\n                if (!used[to]) pq.emplace(keyPrim(mode, v, to), v, to);\n            }\n        }\n\n        return par;\n    }\n\n    vector<int> makeDFSTree(int mode) {\n        vector<vector<pair<long long, int>>> ord(N);\n\n        for (int v = 0; v < N; v++) {\n            for (int to : adj[v]) {\n                long long noise = (long long)(rng() % 100000);\n                long long key;\n\n                if (mode == 0) key = 1LL * A[to] * 100000 + noise;\n                else if (mode == 1) key = 1LL * (101 - A[to]) * 100000 + noise;\n                else key = (long long)(rng() & 0x7fffffff);\n\n                ord[v].push_back({key, to});\n            }\n            sort(ord[v].begin(), ord[v].end());\n        }\n\n        int start;\n        if (mode == 0) start = min_element(A.begin(), A.end()) - A.begin();\n        else if (mode == 1) start = max_element(A.begin(), A.end()) - A.begin();\n        else start = rng() % N;\n\n        vector<int> par(N, -2), used(N, 0), idx(N, 0), stk;\n        stk.push_back(start);\n        used[start] = 1;\n        par[start] = -1;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n\n            while (idx[v] < (int)ord[v].size() && used[ord[v][idx[v]].second]) idx[v]++;\n\n            if (idx[v] == (int)ord[v].size()) {\n                stk.pop_back();\n                continue;\n            }\n\n            int to = ord[v][idx[v]++].second;\n            used[to] = 1;\n            par[to] = v;\n            stk.push_back(to);\n        }\n\n        return par;\n    }\n\n    long long childVal(int c, int childLabel, int parentLabel) const {\n        if (childLabel == 0 || parentLabel == childLabel - 1) return dp_no[c][childLabel];\n        return dp_need[c][childLabel];\n    }\n\n    vector<int> solveOnTree(const vector<int>& treePar) {\n        vector<vector<int>> tadj(N);\n\n        for (int v = 0; v < N; v++) {\n            if (treePar[v] >= 0) {\n                tadj[v].push_back(treePar[v]);\n                tadj[treePar[v]].push_back(v);\n            }\n        }\n\n        children.assign(N, {});\n        vector<int> parent(N, -1), order;\n        order.reserve(N);\n\n        vector<int> stk = {0};\n        parent[0] = -2;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n            stk.pop_back();\n            order.push_back(v);\n\n            for (int to : tadj[v]) {\n                if (to == parent[v]) continue;\n                parent[to] = v;\n                children[v].push_back(to);\n                stk.push_back(to);\n            }\n        }\n\n        dp_no.assign(N, {});\n        dp_need.assign(N, {});\n\n        for (int ii = N - 1; ii >= 0; ii--) {\n            int v = order[ii];\n\n            for (int l = 0; l <= H; l++) {\n                long long base = 1LL * (l + 1) * A[v];\n                vector<long long> bestChild;\n                bestChild.reserve(children[v].size());\n\n                bool ok = true;\n                long long sum = base;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n\n                    for (int lc = 0; lc <= H; lc++) {\n                        best = max(best, childVal(c, lc, l));\n                    }\n\n                    if (best <= NEG / 2) ok = false;\n\n                    sum += best;\n                    bestChild.push_back(best);\n                }\n\n                dp_no[v][l] = ok ? sum : NEG;\n\n                if (l == 0 || !ok) {\n                    dp_need[v][l] = NEG;\n                } else {\n                    int forcedLabel = l - 1;\n                    long long bestDelta = NEG;\n\n                    for (int idx = 0; idx < (int)children[v].size(); idx++) {\n                        int c = children[v][idx];\n                        long long fv = childVal(c, forcedLabel, l);\n\n                        if (fv <= NEG / 2) continue;\n\n                        bestDelta = max(bestDelta, fv - bestChild[idx]);\n                    }\n\n                    if (bestDelta <= NEG / 2) dp_need[v][l] = NEG;\n                    else dp_need[v][l] = sum + bestDelta;\n                }\n            }\n        }\n\n        int rootLabel = 0;\n        bool rootNeed = false;\n        long long bestRoot = dp_no[0][0];\n\n        for (int l = 1; l <= H; l++) {\n            if (dp_need[0][l] > bestRoot) {\n                bestRoot = dp_need[0][l];\n                rootLabel = l;\n                rootNeed = true;\n            }\n        }\n\n        vector<int> label(N, 0);\n\n        function<void(int, int, bool)> rec = [&](int v, int l, bool needSupportChild) {\n            label[v] = l;\n\n            int forcedChild = -1;\n\n            if (needSupportChild) {\n                int forcedLabel = l - 1;\n                long long bestDelta = NEG;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n\n                    for (int lc = 0; lc <= H; lc++) best = max(best, childVal(c, lc, l));\n\n                    long long fv = childVal(c, forcedLabel, l);\n\n                    if (fv <= NEG / 2) continue;\n\n                    long long delta = fv - best;\n\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        forcedChild = c;\n                    }\n                }\n            }\n\n            for (int c : children[v]) {\n                int lcBest = 0;\n                long long valBest = NEG;\n\n                if (c == forcedChild) {\n                    lcBest = l - 1;\n                } else {\n                    for (int lc = 0; lc <= H; lc++) {\n                        long long val = childVal(c, lc, l);\n\n                        if (val > valBest) {\n                            valBest = val;\n                            lcBest = lc;\n                        }\n                    }\n                }\n\n                bool childNeed = !(lcBest == 0 || l == lcBest - 1);\n                rec(c, lcBest, childNeed);\n            }\n        };\n\n        rec(0, rootLabel, rootNeed);\n        return label;\n    }\n\n    vector<int> calcCnt(const vector<int>& d) const {\n        vector<int> cnt(N, 0);\n\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) continue;\n\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) cnt[v]++;\n            }\n        }\n\n        return cnt;\n    }\n\n    bool canMove(const vector<int>& d, const vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n\n        if (old == nl) return false;\n\n        if (nl > 0) {\n            bool has = false;\n\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) {\n                    has = true;\n                    break;\n                }\n            }\n\n            if (!has) return false;\n        }\n\n        for (int to : adj[v]) {\n            if (d[to] > 0 && d[to] - 1 == old && cnt[to] == 1) return false;\n        }\n\n        return true;\n    }\n\n    bool canMoveExcept(\n        const vector<int>& d,\n        const vector<int>& cnt,\n        int v,\n        int nl,\n        int exceptVertex,\n        int exceptFinalDepth\n    ) const {\n        int old = d[v];\n\n        if (old == nl) return false;\n\n        if (nl > 0) {\n            bool has = false;\n\n            for (int to : adj[v]) {\n                int td = (to == exceptVertex ? exceptFinalDepth : d[to]);\n\n                if (td == nl - 1) {\n                    has = true;\n                    break;\n                }\n            }\n\n            if (!has) return false;\n        }\n\n        for (int to : adj[v]) {\n            if (to == exceptVertex) continue;\n\n            if (d[to] > 0 && d[to] - 1 == old && cnt[to] == 1) return false;\n        }\n\n        return true;\n    }\n\n    void applyMove(vector<int>& d, vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n\n        for (int to : adj[v]) {\n            if (d[to] > 0) {\n                if (old == d[to] - 1) cnt[to]--;\n                if (nl == d[to] - 1) cnt[to]++;\n            }\n        }\n\n        d[v] = nl;\n\n        if (nl == 0) {\n            cnt[v] = 0;\n        } else {\n            int c = 0;\n\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) c++;\n            }\n\n            cnt[v] = c;\n        }\n    }\n\n    void greedyImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 20; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int old = d[v];\n\n                for (int nl = H; nl > old; nl--) {\n                    if (canMove(d, cnt, v, nl)) {\n                        applyMove(d, cnt, v, nl);\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void supportPairImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 5; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int dv = d[v];\n\n                if (dv == H) continue;\n\n                for (int t = H; t > dv; t--) {\n                    if (canMove(d, cnt, v, t)) {\n                        applyMove(d, cnt, v, t);\n                        changed = true;\n                        dv = t;\n                        break;\n                    }\n\n                    int need = t - 1;\n                    int bestU = -1;\n                    long long bestNet = 0;\n\n                    for (int u : adj[v]) {\n                        if (d[u] == need) continue;\n                        if (!canMoveExcept(d, cnt, u, need, v, t)) continue;\n\n                        long long net = 1LL * (t - dv) * A[v] + 1LL * (need - d[u]) * A[u];\n\n                        if (net > bestNet) {\n                            bestNet = net;\n                            bestU = u;\n                        }\n                    }\n\n                    if (bestU != -1) {\n                        int oldU = d[bestU];\n\n                        applyMove(d, cnt, bestU, need);\n\n                        if (canMove(d, cnt, v, t)) {\n                            applyMove(d, cnt, v, t);\n                            changed = true;\n                            dv = t;\n                            break;\n                        } else {\n                            applyMove(d, cnt, bestU, oldU);\n                        }\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    bool checkFeasible(const vector<int>& d) const {\n        for (int v = 0; v < N; v++) {\n            if (d[v] < 0 || d[v] > H) return false;\n\n            if (d[v] == 0) continue;\n\n            bool ok = false;\n\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return false;\n        }\n\n        return true;\n    }\n\n    int depthAfterMoveSet(const vector<int>& d, const vector<pair<int, int>>& mv, int x) const {\n        for (auto [v, nd] : mv) {\n            if (v == x) return nd;\n        }\n        return d[x];\n    }\n\n    bool validateMoveSet(const vector<int>& d, const vector<pair<int, int>>& mv) const {\n        vector<int> affected;\n        vector<char> mark(N, 0);\n\n        auto add = [&](int x) {\n            if (!mark[x]) {\n                mark[x] = 1;\n                affected.push_back(x);\n            }\n        };\n\n        for (auto [v, nd] : mv) {\n            if (nd < 0 || nd > H) return false;\n            add(v);\n            for (int to : adj[v]) add(to);\n        }\n\n        for (int x : affected) {\n            int dx = depthAfterMoveSet(d, mv, x);\n\n            if (dx == 0) continue;\n\n            bool ok = false;\n\n            for (int to : adj[x]) {\n                if (depthAfterMoveSet(d, mv, to) == dx - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return false;\n        }\n\n        return true;\n    }\n\n    void groupSupportImprove(vector<int>& d, double timeLimit) {\n        for (int pass = 0; pass < 4 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n\n            int checked = 0;\n\n            for (int u : orderLow) {\n                if (elapsed() >= timeLimit) break;\n                if (++checked > 850) break;\n\n                long long bestGain = 0;\n                vector<pair<int, int>> bestMoves;\n\n                for (int k = 0; k < H; k++) {\n                    int supportDepth = k;\n                    int childDepth = k + 1;\n\n                    vector<pair<long long, int>> raisable;\n\n                    for (int v : adj[u]) {\n                        if (d[v] < childDepth) {\n                            long long g = 1LL * (childDepth - d[v]) * A[v];\n                            if (g > 0) raisable.push_back({g, v});\n                        }\n                    }\n\n                    if (raisable.empty()) continue;\n\n                    sort(raisable.begin(), raisable.end(), greater<pair<long long, int>>());\n\n                    vector<pair<int, int>> mv;\n                    long long gain = 0;\n\n                    if (d[u] != supportDepth) {\n                        mv.push_back({u, supportDepth});\n                        gain += 1LL * (supportDepth - d[u]) * A[u];\n                    }\n\n                    for (auto [g, v] : raisable) {\n                        mv.push_back({v, childDepth});\n                        gain += g;\n\n                        if (gain <= bestGain) continue;\n                        if (!validateMoveSet(d, mv)) continue;\n\n                        bestGain = gain;\n                        bestMoves = mv;\n                    }\n                }\n\n                if (bestGain > 0 && !bestMoves.empty()) {\n                    for (auto [v, nd] : bestMoves) d[v] = nd;\n                    changed = true;\n                }\n            }\n\n            greedyImprove(d);\n            supportPairImprove(d);\n\n            if (!changed) break;\n        }\n    }\n\n    void supportRoleSwapImprove(vector<int>& d, double timeLimit) {\n        for (int pass = 0; pass < 4 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n            vector<int> cnt = calcCnt(d);\n\n            int checked = 0;\n\n            for (int v : orderHigh) {\n                if (elapsed() >= timeLimit) break;\n                if (++checked > 750) break;\n\n                int k = d[v];\n                if (k >= H) continue;\n\n                vector<int> critical;\n\n                for (int to : adj[v]) {\n                    if (d[to] == k + 1 && cnt[to] == 1) critical.push_back(to);\n                }\n\n                if (critical.empty()) continue;\n                if ((int)critical.size() > 10) continue;\n\n                vector<int> cand;\n                vector<char> mark(N, 0);\n\n                auto addCand = [&](int x) {\n                    if (x == v) return;\n                    if (!mark[x]) {\n                        mark[x] = 1;\n                        cand.push_back(x);\n                    }\n                };\n\n                for (int c : critical) {\n                    addCand(c);\n                    for (int u : adj[c]) addCand(u);\n                }\n\n                long long bestGain = 0;\n                int bestU = -1;\n                int bestT = -1;\n\n                for (int u : cand) {\n                    if (d[u] == k) continue;\n\n                    bool covers = true;\n\n                    for (int c : critical) {\n                        if (u == c) continue;\n                        if (!con[u][c]) {\n                            covers = false;\n                            break;\n                        }\n                    }\n\n                    if (!covers) continue;\n\n                    for (int t = H; t > k; t--) {\n                        long long gain = 1LL * (t - k) * A[v] + 1LL * (k - d[u]) * A[u];\n\n                        if (gain <= bestGain) continue;\n\n                        if (!canMoveExcept(d, cnt, u, k, v, t)) continue;\n\n                        vector<int> td = d;\n                        vector<int> tc = cnt;\n\n                        applyMove(td, tc, u, k);\n\n                        if (!canMove(td, tc, v, t)) continue;\n\n                        applyMove(td, tc, v, t);\n\n                        bool localOk = true;\n\n                        for (int x : critical) {\n                            if (td[x] == 0) continue;\n\n                            bool ok = false;\n                            for (int nb : adj[x]) {\n                                if (td[nb] == td[x] - 1) {\n                                    ok = true;\n                                    break;\n                                }\n                            }\n\n                            if (!ok) {\n                                localOk = false;\n                                break;\n                            }\n                        }\n\n                        if (!localOk) continue;\n\n                        bestGain = gain;\n                        bestU = u;\n                        bestT = t;\n                    }\n                }\n\n                if (bestU != -1) {\n                    applyMove(d, cnt, bestU, k);\n                    applyMove(d, cnt, v, bestT);\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n\n            greedyImprove(d);\n            supportPairImprove(d);\n        }\n    }\n\n    void multiSupportRoleImprove(vector<int>& d, double timeLimit) {\n        struct Cand {\n            int u;\n            int mask;\n            long long val;\n        };\n\n        for (int pass = 0; pass < 3 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n            vector<int> cnt = calcCnt(d);\n\n            int checked = 0;\n\n            for (int v : orderHigh) {\n                if (elapsed() >= timeLimit) break;\n                if (++checked > 720) break;\n\n                int k = d[v];\n                if (k >= H) continue;\n\n                vector<int> critical;\n                for (int to : adj[v]) {\n                    if (d[to] == k + 1 && cnt[to] == 1) critical.push_back(to);\n                }\n\n                int C = (int)critical.size();\n                if (C <= 1 || C > 12) continue;\n\n                vector<int> pool;\n                vector<char> mark(N, 0);\n\n                auto addPool = [&](int x) {\n                    if (x == v) return;\n                    if (!mark[x]) {\n                        mark[x] = 1;\n                        pool.push_back(x);\n                    }\n                };\n\n                for (int c : critical) {\n                    addPool(c);\n                    for (int u : adj[c]) addPool(u);\n                }\n\n                vector<Cand> cands;\n\n                for (int u : pool) {\n                    int mask = 0;\n\n                    for (int i = 0; i < C; i++) {\n                        int c = critical[i];\n                        if (u == c || con[u][c]) mask |= (1 << i);\n                    }\n\n                    if (mask == 0) continue;\n\n                    long long val = 1LL * (k - d[u]) * A[u];\n                    cands.push_back({u, mask, val});\n                }\n\n                if (cands.empty()) continue;\n\n                int S = 1 << C;\n                int full = S - 1;\n                int nC = (int)cands.size();\n\n                vector<long long> dp(S, NEG), ndp(S, NEG);\n                vector<vector<unsigned short>> pre(nC + 1, vector<unsigned short>(S, 65535));\n                vector<vector<unsigned char>> take(nC + 1, vector<unsigned char>(S, 0));\n\n                dp[0] = 0;\n\n                for (int i = 1; i <= nC; i++) {\n                    ndp = dp;\n                    int cm = cands[i - 1].mask;\n                    long long cv = cands[i - 1].val;\n\n                    for (int mask = 0; mask < S; mask++) {\n                        if (dp[mask] <= NEG / 2) continue;\n\n                        int nm = mask | cm;\n                        if (nm == mask) continue;\n\n                        long long nv = dp[mask] + cv;\n\n                        if (nv > ndp[nm]) {\n                            ndp[nm] = nv;\n                            pre[i][nm] = (unsigned short)mask;\n                            take[i][nm] = 1;\n                        }\n                    }\n\n                    dp.swap(ndp);\n                }\n\n                if (dp[full] <= NEG / 2) continue;\n\n                vector<int> picked;\n                int mask = full;\n                for (int i = nC; i >= 1; i--) {\n                    if (take[i][mask]) {\n                        picked.push_back(i - 1);\n                        mask = pre[i][mask];\n                    }\n                }\n\n                if (mask != 0) continue;\n\n                long long bestGain = 0;\n                int bestT = -1;\n                vector<pair<int, int>> bestMoves;\n\n                for (int t = H; t > k; t--) {\n                    vector<pair<int, int>> mv;\n                    long long gain = 1LL * (t - k) * A[v];\n\n                    mv.push_back({v, t});\n\n                    for (int id : picked) {\n                        int u = cands[id].u;\n                        if (d[u] == k) continue;\n                        mv.push_back({u, k});\n                        gain += 1LL * (k - d[u]) * A[u];\n                    }\n\n                    if (gain <= bestGain) continue;\n                    if (!validateMoveSet(d, mv)) continue;\n\n                    bestGain = gain;\n                    bestT = t;\n                    bestMoves = mv;\n                }\n\n                if (bestT != -1 && bestGain > 0) {\n                    for (auto [x, nd] : bestMoves) d[x] = nd;\n                    changed = true;\n                }\n            }\n\n            greedyImprove(d);\n            supportPairImprove(d);\n\n            if (!changed) break;\n        }\n    }\n\n    struct PathState {\n        array<int, 11> node;\n        int len;\n        long long delta;\n    };\n\n    bool validatePathMove(const vector<int>& d, const PathState& s, int targetDepth) const {\n        vector<int> affected;\n        vector<int> mark(N, 0);\n\n        auto addAffected = [&](int x) {\n            if (!mark[x]) {\n                mark[x] = 1;\n                affected.push_back(x);\n            }\n        };\n\n        for (int i = 0; i < s.len; i++) {\n            int x = s.node[i];\n            addAffected(x);\n\n            for (int to : adj[x]) addAffected(to);\n        }\n\n        auto getDepth = [&](int x) {\n            for (int i = 0; i < s.len; i++) {\n                if (s.node[i] == x) return targetDepth - i;\n            }\n            return d[x];\n        };\n\n        for (int x : affected) {\n            int dx = getDepth(x);\n\n            if (dx == 0) continue;\n\n            bool ok = false;\n\n            for (int to : adj[x]) {\n                if (getDepth(to) == dx - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return false;\n        }\n\n        return true;\n    }\n\n    pair<long long, PathState> findBestPartialPathMove(const vector<int>& d, int v, int targetDepth) const {\n        constexpr int BEAM = 44;\n\n        PathState init;\n        init.node.fill(-1);\n        init.node[0] = v;\n        init.len = 1;\n        init.delta = 1LL * (targetDepth - d[v]) * A[v];\n\n        vector<PathState> beam;\n        beam.push_back(init);\n\n        long long bestGain = NEG;\n        PathState best;\n        best.len = 0;\n        best.delta = NEG;\n\n        for (int dep = targetDepth - 1; dep >= 0; dep--) {\n            vector<PathState> nxt;\n            nxt.reserve(BEAM * 8);\n\n            for (const auto& s : beam) {\n                int cur = s.node[s.len - 1];\n\n                for (int nb : adj[cur]) {\n                    bool used = false;\n\n                    for (int i = 0; i < s.len; i++) {\n                        if (s.node[i] == nb) {\n                            used = true;\n                            break;\n                        }\n                    }\n\n                    if (used) continue;\n\n                    PathState ns = s;\n                    ns.node[ns.len++] = nb;\n                    ns.delta += 1LL * (dep - d[nb]) * A[nb];\n\n                    nxt.push_back(ns);\n\n                    if (ns.delta > bestGain && ns.delta > 0) {\n                        if (validatePathMove(d, ns, targetDepth)) {\n                            bestGain = ns.delta;\n                            best = ns;\n                        }\n                    }\n                }\n            }\n\n            if (nxt.empty()) break;\n\n            sort(nxt.begin(), nxt.end(), [](const PathState& a, const PathState& b) {\n                return a.delta > b.delta;\n            });\n\n            if ((int)nxt.size() > BEAM) nxt.resize(BEAM);\n            beam.swap(nxt);\n        }\n\n        return {bestGain, best};\n    }\n\n    void pathChainImprove(vector<int>& d, double timeLimit) {\n        for (int pass = 0; pass < 3 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n\n            for (int idx = 0; idx < N && elapsed() < timeLimit; idx++) {\n                int v = orderHigh[idx];\n\n                if (d[v] == H) continue;\n\n                long long bestGain = 0;\n                PathState bestState;\n                int bestTarget = -1;\n\n                for (int t = H; t > d[v]; t--) {\n                    auto [gain, state] = findBestPartialPathMove(d, v, t);\n\n                    if (gain > bestGain) {\n                        bestGain = gain;\n                        bestState = state;\n                        bestTarget = t;\n                    }\n                }\n\n                if (bestGain > 0 && bestTarget >= 0) {\n                    for (int i = 0; i < bestState.len; i++) {\n                        d[bestState.node[i]] = bestTarget - i;\n                    }\n\n                    changed = true;\n                }\n            }\n\n            greedyImprove(d);\n            supportPairImprove(d);\n\n            if (!changed) break;\n        }\n    }\n\n    void lowPerturbAndImprove(vector<int>& d) const {\n        vector<int> best = d;\n        long long bestScore = scoreLabels(d);\n\n        vector<int> cur = d;\n        vector<int> cnt = calcCnt(cur);\n\n        int tried = 0;\n\n        for (int v : orderLow) {\n            if (++tried > 350) break;\n\n            int old = cur[v];\n\n            if (old == 0) continue;\n\n            int chosen = -1;\n\n            for (int nl = 0; nl < old; nl++) {\n                if (!canMove(cur, cnt, v, nl)) continue;\n\n                long long loss = 1LL * A[v] * (old - nl);\n                long long pot = 0;\n\n                for (int to : adj[v]) {\n                    if (cur[to] == nl + 1) pot += A[to];\n                    pot += A[to] / 10;\n                }\n\n                if (loss <= 120 + pot) {\n                    chosen = nl;\n                    break;\n                }\n            }\n\n            if (chosen != -1) applyMove(cur, cnt, v, chosen);\n        }\n\n        greedyImprove(cur);\n        supportPairImprove(cur);\n\n        long long sc = scoreLabels(cur);\n\n        if (sc > bestScore) d = cur;\n    }\n\n    void annealImprove(vector<int>& bestLabel, double timeLimit) {\n        vector<int> cur = bestLabel;\n        vector<int> cnt = calcCnt(cur);\n\n        long long curScore = scoreLabels(cur);\n        long long bestScore = curScore;\n\n        double startTime = elapsed();\n        int iter = 0;\n\n        uniform_real_distribution<double> real01(0.0, 1.0);\n\n        while (elapsed() < timeLimit) {\n            iter++;\n\n            double now = elapsed();\n            double progress = (now - startTime) / max(1e-9, timeLimit - startTime);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 55.0 * (1.0 - progress) + 1.0 * progress;\n\n            int v;\n\n            if ((rng() % 100) < 70) v = orderHigh[rng() % min(N, 550)];\n            else v = rng() % N;\n\n            int old = cur[v];\n            int nl;\n\n            if ((rng() % 100) < 72 && old < H) nl = old + 1 + (rng() % (H - old));\n            else nl = rng() % (H + 1);\n\n            if (nl == old) continue;\n            if (!canMove(cur, cnt, v, nl)) continue;\n\n            long long delta = 1LL * (nl - old) * A[v];\n\n            bool accept = false;\n\n            if (delta >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / temp);\n                if (real01(rng) < prob) accept = true;\n            }\n\n            if (accept) {\n                applyMove(cur, cnt, v, nl);\n                curScore += delta;\n\n                if (curScore > bestScore && checkFeasible(cur)) {\n                    bestScore = curScore;\n                    bestLabel = cur;\n                }\n            }\n\n            if (iter % 2500 == 0) {\n                greedyImprove(cur);\n                supportPairImprove(cur);\n\n                cnt = calcCnt(cur);\n                curScore = scoreLabels(cur);\n\n                if (curScore > bestScore && checkFeasible(cur)) {\n                    bestScore = curScore;\n                    bestLabel = cur;\n                }\n\n                if (curScore + 3000 < bestScore || (rng() % 100) < 12) {\n                    cur = bestLabel;\n                    cnt = calcCnt(cur);\n                    curScore = bestScore;\n                }\n            }\n        }\n\n        greedyImprove(bestLabel);\n        supportPairImprove(bestLabel);\n    }\n\n    vector<int> buildParents(const vector<int>& d) const {\n        vector<int> p(N, -1);\n\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) {\n                p[v] = -1;\n            } else {\n                int best = -1;\n                int bestA = 1e9;\n\n                for (int to : adj[v]) {\n                    if (d[to] == d[v] - 1) {\n                        if (A[to] < bestA) {\n                            bestA = A[to];\n                            best = to;\n                        }\n                    }\n                }\n\n                p[v] = best;\n            }\n        }\n\n        return p;\n    }\n\n    void safeKeepBest(vector<int>& bestLabel, const vector<int>& cand) const {\n        if (!checkFeasible(cand)) return;\n        if (scoreLabels(cand) > scoreLabels(bestLabel)) bestLabel = cand;\n    }\n\n    void run() {\n        cin >> N >> M >> HH;\n\n        A.resize(N);\n        for (int i = 0; i < N; i++) cin >> A[i];\n\n        edges.resize(M);\n        adj.assign(N, {});\n        con.assign(N, bitset<MAXN>());\n\n        for (int i = 0; i < M; i++) {\n            int u, v;\n            cin >> u >> v;\n\n            edges[i] = {u, v, 0};\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n            con[u][v] = 1;\n            con[v][u] = 1;\n        }\n\n        xs.resize(N);\n        ys.resize(N);\n\n        for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n        for (auto& e : edges) {\n            long long dx = xs[e.u] - xs[e.v];\n            long long dy = ys[e.u] - ys[e.v];\n            e.len2 = dx * dx + dy * dy;\n        }\n\n        orderHigh.resize(N);\n        orderLow.resize(N);\n\n        iota(orderHigh.begin(), orderHigh.end(), 0);\n        iota(orderLow.begin(), orderLow.end(), 0);\n\n        sort(orderHigh.begin(), orderHigh.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] > A[b];\n            return adj[a].size() > adj[b].size();\n        });\n\n        sort(orderLow.begin(), orderLow.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] < A[b];\n            return adj[a].size() < adj[b].size();\n        });\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestLabel(N, 0);\n        long long bestScore = scoreLabels(bestLabel);\n\n        int iter = 0;\n\n        while (elapsed() < 1.04) {\n            vector<int> treePar;\n\n            if (iter % 5 == 0) treePar = makeDFSTree((iter / 5) % 3);\n            else treePar = makePrimTree(iter % 6);\n\n            vector<int> label = solveOnTree(treePar);\n\n            greedyImprove(label);\n            supportPairImprove(label);\n\n            if (iter % 2 == 0) lowPerturbAndImprove(label);\n\n            long long sc = scoreLabels(label);\n\n            if (sc > bestScore && checkFeasible(label)) {\n                bestScore = sc;\n                bestLabel = label;\n            }\n\n            iter++;\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            supportRoleSwapImprove(cand, 1.20);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            multiSupportRoleImprove(cand, 1.34);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            pathChainImprove(cand, 1.58);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            groupSupportImprove(cand, 1.70);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            supportRoleSwapImprove(cand, 1.76);\n            multiSupportRoleImprove(cand, 1.82);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        annealImprove(bestLabel, 1.88);\n\n        {\n            vector<int> cand = bestLabel;\n            groupSupportImprove(cand, 1.925);\n            multiSupportRoleImprove(cand, 1.955);\n            pathChainImprove(cand, 1.975);\n            supportRoleSwapImprove(cand, 1.988);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        if (!checkFeasible(bestLabel)) fill(bestLabel.begin(), bestLabel.end(), 0);\n\n        vector<int> parent = buildParents(bestLabel);\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << parent[i];\n        }\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.run();\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nchar opposite_dir(char d) {\n    if (d == 'L') return 'R';\n    if (d == 'R') return 'L';\n    if (d == 'U') return 'D';\n    return 'U';\n}\n\nbool apply_shift(vector<string>& b, char d, int p) {\n    if (d == 'L') {\n        if (b[p][0] == 'o') return false;\n        for (int j = 0; j + 1 < N; j++) b[p][j] = b[p][j + 1];\n        b[p][N - 1] = '.';\n    } else if (d == 'R') {\n        if (b[p][N - 1] == 'o') return false;\n        for (int j = N - 1; j >= 1; j--) b[p][j] = b[p][j - 1];\n        b[p][0] = '.';\n    } else if (d == 'U') {\n        if (b[0][p] == 'o') return false;\n        for (int i = 0; i + 1 < N; i++) b[i][p] = b[i + 1][p];\n        b[N - 1][p] = '.';\n    } else {\n        if (b[N - 1][p] == 'o') return false;\n        for (int i = N - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n    return true;\n}\n\nint count_oni(const vector<string>& b) {\n    int c = 0;\n    for (auto& s : b) for (char ch : s) if (ch == 'x') c++;\n    return c;\n}\n\nbool validate_solution(const vector<string>& init, const vector<Op>& ops) {\n    if ((int)ops.size() > 4 * N * N) return false;\n    vector<string> b = init;\n    for (auto [d, p] : ops) {\n        if (p < 0 || p >= N) return false;\n        if (!apply_shift(b, d, p)) return false;\n    }\n    return count_oni(b) == 0;\n}\n\nbool truncate_when_done(const vector<string>& init, vector<Op>& ops) {\n    vector<string> b = init;\n    for (int t = 0; t < (int)ops.size(); t++) {\n        if (!apply_shift(b, ops[t].d, ops[t].p)) return false;\n        if (count_oni(b) == 0) {\n            ops.resize(t + 1);\n            return true;\n        }\n    }\n    return count_oni(b) == 0;\n}\n\n/* -------------------- Restoring set-cover solver -------------------- */\n\nstruct Cand {\n    char d;\n    int p;\n    int s;\n    uint64_t mask;\n};\n\nint eval_cover(const vector<int>& sel, const vector<Cand>& cand, uint64_t allmask) {\n    uint64_t u = 0;\n    int sum = 0, mx = 0;\n    for (int id : sel) {\n        u |= cand[id].mask;\n        sum += cand[id].s;\n        mx = max(mx, cand[id].s);\n    }\n    if (u != allmask) return 1e9;\n    return 2 * sum - mx;\n}\n\nvoid prune_cover(vector<int>& sel, const vector<Cand>& cand, uint64_t allmask, mt19937& rng) {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        shuffle(sel.begin(), sel.end(), rng);\n        for (int k = 0; k < (int)sel.size(); k++) {\n            uint64_t u = 0;\n            for (int t = 0; t < (int)sel.size(); t++) {\n                if (t != k) u |= cand[sel[t]].mask;\n            }\n            if (u == allmask) {\n                sel.erase(sel.begin() + k);\n                changed = true;\n                break;\n            }\n        }\n    }\n}\n\nvector<Op> build_ops_from_cover(const vector<int>& sel, const vector<Cand>& cand) {\n    vector<Op> ops;\n    if (sel.empty()) return ops;\n\n    int last_pos = 0;\n    for (int i = 1; i < (int)sel.size(); i++) {\n        if (cand[sel[i]].s > cand[sel[last_pos]].s) last_pos = i;\n    }\n\n    for (int k = 0; k < (int)sel.size(); k++) {\n        const Cand& c = cand[sel[k]];\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        if (k != last_pos) {\n            char od = opposite_dir(c.d);\n            for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n        }\n    }\n    return ops;\n}\n\nvector<Op> solve_set_cover(const vector<string>& init, mt19937& rng) {\n    int id[N][N];\n    memset(id, -1, sizeof(id));\n    vector<pair<int,int>> oni;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (init[i][j] == 'x') {\n                id[i][j] = (int)oni.size();\n                oni.push_back({i, j});\n            }\n        }\n    }\n\n    int Mx = oni.size();\n    if (Mx == 0) return {};\n\n    uint64_t allmask = (1ULL << Mx) - 1;\n    vector<Cand> cand;\n\n    auto add_cand = [&](char d, int p, int s, uint64_t mask) {\n        if (mask) cand.push_back({d, p, s, mask});\n    };\n\n    for (int i = 0; i < N; i++) {\n        int first_o = N;\n        for (int j = 0; j < N; j++) if (init[i][j] == 'o') { first_o = j; break; }\n\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int j = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('L', i, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int j = N - 1; j >= 0; j--) if (init[i][j] == 'o') { last_o = j; break; }\n\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int j = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('R', i, s, mask);\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int first_o = N;\n        for (int i = 0; i < N; i++) if (init[i][j] == 'o') { first_o = i; break; }\n\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int i = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('U', j, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int i = N - 1; i >= 0; i--) if (init[i][j] == 'o') { last_o = i; break; }\n\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int i = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('D', j, s, mask);\n            }\n        }\n    }\n\n    int C = cand.size();\n    vector<int> alive(C, 1);\n    for (int i = 0; i < C; i++) {\n        for (int j = 0; j < C; j++) if (i != j) {\n            bool subset = (cand[i].mask & ~cand[j].mask) == 0;\n            if (subset && (cand[j].s < cand[i].s || (cand[j].s == cand[i].s && j < i))) {\n                alive[i] = 0;\n                break;\n            }\n        }\n    }\n\n    vector<Cand> nc;\n    for (int i = 0; i < C; i++) if (alive[i]) nc.push_back(cand[i]);\n    cand.swap(nc);\n\n    vector<int> best_sel;\n\n    {\n        vector<int> sel;\n        for (int k = 0; k < Mx; k++) {\n            int best = -1;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                if ((cand[i].mask >> k) & 1ULL) {\n                    if (best == -1 || cand[i].s < cand[best].s) best = i;\n                }\n            }\n            if (best != -1) sel.push_back(best);\n        }\n\n        sort(sel.begin(), sel.end());\n        sel.erase(unique(sel.begin(), sel.end()), sel.end());\n        prune_cover(sel, cand, allmask, rng);\n        best_sel = sel;\n    }\n\n    int best_score = eval_cover(best_sel, cand, allmask);\n\n    for (int iter = 0; iter < 5000; iter++) {\n        uint64_t covered = 0;\n        vector<int> sel;\n        double alpha = 1.0 + (rng() % 1200) / 1000.0;\n\n        while (covered != allmask) {\n            vector<pair<double,int>> v;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                uint64_t nw = cand[i].mask & ~covered;\n                if (!nw) continue;\n\n                int cnt = __builtin_popcountll(nw);\n                double noise = 0.85 + (rng() % 3000) / 10000.0;\n                double sc = cand[i].s / pow((double)cnt, alpha) * noise;\n                v.push_back({sc, i});\n            }\n\n            if (v.empty()) break;\n            sort(v.begin(), v.end());\n\n            int K = min<int>((int)v.size(), 3 + (rng() % 8));\n            int chosen = v[rng() % K].second;\n            sel.push_back(chosen);\n            covered |= cand[chosen].mask;\n        }\n\n        if (covered != allmask) continue;\n\n        prune_cover(sel, cand, allmask, rng);\n        int sc = eval_cover(sel, cand, allmask);\n\n        if (sc < best_score) {\n            best_score = sc;\n            best_sel = sel;\n        }\n    }\n\n    return build_ops_from_cover(best_sel, cand);\n}\n\n/* -------------------- Dynamic macro solver -------------------- */\n\nstruct DynCand {\n    char d;\n    int p;\n    int s;\n    int rem;\n    bool bounce;\n};\n\nvoid add_dyn_cands_for_line(vector<DynCand>& res, const vector<string>& b, bool bounce_allowed) {\n    for (int i = 0; i < N; i++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[i][s - 1] != 'o'; s++) {\n            if (b[i][s - 1] == 'x') {\n                rem++;\n                res.push_back({'L', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'L', i, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[i][N - s] != 'o'; s++) {\n            if (b[i][N - s] == 'x') {\n                rem++;\n                res.push_back({'R', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'R', i, s, rem, true});\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[s - 1][j] != 'o'; s++) {\n            if (b[s - 1][j] == 'x') {\n                rem++;\n                res.push_back({'U', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'U', j, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[N - s][j] != 'o'; s++) {\n            if (b[N - s][j] == 'x') {\n                rem++;\n                res.push_back({'D', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'D', j, s, rem, true});\n            }\n        }\n    }\n}\n\nint dyn_cost(const DynCand& c) {\n    return c.s * (c.bounce ? 2 : 1);\n}\n\nbool apply_dyn(vector<string>& b, vector<Op>& ops, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n        ops.push_back({c.d, c.p});\n    }\n\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n            ops.push_back({od, c.p});\n        }\n    }\n\n    return true;\n}\n\nbool apply_dyn_board_only(vector<string>& b, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n    }\n\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n        }\n    }\n\n    return true;\n}\n\nvector<Op> dynamic_trial(const vector<string>& init, mt19937& rng, int mode) {\n    vector<string> b = init;\n    vector<Op> ops;\n\n    double alpha = 1.0 + (rng() % 1400) / 1000.0;\n    bool bounce_allowed = (mode != 0);\n\n    for (int step = 0; step < 45; step++) {\n        int oni = count_oni(b);\n        if (oni == 0) return ops;\n        if ((int)ops.size() > 4 * N * N) return {};\n\n        vector<DynCand> cs;\n        add_dyn_cands_for_line(cs, b, bounce_allowed);\n        if (cs.empty()) return {};\n\n        vector<pair<double,int>> rank;\n        for (int i = 0; i < (int)cs.size(); i++) {\n            int cost = dyn_cost(cs[i]);\n            double sc = cost / pow((double)cs[i].rem, alpha);\n\n            if (mode == 0 && cs[i].bounce) continue;\n            if (mode == 1 && cs[i].bounce) sc *= 1.15;\n            if (mode == 2 && !cs[i].bounce) sc *= 0.85;\n            if (mode == 3 && cs[i].bounce) sc *= 0.85;\n\n            double noise = 0.80 + (rng() % 4000) / 10000.0;\n            sc *= noise;\n\n            rank.push_back({sc, i});\n        }\n\n        if (rank.empty()) return {};\n        sort(rank.begin(), rank.end());\n\n        int K;\n        if (mode == 4) K = 1;\n        else K = min<int>((int)rank.size(), 3 + (rng() % 8));\n\n        DynCand chosen = cs[rank[(K == 1 ? 0 : (int)(rng() % K))].second];\n\n        if (!apply_dyn(b, ops, chosen)) return {};\n    }\n\n    if (count_oni(b) == 0) return ops;\n    return {};\n}\n\n/* -------------------- Evaluation helpers -------------------- */\n\nuint64_t hash_board(const vector<string>& b) {\n    uint64_t h = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        for (char c : b[i]) {\n            h ^= (unsigned char)c;\n            h *= 1099511628211ULL;\n        }\n    }\n    return h;\n}\n\nint sum_visible_min_dist(const vector<string>& b) {\n    int sum = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) if (b[i][j] == 'x') {\n            int best = 25;\n\n            bool ok = true;\n            for (int k = 0; k < j; k++) if (b[i][k] == 'o') ok = false;\n            if (ok) best = min(best, j + 1);\n\n            ok = true;\n            for (int k = j + 1; k < N; k++) if (b[i][k] == 'o') ok = false;\n            if (ok) best = min(best, N - j);\n\n            ok = true;\n            for (int k = 0; k < i; k++) if (b[k][j] == 'o') ok = false;\n            if (ok) best = min(best, i + 1);\n\n            ok = true;\n            for (int k = i + 1; k < N; k++) if (b[k][j] == 'o') ok = false;\n            if (ok) best = min(best, N - i);\n\n            if (best == 25) best = 12;\n            sum += best;\n        }\n    }\n\n    return sum;\n}\n\n/* -------------------- Macro beam solver -------------------- */\n\nstruct BeamNode {\n    vector<string> b;\n    vector<DynCand> path;\n    int cost;\n    int rem;\n    double eval;\n};\n\nvector<Op> build_ops_from_dyn_path(const vector<DynCand>& path) {\n    vector<Op> ops;\n    for (auto& c : path) {\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        if (c.bounce) {\n            char od = opposite_dir(c.d);\n            for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n        }\n    }\n    return ops;\n}\n\nvector<Op> beam_search_solver(\n    const vector<string>& init,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline,\n    int incumbent_cost\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    vector<Op> best_ops;\n\n    BeamNode root;\n    root.b = init;\n    root.cost = 0;\n    root.rem = count_oni(init);\n    root.eval = root.rem;\n\n    vector<BeamNode> beam;\n    beam.push_back(root);\n\n    const int BEAM_WIDTH = 120;\n    const int MAX_CAND = 45;\n\n    for (int depth = 0; depth < 45 && elapsed() < deadline; depth++) {\n        vector<BeamNode> nxt;\n        unordered_map<uint64_t, int> seen;\n        seen.reserve(BEAM_WIDTH * MAX_CAND * 2);\n\n        for (auto& node : beam) {\n            if (elapsed() >= deadline) break;\n\n            vector<DynCand> cs;\n            add_dyn_cands_for_line(cs, node.b, true);\n            if (cs.empty()) continue;\n\n            vector<pair<double,int>> ord;\n            ord.reserve(cs.size());\n\n            for (int i = 0; i < (int)cs.size(); i++) {\n                double sc = dyn_cost(cs[i]) / pow((double)cs[i].rem, 1.35);\n                if (cs[i].bounce) sc *= 1.08;\n                sc *= 0.98 + (rng() % 400) / 10000.0;\n                ord.push_back({sc, i});\n            }\n\n            sort(ord.begin(), ord.end());\n            int lim = min<int>(MAX_CAND, ord.size());\n\n            for (int z = 0; z < lim; z++) {\n                const DynCand& c = cs[ord[z].second];\n                int ncst = node.cost + dyn_cost(c);\n                if (ncst >= incumbent_cost + 12) continue;\n\n                BeamNode nb;\n                nb.b = node.b;\n                if (!apply_dyn_board_only(nb.b, c)) continue;\n\n                nb.rem = count_oni(nb.b);\n                if (nb.rem >= node.rem) continue;\n\n                nb.cost = ncst;\n                nb.path = node.path;\n                nb.path.push_back(c);\n\n                if (nb.rem == 0) {\n                    vector<Op> ops = build_ops_from_dyn_path(nb.path);\n                    truncate_when_done(init, ops);\n                    if ((int)ops.size() < incumbent_cost) {\n                        incumbent_cost = ops.size();\n                        best_ops = ops;\n                    }\n                    continue;\n                }\n\n                uint64_t h = hash_board(nb.b);\n                auto it = seen.find(h);\n                if (it != seen.end() && it->second <= nb.cost) continue;\n                seen[h] = nb.cost;\n\n                nb.eval = nb.cost + 1.6 * nb.rem + 0.10 * sum_visible_min_dist(nb.b);\n                nxt.push_back(std::move(nb));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        sort(nxt.begin(), nxt.end(), [](const BeamNode& a, const BeamNode& b) {\n            if (a.eval != b.eval) return a.eval < b.eval;\n            return a.cost < b.cost;\n        });\n\n        if ((int)nxt.size() > BEAM_WIDTH) nxt.resize(BEAM_WIDTH);\n        beam.swap(nxt);\n    }\n\n    return best_ops;\n}\n\n/* -------------------- Single-operation beam solver -------------------- */\n\nstruct StepNode {\n    vector<string> b;\n    vector<Op> path;\n    int rem;\n    double eval;\n};\n\nvector<Op> step_beam_solver(\n    const vector<string>& init,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline,\n    int incumbent\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    const int WIDTH = 170;\n    const int CAND_LIMIT = 30;\n\n    StepNode root;\n    root.b = init;\n    root.rem = count_oni(init);\n    root.eval = root.rem;\n\n    vector<StepNode> beam;\n    beam.push_back(root);\n\n    unordered_map<uint64_t, int> global_seen;\n    global_seen.reserve(30000);\n    global_seen[hash_board(init)] = 0;\n\n    for (int depth = 0; depth + 1 < incumbent && elapsed() < deadline; depth++) {\n        vector<StepNode> nxt;\n        unordered_map<uint64_t, int> layer_seen;\n        layer_seen.reserve(WIDTH * CAND_LIMIT * 2);\n\n        for (auto& node : beam) {\n            if (elapsed() >= deadline) break;\n\n            vector<pair<double, Op>> ord;\n\n            auto try_op_for_rank = [&](char d, int p) {\n                vector<string> nb = node.b;\n                if (!apply_shift(nb, d, p)) return;\n\n                int r = count_oni(nb);\n                int sd = sum_visible_min_dist(nb);\n                double ev = (depth + 1) + 2.35 * r + 0.115 * sd;\n                if (r == node.rem) ev += 1.25;\n                ev *= 0.995 + (rng() % 100) / 10000.0;\n                ord.push_back({ev, {d, p}});\n            };\n\n            for (int i = 0; i < N; i++) {\n                try_op_for_rank('L', i);\n                try_op_for_rank('R', i);\n            }\n            for (int j = 0; j < N; j++) {\n                try_op_for_rank('U', j);\n                try_op_for_rank('D', j);\n            }\n\n            sort(ord.begin(), ord.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n\n            int lim = min<int>(CAND_LIMIT, ord.size());\n\n            for (int z = 0; z < lim; z++) {\n                Op op = ord[z].second;\n\n                StepNode nn;\n                nn.b = node.b;\n                if (!apply_shift(nn.b, op.d, op.p)) continue;\n\n                nn.rem = count_oni(nn.b);\n\n                nn.path = node.path;\n                nn.path.push_back(op);\n\n                if (nn.rem == 0) {\n                    return nn.path;\n                }\n\n                uint64_t h = hash_board(nn.b);\n\n                auto itg = global_seen.find(h);\n                if (itg != global_seen.end() && itg->second <= depth + 1) continue;\n                global_seen[h] = depth + 1;\n\n                auto it = layer_seen.find(h);\n                if (it != layer_seen.end() && it->second <= (int)nn.path.size()) continue;\n                layer_seen[h] = nn.path.size();\n\n                nn.eval = ord[z].first;\n                nxt.push_back(std::move(nn));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        sort(nxt.begin(), nxt.end(), [](const StepNode& a, const StepNode& b) {\n            if (a.eval != b.eval) return a.eval < b.eval;\n            return a.path.size() < b.path.size();\n        });\n\n        if ((int)nxt.size() > WIDTH) nxt.resize(WIDTH);\n        beam.swap(nxt);\n    }\n\n    return {};\n}\n\n/* -------------------- Sequence simplification -------------------- */\n\nvoid postprocess_remove_blocks(\n    const vector<string>& init,\n    vector<Op>& ops,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    if (!validate_solution(init, ops)) return;\n    truncate_when_done(init, ops);\n\n    bool improved = true;\n\n    while (improved && elapsed() < deadline) {\n        improved = false;\n\n        for (int len = 10; len >= 1 && elapsed() < deadline; len--) {\n            if ((int)ops.size() < len) continue;\n\n            vector<int> idx;\n            for (int i = 0; i + len <= (int)ops.size(); i++) idx.push_back(i);\n\n            if (len <= 4) shuffle(idx.begin(), idx.end(), rng);\n\n            for (int st : idx) {\n                if (elapsed() >= deadline) break;\n                if (st + len > (int)ops.size()) continue;\n\n                vector<Op> cand;\n                cand.reserve(ops.size() - len);\n\n                for (int i = 0; i < (int)ops.size(); i++) {\n                    if (i < st || i >= st + len) cand.push_back(ops[i]);\n                }\n\n                if (validate_solution(init, cand)) {\n                    truncate_when_done(init, cand);\n                    ops.swap(cand);\n                    improved = true;\n                    break;\n                }\n            }\n\n            if (improved) break;\n        }\n    }\n}\n\n/* -------------------- Main -------------------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n\n    vector<string> init(N);\n    for (int i = 0; i < N; i++) cin >> init[i];\n\n    mt19937 rng(1234567);\n    auto start = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    vector<Op> best = solve_set_cover(init, rng);\n    if (!validate_solution(init, best)) best.clear();\n    if (!best.empty()) truncate_when_done(init, best);\n\n    {\n        vector<Op> beam_ops = beam_search_solver(\n            init,\n            rng,\n            start,\n            0.53,\n            best.empty() ? 4 * N * N + 1 : (int)best.size()\n        );\n\n        if (!beam_ops.empty()) {\n            truncate_when_done(init, beam_ops);\n            if ((best.empty() || beam_ops.size() < best.size()) && validate_solution(init, beam_ops)) {\n                best = beam_ops;\n            }\n        }\n    }\n\n    int trial = 0;\n    while (elapsed() < 1.72) {\n        int mode;\n        if (trial == 0) mode = 4;\n        else if (trial == 1) mode = 0;\n        else mode = rng() % 5;\n\n        vector<Op> ops = dynamic_trial(init, rng, mode);\n\n        if (!ops.empty()) {\n            truncate_when_done(init, ops);\n            if ((best.empty() || ops.size() < best.size()) && validate_solution(init, ops)) {\n                best = ops;\n            }\n        }\n\n        trial++;\n    }\n\n    if (!best.empty() && elapsed() < 1.84) {\n        vector<Op> step_ops = step_beam_solver(\n            init,\n            rng,\n            start,\n            1.84,\n            (int)best.size()\n        );\n\n        if (!step_ops.empty()) {\n            truncate_when_done(init, step_ops);\n            if ((int)step_ops.size() < (int)best.size() && validate_solution(init, step_ops)) {\n                best = step_ops;\n            }\n        }\n    }\n\n    if (!best.empty()) {\n        postprocess_remove_blocks(init, best, rng, start, 1.94);\n    }\n\n    if (best.empty() || !validate_solution(init, best) || (int)best.size() > 4 * N * N) {\n        rng.seed(42);\n        best = solve_set_cover(init, rng);\n        truncate_when_done(init, best);\n    }\n\n    for (auto [d, p] : best) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T;\nmt19937 rng(123456789);\n\nstruct Graph {\n    array<int, MAXN> a{}, b{}, cnt{};\n    int err = INT_MAX;\n};\n\ndouble elapsed_sec() {\n    static auto st = chrono::steady_clock::now();\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - st).count();\n}\n\nGraph evaluate(const array<int, MAXN>& a, const array<int, MAXN>& b) {\n    Graph g;\n    g.a = a;\n    g.b = b;\n    g.cnt.fill(0);\n\n    int cur = 0;\n    g.cnt[cur] = 1;\n\n    for (int step = 1; step < L; step++) {\n        int c = g.cnt[cur];\n        cur = (c & 1) ? a[cur] : b[cur];\n        g.cnt[cur]++;\n    }\n\n    long long e = 0;\n    for (int i = 0; i < N; i++) {\n        e += llabs((long long)g.cnt[i] - T[i]);\n    }\n\n    g.err = (int)e;\n    return g;\n}\n\nint weighted_pick(const vector<int>& v, const vector<int>& w) {\n    long long sum = 0;\n    for (int x : w) sum += x;\n\n    if (sum <= 0) return v[rng() % v.size()];\n\n    long long r = rng() % sum;\n    for (int i = 0; i < (int)v.size(); i++) {\n        if (r < w[i]) return v[i];\n        r -= w[i];\n    }\n\n    return v.back();\n}\n\nstruct Token {\n    int src;\n    int slot;\n    int w;\n};\n\nvoid add_elite(vector<Graph>& elite, const Graph& g, int K = 8) {\n    elite.push_back(g);\n    sort(elite.begin(), elite.end(), [](const Graph& x, const Graph& y) {\n        return x.err < y.err;\n    });\n    if ((int)elite.size() > K) elite.resize(K);\n}\n\nGraph make_cycle_candidate(int id) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    sort(active.begin(), active.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    if (id == 1) {\n        reverse(active.begin(), active.end());\n    } else if (id >= 2) {\n        int m = (int)active.size();\n        int swaps = (id % 9 + 1) * m / 16;\n        for (int k = 0; k < swaps; k++) {\n            int p = rng() % m;\n            int q = rng() % m;\n            swap(active[p], active[q]);\n        }\n    }\n\n    int m = (int)active.size();\n\n    vector<int> succ(N, root);\n    array<long long, MAXN> in{};\n    in.fill(0);\n\n    for (int k = 0; k < m; k++) {\n        int v = active[k];\n        int to = active[(k + 1) % m];\n        succ[v] = to;\n        in[to] += T[v];\n    }\n\n    vector<int> sources = active;\n    sort(sources.begin(), sources.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    vector<int> assigned(N, root);\n\n    for (int s : sources) {\n        long long w = T[s];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(m);\n\n        for (int d : active) {\n            long long before = llabs(in[d] - 2LL * T[d]);\n            long long after = llabs(in[d] + w - 2LL * T[d]);\n            cand.push_back({after - before, d});\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int choose = 0;\n        if (id >= 2) {\n            int lim = min(5, (int)cand.size());\n            choose = rng() % lim;\n        }\n\n        int d = cand[choose].second;\n        assigned[s] = d;\n        in[d] += w;\n    }\n\n    for (int it = 0; it < 45; it++) {\n        long long best_delta = 0;\n        int best_s = -1;\n        int best_d = -1;\n\n        for (int s : sources) {\n            int old = assigned[s];\n            long long w = T[s];\n\n            for (int d : active) {\n                if (d == old) continue;\n\n                long long cur =\n                    llabs(in[old] - 2LL * T[old]) +\n                    llabs(in[d] - 2LL * T[d]);\n\n                long long nxt =\n                    llabs(in[old] - w - 2LL * T[old]) +\n                    llabs(in[d] + w - 2LL * T[d]);\n\n                long long delta = nxt - cur;\n\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_s = s;\n                    best_d = d;\n                }\n            }\n        }\n\n        if (best_s == -1) break;\n\n        int old = assigned[best_s];\n        long long w = T[best_s];\n\n        in[old] -= w;\n        in[best_d] += w;\n        assigned[best_s] = best_d;\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            a[i] = succ[i];\n            b[i] = assigned[i];\n            if (id >= 2 && (rng() & 1)) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nGraph make_balanced_candidate(int id, bool parity_mode) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    vector<Token> tok;\n    tok.reserve(active.size() * 2);\n\n    for (int s : active) {\n        if (!parity_mode) {\n            tok.push_back({s, 0, T[s]});\n            tok.push_back({s, 1, T[s]});\n        } else {\n            int p = T[s] & 1;\n            tok.push_back({s, 0, T[s] + p});\n            tok.push_back({s, 1, T[s] - p});\n        }\n    }\n\n    int M = (int)tok.size();\n\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    vector<int> noise(M);\n    for (int i = 0; i < M; i++) {\n        noise[i] = (int)(rng() & 1023);\n    }\n\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        long long kx = 1000000LL * tok[x].w + noise[x] * (id % 7);\n        long long ky = 1000000LL * tok[y].w + noise[y] * (id % 7);\n\n        if (kx != ky) return kx > ky;\n        return x < y;\n    });\n\n    if (id % 11 == 0) {\n        shuffle(ord.begin(), ord.end(), rng);\n    } else if (id % 5 == 0) {\n        int block = 8 + (id % 7);\n\n        for (int l = 0; l < M; l += block) {\n            int r = min(M, l + block);\n            shuffle(ord.begin() + l, ord.begin() + r, rng);\n        }\n    }\n\n    array<long long, MAXN> rem{};\n    for (int i = 0; i < N; i++) {\n        rem[i] = 2LL * T[i];\n    }\n\n    array<array<int, 2>, MAXN> dest;\n    for (int i = 0; i < N; i++) {\n        dest[i][0] = dest[i][1] = -1;\n    }\n\n    vector<int> token_dest(M, -1);\n\n    bool hard_no_self = (id % 6 == 0 || id % 6 == 3);\n    bool avoid_same = (id % 6 != 1);\n\n    for (int idx : ord) {\n        int s = tok[idx].src;\n        int sl = tok[idx].slot;\n        int w = tok[idx].w;\n        int other = dest[s][1 - sl];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(active.size());\n\n        for (int d : active) {\n            if (hard_no_self && d == s && active.size() > 1) continue;\n\n            long long delta = llabs(rem[d] - w) - llabs(rem[d]);\n            long long penalty = 0;\n\n            if (d == s) penalty += 2LL * w + 500;\n            if (avoid_same && other == d) penalty += w / 2 + 300;\n\n            long long score =\n                delta * 100000LL +\n                penalty * 100LL +\n                (int)(rng() & 2047);\n\n            cand.push_back({score, d});\n        }\n\n        if (cand.empty()) {\n            for (int d : active) {\n                long long delta = llabs(rem[d] - w) - llabs(rem[d]);\n                cand.push_back({delta * 100000LL + (int)(rng() & 2047), d});\n            }\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int lim = min((int)cand.size(), 1 + (id % 5));\n        if (id % 13 == 0) {\n            lim = min((int)cand.size(), 8);\n        }\n\n        int d = cand[rng() % lim].second;\n\n        dest[s][sl] = d;\n        token_dest[idx] = d;\n        rem[d] -= w;\n    }\n\n    auto violates = [&](int idx, int d) -> bool {\n        int s = tok[idx].src;\n        int sl = tok[idx].slot;\n\n        if (hard_no_self && d == s && active.size() > 1) return true;\n        if (avoid_same && dest[s][1 - sl] == d && active.size() > 2) return true;\n\n        return false;\n    };\n\n    int improve_trials = parity_mode ? 2600 : 3500;\n\n    for (int it = 0; it < improve_trials; it++) {\n        if (rng() & 1) {\n            int idx = rng() % M;\n            int old = token_dest[idx];\n            int d = active[rng() % active.size()];\n\n            if (d == old) continue;\n            if (violates(idx, d)) continue;\n\n            long long w = tok[idx].w;\n\n            long long delta =\n                llabs(rem[old] + w) - llabs(rem[old]) +\n                llabs(rem[d] - w) - llabs(rem[d]);\n\n            if (delta < 0 || (delta == 0 && (rng() & 7) == 0)) {\n                rem[old] += w;\n                rem[d] -= w;\n\n                token_dest[idx] = d;\n                dest[tok[idx].src][tok[idx].slot] = d;\n            }\n        } else {\n            int x = rng() % M;\n            int y = rng() % M;\n\n            if (x == y) continue;\n\n            int dx = token_dest[x];\n            int dy = token_dest[y];\n\n            if (dx == dy) continue;\n            if (violates(x, dy) || violates(y, dx)) continue;\n\n            long long wx = tok[x].w;\n            long long wy = tok[y].w;\n\n            long long before = llabs(rem[dx]) + llabs(rem[dy]);\n\n            long long ndx = rem[dx] + wx - wy;\n            long long ndy = rem[dy] + wy - wx;\n\n            long long after = llabs(ndx) + llabs(ndy);\n            long long delta = after - before;\n\n            if (delta < 0 || (delta == 0 && (rng() & 15) == 0)) {\n                rem[dx] = ndx;\n                rem[dy] = ndy;\n\n                token_dest[x] = dy;\n                token_dest[y] = dx;\n\n                dest[tok[x].src][tok[x].slot] = dy;\n                dest[tok[y].src][tok[y].slot] = dx;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            int x = dest[i][0];\n            int y = dest[i][1];\n\n            if (x < 0) x = root;\n            if (y < 0) y = root;\n\n            a[i] = x;\n            b[i] = y;\n\n            if (!parity_mode && (rng() & 1)) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nvoid phase_optimize(Graph& cur, Graph& best, vector<Graph>& elite, double limit) {\n    for (int pass = 0; pass < 3; pass++) {\n        bool improved = false;\n\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        if (pass) shuffle(ord.begin(), ord.end(), rng);\n\n        for (int i : ord) {\n            if (elapsed_sec() > limit) return;\n            if (cur.a[i] == cur.b[i]) continue;\n\n            swap(cur.a[i], cur.b[i]);\n\n            Graph ng = evaluate(cur.a, cur.b);\n\n            if (ng.err <= cur.err) {\n                cur = ng;\n                improved = true;\n\n                if (cur.err < best.err) {\n                    best = cur;\n                    add_elite(elite, best);\n                }\n            } else {\n                swap(cur.a[i], cur.b[i]);\n            }\n        }\n\n        if (!improved) break;\n    }\n}\n\nbool make_mutation(const Graph& cur, array<int, MAXN>& na, array<int, MAXN>& nb) {\n    vector<int> over, under, wover, wunder;\n\n    for (int i = 0; i < N; i++) {\n        int d = cur.cnt[i] - T[i];\n\n        if (d > 0) {\n            over.push_back(i);\n            wover.push_back(d);\n        } else if (d < 0) {\n            under.push_back(i);\n            wunder.push_back(-d);\n        }\n    }\n\n    if (over.empty() || under.empty()) return false;\n\n    na = cur.a;\n    nb = cur.b;\n\n    int typ = rng() % 100;\n\n    if (typ < 12) {\n        int x = rng() % (2 * N);\n        int y = rng() % (2 * N);\n        if (x == y) return false;\n\n        int sx = x / 2, tx = x & 1;\n        int sy = y / 2, ty = y & 1;\n\n        int& ex = (tx == 0 ? na[sx] : nb[sx]);\n        int& ey = (ty == 0 ? na[sy] : nb[sy]);\n\n        if (ex == ey) return false;\n        swap(ex, ey);\n    } else if (typ < 27) {\n        int i = rng() % N;\n\n        if (na[i] == nb[i]) return false;\n\n        swap(na[i], nb[i]);\n    } else if (typ < 74) {\n        int v = weighted_pick(over, wover);\n        int u = weighted_pick(under, wunder);\n\n        vector<pair<int, int>> edges;\n\n        for (int i = 0; i < N; i++) {\n            if (na[i] == v) edges.push_back({i, 0});\n            if (nb[i] == v) edges.push_back({i, 1});\n        }\n\n        if (edges.empty()) return false;\n\n        auto [s, slot] = edges[rng() % edges.size()];\n\n        if (slot == 0) na[s] = u;\n        else nb[s] = u;\n    } else if (typ < 90) {\n        int s = weighted_pick(over, wover);\n        int u = weighted_pick(under, wunder);\n\n        if (rng() & 1) na[s] = u;\n        else nb[s] = u;\n    } else {\n        int s = rng() % N;\n        int u = weighted_pick(under, wunder);\n\n        if (rng() & 1) na[s] = u;\n        else nb[s] = u;\n    }\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n\n    uint64_t seed = 1469598103934665603ULL;\n\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n\n        seed ^= (uint64_t)(T[i] + 1000003) * (i + 1009);\n        seed *= 1099511628211ULL;\n    }\n\n    rng.seed((uint32_t)(seed ^ (seed >> 32)));\n\n    Graph best;\n    best.err = INT_MAX;\n\n    vector<Graph> elite;\n\n    auto consider = [&](const Graph& g) {\n        if (g.err < best.err) best = g;\n        add_elite(elite, g);\n    };\n\n    for (int id = 0; id < 35; id++) {\n        if (elapsed_sec() > 0.43) break;\n        consider(make_cycle_candidate(id));\n    }\n\n    for (int id = 0; id < 230; id++) {\n        if (elapsed_sec() > 1.04) break;\n        consider(make_balanced_candidate(id, false));\n    }\n\n    for (int id = 0; id < 35; id++) {\n        if (elapsed_sec() > 1.13) break;\n        consider(make_balanced_candidate(id + 1000, true));\n    }\n\n    sort(elite.begin(), elite.end(), [](const Graph& x, const Graph& y) {\n        return x.err < y.err;\n    });\n\n    int phn = min(3, (int)elite.size());\n    for (int i = 0; i < phn && elapsed_sec() < 1.30; i++) {\n        Graph cur = elite[i];\n        phase_optimize(cur, best, elite, 1.30);\n    }\n\n    Graph cur = best;\n    int no_improve = 0;\n\n    while (elapsed_sec() < 1.88) {\n        double now = elapsed_sec();\n\n        if (no_improve > 70 && !elite.empty() && (rng() % 5 == 0)) {\n            int lim = min(5, (int)elite.size());\n            cur = elite[rng() % lim];\n            no_improve = 0;\n        }\n\n        if (now < 1.64) {\n            array<int, MAXN> na, nb;\n            if (!make_mutation(cur, na, nb)) break;\n\n            Graph ng = evaluate(na, nb);\n\n            bool accept = false;\n\n            if (ng.err <= cur.err) {\n                accept = true;\n            } else {\n                double remain = max(0.0, 1.88 - now);\n\n                int temp = max(1, (int)(850.0 * remain / 1.88));\n                int diff = ng.err - cur.err;\n\n                if (diff < temp && (int)(rng() % temp) < temp - diff) {\n                    accept = true;\n                }\n            }\n\n            if (accept) {\n                cur = ng;\n\n                if (cur.err < best.err) {\n                    best = cur;\n                    add_elite(elite, best);\n                    no_improve = 0;\n                } else {\n                    no_improve++;\n                }\n            } else {\n                no_improve++;\n            }\n        } else {\n            Graph best_ng;\n            best_ng.err = INT_MAX;\n\n            int batch = 4;\n            for (int k = 0; k < batch && elapsed_sec() < 1.88; k++) {\n                array<int, MAXN> na, nb;\n                if (!make_mutation(cur, na, nb)) continue;\n\n                Graph ng = evaluate(na, nb);\n\n                if (ng.err < best_ng.err) {\n                    best_ng = ng;\n                }\n            }\n\n            if (best_ng.err == INT_MAX) break;\n\n            if (best_ng.err <= cur.err) {\n                cur = best_ng;\n\n                if (cur.err < best.err) {\n                    best = cur;\n                    add_elite(elite, best);\n                    no_improve = 0;\n                } else {\n                    no_improve++;\n                }\n            } else {\n                int diff = best_ng.err - cur.err;\n                int temp = 35;\n\n                if (diff < temp && (int)(rng() % temp) < temp - diff) {\n                    cur = best_ng;\n                }\n\n                no_improve++;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), 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\nint N, M, Q, L, W;\nvector<int> G;\nvector<double> cx, cy;\n\ninline double dist2p(double x1, double y1, double x2, double y2) {\n    double dx = x1 - x2;\n    double dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\ninline double edist(int a, int b) {\n    return sqrt(dist2p(cx[a], cy[a], cx[b], cy[b]));\n}\n\ninline unsigned long long ekey(int a, int b) {\n    if (a > b) swap(a, b);\n    return (unsigned long long)a << 32 | (unsigned int)b;\n}\n\ninline pair<int,int> decode_key(unsigned long long k) {\n    int a = (int)(k >> 32);\n    int b = (int)(k & 0xffffffffu);\n    return {a, b};\n}\n\nlong long hilbert_index(int x, int y, int bits = 14) {\n    long long d = 0;\n    int n = 1 << bits;\n\n    for (int s = n >> 1; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += 1LL * s * s * ((3 * rx) ^ ry);\n\n        if (ry == 0) {\n            if (rx == 1) {\n                x = n - 1 - x;\n                y = n - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n\n    return d;\n}\n\ndouble mst_cost(const vector<int>& verts) {\n    int n = (int)verts.size();\n    if (n <= 1) return 0.0;\n    if (n == 2) return edist(verts[0], verts[1]);\n\n    vector<double> minv(n, 1e100);\n    vector<char> used(n, 0);\n    minv[0] = 0.0;\n    double res = 0.0;\n\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n\n        used[v] = 1;\n        res += best;\n\n        int cv = verts[v];\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(cv, verts[u]);\n                if (d < minv[u]) minv[u] = d;\n            }\n        }\n    }\n\n    return res;\n}\n\nvector<pair<int,int>> prim_edges(const vector<int>& verts) {\n    int n = (int)verts.size();\n    vector<pair<int,int>> ret;\n\n    if (n <= 1) return ret;\n    if (n == 2) {\n        ret.push_back({verts[0], verts[1]});\n        return ret;\n    }\n\n    vector<double> minv(n, 1e100);\n    vector<int> par(n, -1);\n    vector<char> used(n, 0);\n    minv[0] = 0.0;\n\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n\n        used[v] = 1;\n        if (par[v] != -1) ret.push_back({verts[v], verts[par[v]]});\n\n        int cv = verts[v];\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(cv, verts[u]);\n                if (d < minv[u]) {\n                    minv[u] = d;\n                    par[u] = v;\n                }\n            }\n        }\n    }\n\n    return ret;\n}\n\ndouble total_mst_cost(const vector<vector<int>>& groups) {\n    double s = 0.0;\n    for (auto& g : groups) s += mst_cost(g);\n    return s;\n}\n\nvector<vector<int>> build_from_order(const vector<int>& ord, const vector<int>& perm) {\n    vector<vector<int>> groups(M);\n    int pos = 0;\n\n    for (int id : perm) {\n        groups[id].assign(ord.begin() + pos, ord.begin() + pos + G[id]);\n        pos += G[id];\n    }\n\n    return groups;\n}\n\nstruct OrderEvaluator {\n    const vector<int>* ord;\n    unordered_map<int, double> cache;\n\n    OrderEvaluator(const vector<int>& o) {\n        ord = &o;\n        cache.reserve(6000);\n    }\n\n    double interval_cost(int s, int len) {\n        if (len <= 1) return 0.0;\n        if (len == 2) return edist((*ord)[s], (*ord)[s + 1]);\n\n        int key = s * 1000 + len;\n        auto it = cache.find(key);\n        if (it != cache.end()) return it->second;\n\n        vector<int> verts;\n        verts.reserve(len);\n        for (int i = 0; i < len; i++) verts.push_back((*ord)[s + i]);\n\n        double c = mst_cost(verts);\n        cache[key] = c;\n        return c;\n    }\n\n    vector<int> improve_perm(vector<int> perm, int maxPass = 20) {\n        if (M <= 1) return perm;\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            bool changed = false;\n\n            vector<int> pref(M + 1, 0);\n            for (int i = 0; i < M; i++) pref[i + 1] = pref[i] + G[perm[i]];\n\n            for (int i = 0; i + 1 < M; i++) {\n                int s = pref[i];\n                int a = perm[i], b = perm[i + 1];\n\n                double oldc = interval_cost(s, G[a]) + interval_cost(s + G[a], G[b]);\n                double newc = interval_cost(s, G[b]) + interval_cost(s + G[b], G[a]);\n\n                if (newc + 1e-9 < oldc) {\n                    swap(perm[i], perm[i + 1]);\n                    changed = true;\n                    for (int j = i; j < M; j++) pref[j + 1] = pref[j] + G[perm[j]];\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        return perm;\n    }\n};\n\nvector<vector<int>> make_size_perms() {\n    vector<vector<int>> vars;\n\n    vector<int> p(M);\n    iota(p.begin(), p.end(), 0);\n    vars.push_back(p);\n\n    vector<int> r = p;\n    reverse(r.begin(), r.end());\n    vars.push_back(r);\n\n    vector<int> asc = p;\n    sort(asc.begin(), asc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n    vars.push_back(asc);\n\n    vector<int> desc = p;\n    sort(desc.begin(), desc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n    vars.push_back(desc);\n\n    return vars;\n}\n\npair<vector<int>, int> split_group_ids_subset_sum(const vector<int>& gids, int total) {\n    int target = total / 2;\n\n    vector<char> dp(total + 1, 0);\n    vector<int> preSum(total + 1, -1), preId(total + 1, -1);\n    dp[0] = 1;\n\n    for (int id : gids) {\n        int w = G[id];\n        for (int s = total - w; s >= 0; s--) {\n            if (dp[s] && !dp[s + w]) {\n                dp[s + w] = 1;\n                preSum[s + w] = s;\n                preId[s + w] = id;\n            }\n        }\n    }\n\n    int best = -1;\n    for (int d = 0; d <= total; d++) {\n        int s1 = target - d;\n        int s2 = target + d;\n\n        if (s1 > 0 && s1 < total && dp[s1]) {\n            best = s1;\n            break;\n        }\n        if (s2 > 0 && s2 < total && dp[s2]) {\n            best = s2;\n            break;\n        }\n    }\n\n    if (best == -1) {\n        vector<int> left = {gids[0]};\n        return {left, G[gids[0]]};\n    }\n\n    vector<int> left;\n    int cur = best;\n\n    while (cur > 0) {\n        int id = preId[cur];\n        left.push_back(id);\n        cur = preSum[cur];\n    }\n\n    return {left, best};\n}\n\nvoid recursive_partition(\n    const vector<int>& cities,\n    const vector<int>& gids,\n    int depth,\n    int variant,\n    vector<vector<int>>& groups\n) {\n    if (gids.size() == 1) {\n        groups[gids[0]] = cities;\n        return;\n    }\n\n    int total = cities.size();\n    auto [leftIds, leftCount] = split_group_ids_subset_sum(gids, total);\n\n    vector<char> inLeft(M, 0);\n    for (int id : leftIds) inLeft[id] = 1;\n\n    vector<int> rightIds;\n    for (int id : gids) {\n        if (!inLeft[id]) rightIds.push_back(id);\n    }\n\n    vector<int> sorted = cities;\n\n    if (variant == 0) {\n        double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n\n        for (int v : cities) {\n            minx = min(minx, cx[v]);\n            maxx = max(maxx, cx[v]);\n            miny = min(miny, cy[v]);\n            maxy = max(maxy, cy[v]);\n        }\n\n        bool useX = (maxx - minx >= maxy - miny);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            if (useX) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            } else {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            }\n        });\n    } else if (variant == 1) {\n        bool useX = (depth % 2 == 0);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            if (useX) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            } else {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            }\n        });\n    } else if (variant == 2) {\n        double mx = 0.0, my = 0.0;\n\n        for (int v : cities) {\n            mx += cx[v];\n            my += cy[v];\n        }\n\n        mx /= cities.size();\n        my /= cities.size();\n\n        double sxx = 0.0, syy = 0.0, sxy = 0.0;\n\n        for (int v : cities) {\n            double x = cx[v] - mx;\n            double y = cy[v] - my;\n            sxx += x * x;\n            syy += y * y;\n            sxy += x * y;\n        }\n\n        double theta = 0.5 * atan2(2.0 * sxy, sxx - syy);\n        double vx = cos(theta), vy = sin(theta);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            double pa = cx[a] * vx + cy[a] * vy;\n            double pb = cx[b] * vx + cy[b] * vy;\n            if (pa != pb) return pa < pb;\n            return a < b;\n        });\n    } else {\n        bool diag = (depth % 2 == 0);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            double pa = diag ? (cx[a] + cy[a]) : (cx[a] - cy[a]);\n            double pb = diag ? (cx[b] + cy[b]) : (cx[b] - cy[b]);\n            if (pa != pb) return pa < pb;\n            return a < b;\n        });\n    }\n\n    vector<int> leftCities(sorted.begin(), sorted.begin() + leftCount);\n    vector<int> rightCities(sorted.begin() + leftCount, sorted.end());\n\n    recursive_partition(leftCities, leftIds, depth + 1, variant, groups);\n    recursive_partition(rightCities, rightIds, depth + 1, variant, groups);\n}\n\nvector<vector<int>> make_recursive_candidate(int variant) {\n    vector<int> cities(N), gids(M);\n    iota(cities.begin(), cities.end(), 0);\n    iota(gids.begin(), gids.end(), 0);\n\n    vector<vector<int>> groups(M);\n    recursive_partition(cities, gids, 0, variant, groups);\n    return groups;\n}\n\nvector<vector<int>> make_greedy_candidate(int variant) {\n    vector<vector<int>> groups(M);\n    vector<char> used(N, 0);\n\n    vector<int> gids(M);\n    iota(gids.begin(), gids.end(), 0);\n\n    int orderType = variant % 3;\n    int seedType = variant / 3;\n\n    if (orderType == 0) {\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] > G[b];\n            return a < b;\n        });\n    } else if (orderType == 1) {\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] < G[b];\n            return a < b;\n        });\n    }\n\n    vector<long long> hval(N);\n    for (int i = 0; i < N; i++) {\n        int xi = min(16383, max(0, (int)llround(cx[i] * 16383.0 / 10000.0)));\n        int yi = min(16383, max(0, (int)llround(cy[i] * 16383.0 / 10000.0)));\n        hval[i] = hilbert_index(xi, yi);\n    }\n\n    for (int gid : gids) {\n        vector<int> rem;\n        rem.reserve(N);\n\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) rem.push_back(i);\n        }\n\n        if ((int)rem.size() == G[gid]) {\n            groups[gid] = rem;\n            for (int v : rem) used[v] = 1;\n            continue;\n        }\n\n        int seed = rem[0];\n\n        if (seedType == 0) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) { return cx[a] < cx[b]; });\n        } else if (seedType == 1) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) { return cx[a] < cx[b]; });\n        } else if (seedType == 2) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) { return cy[a] < cy[b]; });\n        } else if (seedType == 3) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) { return cy[a] < cy[b]; });\n        } else if (seedType == 4) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) { return hval[a] < hval[b]; });\n        } else if (seedType == 5) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) { return hval[a] < hval[b]; });\n        } else if (seedType == 6) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cx[a] + cy[a] < cx[b] + cy[b];\n            });\n        } else if (seedType == 7) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cx[a] + cy[a] < cx[b] + cy[b];\n            });\n        } else {\n            double mx = 0.0, my = 0.0;\n\n            for (int v : rem) {\n                mx += cx[v];\n                my += cy[v];\n            }\n\n            mx /= rem.size();\n            my /= rem.size();\n\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return dist2p(cx[a], cy[a], mx, my) < dist2p(cx[b], cy[b], mx, my);\n            });\n        }\n\n        vector<pair<double,int>> cand;\n        cand.reserve(rem.size());\n\n        for (int v : rem) {\n            cand.push_back({dist2p(cx[v], cy[v], cx[seed], cy[seed]), v});\n        }\n\n        sort(cand.begin(), cand.end());\n\n        vector<int> sel;\n        for (int i = 0; i < G[gid]; i++) sel.push_back(cand[i].second);\n\n        if ((int)sel.size() >= 4) {\n            double mx = 0.0, my = 0.0;\n            for (int v : sel) {\n                mx += cx[v];\n                my += cy[v];\n            }\n            mx /= sel.size();\n            my /= sel.size();\n\n            cand.clear();\n            for (int v : rem) cand.push_back({dist2p(cx[v], cy[v], mx, my), v});\n\n            sort(cand.begin(), cand.end());\n            sel.clear();\n            for (int i = 0; i < G[gid]; i++) sel.push_back(cand[i].second);\n        }\n\n        groups[gid] = sel;\n        for (int v : sel) used[v] = 1;\n    }\n\n    return groups;\n}\n\nvector<vector<int>> capacitated_lloyd(vector<vector<int>> init, int iterations) {\n    vector<vector<int>> cur = init;\n    vector<vector<int>> best = cur;\n    double bestCost = total_mst_cost(best);\n\n    if (M == 1) return cur;\n\n    for (int it = 0; it < iterations; it++) {\n        vector<double> gx(M, 0.0), gy(M, 0.0);\n\n        for (int gid = 0; gid < M; gid++) {\n            for (int v : cur[gid]) {\n                gx[gid] += cx[v];\n                gy[gid] += cy[v];\n            }\n            gx[gid] /= max(1, (int)cur[gid].size());\n            gy[gid] /= max(1, (int)cur[gid].size());\n        }\n\n        struct Item {\n            double margin;\n            int city;\n            vector<pair<double,int>> ord;\n        };\n\n        vector<Item> items;\n        items.reserve(N);\n\n        for (int v = 0; v < N; v++) {\n            vector<pair<double,int>> ds;\n            ds.reserve(M);\n\n            for (int gid = 0; gid < M; gid++) {\n                double d = dist2p(cx[v], cy[v], gx[gid], gy[gid]);\n                ds.push_back({d, gid});\n            }\n\n            int keep = min(M, max(12, min(36, M)));\n            nth_element(ds.begin(), ds.begin() + keep - 1, ds.end());\n            ds.resize(keep);\n            sort(ds.begin(), ds.end());\n\n            double margin = 1e18;\n            if ((int)ds.size() >= 2) margin = ds[1].first - ds[0].first;\n\n            items.push_back({margin, v, move(ds)});\n        }\n\n        sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n            return a.margin > b.margin;\n        });\n\n        vector<int> rem = G;\n        vector<vector<int>> nxt(M);\n\n        for (auto& item : items) {\n            int chosen = -1;\n\n            for (auto [d, gid] : item.ord) {\n                if (rem[gid] > 0) {\n                    chosen = gid;\n                    break;\n                }\n            }\n\n            if (chosen == -1) {\n                double bd = 1e100;\n                for (int gid = 0; gid < M; gid++) {\n                    if (rem[gid] <= 0) continue;\n                    double d = dist2p(cx[item.city], cy[item.city], gx[gid], gy[gid]);\n                    if (d < bd) {\n                        bd = d;\n                        chosen = gid;\n                    }\n                }\n            }\n\n            nxt[chosen].push_back(item.city);\n            rem[chosen]--;\n        }\n\n        cur.swap(nxt);\n\n        double c = total_mst_cost(cur);\n        if (c < bestCost) {\n            bestCost = c;\n            best = cur;\n        }\n    }\n\n    return best;\n}\n\nstring subset_key(vector<int> v) {\n    sort(v.begin(), v.end());\n    string s;\n    s.reserve(v.size() * 5);\n\n    for (int x : v) {\n        s += to_string(x);\n        s += ',';\n    }\n\n    return s;\n}\n\nvector<pair<int,int>> do_query(const vector<int>& c) {\n    cout << \"? \" << c.size();\n    for (int v : c) cout << ' ' << v;\n    cout << endl;\n    cout.flush();\n\n    vector<pair<int,int>> ret;\n\n    for (int i = 0; i < (int)c.size() - 1; i++) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        ret.push_back({a, b});\n    }\n\n    return ret;\n}\n\nvector<int> nearest_subset_to_seed(const vector<int>& group, int seed) {\n    vector<pair<double,int>> v;\n    v.reserve(group.size());\n\n    for (int x : group) v.push_back({edist(seed, x), x});\n\n    sort(v.begin(), v.end());\n\n    vector<int> sub;\n    int lim = min(L, (int)v.size());\n\n    for (int i = 0; i < lim; i++) sub.push_back(v[i].second);\n\n    return sub;\n}\n\nvector<int> nearest_subset_to_edge(const vector<int>& group, int a, int b) {\n    double mx = (cx[a] + cx[b]) * 0.5;\n    double my = (cy[a] + cy[b]) * 0.5;\n\n    vector<pair<double,int>> v;\n    v.reserve(group.size());\n\n    for (int x : group) {\n        double d = dist2p(cx[x], cy[x], mx, my);\n        if (x == a || x == b) d -= 1e18;\n        v.push_back({d, x});\n    }\n\n    sort(v.begin(), v.end());\n\n    vector<int> sub;\n    int lim = min(L, (int)v.size());\n\n    for (int i = 0; i < lim; i++) sub.push_back(v[i].second);\n\n    bool hasA = false, hasB = false;\n    for (int x : sub) {\n        if (x == a) hasA = true;\n        if (x == b) hasB = true;\n    }\n\n    if (!hasA && !sub.empty()) sub.back() = a;\n\n    hasB = false;\n    for (int x : sub) if (x == b) hasB = true;\n\n    if (!hasB && sub.size() >= 2) sub[sub.size() - 2] = b;\n\n    sort(sub.begin(), sub.end());\n    sub.erase(unique(sub.begin(), sub.end()), sub.end());\n\n    for (int x : group) {\n        if ((int)sub.size() >= min(L, (int)group.size())) break;\n        if (find(sub.begin(), sub.end(), x) == sub.end()) sub.push_back(x);\n    }\n\n    return sub;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> Q >> L >> W;\n    G.resize(M);\n\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    cx.resize(N);\n    cy.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cx[i] = (lx + rx) * 0.5;\n        cy[i] = (ly + ry) * 0.5;\n    }\n\n    vector<vector<vector<int>>> candidates;\n    auto perms = make_size_perms();\n\n    auto add_order_candidates = [&](const vector<int>& ord) {\n        OrderEvaluator ev(ord);\n\n        for (auto p : perms) {\n            candidates.push_back(build_from_order(ord, p));\n\n            if (timer.sec() < 0.75) {\n                vector<int> imp = ev.improve_perm(p, 18);\n                candidates.push_back(build_from_order(ord, imp));\n            }\n        }\n    };\n\n    for (int t = 0; t < 8; t++) {\n        vector<pair<long long,int>> v;\n\n        for (int i = 0; i < N; i++) {\n            double x = cx[i], y = cy[i];\n            double X = x, Y = y;\n\n            if (t == 0) { X = x; Y = y; }\n            if (t == 1) { X = y; Y = x; }\n            if (t == 2) { X = 10000 - x; Y = y; }\n            if (t == 3) { X = x; Y = 10000 - y; }\n            if (t == 4) { X = 10000 - x; Y = 10000 - y; }\n            if (t == 5) { X = y; Y = 10000 - x; }\n            if (t == 6) { X = 10000 - y; Y = x; }\n            if (t == 7) { X = 10000 - y; Y = 10000 - x; }\n\n            int xi = min(16383, max(0, (int)llround(X * 16383.0 / 10000.0)));\n            int yi = min(16383, max(0, (int)llround(Y * 16383.0 / 10000.0)));\n            v.push_back({hilbert_index(xi, yi), i});\n        }\n\n        sort(v.begin(), v.end());\n\n        vector<int> ord;\n        ord.reserve(N);\n\n        for (auto [d, i] : v) ord.push_back(i);\n\n        add_order_candidates(ord);\n    }\n\n    const double PI = acos(-1.0);\n\n    for (int t = 0; t < 14; t++) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        double ang = (t >= 6 ? (t - 6) * PI / 14.0 : 0.0);\n        double vx = cos(ang), vy = sin(ang);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            double ka, kb;\n\n            if (t == 0) ka = cx[a], kb = cx[b];\n            else if (t == 1) ka = cy[a], kb = cy[b];\n            else if (t == 2) ka = cx[a] + cy[a], kb = cx[b] + cy[b];\n            else if (t == 3) ka = cx[a] - cy[a], kb = cx[b] - cy[b];\n            else if (t == 4) ka = -cx[a] + cy[a], kb = -cx[b] + cy[b];\n            else if (t == 5) ka = -cx[a] - cy[a], kb = -cx[b] - cy[b];\n            else ka = cx[a] * vx + cy[a] * vy, kb = cx[b] * vx + cy[b] * vy;\n\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n\n        add_order_candidates(ord);\n    }\n\n    for (int v = 0; v < 4; v++) {\n        candidates.push_back(make_recursive_candidate(v));\n    }\n\n    for (int v = 0; v < 27; v++) {\n        if (timer.sec() > 1.05) break;\n        candidates.push_back(make_greedy_candidate(v));\n    }\n\n    vector<pair<double,int>> candScores;\n    candScores.reserve(candidates.size());\n\n    double bestScore = 1e100;\n    vector<vector<int>> groups;\n\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        double sc = total_mst_cost(candidates[i]);\n        candScores.push_back({sc, i});\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = candidates[i];\n        }\n    }\n\n    sort(candScores.begin(), candScores.end());\n\n    int lloydTried = 0;\n    for (auto [sc0, idx] : candScores) {\n        if (lloydTried >= 4) break;\n        if (timer.sec() > 1.12) break;\n\n        auto km = capacitated_lloyd(candidates[idx], 4);\n        double sc = total_mst_cost(km);\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = km;\n        }\n\n        lloydTried++;\n    }\n\n    vector<int> cityGroup(N), cityPos(N);\n    vector<double> groupCost(M);\n\n    for (int gid = 0; gid < M; gid++) {\n        for (int p = 0; p < (int)groups[gid].size(); p++) {\n            cityGroup[groups[gid][p]] = gid;\n            cityPos[groups[gid][p]] = p;\n        }\n        groupCost[gid] = mst_cost(groups[gid]);\n    }\n\n    const int KNN = 28;\n    vector<vector<int>> knn(N);\n\n    for (int i = 0; i < N; i++) {\n        vector<pair<double,int>> v;\n        v.reserve(N - 1);\n\n        for (int j = 0; j < N; j++) {\n            if (i == j) continue;\n            v.push_back({edist(i, j), j});\n        }\n\n        nth_element(v.begin(), v.begin() + KNN, v.end());\n        v.resize(KNN);\n        sort(v.begin(), v.end());\n\n        for (auto [d, j] : v) knn[i].push_back(j);\n    }\n\n    auto mst_cost_with_swap = [&](int gid, int outCity, int inCity) {\n        vector<int> tmp = groups[gid];\n        int p = cityPos[outCity];\n        tmp[p] = inCity;\n        return mst_cost(tmp);\n    };\n\n    for (int pass = 0; pass < 7; pass++) {\n        if (timer.sec() > 1.34) break;\n\n        vector<double> gx(M, 0.0), gy(M, 0.0);\n\n        for (int gid = 0; gid < M; gid++) {\n            for (int v : groups[gid]) {\n                gx[gid] += cx[v];\n                gy[gid] += cy[v];\n            }\n            gx[gid] /= groups[gid].size();\n            gy[gid] /= groups[gid].size();\n        }\n\n        struct Cand {\n            double approx;\n            int a, b;\n        };\n\n        vector<Cand> sw;\n        unordered_set<unsigned long long> seen;\n        seen.reserve(N * 64);\n\n        auto add_swap_cand = [&](int a, int b) {\n            int ga = cityGroup[a], gb = cityGroup[b];\n            if (ga == gb) return;\n\n            unsigned long long key = ekey(a, b);\n            if (seen.count(key)) return;\n            seen.insert(key);\n\n            double da1 = sqrt(dist2p(cx[a], cy[a], gx[ga], gy[ga]));\n            double db1 = sqrt(dist2p(cx[b], cy[b], gx[gb], gy[gb]));\n            double da2 = sqrt(dist2p(cx[a], cy[a], gx[gb], gy[gb]));\n            double db2 = sqrt(dist2p(cx[b], cy[b], gx[ga], gy[ga]));\n            double approx = da2 + db2 - da1 - db1;\n\n            if (approx < 800.0) sw.push_back({approx, a, b});\n        };\n\n        for (int a = 0; a < N; a++) {\n            for (int b : knn[a]) add_swap_cand(a, b);\n        }\n\n        // Centroid-targeted candidate swaps.\n        if (M > 1) {\n            for (int a = 0; a < N; a++) {\n                int ga = cityGroup[a];\n\n                vector<pair<double,int>> tg;\n                tg.reserve(M - 1);\n\n                for (int gid = 0; gid < M; gid++) {\n                    if (gid == ga) continue;\n                    double d = dist2p(cx[a], cy[a], gx[gid], gy[gid]);\n                    tg.push_back({d, gid});\n                }\n\n                int tk = min(4, (int)tg.size());\n                nth_element(tg.begin(), tg.begin() + tk - 1, tg.end());\n                tg.resize(tk);\n\n                for (auto [dcent, gb] : tg) {\n                    vector<pair<double,int>> bs;\n                    bs.reserve(groups[gb].size());\n\n                    for (int b : groups[gb]) {\n                        double d = dist2p(cx[b], cy[b], gx[ga], gy[ga]);\n                        bs.push_back({d, b});\n                    }\n\n                    int bk = min(3, (int)bs.size());\n                    nth_element(bs.begin(), bs.begin() + bk - 1, bs.end());\n                    bs.resize(bk);\n\n                    for (auto [db, b] : bs) add_swap_cand(a, b);\n                }\n            }\n        }\n\n        sort(sw.begin(), sw.end(), [](const Cand& x, const Cand& y) {\n            return x.approx < y.approx;\n        });\n\n        if ((int)sw.size() > 12000) sw.resize(12000);\n\n        bool changed = false;\n\n        for (auto c : sw) {\n            if (timer.sec() > 1.53) break;\n\n            int a = c.a, b = c.b;\n            int ga = cityGroup[a], gb = cityGroup[b];\n            if (ga == gb) continue;\n\n            double oldCost = groupCost[ga] + groupCost[gb];\n            double na = mst_cost_with_swap(ga, a, b);\n            double nb = mst_cost_with_swap(gb, b, a);\n            double newCost = na + nb;\n\n            if (newCost + 1e-7 < oldCost) {\n                int pa = cityPos[a], pb = cityPos[b];\n\n                groups[ga][pa] = b;\n                groups[gb][pb] = a;\n\n                cityGroup[a] = gb;\n                cityGroup[b] = ga;\n                cityPos[a] = pb;\n                cityPos[b] = pa;\n\n                groupCost[ga] = na;\n                groupCost[gb] = nb;\n\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    vector<vector<pair<int,int>>> backupEdges(M);\n\n    for (int gid = 0; gid < M; gid++) {\n        backupEdges[gid] = prim_edges(groups[gid]);\n    }\n\n    vector<vector<pair<int,int>>> finalEdges(M);\n    vector<unordered_map<unsigned long long,int>> oracleEdges(M);\n\n    struct PlannedQuery {\n        int gid;\n        vector<int> cities;\n        bool exactSmall;\n    };\n\n    vector<PlannedQuery> queries;\n    unordered_set<string> usedSubset;\n    usedSubset.reserve(2000);\n\n    auto add_query = [&](int gid, const vector<int>& c, bool exactSmall) -> bool {\n        if ((int)queries.size() >= Q) return false;\n        if ((int)c.size() < 2 || (int)c.size() > L) return false;\n\n        string key = subset_key(c);\n        if (usedSubset.count(key)) return false;\n        usedSubset.insert(key);\n\n        queries.push_back({gid, c, exactSmall});\n        return true;\n    };\n\n    vector<int> smallIds;\n\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n        if (3 <= g && g <= L) smallIds.push_back(gid);\n    }\n\n    sort(smallIds.begin(), smallIds.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    for (int gid : smallIds) {\n        add_query(gid, groups[gid], true);\n    }\n\n    vector<int> largeIds;\n\n    for (int gid = 0; gid < M; gid++) {\n        if ((int)groups[gid].size() > L) largeIds.push_back(gid);\n    }\n\n    sort(largeIds.begin(), largeIds.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    vector<vector<pair<double,pair<int,int>>>> longEdges(M);\n\n    for (int gid : largeIds) {\n        for (auto [a, b] : backupEdges[gid]) {\n            longEdges[gid].push_back({edist(a, b), {a, b}});\n        }\n\n        sort(longEdges[gid].begin(), longEdges[gid].end(), [](auto& x, auto& y) {\n            return x.first > y.first;\n        });\n    }\n\n    int round = 0;\n\n    while ((int)queries.size() < Q && !largeIds.empty()) {\n        bool any = false;\n\n        for (int gid : largeIds) {\n            if ((int)queries.size() >= Q) break;\n\n            int g = groups[gid].size();\n            vector<int> sub;\n\n            // Prefer long estimated MST edges first; then seed neighborhoods.\n            if (round < (int)longEdges[gid].size()) {\n                auto [a, b] = longEdges[gid][round].second;\n                sub = nearest_subset_to_edge(groups[gid], a, b);\n            } else {\n                int idx = (round - (int)longEdges[gid].size()) % g;\n                int seed = groups[gid][idx];\n                sub = nearest_subset_to_seed(groups[gid], seed);\n            }\n\n            if (add_query(gid, sub, false)) any = true;\n        }\n\n        round++;\n        if (!any && round > 2 * N + 20) break;\n    }\n\n    for (auto& qu : queries) {\n        auto ret = do_query(qu.cities);\n        int gid = qu.gid;\n\n        for (auto [a, b] : ret) {\n            oracleEdges[gid][ekey(a, b)]++;\n        }\n\n        if (qu.exactSmall) {\n            finalEdges[gid] = ret;\n        }\n    }\n\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n\n        if (g <= 1) {\n            finalEdges[gid].clear();\n        } else if (g == 2) {\n            finalEdges[gid] = {{groups[gid][0], groups[gid][1]}};\n        } else if (g <= L && !finalEdges[gid].empty()) {\n            // Exact MST already obtained.\n        } else {\n            struct EdgeCand {\n                double w;\n                int a, b;\n            };\n\n            vector<EdgeCand> cand;\n\n            for (auto& kv : oracleEdges[gid]) {\n                auto [a, b] = decode_key(kv.first);\n                int cnt = kv.second;\n                double factor = 0.56 - 0.04 * min(4, cnt - 1);\n                cand.push_back({edist(a, b) * factor, a, b});\n            }\n\n            for (auto [a, b] : backupEdges[gid]) {\n                cand.push_back({edist(a, b), a, b});\n            }\n\n            for (int a : groups[gid]) {\n                vector<pair<double,int>> near;\n\n                for (int b : groups[gid]) {\n                    if (a == b) continue;\n                    near.push_back({edist(a, b), b});\n                }\n\n                sort(near.begin(), near.end());\n\n                int lim = min(5, (int)near.size());\n                for (int i = 0; i < lim; i++) {\n                    int b = near[i].second;\n                    cand.push_back({near[i].first * 1.04, a, b});\n                }\n            }\n\n            sort(cand.begin(), cand.end(), [](const EdgeCand& x, const EdgeCand& y) {\n                if (x.w != y.w) return x.w < y.w;\n                if (x.a != y.a) return x.a < y.a;\n                return x.b < y.b;\n            });\n\n            DSU dsu(N);\n            vector<pair<int,int>> tree;\n            tree.reserve(g - 1);\n\n            for (auto& e : cand) {\n                if (dsu.unite(e.a, e.b)) {\n                    tree.push_back({e.a, e.b});\n                    if ((int)tree.size() == g - 1) break;\n                }\n            }\n\n            if ((int)tree.size() != g - 1) {\n                tree = backupEdges[gid];\n            }\n\n            finalEdges[gid] = tree;\n        }\n    }\n\n    cout << \"!\" << '\\n';\n\n    for (int gid = 0; gid < M; gid++) {\n        for (int i = 0; i < (int)groups[gid].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[gid][i];\n        }\n        cout << '\\n';\n\n        for (auto [a, b] : finalEdges[gid]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Act {\n    char a, d;\n};\n\nconst int MAXC = 400;\nconst int INF = 1e9;\n\nint N, M;\nvector<int> pos_id;\nvector<bitset<MAXC>> future_mask;\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\nauto START_TIME = chrono::steady_clock::now();\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\ninline int id(int r, int c) { return r * N + c; }\ninline int rr(int x) { return x / N; }\ninline int cc(int x) { return x % N; }\ninline bool inside(int r, int c) { return 0 <= r && r < N && 0 <= c && c < N; }\n\ninline bool blocked(const bitset<MAXC>& g, int r, int c) {\n    if (!inside(r, c)) return true;\n    return g[id(r, c)];\n}\n\nint slide_stop(const bitset<MAXC>& g, int s, int dir) {\n    int r = rr(s), c = cc(s);\n    while (true) {\n        int nr = r + dr[dir], nc = c + dc[dir];\n        if (blocked(g, nr, nc)) break;\n        r = nr;\n        c = nc;\n    }\n    return id(r, c);\n}\n\nstruct BFSRes {\n    array<int, MAXC> dist;\n    array<int, MAXC> par;\n    array<char, MAXC> pact;\n    array<char, MAXC> pdir;\n};\n\nBFSRes forward_bfs(const bitset<MAXC>& g, int start, int forbid_stop = -1) {\n    BFSRes res;\n    res.dist.fill(INF);\n    res.par.fill(-1);\n    res.pact.fill(0);\n    res.pdir.fill(0);\n\n    if (g[start]) return res;\n\n    int q[MAXC], head = 0, tail = 0;\n    res.dist[start] = 0;\n    q[tail++] = start;\n\n    while (head < tail) {\n        int v = q[head++];\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d], nc = c + dc[d];\n\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (to != forbid_stop && res.dist[to] == INF) {\n                    res.dist[to] = res.dist[v] + 1;\n                    res.par[to] = v;\n                    res.pact[to] = 'M';\n                    res.pdir[to] = dch[d];\n                    q[tail++] = to;\n                }\n            }\n\n            int to = slide_stop(g, v, d);\n            if (to != v && to != forbid_stop && res.dist[to] == INF) {\n                res.dist[to] = res.dist[v] + 1;\n                res.par[to] = v;\n                res.pact[to] = 'S';\n                res.pdir[to] = dch[d];\n                q[tail++] = to;\n            }\n        }\n    }\n\n    return res;\n}\n\narray<int, MAXC> reverse_bfs_dist(const bitset<MAXC>& g, int target) {\n    array<int, MAXC> dist;\n    dist.fill(INF);\n\n    if (g[target]) return dist;\n\n    int q[MAXC], head = 0, tail = 0;\n    dist[target] = 0;\n    q[tail++] = target;\n\n    while (head < tail) {\n        int v = q[head++];\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            int pr = r - dr[d], pc = c - dc[d];\n\n            if (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q[tail++] = u;\n                }\n            }\n\n            int br = r + dr[d], bc = c + dc[d];\n            if (!blocked(g, br, bc)) continue;\n\n            pr = r - dr[d];\n            pc = c - dc[d];\n\n            while (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q[tail++] = u;\n                }\n                pr -= dr[d];\n                pc -= dc[d];\n            }\n        }\n    }\n\n    return dist;\n}\n\nvector<Act> restore_forward(const BFSRes& bfs, int start, int goal) {\n    vector<Act> rev;\n    int cur = goal;\n\n    while (cur != start) {\n        if (cur < 0 || bfs.par[cur] < 0) return {};\n        rev.push_back({bfs.pact[cur], bfs.pdir[cur]});\n        cur = bfs.par[cur];\n    }\n\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nvector<Act> restore_by_reverse_dist(\n    const bitset<MAXC>& g,\n    const array<int, MAXC>& dist,\n    int start,\n    int target\n) {\n    vector<Act> ret;\n    int cur = start;\n\n    while (cur != target) {\n        int cd = dist[cur];\n        bool found = false;\n\n        for (int d = 0; d < 4 && !found; d++) {\n            int r = rr(cur), c = cc(cur);\n\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (dist[to] == cd - 1) {\n                    ret.push_back({'M', dch[d]});\n                    cur = to;\n                    found = true;\n                    break;\n                }\n            }\n\n            int to = slide_stop(g, cur, d);\n            if (to != cur && dist[to] == cd - 1) {\n                ret.push_back({'S', dch[d]});\n                cur = to;\n                found = true;\n                break;\n            }\n        }\n\n        if (!found) {\n            ret.clear();\n            return ret;\n        }\n    }\n\n    return ret;\n}\n\nint dir_from_to(int p, int b) {\n    int pr = rr(p), pc = cc(p);\n    int br = rr(b), bc = cc(b);\n\n    for (int d = 0; d < 4; d++) {\n        if (pr + dr[d] == br && pc + dc[d] == bc) return d;\n    }\n    return -1;\n}\n\nstruct State {\n    bitset<MAXC> grid;\n    int cost = 0;\n    vector<Act> acts;\n};\n\nstruct Params {\n    bool allow_future_target_block;\n    int beam_w;\n    int cost_first_keep;\n    int h_weight;\n    int bf_penalty;\n    double deadline;\n};\n\nstruct Option {\n    int cost;\n    int b;\n    int p;\n};\n\nint manhattan_id(int a, int b) {\n    return abs(rr(a) - rr(b)) + abs(cc(a) - cc(b));\n}\n\nint blocked_future_count(const bitset<MAXC>& g, int from_index) {\n    int cnt = 0;\n    for (int k = from_index; k < M; k++) {\n        if (g[pos_id[k]]) cnt++;\n    }\n    return cnt;\n}\n\nint one_step_heuristic(const State& st, int leg, const Params& prm) {\n    if (prm.h_weight == 0) return 0;\n    if (leg + 1 >= M) return 0;\n    if (elapsed_sec() > prm.deadline - 0.12) return 0;\n\n    int s = pos_id[leg];\n    int t = pos_id[leg + 1];\n\n    BFSRes bfs = forward_bfs(st.grid, s, -1);\n    int d = bfs.dist[t];\n\n    if (d >= INF) return manhattan_id(s, t) + 20;\n    return d;\n}\n\nvector<State> expand_state(const State& st, int leg, const Params& prm) {\n    constexpr int TOP_K = 5;\n    constexpr int ALLOW_EXTRA = 4;\n\n    vector<State> res;\n\n    int start = pos_id[leg - 1];\n    int target = pos_id[leg];\n\n    BFSRes bfs_normal = forward_bfs(st.grid, start, -1);\n    BFSRes bfs_avoid = forward_bfs(st.grid, start, target);\n\n    int base_cost = bfs_normal.dist[target];\n    vector<Act> base_path;\n\n    if (base_cost < INF) {\n        base_path = restore_forward(bfs_normal, start, target);\n\n        State ns;\n        ns.grid = st.grid;\n        ns.acts = st.acts;\n        ns.acts.insert(ns.acts.end(), base_path.begin(), base_path.end());\n        ns.cost = (int)ns.acts.size();\n        res.push_back(std::move(ns));\n\n        for (int d = 0; d < 4; d++) {\n            int br = rr(target) + dr[d];\n            int bc = cc(target) + dc[d];\n            if (!inside(br, bc)) continue;\n\n            int b = id(br, bc);\n\n            if (!prm.allow_future_target_block && !st.grid[b] && future_mask[leg + 1][b]) {\n                continue;\n            }\n\n            bitset<MAXC> g2 = st.grid;\n            g2.flip(b);\n\n            if (g2[target]) continue;\n\n            State ps;\n            ps.grid = g2;\n            ps.acts = st.acts;\n            ps.acts.insert(ps.acts.end(), base_path.begin(), base_path.end());\n            ps.acts.push_back({'A', dch[d]});\n            ps.cost = (int)ps.acts.size();\n            res.push_back(std::move(ps));\n        }\n    }\n\n    if (elapsed_sec() > prm.deadline - 0.16) return res;\n\n    vector<Option> opts;\n\n    for (int b = 0; b < N * N; b++) {\n        if ((b & 31) == 0 && elapsed_sec() > prm.deadline - 0.07) break;\n\n        if (!prm.allow_future_target_block && !st.grid[b] && future_mask[leg][b]) {\n            continue;\n        }\n\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(b);\n\n        if (g2[target]) continue;\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n\n        int best_cost = INF;\n        int best_p = -1;\n\n        int br = rr(b), bc = cc(b);\n\n        for (int d = 0; d < 4; d++) {\n            int pr = br - dr[d], pc = bc - dc[d];\n            if (!inside(pr, pc)) continue;\n\n            int p = id(pr, pc);\n\n            if (st.grid[p]) continue;\n            if (g2[p]) continue;\n            if (bfs_avoid.dist[p] >= INF) continue;\n            if (dist_to_target[p] >= INF) continue;\n\n            int cand = bfs_avoid.dist[p] + 1 + dist_to_target[p];\n\n            if (cand < best_cost) {\n                best_cost = cand;\n                best_p = p;\n            }\n        }\n\n        if (best_p < 0) continue;\n        if (base_cost < INF && best_cost > base_cost + ALLOW_EXTRA) continue;\n\n        opts.push_back({best_cost, b, best_p});\n    }\n\n    sort(opts.begin(), opts.end(), [](const Option& x, const Option& y) {\n        return x.cost < y.cost;\n    });\n\n    if ((int)opts.size() > TOP_K) opts.resize(TOP_K);\n\n    for (const auto& op : opts) {\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(op.b);\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n\n        if (dist_to_target[op.p] >= INF) continue;\n\n        auto path1 = restore_forward(bfs_avoid, start, op.p);\n        if (path1.empty() && op.p != start) continue;\n\n        int ad = dir_from_to(op.p, op.b);\n        if (ad < 0) continue;\n\n        auto path2 = restore_by_reverse_dist(g2, dist_to_target, op.p, target);\n        if (path2.empty() && op.p != target) continue;\n\n        State ns;\n        ns.grid = g2;\n        ns.acts = st.acts;\n        ns.acts.insert(ns.acts.end(), path1.begin(), path1.end());\n        ns.acts.push_back({'A', dch[ad]});\n        ns.acts.insert(ns.acts.end(), path2.begin(), path2.end());\n        ns.cost = (int)ns.acts.size();\n\n        res.push_back(std::move(ns));\n    }\n\n    return res;\n}\n\nvector<Act> simple_fallback_empty_board() {\n    vector<Act> ret;\n    int cur = pos_id[0];\n\n    for (int k = 1; k < M; k++) {\n        int t = pos_id[k];\n\n        int r = rr(cur), c = cc(cur);\n        int tr = rr(t), tc = cc(t);\n\n        while (r < tr) {\n            ret.push_back({'M', 'D'});\n            r++;\n        }\n        while (r > tr) {\n            ret.push_back({'M', 'U'});\n            r--;\n        }\n        while (c < tc) {\n            ret.push_back({'M', 'R'});\n            c++;\n        }\n        while (c > tc) {\n            ret.push_back({'M', 'L'});\n            c--;\n        }\n\n        cur = t;\n    }\n\n    return ret;\n}\n\nint dir_index(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\nbool simulate_skip(const vector<Act>& acts, int skip = -1) {\n    int effective_len = (int)acts.size() - (skip >= 0);\n    if (effective_len > 2 * N * M) return false;\n\n    bitset<MAXC> g;\n    int cur = pos_id[0];\n    int nxt = 1;\n\n    for (int idx = 0; idx < (int)acts.size(); idx++) {\n        if (idx == skip) continue;\n\n        auto [a, ch] = acts[idx];\n        int d = dir_index(ch);\n        int r = rr(cur), c = cc(cur);\n\n        if (a == 'M') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n\n            int to = id(nr, nc);\n            if (g[to]) return false;\n\n            cur = to;\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'S') {\n            while (true) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (!inside(nr, nc) || g[id(nr, nc)]) break;\n                r = nr;\n                c = nc;\n            }\n\n            cur = id(r, c);\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'A') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n\n            int b = id(nr, nc);\n            g.flip(b);\n        } else {\n            return false;\n        }\n    }\n\n    return nxt == M;\n}\n\nbool simulate(const vector<Act>& acts) {\n    return simulate_skip(acts, -1);\n}\n\nvector<Act> solve_variant(const Params& prm) {\n    vector<State> beam;\n\n    State init;\n    init.grid.reset();\n    init.cost = 0;\n    beam.push_back(init);\n\n    for (int leg = 1; leg < M; leg++) {\n        vector<State> candidates;\n\n        for (const auto& st : beam) {\n            auto ex = expand_state(st, leg, prm);\n            for (auto& ns : ex) candidates.push_back(std::move(ns));\n        }\n\n        if (candidates.empty()) return simple_fallback_empty_board();\n\n        sort(candidates.begin(), candidates.end(), [](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        vector<State> unique_candidates;\n        unique_candidates.reserve(candidates.size());\n\n        for (auto& st : candidates) {\n            bool dup = false;\n            for (const auto& u : unique_candidates) {\n                if (u.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) unique_candidates.push_back(std::move(st));\n        }\n\n        candidates.swap(unique_candidates);\n\n        vector<State> nb;\n\n        sort(candidates.begin(), candidates.end(), [](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        for (auto& st : candidates) {\n            bool dup = false;\n            for (const auto& kept : nb) {\n                if (kept.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (dup) continue;\n\n            nb.push_back(st);\n            if ((int)nb.size() >= prm.cost_first_keep) break;\n        }\n\n        struct Ranked {\n            long long score;\n            int cost;\n            int idx;\n        };\n\n        vector<Ranked> rank;\n        rank.reserve(candidates.size());\n\n        for (int i = 0; i < (int)candidates.size(); i++) {\n            int h = one_step_heuristic(candidates[i], leg, prm);\n            int bf = prm.bf_penalty ? blocked_future_count(candidates[i].grid, leg + 1) : 0;\n\n            long long sc =\n                100LL * candidates[i].cost +\n                1LL * prm.h_weight * h +\n                1LL * prm.bf_penalty * bf;\n\n            rank.push_back({sc, candidates[i].cost, i});\n        }\n\n        sort(rank.begin(), rank.end(), [](const Ranked& a, const Ranked& b) {\n            if (a.score != b.score) return a.score < b.score;\n            return a.cost < b.cost;\n        });\n\n        for (const auto& rnk : rank) {\n            const State& st = candidates[rnk.idx];\n\n            bool dup = false;\n            for (const auto& kept : nb) {\n                if (kept.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (dup) continue;\n\n            nb.push_back(st);\n            if ((int)nb.size() >= prm.beam_w) break;\n        }\n\n        if (nb.empty()) return simple_fallback_empty_board();\n\n        beam = std::move(nb);\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)beam.size(); i++) {\n        if (beam[i].cost < beam[best].cost) best = i;\n    }\n\n    return beam[best].acts;\n}\n\nvoid erase_one(vector<Act>& ans, int skip) {\n    vector<Act> nxt;\n    nxt.reserve(ans.size() - 1);\n\n    for (int i = 0; i < (int)ans.size(); i++) {\n        if (i != skip) nxt.push_back(ans[i]);\n    }\n\n    ans.swap(nxt);\n}\n\nvoid greedy_delete_limited(vector<Act>& ans) {\n    // Same safe cleanup as the best previous version, but without vector copying\n    // for each simulation trial.\n    int i = 0;\n\n    while (i < (int)ans.size()) {\n        if (elapsed_sec() > 1.88) break;\n\n        if (simulate_skip(ans, i)) {\n            erase_one(ans, i);\n        } else {\n            i++;\n        }\n    }\n}\n\nvoid consider_answer(vector<Act>& best, const vector<Act>& cand) {\n    if (!simulate(cand)) return;\n\n    if (best.empty() || cand.size() < best.size()) {\n        best = cand;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    pos_id.resize(M);\n    for (int k = 0; k < M; k++) {\n        int r, c;\n        cin >> r >> c;\n        pos_id[k] = id(r, c);\n    }\n\n    future_mask.assign(M + 1, bitset<MAXC>());\n    future_mask[M].reset();\n\n    for (int k = M - 1; k >= 0; k--) {\n        future_mask[k] = future_mask[k + 1];\n        future_mask[k].set(pos_id[k]);\n    }\n\n    vector<Act> best;\n\n    // Variant 1: allow temporary blocks on future targets.\n    {\n        Params prm;\n        prm.allow_future_target_block = true;\n        prm.beam_w = 6;\n        prm.cost_first_keep = 4;\n        prm.h_weight = 12;\n        prm.bf_penalty = 10;\n        prm.deadline = 1.18;\n\n        auto ans = solve_variant(prm);\n        consider_answer(best, ans);\n    }\n\n    // Variant 2: safer policy, forbid newly blocking future targets.\n    if (elapsed_sec() < 1.50) {\n        Params prm;\n        prm.allow_future_target_block = false;\n        prm.beam_w = 5;\n        prm.cost_first_keep = 2;\n        prm.h_weight = 12;\n        prm.bf_penalty = 0;\n        prm.deadline = 1.72;\n\n        auto ans = solve_variant(prm);\n        consider_answer(best, ans);\n    }\n\n    // Variant 3: cost-focused variant.\n    if (elapsed_sec() < 1.62) {\n        Params prm;\n        prm.allow_future_target_block = true;\n        prm.beam_w = 5;\n        prm.cost_first_keep = 5;\n        prm.h_weight = 0;\n        prm.bf_penalty = 6;\n        prm.deadline = 1.80;\n\n        auto ans = solve_variant(prm);\n        consider_answer(best, ans);\n    }\n\n    if (best.empty()) {\n        best = simple_fallback_empty_board();\n    }\n\n    if (!simulate(best)) {\n        best = simple_fallback_empty_board();\n    } else {\n        greedy_delete_limited(best);\n    }\n\n    if (!simulate(best)) {\n        best = simple_fallback_empty_board();\n    }\n\n    for (auto [a, d] : best) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point 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 Rect { int a,b,c,d; };\nstruct Blocker { int id,gap,lim; };\nstruct SplitCand { int axis,k,cut; double cost; };\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\nvector<long double> wt;\nmt19937 rng(1234567);\nTimer timer_;\n\nlong long area(const Rect& r){ return 1LL*(r.c-r.a)*(r.d-r.b); }\n\ndouble sc_area(long long s,long long r){\n    if(s<=0) return 0;\n    double q=(double)min(s,r)/(double)max(s,r);\n    return 1.0-(1.0-q)*(1.0-q);\n}\n\ndouble eval(const vector<Rect>& v){\n    double s=0;\n    for(int i=0;i<n;i++){\n        const auto& r=v[i];\n        if(r.a<=xs[i]&&xs[i]+1<=r.c&&r.b<=ys[i]&&ys[i]+1<=r.d)\n            s+=sc_area(area(r),rs[i]);\n    }\n    return s;\n}\n\nbool ov1(int l1,int r1,int l2,int r2){ return max(l1,l2)<min(r1,r2); }\n\n/* ---------- slicing ---------- */\n\nvoid build_rec(const vector<int>& ids,int L,int B,int R,int T,vector<Rect>& out,int topK){\n    int m=ids.size();\n    if(m==1){ out[ids[0]]={L,B,R,T}; return; }\n\n    long double tot=0;\n    for(int id:ids) tot+=wt[id];\n\n    long long reg=1LL*(R-L)*(T-B);\n    vector<SplitCand> cand;\n\n    for(int ax=0;ax<2;ax++){\n        vector<int> v=ids;\n        if(ax==0) sort(v.begin(),v.end(),[&](int p,int q){\n            if(xs[p]!=xs[q]) return xs[p]<xs[q];\n            return ys[p]<ys[q];\n        });\n        else sort(v.begin(),v.end(),[&](int p,int q){\n            if(ys[p]!=ys[q]) return ys[p]<ys[q];\n            return xs[p]<xs[q];\n        });\n\n        vector<long double> pref(m+1,0);\n        for(int i=0;i<m;i++) pref[i+1]=pref[i]+wt[v[i]];\n\n        for(int k=1;k<m;k++){\n            int cl=(ax==0?xs[v[k-1]]:ys[v[k-1]]);\n            int cr=(ax==0?xs[v[k]]:ys[v[k]]);\n            if(cl>=cr) continue;\n\n            int st=(ax==0?L:B), en=(ax==0?R:T);\n            int other=(ax==0?T-B:R-L);\n            int lo=max(cl+1,st+1), hi=min(cr,en-1);\n            if(lo>hi) continue;\n\n            long double ratio=pref[k]/tot;\n            int cut=(int)llround((long double)st+ratio*(en-st));\n            cut=min(max(cut,lo),hi);\n\n            long long ar1=1LL*(cut-st)*other, ar2=reg-ar1;\n            long double t1=pref[k], t2=tot-t1;\n            long double scale=(long double)reg/tot;\n\n            double e1=fabs((double)((long double)ar1/t1-scale));\n            double e2=fabs((double)((long double)ar2/t2-scale));\n            double cost=e1*(double)(t1/tot)+e2*(double)(t2/tot);\n\n            if(k==1) cost+=0.08*(1.0-sc_area(ar1,rs[v[0]]));\n            if(m-k==1) cost+=0.08*(1.0-sc_area(ar2,rs[v[m-1]]));\n\n            cand.push_back({ax,k,cut,cost});\n        }\n    }\n\n    if(cand.empty()){\n        vector<int> v=ids;\n        sort(v.begin(),v.end(),[&](int p,int q){\n            if(xs[p]!=xs[q]) return xs[p]<xs[q];\n            return ys[p]<ys[q];\n        });\n        int k=m/2, cut=min(max((L+R)/2,L+1),R-1);\n        vector<int> A(v.begin(),v.begin()+k), C(v.begin()+k,v.end());\n        build_rec(A,L,B,cut,T,out,topK);\n        build_rec(C,cut,B,R,T,out,topK);\n        return;\n    }\n\n    sort(cand.begin(),cand.end(),[](auto& x,auto& y){return x.cost<y.cost;});\n    int pick=0;\n    if(topK>1){\n        int lim=min<int>(topK,cand.size());\n        double u=uniform_real_distribution<double>(0,1)(rng);\n        pick=min(lim-1,(int)(u*u*lim));\n    }\n\n    auto ch=cand[pick];\n    vector<int> v=ids;\n    if(ch.axis==0) sort(v.begin(),v.end(),[&](int p,int q){\n        if(xs[p]!=xs[q]) return xs[p]<xs[q];\n        return ys[p]<ys[q];\n    });\n    else sort(v.begin(),v.end(),[&](int p,int q){\n        if(ys[p]!=ys[q]) return ys[p]<ys[q];\n        return xs[p]<xs[q];\n    });\n\n    vector<int> A(v.begin(),v.begin()+ch.k), C(v.begin()+ch.k,v.end());\n    if(ch.axis==0){\n        build_rec(A,L,B,ch.cut,T,out,topK);\n        build_rec(C,ch.cut,B,R,T,out,topK);\n    }else{\n        build_rec(A,L,B,R,ch.cut,out,topK);\n        build_rec(C,L,ch.cut,R,T,out,topK);\n    }\n}\n\nvector<Rect> build_slicing(int topK,double noise){\n    wt.assign(n,0);\n    if(noise<=0){\n        for(int i=0;i<n;i++) wt[i]=rs[i];\n    }else{\n        normal_distribution<double> nd(0.0,noise);\n        for(int i=0;i<n;i++){\n            double mul=exp(nd(rng));\n            mul=min(1.45,max(0.70,mul));\n            wt[i]=(long double)rs[i]*mul;\n        }\n    }\n    vector<Rect> res(n);\n    vector<int> ids(n);\n    iota(ids.begin(),ids.end(),0);\n    build_rec(ids,0,0,10000,10000,res,topK);\n    return res;\n}\n\n/* ---------- local search ---------- */\n\nbool shrink_pass(vector<Rect>& v,bool rnd,double deadline){\n    vector<int> ord(n); iota(ord.begin(),ord.end(),0);\n    if(rnd) shuffle(ord.begin(),ord.end(),rng);\n    bool moved=false;\n\n    for(int id:ord){\n        if(timer_.elapsed()>deadline) break;\n        Rect cur=v[id], best=cur;\n        long long A=area(cur);\n        double old=sc_area(A,rs[id]), bg=1e-15;\n\n        auto tr=[&](int dir,int maxd){\n            if(maxd<=0) return;\n            int len=(dir<2?cur.d-cur.b:cur.c-cur.a);\n            vector<int> ds;\n            long long ex=A-rs[id];\n            if(ex>0){\n                long long q=ex/len;\n                for(long long z:{q-2,q-1,q,q+1,q+2})\n                    if(1<=z&&z<=maxd) ds.push_back((int)z);\n            }\n            ds.push_back(1); ds.push_back(maxd);\n            sort(ds.begin(),ds.end());\n            ds.erase(unique(ds.begin(),ds.end()),ds.end());\n\n            for(int d:ds){\n                Rect nr=cur;\n                if(dir==0) nr.a+=d;\n                if(dir==1) nr.c-=d;\n                if(dir==2) nr.b+=d;\n                if(dir==3) nr.d-=d;\n                if(!(nr.a<nr.c&&nr.b<nr.d)) continue;\n                if(!(nr.a<=xs[id]&&xs[id]+1<=nr.c&&nr.b<=ys[id]&&ys[id]+1<=nr.d)) continue;\n                double g=sc_area(area(nr),rs[id])-old;\n                if(g>bg){ bg=g; best=nr; }\n            }\n        };\n\n        tr(0,xs[id]-cur.a);\n        tr(1,cur.c-(xs[id]+1));\n        tr(2,ys[id]-cur.b);\n        tr(3,cur.d-(ys[id]+1));\n\n        if(bg>1e-14){ v[id]=best; moved=true; }\n    }\n    return moved;\n}\n\nint max_expand_delta(const vector<Rect>& v,int id,int dir){\n    const Rect& r=v[id];\n    int lim;\n    if(dir==0){\n        lim=r.a;\n        for(int j=0;j<n;j++) if(j!=id){\n            const auto& o=v[j];\n            if(ov1(r.b,r.d,o.b,o.d)&&o.c<=r.a) lim=min(lim,r.a-o.c);\n        }\n    }else if(dir==1){\n        lim=10000-r.c;\n        for(int j=0;j<n;j++) if(j!=id){\n            const auto& o=v[j];\n            if(ov1(r.b,r.d,o.b,o.d)&&o.a>=r.c) lim=min(lim,o.a-r.c);\n        }\n    }else if(dir==2){\n        lim=r.b;\n        for(int j=0;j<n;j++) if(j!=id){\n            const auto& o=v[j];\n            if(ov1(r.a,r.c,o.a,o.c)&&o.d<=r.b) lim=min(lim,r.b-o.d);\n        }\n    }else{\n        lim=10000-r.d;\n        for(int j=0;j<n;j++) if(j!=id){\n            const auto& o=v[j];\n            if(ov1(r.a,r.c,o.a,o.c)&&o.b>=r.d) lim=min(lim,o.b-r.d);\n        }\n    }\n    return lim;\n}\n\nbool expand_pass(vector<Rect>& v,bool rnd,double deadline){\n    vector<int> ord(n); iota(ord.begin(),ord.end(),0);\n    if(rnd) shuffle(ord.begin(),ord.end(),rng);\n    bool moved=false;\n\n    for(int id:ord){\n        if(timer_.elapsed()>deadline) break;\n        Rect cur=v[id], best=cur;\n        long long A=area(cur);\n        double old=sc_area(A,rs[id]), bg=1e-15;\n\n        for(int dir=0;dir<4;dir++){\n            int maxd=max_expand_delta(v,id,dir);\n            if(maxd<=0) continue;\n            int len=(dir<2?cur.d-cur.b:cur.c-cur.a);\n            vector<int> ds;\n            long long need=rs[id]-A;\n            if(need>0){\n                long long q=need/len;\n                for(long long z:{q-2,q-1,q,q+1,q+2})\n                    if(1<=z&&z<=maxd) ds.push_back((int)z);\n            }\n            ds.push_back(1); ds.push_back(maxd);\n            sort(ds.begin(),ds.end());\n            ds.erase(unique(ds.begin(),ds.end()),ds.end());\n\n            for(int d:ds){\n                Rect nr=cur;\n                if(dir==0) nr.a-=d;\n                if(dir==1) nr.c+=d;\n                if(dir==2) nr.b-=d;\n                if(dir==3) nr.d+=d;\n                double g=sc_area(area(nr),rs[id])-old;\n                if(g>bg){ bg=g; best=nr; }\n            }\n        }\n\n        if(bg>1e-14){ v[id]=best; moved=true; }\n    }\n    return moved;\n}\n\nbool steal_pass(vector<Rect>& v,bool rnd,double deadline,bool ext=false){\n    vector<int> ord(n); iota(ord.begin(),ord.end(),0);\n    if(rnd) shuffle(ord.begin(),ord.end(),rng);\n    bool moved=false;\n\n    for(int id:ord){\n        if(timer_.elapsed()>deadline) break;\n        Rect r=v[id];\n        long long Ai=area(r);\n        double oldi=sc_area(Ai,rs[id]);\n        int bestDir=-1,bestD=0;\n        double bestG=1e-13;\n\n        for(int dir=0;dir<4;dir++){\n            vector<Blocker> bs;\n            int maxD;\n            int lenI=(dir<2?r.d-r.b:r.c-r.a);\n\n            auto add_block=[&](int j,int gap,int lim){\n                int cap=(lim>=gap?lim:gap);\n                bs.push_back({j,gap,lim});\n                maxD=min(maxD,cap);\n            };\n\n            if(dir==0){\n                maxD=r.a;\n                for(int j=0;j<n;j++) if(j!=id){\n                    const auto& o=v[j];\n                    if(ov1(r.b,r.d,o.b,o.d)&&o.c<=r.a)\n                        add_block(j,r.a-o.c,r.a-(xs[j]+1));\n                }\n            }else if(dir==1){\n                maxD=10000-r.c;\n                for(int j=0;j<n;j++) if(j!=id){\n                    const auto& o=v[j];\n                    if(ov1(r.b,r.d,o.b,o.d)&&o.a>=r.c)\n                        add_block(j,o.a-r.c,xs[j]-r.c);\n                }\n            }else if(dir==2){\n                maxD=r.b;\n                for(int j=0;j<n;j++) if(j!=id){\n                    const auto& o=v[j];\n                    if(ov1(r.a,r.c,o.a,o.c)&&o.d<=r.b)\n                        add_block(j,r.b-o.d,r.b-(ys[j]+1));\n                }\n            }else{\n                maxD=10000-r.d;\n                for(int j=0;j<n;j++) if(j!=id){\n                    const auto& o=v[j];\n                    if(ov1(r.a,r.c,o.a,o.c)&&o.b>=r.d)\n                        add_block(j,o.b-r.d,ys[j]-r.d);\n                }\n            }\n\n            if(maxD<=0) continue;\n            vector<int> cand;\n\n            auto add1=[&](long long x){\n                if(1<=x&&x<=maxD) cand.push_back((int)x);\n            };\n            auto near=[&](long long x){\n                for(long long y:{x-3,x-2,x-1,x,x+1,x+2,x+3}) add1(y);\n            };\n\n            add1(1); add1(maxD); add1(maxD/2); add1(maxD/3); add1(2LL*maxD/3);\n            if(ext){\n                for(int k=1;k<8;k++) add1(1LL*maxD*k/8);\n                for(int t=0;t<8;t++) add1(uniform_int_distribution<int>(1,maxD)(rng));\n            }\n\n            long long need=rs[id]-Ai;\n            if(need>0) near(need/lenI);\n\n            for(auto bl:bs){\n                add1(bl.gap); add1(bl.gap+1); add1(bl.lim);\n                if(ext){\n                    for(int z=-8;z<=8;z++){ add1(bl.gap+z); add1(bl.lim+z); }\n                }\n                int j=bl.id;\n                const auto& o=v[j];\n                int lenJ=(dir<2?o.d-o.b:o.c-o.a);\n                long long Aj=area(o);\n                if(Aj>rs[j]){\n                    long long red=Aj-rs[j];\n                    near(bl.gap+red/lenJ);\n                    if(ext){\n                        near(bl.gap+red/lenJ-8);\n                        near(bl.gap+red/lenJ+8);\n                    }\n                }\n            }\n\n            sort(cand.begin(),cand.end());\n            cand.erase(unique(cand.begin(),cand.end()),cand.end());\n\n            for(int d:cand){\n                if(d<=0||d>maxD) continue;\n                bool ok=true;\n                double g=sc_area(Ai+1LL*d*lenI,rs[id])-oldi;\n\n                for(auto bl:bs){\n                    if(d<=bl.gap) continue;\n                    if(d>bl.lim){ ok=false; break; }\n                    int j=bl.id;\n                    const auto& o=v[j];\n                    long long Aj=area(o);\n                    int lenJ=(dir<2?o.d-o.b:o.c-o.a);\n                    long long nAj=Aj-1LL*(d-bl.gap)*lenJ;\n                    g+=sc_area(nAj,rs[j])-sc_area(Aj,rs[j]);\n                }\n\n                if(ok&&g>bestG){ bestG=g; bestDir=dir; bestD=d; }\n            }\n        }\n\n        if(bestDir!=-1){\n            Rect old=v[id];\n            if(bestDir==0) v[id].a-=bestD;\n            if(bestDir==1) v[id].c+=bestD;\n            if(bestDir==2) v[id].b-=bestD;\n            if(bestDir==3) v[id].d+=bestD;\n\n            for(int j=0;j<n;j++) if(j!=id){\n                Rect& o=v[j];\n                if(bestDir==0){\n                    if(ov1(old.b,old.d,o.b,o.d)&&o.c<=old.a){\n                        int gap=old.a-o.c;\n                        if(bestD>gap) o.c=old.a-bestD;\n                    }\n                }else if(bestDir==1){\n                    if(ov1(old.b,old.d,o.b,o.d)&&o.a>=old.c){\n                        int gap=o.a-old.c;\n                        if(bestD>gap) o.a=old.c+bestD;\n                    }\n                }else if(bestDir==2){\n                    if(ov1(old.a,old.c,o.a,o.c)&&o.d<=old.b){\n                        int gap=old.b-o.d;\n                        if(bestD>gap) o.d=old.b-bestD;\n                    }\n                }else{\n                    if(ov1(old.a,old.c,o.a,o.c)&&o.b>=old.d){\n                        int gap=o.b-old.d;\n                        if(bestD>gap) o.b=old.d+bestD;\n                    }\n                }\n            }\n            moved=true;\n        }\n    }\n    return moved;\n}\n\n/* ---------- slide / sacrifice escapes ---------- */\n\nint max_slide_delta(const vector<Rect>& v,int id,int dir){\n    const Rect& r=v[id];\n    int lim=0;\n    if(dir==0){\n        lim=min(r.a,r.c-(xs[id]+1));\n        for(int j=0;j<n;j++) if(j!=id){\n            const auto& o=v[j];\n            if(ov1(r.b,r.d,o.b,o.d)&&o.c<=r.a) lim=min(lim,r.a-o.c);\n        }\n    }else if(dir==1){\n        lim=min(10000-r.c,xs[id]-r.a);\n        for(int j=0;j<n;j++) if(j!=id){\n            const auto& o=v[j];\n            if(ov1(r.b,r.d,o.b,o.d)&&o.a>=r.c) lim=min(lim,o.a-r.c);\n        }\n    }else if(dir==2){\n        lim=min(r.b,r.d-(ys[id]+1));\n        for(int j=0;j<n;j++) if(j!=id){\n            const auto& o=v[j];\n            if(ov1(r.a,r.c,o.a,o.c)&&o.d<=r.b) lim=min(lim,r.b-o.d);\n        }\n    }else{\n        lim=min(10000-r.d,ys[id]-r.b);\n        for(int j=0;j<n;j++) if(j!=id){\n            const auto& o=v[j];\n            if(ov1(r.a,r.c,o.a,o.c)&&o.b>=r.d) lim=min(lim,o.b-r.d);\n        }\n    }\n    return max(0,lim);\n}\n\ndouble side_need(const vector<Rect>& v,int id,int side){\n    const Rect& r=v[id];\n    double best=0;\n    for(int j=0;j<n;j++) if(j!=id){\n        const auto& o=v[j];\n        bool near=false;\n        if(side==0) near=ov1(r.b,r.d,o.b,o.d)&&o.c<=r.a;\n        if(side==1) near=ov1(r.b,r.d,o.b,o.d)&&o.a>=r.c;\n        if(side==2) near=ov1(r.a,r.c,o.a,o.c)&&o.d<=r.b;\n        if(side==3) near=ov1(r.a,r.c,o.a,o.c)&&o.b>=r.d;\n        if(!near) continue;\n        long long A=area(o);\n        if(A<rs[j]) best=max(best,(double)(rs[j]-A)/(double)rs[j]);\n    }\n    return best;\n}\n\nbool apply_slide(Rect& r,int dir,int d){\n    if(dir==0){ r.a-=d; r.c-=d; }\n    if(dir==1){ r.a+=d; r.c+=d; }\n    if(dir==2){ r.b-=d; r.d-=d; }\n    if(dir==3){ r.b+=d; r.d+=d; }\n    return true;\n}\n\nbool slide_pass(vector<Rect>& v,double deadline){\n    vector<int> ord(n); iota(ord.begin(),ord.end(),0);\n    shuffle(ord.begin(),ord.end(),rng);\n    bool moved=false;\n\n    for(int id:ord){\n        if(timer_.elapsed()>deadline) break;\n        int bd=-1, bestD=0;\n        double bv=0;\n\n        for(int dir=0;dir<4;dir++){\n            int md=max_slide_delta(v,id,dir);\n            if(md<=0) continue;\n            int side=(dir==0?1:dir==1?0:dir==2?3:2);\n            double need=side_need(v,id,side);\n            double val=need*sqrt((double)md+1.0)+uniform_real_distribution<double>(0.0,0.02)(rng);\n            if(val>bv){\n                bv=val; bd=dir;\n                bestD = need>0 ? max(1,min(md,(int)(md*0.75)+1))\n                               : uniform_int_distribution<int>(1,md)(rng);\n            }\n        }\n\n        if(bd!=-1&&bestD>0){\n            apply_slide(v[id],bd,bestD);\n            moved=true;\n        }\n    }\n    return moved;\n}\n\nbool slide_one_pass(vector<Rect>& v,double deadline){\n    if(timer_.elapsed()>deadline) return false;\n\n    int bestId=-1,bestDir=-1,bestD=0;\n    double bestVal=0.0;\n\n    vector<int> ord(n);\n    iota(ord.begin(),ord.end(),0);\n    shuffle(ord.begin(),ord.end(),rng);\n\n    for(int id:ord){\n        if(timer_.elapsed()>deadline) break;\n\n        for(int dir=0;dir<4;dir++){\n            int md=max_slide_delta(v,id,dir);\n            if(md<=0) continue;\n\n            int side=(dir==0?1:dir==1?0:dir==2?3:2);\n            double need=side_need(v,id,side);\n\n            double val=need*sqrt((double)md+1.0)\n                     + 0.15*sc_area(area(v[id]),rs[id])\n                     + uniform_real_distribution<double>(0.0,0.03)(rng);\n\n            if(val>bestVal){\n                bestVal=val;\n                bestId=id;\n                bestDir=dir;\n\n                if(need>0){\n                    vector<int> cand;\n                    cand.push_back(max(1,min(md,(int)(md*0.50)+1)));\n                    cand.push_back(max(1,min(md,(int)(md*0.75)+1)));\n                    cand.push_back(md);\n                    bestD=cand[uniform_int_distribution<int>(0,(int)cand.size()-1)(rng)];\n                }else{\n                    bestD=uniform_int_distribution<int>(1,md)(rng);\n                }\n            }\n        }\n    }\n\n    if(bestId==-1) return false;\n    apply_slide(v[bestId],bestDir,bestD);\n    return true;\n}\n\nint max_shrink_keep_point(const Rect& r,int id,int dir){\n    if(dir==0) return xs[id]-r.a;\n    if(dir==1) return r.c-(xs[id]+1);\n    if(dir==2) return ys[id]-r.b;\n    return r.d-(ys[id]+1);\n}\n\nbool sacrifice_shrink_one_pass(vector<Rect>& v,double deadline){\n    if(timer_.elapsed()>deadline) return false;\n\n    int bestId=-1,bestDir=-1,bestD=0;\n    double bestVal=-1e100;\n\n    vector<int> ord(n);\n    iota(ord.begin(),ord.end(),0);\n    shuffle(ord.begin(),ord.end(),rng);\n\n    for(int id:ord){\n        if(timer_.elapsed()>deadline) break;\n\n        Rect r=v[id];\n        long long A=area(r);\n        double oldScore=sc_area(A,rs[id]);\n\n        for(int dir=0;dir<4;dir++){\n            int md=max_shrink_keep_point(r,id,dir);\n            if(md<=0) continue;\n\n            int len=(dir<2?r.d-r.b:r.c-r.a);\n            int side=dir; // shrinking this side creates free space on the same side\n            double need=side_need(v,id,side);\n\n            vector<int> ds;\n            auto addd=[&](long long x){\n                if(1<=x&&x<=md) ds.push_back((int)x);\n            };\n\n            addd(1);\n            addd(md);\n            addd(md/2);\n            addd(md/3);\n            addd(2LL*md/3);\n\n            long long excess=A-rs[id];\n            if(excess>0){\n                long long q=excess/max(1,len);\n                for(long long z:{q-2,q-1,q,q+1,q+2}) addd(z);\n            }\n\n            // Small and medium cuts are useful as sacrifices.\n            addd(20);\n            addd(50);\n            addd(100);\n            addd(200);\n            addd(500);\n\n            sort(ds.begin(),ds.end());\n            ds.erase(unique(ds.begin(),ds.end()),ds.end());\n\n            for(int d:ds){\n                Rect nr=r;\n                if(dir==0) nr.a+=d;\n                if(dir==1) nr.c-=d;\n                if(dir==2) nr.b+=d;\n                if(dir==3) nr.d-=d;\n                if(!(nr.a<nr.c&&nr.b<nr.d)) continue;\n\n                double newScore=sc_area(area(nr),rs[id]);\n                double loss=max(0.0,oldScore-newScore);\n                double freeArea=(double)d*(double)len;\n\n                double val =\n                    3.0*need*sqrt(freeArea+1.0)\n                    - 8.0*loss\n                    + 0.08*(oldScore)\n                    + uniform_real_distribution<double>(0.0,0.05)(rng);\n\n                // Prefer not to destroy already bad rectangles too much.\n                if(oldScore<0.90) val-=0.2*loss;\n\n                if(val>bestVal){\n                    bestVal=val;\n                    bestId=id;\n                    bestDir=dir;\n                    bestD=d;\n                }\n            }\n        }\n    }\n\n    if(bestId==-1 || bestD<=0) return false;\n\n    Rect& r=v[bestId];\n    if(bestDir==0) r.a+=bestD;\n    if(bestDir==1) r.c-=bestD;\n    if(bestDir==2) r.b+=bestD;\n    if(bestDir==3) r.d-=bestD;\n\n    return true;\n}\n\n/* ---------- drivers ---------- */\n\nvoid shrink_only(vector<Rect>& v,double dl){\n    for(int it=0;it<20&&timer_.elapsed()<dl;it++)\n        if(!shrink_pass(v,false,dl)) break;\n}\n\nvoid improve(vector<Rect>& v,double dl){\n    for(int it=0;timer_.elapsed()<dl;it++){\n        bool mv=false;\n        mv|=shrink_pass(v,true,dl);\n        mv|=steal_pass(v,true,dl,false);\n        mv|=expand_pass(v,true,dl);\n        if(!mv) break;\n    }\n}\n\nvoid improve_ext(vector<Rect>& v,double dl){\n    for(int it=0;timer_.elapsed()<dl;it++){\n        bool mv=false;\n        mv|=shrink_pass(v,true,dl);\n        mv|=steal_pass(v,true,dl,false);\n        mv|=expand_pass(v,true,dl);\n        if(!mv&&timer_.elapsed()<dl){\n            mv|=steal_pass(v,true,dl,true);\n            if(mv){\n                expand_pass(v,true,dl);\n                shrink_pass(v,true,dl);\n            }\n        }\n        if(!mv) break;\n    }\n}\n\nvoid slide_improve(vector<Rect>& v,double dl){\n    for(int it=0;it<3&&timer_.elapsed()<dl;it++){\n        if(!slide_pass(v,dl)) break;\n        improve_ext(v,dl);\n    }\n}\n\nvoid slide_one_improve(vector<Rect>& v,double dl,int reps){\n    for(int it=0;it<reps&&timer_.elapsed()<dl;it++){\n        if(!slide_one_pass(v,dl)) break;\n        improve_ext(v,dl);\n    }\n}\n\nvoid sacrifice_improve(vector<Rect>& v,double dl,int reps){\n    for(int it=0;it<reps&&timer_.elapsed()<dl;it++){\n        if(!sacrifice_shrink_one_pass(v,dl)) break;\n        improve_ext(v,dl);\n    }\n}\n\nvector<Rect> unit_solution(){\n    vector<Rect> v(n);\n    for(int i=0;i<n;i++) v[i]={xs[i],ys[i],xs[i]+1,ys[i]+1};\n    return v;\n}\n\n/* ---------- main ---------- */\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin>>n;\n    xs.resize(n); ys.resize(n); rs.resize(n);\n    for(int i=0;i<n;i++) cin>>xs[i]>>ys[i]>>rs[i];\n\n    vector<Rect> best=unit_solution();\n    double bestScore=eval(best);\n\n    auto consider=[&](const vector<Rect>& sol){\n        double s=eval(sol);\n        if(s>bestScore){\n            bestScore=s;\n            best=sol;\n        }\n    };\n\n    vector<pair<double,vector<Rect>>> tops;\n    auto insert_top=[&](vector<Rect> sol){\n        double s=eval(sol);\n        tops.push_back({s,sol});\n        sort(tops.begin(),tops.end(),[](auto& p,auto& q){return p.first>q.first;});\n        if((int)tops.size()>8) tops.pop_back();\n        consider(sol);\n    };\n\n    int cnt=0;\n    while(timer_.elapsed()<2.85){\n        int topK;\n        if(cnt==0) topK=1;\n        else if(cnt%5==0) topK=3;\n        else if(cnt%5==1) topK=5;\n        else topK=10;\n\n        double noise=0;\n        if(cnt>0){\n            if(cnt%3==0) noise=0.06;\n            else if(cnt%3==1) noise=0.10;\n            else noise=0.14;\n        }\n\n        auto sol=build_slicing(topK,noise);\n        shrink_only(sol,2.85);\n        insert_top(sol);\n        cnt++;\n    }\n\n    sort(tops.begin(),tops.end(),[](auto& p,auto& q){return p.first>q.first;});\n\n    int m=tops.size();\n    for(int i=0;i<m&&timer_.elapsed()<4.76;i++){\n        auto sol=tops[i].second;\n        double rem=4.76-timer_.elapsed();\n        double dl=timer_.elapsed()+rem/max(1,m-i);\n        improve(sol,dl);\n        consider(sol);\n    }\n\n    if(timer_.elapsed()<4.90){\n        auto sol=unit_solution();\n        improve(sol,4.90);\n        consider(sol);\n    }\n\n    if(timer_.elapsed()<4.955){\n        auto sol=best;\n        improve(sol,4.955);\n        consider(sol);\n    }\n\n    if(timer_.elapsed()<4.965){\n        auto sol=best;\n        improve_ext(sol,4.965);\n        consider(sol);\n    }\n\n    // Final escape trials. All are copy-based and accepted only by full evaluation.\n    int trial=0;\n    while(timer_.elapsed()<4.992){\n        auto sol=best;\n        double dl=min(4.992, timer_.elapsed()+0.0075);\n\n        if(trial%6==0 || trial%6==1){\n            slide_improve(sol,dl);\n        }else if(trial%6==2){\n            slide_one_improve(sol,dl,1);\n        }else if(trial%6==3){\n            slide_one_improve(sol,dl,2);\n        }else if(trial%6==4){\n            sacrifice_improve(sol,dl,1);\n        }else{\n            sacrifice_improve(sol,dl,1);\n            if(timer_.elapsed()<dl) slide_one_improve(sol,dl,1);\n        }\n\n        consider(sol);\n        trial++;\n    }\n\n    for(int i=0;i<n;i++){\n        cout<<best[i].a<<' '<<best[i].b<<' '<<best[i].c<<' '<<best[i].d<<\"\\n\";\n    }\n    return 0;\n}","ahc002":"#pragma GCC optimize(\"O3\")\n#pragma GCC optimize(\"unroll-loops\")\n\n#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 50;\nconstexpr int V = N * N;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Path {\n    int score = 0;\n    vector<int> cells;\n    string moves;\n};\n\nstruct Params {\n    double wp;\n    double wd;\n    double w1;\n    double w2;\n    double noise;\n    double randomMoveProb;\n};\n\nint si, sj;\nint tile_id[V];\nint point_val[V];\nint nb[V][4];\nchar nb_dir[V][4];\n\nPath best_path;\nvector<Path> pool;\n\nParams make_params(XorShift &rng) {\n    Params p;\n    int mode = rng.nextInt(10);\n\n    if (mode == 0) {\n        p = {1.8, 4.0, 0.22, 0.08, 30.0, 0.02};\n    } else if (mode == 1) {\n        p = {1.0, -24.0, 0.12, 0.05, 45.0, 0.03};\n    } else if (mode == 2) {\n        p = {1.2, 8.0, 0.36, 0.11, 55.0, 0.04};\n    } else if (mode == 3) {\n        p = {1.0, 0.0, 0.16, 0.05, 120.0, 0.12};\n    } else if (mode == 4) {\n        p = {0.85, -34.0, 0.07, 0.03, 60.0, 0.04};\n    } else if (mode == 5) {\n        p = {1.0, 18.0, 0.46, 0.15, 45.0, 0.02};\n    } else if (mode == 6) {\n        p = {2.4, -8.0, 0.26, 0.08, 40.0, 0.02};\n    } else if (mode == 7) {\n        p = {0.9, 2.0, 0.12, 0.04, 160.0, 0.15};\n    } else if (mode == 8) {\n        p = {1.5, -16.0, 0.28, 0.12, 35.0, 0.02};\n    } else {\n        p = {1.1, 26.0, 0.35, 0.20, 65.0, 0.05};\n    }\n\n    p.wp *= 0.75 + rng.nextDouble() * 0.70;\n    p.wd *= 0.75 + rng.nextDouble() * 0.70;\n    p.w1 *= 0.70 + rng.nextDouble() * 0.80;\n    p.w2 *= 0.70 + rng.nextDouble() * 0.80;\n    p.noise *= 0.70 + rng.nextDouble() * 0.80;\n\n    return p;\n}\n\ndouble eval_move(\n    int to,\n    const vector<int> &seen,\n    int mark,\n    const Params &par,\n    XorShift &rng\n) {\n    int tid_to = tile_id[to];\n\n    int degree1 = 0;\n    int best_next_point = 0;\n    double best_look2 = 0.0;\n\n    for (int k = 0; k < 4; k++) {\n        int v1 = nb[to][k];\n        if (v1 < 0) continue;\n\n        int tid1 = tile_id[v1];\n        if (tid1 == tid_to) continue;\n        if (seen[tid1] == mark) continue;\n\n        degree1++;\n        best_next_point = max(best_next_point, point_val[v1]);\n\n        int degree2 = 0;\n        int best_p2 = 0;\n\n        for (int l = 0; l < 4; l++) {\n            int v2 = nb[v1][l];\n            if (v2 < 0) continue;\n\n            int tid2 = tile_id[v2];\n            if (tid2 == tid_to || tid2 == tid1) continue;\n            if (seen[tid2] == mark) continue;\n\n            degree2++;\n            best_p2 = max(best_p2, point_val[v2]);\n        }\n\n        double look2 = point_val[v1] + 8.0 * degree2 + 0.25 * best_p2;\n        best_look2 = max(best_look2, look2);\n    }\n\n    double e = 0.0;\n    e += par.wp * point_val[to];\n    e += par.wd * degree1;\n    e += par.w1 * best_next_point;\n    e += par.w2 * best_look2;\n    e += par.noise * (rng.nextDouble() - 0.5);\n\n    return e;\n}\n\nint choose_next(\n    int pos,\n    const vector<int> &seen,\n    int mark,\n    const Params &par,\n    XorShift &rng,\n    char &out_dir\n) {\n    int cand[4];\n    char cdir[4];\n    int cnt = 0;\n\n    for (int k = 0; k < 4; k++) {\n        int to = nb[pos][k];\n        if (to < 0) continue;\n\n        int tid = tile_id[to];\n        if (seen[tid] == mark) continue;\n\n        cand[cnt] = to;\n        cdir[cnt] = nb_dir[pos][k];\n        cnt++;\n    }\n\n    if (cnt == 0) return -1;\n\n    if (cnt == 1) {\n        out_dir = cdir[0];\n        return cand[0];\n    }\n\n    if (rng.nextDouble() < par.randomMoveProb) {\n        int id = rng.nextInt(cnt);\n        out_dir = cdir[id];\n        return cand[id];\n    }\n\n    double best_eval = -1e100;\n    int best_id = 0;\n\n    for (int i = 0; i < cnt; i++) {\n        double e = eval_move(cand[i], seen, mark, par, rng);\n        if (e > best_eval) {\n            best_eval = e;\n            best_id = i;\n        }\n    }\n\n    out_dir = cdir[best_id];\n    return cand[best_id];\n}\n\nvoid consider_path(const Path &p) {\n    if (p.score > best_path.score) {\n        best_path = p;\n    }\n\n    constexpr int POOL_SIZE = 24;\n\n    if ((int)pool.size() < POOL_SIZE) {\n        pool.push_back(p);\n    } else {\n        int worst = 0;\n        for (int i = 1; i < (int)pool.size(); i++) {\n            if (pool[i].score < pool[worst].score) worst = i;\n        }\n\n        if (p.score > pool[worst].score) {\n            pool[worst] = p;\n        }\n    }\n}\n\nPath build_greedy_from_prefix(\n    const Path *base,\n    int prefix_len,\n    vector<int> &seen,\n    int mark,\n    XorShift &rng\n) {\n    Path cur;\n    cur.cells.reserve(V);\n    cur.moves.reserve(V);\n\n    if (base == nullptr) {\n        int st = si * N + sj;\n        cur.cells.push_back(st);\n        cur.score = point_val[st];\n        seen[tile_id[st]] = mark;\n    } else {\n        prefix_len = max(prefix_len, 1);\n        prefix_len = min(prefix_len, (int)base->cells.size());\n\n        cur.cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n        cur.moves.assign(base->moves.begin(), base->moves.begin() + prefix_len - 1);\n\n        cur.score = 0;\n        for (int c : cur.cells) {\n            cur.score += point_val[c];\n            seen[tile_id[c]] = mark;\n        }\n    }\n\n    Params par = make_params(rng);\n\n    while (true) {\n        int pos = cur.cells.back();\n        char d = '?';\n        int nxt = choose_next(pos, seen, mark, par, rng, d);\n\n        if (nxt < 0) break;\n\n        seen[tile_id[nxt]] = mark;\n        cur.cells.push_back(nxt);\n        cur.moves.push_back(d);\n        cur.score += point_val[nxt];\n    }\n\n    return cur;\n}\n\nint select_prefix_len(const Path &p, XorShift &rng) {\n    int L = (int)p.cells.size();\n    if (L <= 1) return 1;\n\n    double u = rng.nextDouble();\n    double x;\n    int typ = rng.nextInt(100);\n\n    if (typ < 45) {\n        x = sqrt(u);\n    } else if (typ < 75) {\n        x = u;\n    } else if (typ < 92) {\n        x = u * u;\n    } else {\n        x = 0.82 + 0.18 * u;\n    }\n\n    int prefix_len = 1 + (int)(x * (L - 1));\n    prefix_len = min(prefix_len, L - 1);\n    prefix_len = max(prefix_len, 1);\n    return prefix_len;\n}\n\nstruct DFSSearcher {\n    vector<int> &seen;\n    int mark;\n    XorShift &rng;\n    Timer &timer;\n    double time_limit;\n    Params par;\n\n    vector<int> cur_cells;\n    string cur_moves;\n\n    int nodes = 0;\n    int node_limit = 50000;\n\n    DFSSearcher(\n        vector<int> &seen_,\n        int mark_,\n        XorShift &rng_,\n        Timer &timer_,\n        double time_limit_\n    )\n        : seen(seen_),\n          mark(mark_),\n          rng(rng_),\n          timer(timer_),\n          time_limit(time_limit_) {\n        par = make_params(rng);\n        par.noise *= 0.45;\n        par.randomMoveProb = 0.0;\n    }\n\n    bool time_or_budget_over() {\n        if ((nodes & 2047) == 0) {\n            if (timer.elapsed() > time_limit) return true;\n        }\n        return nodes >= node_limit;\n    }\n\n    bool dfs(int pos, int score) {\n        nodes++;\n\n        if (score > best_path.score) {\n            best_path.score = score;\n            best_path.cells = cur_cells;\n            best_path.moves = cur_moves;\n        }\n\n        if (time_or_budget_over()) return true;\n\n        struct Cand {\n            int to;\n            char dir;\n            double e;\n        };\n\n        Cand cand[4];\n        int cnt = 0;\n\n        for (int k = 0; k < 4; k++) {\n            int to = nb[pos][k];\n            if (to < 0) continue;\n\n            int tid = tile_id[to];\n            if (seen[tid] == mark) continue;\n\n            cand[cnt++] = {to, nb_dir[pos][k], eval_move(to, seen, mark, par, rng)};\n        }\n\n        if (cnt == 0) return false;\n\n        sort(cand, cand + cnt, [](const Cand &a, const Cand &b) {\n            return a.e > b.e;\n        });\n\n        if (cnt >= 2 && rng.nextInt(100) < 18) {\n            swap(cand[0], cand[rng.nextInt(cnt)]);\n        }\n\n        for (int i = 0; i < cnt; i++) {\n            int to = cand[i].to;\n            int tid = tile_id[to];\n\n            seen[tid] = mark;\n            cur_cells.push_back(to);\n            cur_moves.push_back(cand[i].dir);\n\n            bool stop = dfs(to, score + point_val[to]);\n\n            cur_moves.pop_back();\n            cur_cells.pop_back();\n            seen[tid] = 0;\n\n            if (stop) return true;\n        }\n\n        return false;\n    }\n\n    void run_from_prefix(const Path *base, int prefix_len) {\n        cur_cells.clear();\n        cur_moves.clear();\n        cur_cells.reserve(V);\n        cur_moves.reserve(V);\n\n        int score = 0;\n\n        if (base == nullptr) {\n            int st = si * N + sj;\n            cur_cells.push_back(st);\n            score = point_val[st];\n            seen[tile_id[st]] = mark;\n        } else {\n            prefix_len = max(prefix_len, 1);\n            prefix_len = min(prefix_len, (int)base->cells.size());\n\n            cur_cells.assign(base->cells.begin(), base->cells.begin() + prefix_len);\n            cur_moves.assign(base->moves.begin(), base->moves.begin() + prefix_len - 1);\n\n            for (int c : cur_cells) {\n                score += point_val[c];\n                seen[tile_id[c]] = mark;\n            }\n        }\n\n        if (score > best_path.score) {\n            best_path.score = score;\n            best_path.cells = cur_cells;\n            best_path.moves = cur_moves;\n        }\n\n        dfs(cur_cells.back(), score);\n    }\n};\n\nchar dir_between(int a, int b) {\n    int ai = a / N, aj = a % N;\n    int bi = b / N, bj = b % N;\n\n    if (bi == ai - 1 && bj == aj) return 'U';\n    if (bi == ai + 1 && bj == aj) return 'D';\n    if (bi == ai && bj == aj - 1) return 'L';\n    return 'R';\n}\n\nvoid rebuild_moves(Path &p) {\n    p.moves.clear();\n    p.moves.reserve(p.cells.size());\n\n    for (int i = 0; i + 1 < (int)p.cells.size(); i++) {\n        p.moves.push_back(dir_between(p.cells[i], p.cells[i + 1]));\n    }\n}\n\nstruct DetourSolver {\n    vector<unsigned char> &used_tile;\n    Timer &timer;\n    double limit;\n    int target;\n    int max_depth;\n\n    int cur[8];\n    int best[8];\n    int best_len = 0;\n    int best_score = 0;\n\n    int nodes = 0;\n    bool stopped = false;\n\n    DetourSolver(\n        vector<unsigned char> &used_tile_,\n        Timer &timer_,\n        double limit_,\n        int target_,\n        int max_depth_\n    )\n        : used_tile(used_tile_),\n          timer(timer_),\n          limit(limit_),\n          target(target_),\n          max_depth(max_depth_) {}\n\n    void dfs(int pos, int depth, int score) {\n        nodes++;\n\n        if ((nodes & 511) == 0) {\n            if (timer.elapsed() > limit) {\n                stopped = true;\n                return;\n            }\n        }\n\n        if (score + 99 * (max_depth - depth) <= best_score) return;\n\n        for (int k = 0; k < 4; k++) {\n            int to = nb[pos][k];\n            if (to < 0) continue;\n\n            if (to == target) {\n                if (depth >= 1 && score > best_score) {\n                    best_score = score;\n                    best_len = depth;\n                    for (int i = 0; i < depth; i++) {\n                        best[i] = cur[i];\n                    }\n                }\n                continue;\n            }\n\n            if (depth >= max_depth) continue;\n\n            int tid = tile_id[to];\n            if (used_tile[tid]) continue;\n\n            used_tile[tid] = 1;\n            cur[depth] = to;\n\n            dfs(to, depth + 1, score + point_val[to]);\n\n            used_tile[tid] = 0;\n\n            if (stopped) return;\n        }\n    }\n};\n\nbool find_best_detour_for_edge(\n    int start,\n    int target,\n    vector<unsigned char> &used_tile,\n    int max_intermediate,\n    Timer &timer,\n    double limit,\n    vector<int> &best_nodes,\n    int &best_score\n) {\n    DetourSolver solver(used_tile, timer, limit, target, max_intermediate);\n    solver.dfs(start, 0, 0);\n\n    best_score = solver.best_score;\n    best_nodes.clear();\n    best_nodes.reserve(solver.best_len);\n\n    for (int i = 0; i < solver.best_len; i++) {\n        best_nodes.push_back(solver.best[i]);\n    }\n\n    return best_score > 0;\n}\n\nvoid improve_by_detour_insertion(\n    Path &p,\n    int max_tid,\n    Timer &timer,\n    double limit\n) {\n    vector<unsigned char> used_tile(max_tid + 1, 0);\n\n    for (int c : p.cells) {\n        used_tile[tile_id[c]] = 1;\n    }\n\n    constexpr int MAX_INTERMEDIATE = 5;\n\n    while (timer.elapsed() < limit) {\n        int best_edge = -1;\n        int best_add_score = 0;\n        vector<int> best_insert_nodes;\n\n        int L = (int)p.cells.size();\n\n        for (int i = 0; i + 1 < L; i++) {\n            if ((i & 31) == 0 && timer.elapsed() > limit) break;\n\n            vector<int> cand_nodes;\n            int cand_score = 0;\n\n            find_best_detour_for_edge(\n                p.cells[i],\n                p.cells[i + 1],\n                used_tile,\n                MAX_INTERMEDIATE,\n                timer,\n                limit,\n                cand_nodes,\n                cand_score\n            );\n\n            if (cand_score > best_add_score) {\n                best_add_score = cand_score;\n                best_edge = i;\n                best_insert_nodes = std::move(cand_nodes);\n            }\n        }\n\n        if (best_edge < 0 || best_insert_nodes.empty()) break;\n\n        p.cells.insert(\n            p.cells.begin() + best_edge + 1,\n            best_insert_nodes.begin(),\n            best_insert_nodes.end()\n        );\n\n        for (int c : best_insert_nodes) {\n            used_tile[tile_id[c]] = 1;\n            p.score += point_val[c];\n        }\n    }\n\n    rebuild_moves(p);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tid = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n            int id = i * N + j;\n            tile_id[id] = x;\n            max_tid = max(max_tid, x);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> point_val[i * N + j];\n        }\n    }\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    for (int i = 0; i < V; i++) {\n        for (int k = 0; k < 4; k++) {\n            nb[i][k] = -1;\n            nb_dir[i][k] = '?';\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n\n            for (int k = 0; k < 4; k++) {\n                int ni = i + di[k];\n                int nj = j + dj[k];\n\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    nb[id][k] = ni * N + nj;\n                    nb_dir[id][k] = dc[k];\n                }\n            }\n        }\n    }\n\n    uint64_t seed = 123456789;\n    seed ^= (uint64_t)(si * 51 + sj + 1) * 1000003ULL;\n\n    for (int i = 0; i < V; i++) {\n        seed ^= (uint64_t)(tile_id[i] + 1) * 11995408973635179863ULL;\n        seed ^= (uint64_t)(point_val[i] + 7) * 10150724397891781847ULL;\n        seed = seed * 6364136223846793005ULL + 1442695040888963407ULL;\n    }\n\n    XorShift rng(seed);\n    Timer timer;\n\n    vector<int> seen(max_tid + 1, 0);\n    int mark = 1;\n\n    {\n        int st = si * N + sj;\n        best_path.score = point_val[st];\n        best_path.cells = {st};\n        best_path.moves = \"\";\n    }\n\n    const double GREEDY_PHASE = 0.62;\n    const double SEARCH_LIMIT = 1.92;\n    const double FINAL_LIMIT = 1.975;\n\n    // Phase 1: randomized greedy rollouts.\n    while (timer.elapsed() < GREEDY_PHASE) {\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        Path cur;\n\n        bool fresh = pool.empty() || rng.nextInt(100) < 24;\n\n        if (fresh) {\n            cur = build_greedy_from_prefix(nullptr, 0, seen, mark, rng);\n        } else {\n            const Path *base;\n\n            if (rng.nextInt(100) < 68) {\n                base = &best_path;\n            } else {\n                base = &pool[rng.nextInt((int)pool.size())];\n            }\n\n            int prefix_len = select_prefix_len(*base, rng);\n            cur = build_greedy_from_prefix(base, prefix_len, seen, mark, rng);\n        }\n\n        consider_path(cur);\n    }\n\n    // Phase 2: DFS/local tail search from promising prefixes.\n    while (timer.elapsed() < SEARCH_LIMIT) {\n        mark++;\n        if (mark == INT_MAX) {\n            fill(seen.begin(), seen.end(), 0);\n            mark = 1;\n        }\n\n        const Path *base = nullptr;\n        int prefix_len = 1;\n\n        int mode = rng.nextInt(100);\n\n        if (mode < 15 || pool.empty()) {\n            base = nullptr;\n            prefix_len = 1;\n        } else if (mode < 78) {\n            base = &best_path;\n            prefix_len = select_prefix_len(*base, rng);\n        } else {\n            base = &pool[rng.nextInt((int)pool.size())];\n            prefix_len = select_prefix_len(*base, rng);\n        }\n\n        DFSSearcher dfs(seen, mark, rng, timer, SEARCH_LIMIT);\n\n        int L = (base == nullptr ? 1 : (int)base->cells.size());\n\n        if (base != nullptr && prefix_len > L * 3 / 4) {\n            dfs.node_limit = 35000 + rng.nextInt(50000);\n        } else {\n            dfs.node_limit = 18000 + rng.nextInt(45000);\n        }\n\n        dfs.run_from_prefix(base, prefix_len);\n\n        if (rng.nextInt(100) < 25) {\n            consider_path(best_path);\n        }\n    }\n\n    // Phase 3: deterministic safe short-detour insertion.\n    improve_by_detour_insertion(best_path, max_tid, timer, FINAL_LIMIT);\n\n    cout << best_path.moves << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HEDGE = 30 * 29;\nstatic constexpr int VEDGE = 29 * 30;\nstatic constexpr int E = HEDGE + VEDGE;\nstatic constexpr int RCVAR = 60;\nstatic constexpr int SEGVAR = 120;\n\nstatic constexpr double MIN_EDGE = 1000.0;\nstatic constexpr double MAX_EDGE = 9000.0;\n\nstruct Obs {\n    array<int, RCVAR> x;\n    vector<int> edges;\n    long long y;\n};\n\nvector<Obs> observations;\n\ndouble hcost[N], vcost[N];\ndouble edge_est[E];\nint edge_freq[E];\n\nint splitH[N], splitV[N];\ndouble segH[N][2], segV[N][2];\n\nbool edge_ready = false;\nbool seg_ready = false;\n\nuint64_t rng_state = 88172645463325252ull;\n\nuint64_t xorshift() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\ndouble clamp_double(double x, double lo, double hi) {\n    return max(lo, min(hi, x));\n}\n\ndouble clamp_edge(double x) {\n    return clamp_double(x, MIN_EDGE, MAX_EDGE);\n}\n\ndouble observation_weight(int len, long long y) {\n    if (len <= 0) return 0.0;\n\n    double w_len = 400.0 / ((double)len * len);\n\n    double w_y = w_len;\n    if (y > 0) {\n        w_y = 10000000000.0 / ((double)y * (double)y);\n    }\n\n    double w = 0.20 * w_len + 0.80 * w_y;\n    return clamp_double(w, 0.04, 6.0);\n}\n\nint hid(int i, int j) {\n    return i * 29 + j;\n}\n\nint vid(int i, int j) {\n    return HEDGE + i * 30 + j;\n}\n\ndouble base_weight(int id) {\n    if (id < HEDGE) {\n        return hcost[id / 29];\n    } else {\n        int x = id - HEDGE;\n        return vcost[x % 30];\n    }\n}\n\ndouble segment_weight(int id) {\n    if (!seg_ready) return base_weight(id);\n\n    if (id < HEDGE) {\n        int i = id / 29;\n        int j = id % 29;\n        int p = (j < splitH[i] ? 0 : 1);\n        return segH[i][p];\n    } else {\n        int x = id - HEDGE;\n        int i = x / 30;\n        int j = x % 30;\n        int p = (i < splitV[j] ? 0 : 1);\n        return segV[j][p];\n    }\n}\n\ndouble structural_weight(int id) {\n    return segment_weight(id);\n}\n\nvoid solve_row_col_model() {\n    static double a[RCVAR][RCVAR + 1];\n\n    for (int i = 0; i < RCVAR; i++) {\n        for (int j = 0; j <= RCVAR; j++) {\n            a[i][j] = 0.0;\n        }\n    }\n\n    const double lambda = 80.0;\n\n    for (int i = 0; i < RCVAR; i++) {\n        a[i][i] += lambda;\n    }\n\n    for (const auto& ob : observations) {\n        vector<pair<int, int>> nz;\n        int len = 0;\n\n        for (int i = 0; i < RCVAR; i++) {\n            if (ob.x[i]) {\n                nz.push_back({i, ob.x[i]});\n                len += ob.x[i];\n            }\n        }\n\n        if (len == 0) continue;\n\n        double w = observation_weight(len, ob.y);\n        double r = (double)ob.y - 5000.0 * len;\n\n        for (auto [i, xi] : nz) {\n            a[i][RCVAR] += w * xi * r;\n            for (auto [j, xj] : nz) {\n                a[i][j] += w * (double)xi * xj;\n            }\n        }\n    }\n\n    for (int col = 0; col < RCVAR; col++) {\n        int piv = col;\n\n        for (int row = col + 1; row < RCVAR; row++) {\n            if (fabs(a[row][col]) > fabs(a[piv][col])) {\n                piv = row;\n            }\n        }\n\n        if (piv != col) {\n            for (int j = col; j <= RCVAR; j++) {\n                swap(a[piv][j], a[col][j]);\n            }\n        }\n\n        double div = a[col][col];\n        if (fabs(div) < 1e-12) continue;\n\n        for (int j = col; j <= RCVAR; j++) {\n            a[col][j] /= div;\n        }\n\n        for (int row = 0; row < RCVAR; row++) {\n            if (row == col) continue;\n\n            double factor = a[row][col];\n            if (fabs(factor) < 1e-12) continue;\n\n            for (int j = col; j <= RCVAR; j++) {\n                a[row][j] -= factor * a[col][j];\n            }\n        }\n    }\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = clamp_edge(5000.0 + a[i][RCVAR]);\n    }\n\n    for (int j = 0; j < 30; j++) {\n        vcost[j] = clamp_edge(5000.0 + a[30 + j][RCVAR]);\n    }\n}\n\nvoid smooth_edge_est(double strength) {\n    static double nxt[E];\n\n    for (int id = 0; id < E; id++) {\n        nxt[id] = edge_est[id];\n    }\n\n    for (int i = 0; i < 30; i++) {\n        for (int j = 0; j < 29; j++) {\n            int id = hid(i, j);\n\n            double sum = edge_est[id] * 2.0;\n            double den = 2.0;\n\n            if (j > 0) {\n                int nid = hid(i, j - 1);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            if (j + 1 < 29) {\n                int nid = hid(i, j + 1);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            nxt[id] = edge_est[id] * (1.0 - strength) + (sum / den) * strength;\n        }\n    }\n\n    for (int i = 0; i < 29; i++) {\n        for (int j = 0; j < 30; j++) {\n            int id = vid(i, j);\n\n            double sum = edge_est[id] * 2.0;\n            double den = 2.0;\n\n            if (i > 0) {\n                int nid = vid(i - 1, j);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            if (i + 1 < 29) {\n                int nid = vid(i + 1, j);\n                double diff = fabs(edge_est[id] - edge_est[nid]);\n                double w = diff < 2500.0 ? 1.0 : 0.25;\n                sum += edge_est[nid] * w;\n                den += w;\n            }\n\n            nxt[id] = edge_est[id] * (1.0 - strength) + (sum / den) * strength;\n        }\n    }\n\n    for (int id = 0; id < E; id++) {\n        edge_est[id] = clamp_edge(nxt[id]);\n    }\n}\n\nvoid rebuild_edge_model(int turn) {\n    static double prior[E];\n    static double b[E], x[E], r[E], p[E], Ap[E];\n\n    for (int id = 0; id < E; id++) {\n        prior[id] = structural_weight(id);\n        b[id] = 0.0;\n        x[id] = 0.0;\n    }\n\n    vector<double> ws;\n    ws.reserve(observations.size());\n\n    for (const auto& ob : observations) {\n        int len = (int)ob.edges.size();\n\n        if (len == 0) {\n            ws.push_back(0.0);\n            continue;\n        }\n\n        double pred = 0.0;\n        for (int id : ob.edges) {\n            pred += prior[id];\n        }\n\n        double rr = (double)ob.y - pred;\n        double clip = max(4500.0, 0.16 * pred);\n        rr = clamp_double(rr, -clip, clip);\n\n        double w = observation_weight(len, ob.y);\n        ws.push_back(w);\n\n        for (int id : ob.edges) {\n            b[id] += w * rr;\n        }\n    }\n\n    double lambda;\n    if (turn < 250) lambda = 8.0;\n    else if (turn < 700) lambda = 6.0;\n    else lambda = 5.0;\n\n    auto matvec = [&](const double in[E], double out[E]) {\n        for (int id = 0; id < E; id++) {\n            out[id] = lambda * in[id];\n        }\n\n        int m = (int)observations.size();\n\n        for (int oi = 0; oi < m; oi++) {\n            const auto& ob = observations[oi];\n            if (ws[oi] == 0.0) continue;\n\n            double s = 0.0;\n\n            for (int id : ob.edges) {\n                s += in[id];\n            }\n\n            double c = ws[oi] * s;\n\n            for (int id : ob.edges) {\n                out[id] += c;\n            }\n        }\n    };\n\n    for (int id = 0; id < E; id++) {\n        r[id] = b[id];\n        p[id] = r[id];\n    }\n\n    double rsold = 0.0;\n\n    for (int id = 0; id < E; id++) {\n        rsold += r[id] * r[id];\n    }\n\n    int iters;\n    if (turn < 250) iters = 22;\n    else if (turn < 700) iters = 28;\n    else iters = 34;\n\n    for (int it = 0; it < iters; it++) {\n        if (rsold < 1e-7) break;\n\n        matvec(p, Ap);\n\n        double denom = 0.0;\n\n        for (int id = 0; id < E; id++) {\n            denom += p[id] * Ap[id];\n        }\n\n        if (fabs(denom) < 1e-12) break;\n\n        double alpha = rsold / denom;\n\n        for (int id = 0; id < E; id++) {\n            x[id] += alpha * p[id];\n            r[id] -= alpha * Ap[id];\n        }\n\n        double rsnew = 0.0;\n\n        for (int id = 0; id < E; id++) {\n            rsnew += r[id] * r[id];\n        }\n\n        if (rsnew < 1e-7) break;\n\n        double beta = rsnew / rsold;\n\n        for (int id = 0; id < E; id++) {\n            p[id] = r[id] + beta * p[id];\n        }\n\n        rsold = rsnew;\n    }\n\n    for (int id = 0; id < E; id++) {\n        double conf = (double)edge_freq[id] / (double)(edge_freq[id] + 7);\n        double z = x[id] * conf;\n        edge_est[id] = clamp_edge(prior[id] + z);\n    }\n\n    smooth_edge_est(turn < 300 ? 0.035 : 0.020);\n\n    edge_ready = true;\n}\n\nvoid update_splits_from_edge() {\n    for (int i = 0; i < 30; i++) {\n        double best = 1e100;\n        int bestx = 14;\n\n        for (int x = 1; x <= 28; x++) {\n            double sl = 0.0, wl = 0.0;\n            double sr = 0.0, wr = 0.0;\n\n            for (int j = 0; j < 29; j++) {\n                int id = hid(i, j);\n                double w = 0.4 + edge_freq[id];\n\n                if (j < x) {\n                    sl += edge_est[id] * w;\n                    wl += w;\n                } else {\n                    sr += edge_est[id] * w;\n                    wr += w;\n                }\n            }\n\n            double ml = sl / max(1e-9, wl);\n            double mr = sr / max(1e-9, wr);\n\n            double sse = 0.0;\n\n            for (int j = 0; j < 29; j++) {\n                int id = hid(i, j);\n                double w = 0.4 + edge_freq[id];\n                double m = (j < x ? ml : mr);\n                double d = edge_est[id] - m;\n                sse += w * d * d;\n            }\n\n            if (sse < best) {\n                best = sse;\n                bestx = x;\n            }\n        }\n\n        splitH[i] = bestx;\n    }\n\n    for (int j = 0; j < 30; j++) {\n        double best = 1e100;\n        int besty = 14;\n\n        for (int y = 1; y <= 28; y++) {\n            double su = 0.0, wu = 0.0;\n            double sd = 0.0, wd = 0.0;\n\n            for (int i = 0; i < 29; i++) {\n                int id = vid(i, j);\n                double w = 0.4 + edge_freq[id];\n\n                if (i < y) {\n                    su += edge_est[id] * w;\n                    wu += w;\n                } else {\n                    sd += edge_est[id] * w;\n                    wd += w;\n                }\n            }\n\n            double mu = su / max(1e-9, wu);\n            double md = sd / max(1e-9, wd);\n\n            double sse = 0.0;\n\n            for (int i = 0; i < 29; i++) {\n                int id = vid(i, j);\n                double w = 0.4 + edge_freq[id];\n                double m = (i < y ? mu : md);\n                double d = edge_est[id] - m;\n                sse += w * d * d;\n            }\n\n            if (sse < best) {\n                best = sse;\n                besty = y;\n            }\n        }\n\n        splitV[j] = besty;\n    }\n}\n\nint seg_index_from_edge(int id) {\n    if (id < HEDGE) {\n        int i = id / 29;\n        int j = id % 29;\n        int p = (j < splitH[i] ? 0 : 1);\n        return i * 2 + p;\n    } else {\n        int x = id - HEDGE;\n        int i = x / 30;\n        int j = x % 30;\n        int p = (i < splitV[j] ? 0 : 1);\n        return 60 + j * 2 + p;\n    }\n}\n\nvoid solve_segment_model(int turn) {\n    static double a[SEGVAR][SEGVAR + 1];\n\n    for (int i = 0; i < SEGVAR; i++) {\n        for (int j = 0; j <= SEGVAR; j++) {\n            a[i][j] = 0.0;\n        }\n    }\n\n    double lambda = (turn < 300 ? 65.0 : 45.0);\n    double tie = (turn < 300 ? 25.0 : 16.0);\n\n    for (int i = 0; i < 30; i++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = i * 2 + p;\n            double prior = hcost[i] - 5000.0;\n            a[idx][idx] += lambda;\n            a[idx][SEGVAR] += lambda * prior;\n        }\n\n        int a0 = i * 2;\n        int a1 = i * 2 + 1;\n        a[a0][a0] += tie;\n        a[a1][a1] += tie;\n        a[a0][a1] -= tie;\n        a[a1][a0] -= tie;\n    }\n\n    for (int j = 0; j < 30; j++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = 60 + j * 2 + p;\n            double prior = vcost[j] - 5000.0;\n            a[idx][idx] += lambda;\n            a[idx][SEGVAR] += lambda * prior;\n        }\n\n        int a0 = 60 + j * 2;\n        int a1 = 60 + j * 2 + 1;\n        a[a0][a0] += tie;\n        a[a1][a1] += tie;\n        a[a0][a1] -= tie;\n        a[a1][a0] -= tie;\n    }\n\n    static int cnt[SEGVAR];\n\n    for (const auto& ob : observations) {\n        fill(cnt, cnt + SEGVAR, 0);\n\n        int len = (int)ob.edges.size();\n        if (len == 0) continue;\n\n        for (int id : ob.edges) {\n            cnt[seg_index_from_edge(id)]++;\n        }\n\n        vector<pair<int, int>> nz;\n\n        for (int i = 0; i < SEGVAR; i++) {\n            if (cnt[i]) {\n                nz.push_back({i, cnt[i]});\n            }\n        }\n\n        double w = observation_weight(len, ob.y);\n        double r = (double)ob.y - 5000.0 * len;\n\n        for (auto [i, xi] : nz) {\n            a[i][SEGVAR] += w * xi * r;\n            for (auto [j, xj] : nz) {\n                a[i][j] += w * (double)xi * xj;\n            }\n        }\n    }\n\n    for (int col = 0; col < SEGVAR; col++) {\n        int piv = col;\n\n        for (int row = col + 1; row < SEGVAR; row++) {\n            if (fabs(a[row][col]) > fabs(a[piv][col])) {\n                piv = row;\n            }\n        }\n\n        if (piv != col) {\n            for (int j = col; j <= SEGVAR; j++) {\n                swap(a[piv][j], a[col][j]);\n            }\n        }\n\n        double div = a[col][col];\n        if (fabs(div) < 1e-12) continue;\n\n        for (int j = col; j <= SEGVAR; j++) {\n            a[col][j] /= div;\n        }\n\n        for (int row = 0; row < SEGVAR; row++) {\n            if (row == col) continue;\n\n            double factor = a[row][col];\n            if (fabs(factor) < 1e-12) continue;\n\n            for (int j = col; j <= SEGVAR; j++) {\n                a[row][j] -= factor * a[col][j];\n            }\n        }\n    }\n\n    for (int i = 0; i < 30; i++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = i * 2 + p;\n            segH[i][p] = clamp_edge(5000.0 + a[idx][SEGVAR]);\n        }\n    }\n\n    for (int j = 0; j < 30; j++) {\n        for (int p = 0; p < 2; p++) {\n            int idx = 60 + j * 2 + p;\n            segV[j][p] = clamp_edge(5000.0 + a[idx][SEGVAR]);\n        }\n    }\n\n    seg_ready = true;\n}\n\nvoid online_edge_update(long long y, const vector<int>& edges) {\n    if (!edge_ready || edges.empty()) return;\n\n    double pred = 0.0;\n\n    for (int id : edges) {\n        pred += edge_est[id];\n    }\n\n    double err = (double)y - pred;\n    double clip = max(4000.0, 0.12 * pred);\n    err = clamp_double(err, -clip, clip);\n\n    double delta = 0.006 * err / (double)edges.size();\n\n    for (int id : edges) {\n        edge_est[id] += delta;\n        edge_est[id] = clamp_edge(edge_est[id]);\n    }\n}\n\ndouble learned_weight_raw(int id, int turn) {\n    double b = base_weight(id);\n    double s = segment_weight(id);\n\n    double seg_mix = ((double)turn - 80.0) / 420.0;\n    seg_mix = clamp_double(seg_mix, 0.0, 0.84);\n\n    double w = b * (1.0 - seg_mix) + s * seg_mix;\n\n    if (edge_ready) {\n        double edge_mix = ((double)turn - 260.0) / 760.0;\n        edge_mix = clamp_double(edge_mix, 0.0, 0.24);\n        w = w * (1.0 - edge_mix) + edge_est[id] * edge_mix;\n    }\n\n    return clamp_edge(w);\n}\n\ndouble model_weight_for_search(int id, int turn) {\n    double learned = learned_weight_raw(id, turn);\n\n    double rel = ((double)turn - 25.0) / 520.0;\n    rel = clamp_double(rel, 0.0, 1.0);\n\n    double w = 5000.0 * (1.0 - rel) + learned * rel;\n    return clamp_edge(w);\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool horizontal_first) {\n    string res;\n\n    auto add_vertical = [&]() {\n        if (si < ti) {\n            while (si < ti) {\n                res.push_back('D');\n                si++;\n            }\n        } else {\n            while (si > ti) {\n                res.push_back('U');\n                si--;\n            }\n        }\n    };\n\n    auto add_horizontal = [&]() {\n        if (sj < tj) {\n            while (sj < tj) {\n                res.push_back('R');\n                sj++;\n            }\n        } else {\n            while (sj > tj) {\n                res.push_back('L');\n                sj--;\n            }\n        }\n    };\n\n    if (horizontal_first) {\n        add_horizontal();\n        add_vertical();\n    } else {\n        add_vertical();\n        add_horizontal();\n    }\n\n    return res;\n}\n\nvoid extract_features(\n    int si,\n    int sj,\n    const string& path,\n    array<int, RCVAR>& feat,\n    vector<int>& edges\n) {\n    feat.fill(0);\n    edges.clear();\n\n    int i = si;\n    int j = sj;\n\n    for (char c : path) {\n        if (c == 'R') {\n            int id = hid(i, j);\n            edges.push_back(id);\n            feat[i]++;\n            j++;\n        } else if (c == 'L') {\n            int id = hid(i, j - 1);\n            edges.push_back(id);\n            feat[i]++;\n            j--;\n        } else if (c == 'D') {\n            int id = vid(i, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i++;\n        } else {\n            int id = vid(i - 1, j);\n            edges.push_back(id);\n            feat[30 + j]++;\n            i--;\n        }\n    }\n}\n\ndouble estimated_path_cost(int si, int sj, const string& path, int turn) {\n    int i = si;\n    int j = sj;\n    double cost = 0.0;\n\n    for (char c : path) {\n        if (c == 'R') {\n            cost += model_weight_for_search(hid(i, j), turn);\n            j++;\n        } else if (c == 'L') {\n            cost += model_weight_for_search(hid(i, j - 1), turn);\n            j--;\n        } else if (c == 'D') {\n            cost += model_weight_for_search(vid(i, j), turn);\n            i++;\n        } else {\n            cost += model_weight_for_search(vid(i - 1, j), turn);\n            i--;\n        }\n    }\n\n    return cost;\n}\n\nstring choose_early_path(int si, int sj, int ti, int tj, int turn) {\n    string p1 = manhattan_path(si, sj, ti, tj, true);\n    string p2 = manhattan_path(si, sj, ti, tj, false);\n\n    if (p1 == p2) return p1;\n\n    if (turn < 45) {\n        return (xorshift() & 1) ? p1 : p2;\n    }\n\n    double c1 = estimated_path_cost(si, sj, p1, turn);\n    double c2 = estimated_path_cost(si, sj, p2, turn);\n\n    int eps = (turn < 100 ? 18 : 7);\n\n    if ((int)(xorshift() % 100) < eps) {\n        return (c1 < c2) ? p2 : p1;\n    }\n\n    return (c1 < c2) ? p1 : p2;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    const double INF = 1e100;\n\n    vector<double> dist(900, INF);\n    vector<int> parent(900, -1);\n    vector<char> pchar(900, '?');\n\n    auto node = [](int i, int j) {\n        return i * 30 + j;\n    };\n\n    priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;\n\n    int s = node(si, sj);\n    int t = node(ti, tj);\n\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\n        if (d != dist[u]) continue;\n        if (u == t) break;\n\n        int i = u / 30;\n        int j = u % 30;\n\n        auto relax = [&](int ni, int nj, char c, int eid) {\n            int v = node(ni, nj);\n            double nd = d + model_weight_for_search(eid, turn);\n\n            if (nd < dist[v]) {\n                dist[v] = nd;\n                parent[v] = u;\n                pchar[v] = c;\n                pq.push({nd, v});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, 'U', vid(i - 1, j));\n        if (i + 1 < 30) relax(i + 1, j, 'D', vid(i, j));\n        if (j > 0) relax(i, j - 1, 'L', hid(i, j - 1));\n        if (j + 1 < 30) relax(i, j + 1, 'R', hid(i, j));\n    }\n\n    string res;\n    int cur = t;\n\n    while (cur != s) {\n        res.push_back(pchar[cur]);\n        cur = parent[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nbool rebuild_trigger(int turn) {\n    if (turn < 60) return false;\n\n    if (turn < 300) {\n        return turn % 12 == 11;\n    } else if (turn < 800) {\n        return turn % 24 == 23;\n    } else {\n        return turn % 14 == 13;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 30; i++) {\n        hcost[i] = 5000.0;\n        vcost[i] = 5000.0;\n        splitH[i] = 14;\n        splitV[i] = 14;\n\n        segH[i][0] = segH[i][1] = 5000.0;\n        segV[i][0] = segV[i][1] = 5000.0;\n    }\n\n    for (int id = 0; id < E; id++) {\n        edge_est[id] = 5000.0;\n        edge_freq[id] = 0;\n    }\n\n    for (int turn = 0; turn < 1000; turn++) {\n        int si, sj, ti, tj;\n\n        if (!(cin >> si >> sj >> ti >> tj)) {\n            return 0;\n        }\n\n        string path;\n\n        if (turn < 100) {\n            path = choose_early_path(si, sj, ti, tj, turn);\n        } else {\n            path = dijkstra_path(si, sj, ti, tj, turn);\n        }\n\n        array<int, RCVAR> feat;\n        vector<int> edges;\n        extract_features(si, sj, path, feat, edges);\n\n        cout << path << endl;\n        cout.flush();\n\n        long long result;\n\n        if (!(cin >> result)) {\n            return 0;\n        }\n\n        Obs ob;\n        ob.x = feat;\n        ob.edges = edges;\n        ob.y = result;\n        observations.push_back(ob);\n\n        for (int id : edges) {\n            edge_freq[id]++;\n        }\n\n        if (turn < 260 || turn % 5 == 4 || turn >= 850) {\n            solve_row_col_model();\n        }\n\n        if (rebuild_trigger(turn)) {\n            if (turn >= 75 && edge_ready) {\n                update_splits_from_edge();\n                solve_segment_model(turn);\n            }\n\n            rebuild_edge_model(turn);\n        }\n\n        online_edge_update(result, edges);\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int C = 400;\nstatic constexpr int ALPHA = 8;\nstatic constexpr int MAXM = 800;\nstatic constexpr long long BIG = 2000000000LL;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) { return (int)(next() % n); }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstruct Precomp {\n    int M;\n    vector<array<vector<int>, ALPHA>> inc;\n\n    inline int placementCell(int sid, int idx, int p) const {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    }\n\n    void build(const vector<string>& s) {\n        M = (int)s.size();\n        inc.clear();\n        inc.resize(C);\n\n        int reservePerBucket = max(16, M * 2 * 12 / 8 + 20);\n        for (int c = 0; c < C; c++) {\n            for (int ch = 0; ch < ALPHA; ch++) {\n                inc[c][ch].reserve(reservePerBucket);\n            }\n        }\n\n        for (int sid = 0; sid < M; sid++) {\n            int len = (int)s[sid].size();\n            for (int idx = 0; idx < 800; idx++) {\n                int pid = sid * 800 + idx;\n                for (int p = 0; p < len; p++) {\n                    int cell = placementCell(sid, idx, p);\n                    int req = s[sid][p] - 'A';\n                    inc[cell][req].push_back(pid);\n                }\n            }\n        }\n    }\n};\n\nstruct KmerScorer {\n    int maxQ = 2;\n    vector<vector<int>> dense;\n    vector<unordered_map<unsigned long long, int>> sparse;\n    int mult[13] = {0, 0, 1, 2, 5, 12, 30, 80, 200, 500, 1200, 2500, 5000};\n\n    KmerScorer() {\n        dense.resize(13);\n        sparse.resize(13);\n    }\n\n    void build(const vector<string>& s) {\n        maxQ = 2;\n        for (auto& t : s) maxQ = max(maxQ, min(12, (int)t.size()));\n\n        for (int q = 2; q <= min(8, maxQ); q++) {\n            dense[q].assign(1 << (3 * q), 0);\n        }\n\n        for (auto& t : s) {\n            int L = (int)t.size();\n            vector<int> a(L);\n            for (int i = 0; i < L; i++) a[i] = t[i] - 'A';\n\n            for (int q = 2; q <= min(12, L); q++) {\n                for (int l = 0; l + q <= L; l++) {\n                    unsigned long long code = 0;\n                    for (int p = 0; p < q; p++) code = (code << 3) | a[l + p];\n\n                    int w = mult[q];\n                    if (q <= 8) dense[q][(int)code] += w;\n                    else sparse[q][code] += w;\n                }\n            }\n        }\n    }\n\n    inline int getWeight(int q, unsigned long long code) const {\n        if (q <= 8) return dense[q][(int)code];\n        auto it = sparse[q].find(code);\n        if (it == sparse[q].end()) return 0;\n        return it->second;\n    }\n\n    unsigned long long codeWindow(\n        const vector<unsigned char>& board,\n        int i,\n        int j,\n        int dir,\n        int q,\n        int overrideCell = -1,\n        int overrideVal = 0\n    ) const {\n        unsigned long long code = 0;\n        for (int p = 0; p < q; p++) {\n            int ni = i;\n            int nj = j;\n            if (dir == 0) nj = (j + p) % N;\n            else ni = (i + p) % N;\n\n            int cell = ni * N + nj;\n            int v = (cell == overrideCell ? overrideVal : board[cell]);\n            if (v < 0 || v >= 8) return ULLONG_MAX;\n            code = (code << 3) | (unsigned)v;\n        }\n        return code;\n    }\n\n    long long score(const vector<unsigned char>& board) const {\n        long long res = 0;\n        for (int q = 2; q <= maxQ; q++) {\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j < N; j++) {\n                    auto c1 = codeWindow(board, i, j, 0, q);\n                    if (c1 != ULLONG_MAX) res += getWeight(q, c1);\n                    auto c2 = codeWindow(board, i, j, 1, q);\n                    if (c2 != ULLONG_MAX) res += getWeight(q, c2);\n                }\n            }\n        }\n        return res;\n    }\n\n    long long delta(const vector<unsigned char>& board, int cell, int nc) const {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        int i = cell / N;\n        int j = cell % N;\n        long long d = 0;\n\n        for (int q = 2; q <= maxQ; q++) {\n            for (int off = 0; off < q; off++) {\n                int sj = (j - off + N) % N;\n\n                auto oldCode = codeWindow(board, i, sj, 0, q);\n                auto newCode = codeWindow(board, i, sj, 0, q, cell, nc);\n                if (oldCode != ULLONG_MAX) d -= getWeight(q, oldCode);\n                if (newCode != ULLONG_MAX) d += getWeight(q, newCode);\n\n                int si = (i - off + N) % N;\n                oldCode = codeWindow(board, si, j, 1, q);\n                newCode = codeWindow(board, si, j, 1, q, cell, nc);\n                if (oldCode != ULLONG_MAX) d -= getWeight(q, oldCode);\n                if (newCode != ULLONG_MAX) d += getWeight(q, newCode);\n            }\n        }\n\n        return d;\n    }\n};\n\nstruct Evaluator {\n    int M;\n    const vector<string>* ps;\n    const Precomp* pc;\n\n    vector<unsigned char> board;\n    vector<unsigned char> mis;\n    vector<array<unsigned short, 13>> hist;\n    vector<long long> val;\n\n    long long obj = 0;\n    int covered = 0;\n\n    long long nearTable[13] = {\n        0,\n        1000000,\n        300000,\n        100000,\n        30000,\n        10000,\n        3000,\n        1000,\n        300,\n        100,\n        30,\n        10,\n        0\n    };\n\n    Evaluator() {}\n\n    Evaluator(const vector<string>& s, const Precomp& pre, const vector<unsigned char>& _board) {\n        ps = &s;\n        pc = &pre;\n        M = (int)s.size();\n        board = _board;\n        build();\n    }\n\n    inline const string& str(int sid) const {\n        return (*ps)[sid];\n    }\n\n    inline int placementCell(int sid, int idx, int p) const {\n        return pc->placementCell(sid, idx, p);\n    }\n\n    inline long long calcVal(int sid) const {\n        if (hist[sid][0] > 0) return BIG + min<int>(hist[sid][0], 1000);\n        for (int d = 1; d <= 12; d++) {\n            if (hist[sid][d] > 0) return nearTable[d] + min<int>(hist[sid][d], 1000);\n        }\n        return 0;\n    }\n\n    void build() {\n        int P = M * 800;\n\n        mis.assign(P, 0);\n        hist.assign(M, {});\n        val.assign(M, 0);\n\n        for (int sid = 0; sid < M; sid++) {\n            int len = (int)str(sid).size();\n\n            for (int idx = 0; idx < 800; idx++) {\n                int pid = sid * 800 + idx;\n                int mm = 0;\n\n                for (int p = 0; p < len; p++) {\n                    int cell = placementCell(sid, idx, p);\n                    int req = str(sid)[p] - 'A';\n                    if (board[cell] != req) mm++;\n                }\n\n                mis[pid] = (unsigned char)mm;\n                hist[sid][mm]++;\n            }\n        }\n\n        obj = 0;\n        covered = 0;\n\n        for (int sid = 0; sid < M; sid++) {\n            val[sid] = calcVal(sid);\n            obj += val[sid];\n            if (hist[sid][0] > 0) covered++;\n        }\n    }\n\n    inline void processPlacementChange(int pid, int deltaMis, long long& deltaObj) {\n        int sid = pid / 800;\n\n        long long oldVal = val[sid];\n        bool oldCov = hist[sid][0] > 0;\n\n        int oldMis = mis[pid];\n        hist[sid][oldMis]--;\n\n        int nm = oldMis + deltaMis;\n\n        mis[pid] = (unsigned char)nm;\n        hist[sid][nm]++;\n\n        bool newCov = hist[sid][0] > 0;\n\n        if (oldCov && !newCov) covered--;\n        if (!oldCov && newCov) covered++;\n\n        long long newVal = calcVal(sid);\n        val[sid] = newVal;\n        deltaObj += newVal - oldVal;\n    }\n\n    long long applyChange(int cell, int nc) {\n        int oc = board[cell];\n        if (oc == nc) return 0;\n\n        long long deltaObj = 0;\n\n        if (0 <= oc && oc < ALPHA) {\n            for (int pid : pc->inc[cell][oc]) processPlacementChange(pid, +1, deltaObj);\n        }\n\n        if (0 <= nc && nc < ALPHA) {\n            for (int pid : pc->inc[cell][nc]) processPlacementChange(pid, -1, deltaObj);\n        }\n\n        board[cell] = (unsigned char)nc;\n        obj += deltaObj;\n        return deltaObj;\n    }\n\n    int minMismatchOfString(int sid) const {\n        for (int d = 0; d <= 12; d++) {\n            if (hist[sid][d] > 0) return d;\n        }\n        return 13;\n    }\n\n    int bestPlacementIndex(int sid, XorShift& rng) const {\n        int best = 100;\n        int cnt = 0;\n        int bestIdx = 0;\n        int base = sid * 800;\n\n        for (int idx = 0; idx < 800; idx++) {\n            int mm = mis[base + idx];\n\n            if (mm < best) {\n                best = mm;\n                cnt = 1;\n                bestIdx = idx;\n            } else if (mm == best) {\n                cnt++;\n                if (rng.nextInt(cnt) == 0) bestIdx = idx;\n            }\n        }\n\n        return bestIdx;\n    }\n};\n\nstruct BestState {\n    int covered = -1;\n    long long obj = LLONG_MIN;\n    vector<unsigned char> board;\n\n    void update(const Evaluator& ev) {\n        if (ev.covered > covered || (ev.covered == covered && ev.obj > obj)) {\n            covered = ev.covered;\n            obj = ev.obj;\n            board = ev.board;\n        }\n    }\n};\n\nstatic bool containsLinear(const string& a, const string& b) {\n    return a.find(b) != string::npos;\n}\n\nstatic bool containsCyclic20(const string& a, const string& b) {\n    string d = a + a.substr(0, min<int>((int)b.size() - 1, 19));\n    return d.find(b) != string::npos;\n}\n\nstatic bool containsBuild(const string& row, const string& t) {\n    if ((int)row.size() == 20) return containsCyclic20(row, t);\n    return containsLinear(row, t);\n}\n\nstatic string mergeBestString(const string& a, const string& b) {\n    if (a.empty()) return b;\n    if (containsLinear(a, b)) return a;\n    if (containsLinear(b, a) && (int)b.size() <= 20) return b;\n\n    string best = \"\";\n\n    int la = (int)a.size();\n    int lb = (int)b.size();\n\n    for (int ov = min(la, lb); ov >= 0; ov--) {\n        bool ok = true;\n        for (int i = 0; i < ov; i++) {\n            if (a[la - ov + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n\n        if (ok) {\n            string c = a + b.substr(ov);\n            if ((int)c.size() <= 20) best = c;\n            break;\n        }\n    }\n\n    for (int ov = min(la, lb); ov >= 0; ov--) {\n        bool ok = true;\n        for (int i = 0; i < ov; i++) {\n            if (b[lb - ov + i] != a[i]) {\n                ok = false;\n                break;\n            }\n        }\n\n        if (ok) {\n            string c = b + a.substr(ov);\n            if ((int)c.size() <= 20) {\n                if (best.empty() || c.size() < best.size()) best = c;\n            }\n            break;\n        }\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    int inputN, M;\n    cin >> inputN >> M;\n\n    vector<string> s(M);\n    for (int i = 0; i < M; i++) cin >> s[i];\n\n    XorShift rng(123456789);\n\n    auto elapsedSec = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    Precomp pre;\n    pre.build(s);\n\n    KmerScorer ksc;\n    ksc.build(s);\n\n    vector<int> freq(ALPHA, 1);\n    for (auto& t : s) {\n        for (char ch : t) freq[ch - 'A']++;\n    }\n\n    vector<int> pref(ALPHA);\n    pref[0] = freq[0];\n    for (int i = 1; i < ALPHA; i++) pref[i] = pref[i - 1] + freq[i];\n    int fsum = pref.back();\n\n    auto randomChar = [&]() {\n        int r = rng.nextInt(fsum);\n        return (unsigned char)(lower_bound(pref.begin(), pref.end(), r + 1) - pref.begin());\n    };\n\n    auto placementCellRaw = [&](int idx, int p) {\n        int dir = idx / 400;\n        int st = idx % 400;\n        int i = st / N;\n        int j = st % N;\n\n        if (dir == 0) return i * N + ((j + p) % N);\n        else return ((i + p) % N) * N + j;\n    };\n\n    auto conflictOfPlacement = [&](const vector<unsigned char>& b, const string& t, int idx) {\n        int conf = 0;\n        int len = (int)t.size();\n\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            int req = t[p] - 'A';\n            if (b[cell] != req) conf++;\n        }\n\n        return conf;\n    };\n\n    auto stampRaw = [&](vector<unsigned char>& b, const string& t, int idx) {\n        int len = (int)t.size();\n\n        for (int p = 0; p < len; p++) {\n            int cell = placementCellRaw(idx, p);\n            b[cell] = (unsigned char)(t[p] - 'A');\n        }\n    };\n\n    vector<unsigned char> boardStamp(C);\n    for (int i = 0; i < C; i++) boardStamp[i] = randomChar();\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n\n    for (int pass = 0; pass < 6; pass++) {\n        if (pass == 5) {\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return s[a].size() < s[b].size();\n            });\n        } else {\n            shuffle(order.begin(), order.end(), mt19937((unsigned)rng.next()));\n        }\n\n        for (int sid : order) {\n            int bestConf = 100;\n            int bestIdx = 0;\n            int cnt = 0;\n\n            for (int idx = 0; idx < 800; idx++) {\n                int conf = conflictOfPlacement(boardStamp, s[sid], idx);\n\n                if (conf < bestConf) {\n                    bestConf = conf;\n                    bestIdx = idx;\n                    cnt = 1;\n                } else if (conf == bestConf) {\n                    cnt++;\n                    if (rng.nextInt(cnt) == 0) bestIdx = idx;\n                }\n            }\n\n            stampRaw(boardStamp, s[sid], bestIdx);\n        }\n    }\n\n    BestState best;\n\n    auto betterState = [&](int c1, long long o1, int c2, long long o2) {\n        if (c1 != c2) return c1 > c2;\n        return o1 > o2;\n    };\n\n    auto optimizeLineRotations = [&](Evaluator& ev, double endTime, int rounds) {\n        for (int rd = 0; rd < rounds; rd++) {\n            for (int phase = 0; phase < 2; phase++) {\n                for (int line = 0; line < N; line++) {\n                    if (elapsedSec() > endTime) return;\n\n                    vector<unsigned char> orig(N);\n\n                    if (phase == 0) {\n                        for (int j = 0; j < N; j++) orig[j] = ev.board[line * N + j];\n                    } else {\n                        for (int i = 0; i < N; i++) orig[i] = ev.board[i * N + line];\n                    }\n\n                    int bestShift = 0;\n                    int bestCov = ev.covered;\n                    long long bestObj = ev.obj;\n\n                    auto applyShift = [&](int sh) {\n                        if (phase == 0) {\n                            int r = line;\n                            for (int j = 0; j < N; j++) {\n                                int v = orig[(j + sh) % N];\n                                ev.applyChange(r * N + j, v);\n                            }\n                        } else {\n                            int c = line;\n                            for (int i = 0; i < N; i++) {\n                                int v = orig[(i + sh) % N];\n                                ev.applyChange(i * N + c, v);\n                            }\n                        }\n                    };\n\n                    for (int sh = 1; sh < N; sh++) {\n                        applyShift(sh);\n\n                        if (betterState(ev.covered, ev.obj, bestCov, bestObj)) {\n                            bestCov = ev.covered;\n                            bestObj = ev.obj;\n                            bestShift = sh;\n                        }\n                    }\n\n                    applyShift(bestShift);\n                }\n            }\n        }\n    };\n\n    auto optimizeLineSwaps = [&](Evaluator& ev, double endTime, int rounds) {\n        for (int rd = 0; rd < rounds; rd++) {\n            for (int phase = 0; phase < 2; phase++) {\n                for (int a = 0; a < N; a++) {\n                    for (int b = a + 1; b < N; b++) {\n                        if (elapsedSec() > endTime) return;\n\n                        vector<unsigned char> va(N), vb(N);\n\n                        if (phase == 0) {\n                            for (int j = 0; j < N; j++) {\n                                va[j] = ev.board[a * N + j];\n                                vb[j] = ev.board[b * N + j];\n                            }\n                            for (int j = 0; j < N; j++) {\n                                ev.applyChange(a * N + j, vb[j]);\n                                ev.applyChange(b * N + j, va[j]);\n                            }\n                        } else {\n                            for (int i = 0; i < N; i++) {\n                                va[i] = ev.board[i * N + a];\n                                vb[i] = ev.board[i * N + b];\n                            }\n                            for (int i = 0; i < N; i++) {\n                                ev.applyChange(i * N + a, vb[i]);\n                                ev.applyChange(i * N + b, va[i]);\n                            }\n                        }\n\n                        int afterCov = ev.covered;\n                        long long afterObj = ev.obj;\n\n                        if (phase == 0) {\n                            for (int j = 0; j < N; j++) {\n                                ev.applyChange(a * N + j, va[j]);\n                                ev.applyChange(b * N + j, vb[j]);\n                            }\n                        } else {\n                            for (int i = 0; i < N; i++) {\n                                ev.applyChange(i * N + a, va[i]);\n                                ev.applyChange(i * N + b, vb[i]);\n                            }\n                        }\n\n                        int beforeCov = ev.covered;\n                        long long beforeObj = ev.obj;\n\n                        if (betterState(afterCov, afterObj, beforeCov, beforeObj)) {\n                            if (phase == 0) {\n                                for (int j = 0; j < N; j++) {\n                                    ev.applyChange(a * N + j, vb[j]);\n                                    ev.applyChange(b * N + j, va[j]);\n                                }\n                            } else {\n                                for (int i = 0; i < N; i++) {\n                                    ev.applyChange(i * N + a, vb[i]);\n                                    ev.applyChange(i * N + b, va[i]);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    };\n\n    auto makeRowPackBoard = [&](int mode, uint64_t seed) {\n        XorShift rr(seed);\n        vector<unsigned char> b(C, 0);\n\n        auto randomCharLocal = [&]() {\n            int r = rr.nextInt(fsum);\n            return (unsigned char)(lower_bound(pref.begin(), pref.end(), r + 1) - pref.begin());\n        };\n\n        auto lineScore = [&](const string& row, const vector<int>& baseCovered) {\n            int sc = 0;\n            for (int sid = 0; sid < M; sid++) {\n                if (!baseCovered[sid] && containsCyclic20(row, s[sid])) sc++;\n            }\n            return sc;\n        };\n\n        auto improveFillerOnly = [&](string row, int fixedLen, const vector<int>& baseCovered) {\n            if (fixedLen >= 20) return row;\n\n            int curScore = lineScore(row, baseCovered);\n\n            for (int rd = 0; rd < 2; rd++) {\n                bool any = false;\n\n                for (int pos = fixedLen; pos < 20; pos++) {\n                    char old = row[pos];\n                    int bestCh = old - 'A';\n                    int bestScore = curScore;\n\n                    for (int ch = 0; ch < ALPHA; ch++) {\n                        if (ch == old - 'A') continue;\n\n                        row[pos] = char('A' + ch);\n                        int sc = lineScore(row, baseCovered);\n\n                        if (sc > bestScore) {\n                            bestScore = sc;\n                            bestCh = ch;\n                        }\n                    }\n\n                    row[pos] = old;\n\n                    if (bestScore > curScore) {\n                        row[pos] = char('A' + bestCh);\n                        curScore = bestScore;\n                        any = true;\n                    }\n                }\n\n                if (!any) break;\n            }\n\n            return row;\n        };\n\n        vector<int> covered(M, 0);\n\n        for (int row = 0; row < N; row++) {\n            vector<int> baseCovered = covered;\n            string cur;\n\n            while ((int)cur.size() < 20) {\n                int bestSid = -1;\n                string bestMerged;\n                int bestScore = INT_MIN;\n\n                for (int sid = 0; sid < M; sid++) {\n                    if (covered[sid]) continue;\n\n                    string merged = mergeBestString(cur, s[sid]);\n                    if (merged.empty()) continue;\n                    if ((int)merged.size() > 20) continue;\n\n                    int add = (int)merged.size() - (int)cur.size();\n\n                    int gain = 1;\n                    if (mode >= 1) {\n                        gain = 0;\n                        int checked = 0;\n                        int lim = (mode == 3 ? 260 : 150);\n                        int step = 37 + mode * 6;\n\n                        for (int tid = 0; tid < M && checked < lim; tid++) {\n                            int id = (tid * step + row * 17 + mode * 101 + rr.nextInt(3)) % M;\n                            if (covered[id]) continue;\n                            checked++;\n                            if (containsBuild(merged, s[id])) gain++;\n                        }\n\n                        gain = max(gain, 1);\n                    }\n\n                    int overlap = (int)s[sid].size() - add;\n                    int score = 0;\n\n                    if (mode == 0) {\n                        score = (int)s[sid].size() * 100 / (add + 1);\n                    } else if (mode == 1) {\n                        score = gain * 1200 + (int)s[sid].size() * 40 - add * 35;\n                    } else if (mode == 2) {\n                        score = gain * 1000 + (int)s[sid].size() * 120 / (add + 1) + rr.nextInt(80);\n                    } else if (mode == 3) {\n                        score = gain * 1600 + overlap * 220 + (int)s[sid].size() * 20 - add * 30;\n                    } else if (mode == 4) {\n                        score = gain * 1100 + overlap * 350 + rr.nextInt(250);\n                    } else {\n                        score = gain * 900 + (int)s[sid].size() * 80 - add * 20 + rr.nextInt(700);\n                    }\n\n                    if (score > bestScore || (score == bestScore && rr.nextInt(2) == 0)) {\n                        bestScore = score;\n                        bestSid = sid;\n                        bestMerged = merged;\n                    }\n                }\n\n                if (bestSid == -1) break;\n\n                cur = bestMerged;\n\n                for (int sid = 0; sid < M; sid++) {\n                    if (!covered[sid] && containsBuild(cur, s[sid])) covered[sid] = 1;\n                }\n            }\n\n            int fixedLen = (int)cur.size();\n\n            while ((int)cur.size() < 20) {\n                cur.push_back(char('A' + randomCharLocal()));\n            }\n\n            cur = improveFillerOnly(cur, fixedLen, baseCovered);\n\n            for (int sid = 0; sid < M; sid++) {\n                if (!covered[sid] && containsCyclic20(cur, s[sid])) covered[sid] = 1;\n            }\n\n            for (int j = 0; j < N; j++) {\n                b[row * N + j] = (unsigned char)(cur[j] - 'A');\n            }\n        }\n\n        return b;\n    };\n\n    auto makeSetCoverRowsBoard = [&](const vector<vector<unsigned char>>& boards) {\n        vector<string> rows;\n\n        for (auto& b : boards) {\n            for (int i = 0; i < N; i++) {\n                string row;\n                for (int j = 0; j < N; j++) row.push_back(char('A' + b[i * N + j]));\n                rows.push_back(row);\n            }\n        }\n\n        int R = (int)rows.size();\n        vector<bitset<MAXM>> masks(R);\n\n        for (int r = 0; r < R; r++) {\n            for (int sid = 0; sid < M; sid++) {\n                if (containsCyclic20(rows[r], s[sid])) masks[r].set(sid);\n            }\n        }\n\n        vector<unsigned char> b(C, 0);\n        vector<int> used(R, 0);\n        bitset<MAXM> cov;\n\n        for (int i = 0; i < N; i++) {\n            int bestR = -1;\n            int bestGain = -1;\n            int bestTotal = -1;\n\n            for (int r = 0; r < R; r++) {\n                if (used[r]) continue;\n\n                bitset<MAXM> add = masks[r] & (~cov);\n                int gain = (int)add.count();\n                int total = (int)masks[r].count();\n\n                if (gain > bestGain || (gain == bestGain && total > bestTotal)) {\n                    bestGain = gain;\n                    bestTotal = total;\n                    bestR = r;\n                }\n            }\n\n            if (bestR == -1) break;\n\n            used[bestR] = 1;\n            cov |= masks[bestR];\n\n            for (int j = 0; j < N; j++) {\n                b[i * N + j] = (unsigned char)(rows[bestR][j] - 'A');\n            }\n        }\n\n        return b;\n    };\n\n    {\n        Evaluator ev0(s, pre, boardStamp);\n        best.update(ev0);\n    }\n\n    vector<vector<unsigned char>> rowBoards;\n\n    for (int mode = 0; mode < 6; mode++) {\n        if (elapsedSec() > 0.64) break;\n\n        vector<unsigned char> boardRows = makeRowPackBoard(mode, 987654321ULL + 10007ULL * mode);\n        rowBoards.push_back(boardRows);\n\n        Evaluator evRows(s, pre, boardRows);\n        best.update(evRows);\n    }\n\n    // New candidate: greedily select best 20 rows among all row-packing variants.\n    if (!rowBoards.empty() && elapsedSec() < 0.72) {\n        vector<unsigned char> boardCoverRows = makeSetCoverRowsBoard(rowBoards);\n        Evaluator evCoverRows(s, pre, boardCoverRows);\n        best.update(evCoverRows);\n    }\n\n    if (elapsedSec() < 0.80) {\n        Evaluator evRot(s, pre, best.board);\n        optimizeLineRotations(evRot, 0.80, 1);\n        best.update(evRot);\n    }\n\n    if (elapsedSec() < 0.95) {\n        Evaluator evSwap(s, pre, best.board);\n        optimizeLineSwaps(evSwap, 0.95, 1);\n        best.update(evSwap);\n    }\n\n    auto doSearch = [&](Evaluator& ev, bool useKmer, double endTime) {\n        long long curK = 0;\n        if (useKmer) curK = ksc.score(ev.board);\n\n        vector<pair<int, int>> changed;\n        int iter = 0;\n\n        best.update(ev);\n\n        while (true) {\n            if ((iter & 7) == 0 && elapsedSec() > endTime) break;\n\n            double progress = min(1.0, elapsedSec() / endTime);\n            double temp = useKmer\n                ? (1500000.0 * (1.0 - progress) + 20000.0 * progress)\n                : (200000.0 * (1.0 - progress) + 2000.0 * progress);\n\n            long long kScale = 0;\n            if (useKmer) kScale = (ev.covered < M ? 220 : 30);\n\n            if (ev.covered < M && iter % 5 == 0) {\n                int bestSid = -1;\n                int bestMM = 100;\n                int cnt = 0;\n\n                for (int sid = 0; sid < M; sid++) {\n                    if (ev.hist[sid][0] == 0) {\n                        int mm = ev.minMismatchOfString(sid);\n\n                        if (mm < bestMM) {\n                            bestMM = mm;\n                            bestSid = sid;\n                            cnt = 1;\n                        } else if (mm == bestMM) {\n                            cnt++;\n                            if (rng.nextInt(cnt) == 0) bestSid = sid;\n                        }\n                    }\n                }\n\n                if (bestSid != -1) {\n                    int idx = ev.bestPlacementIndex(bestSid, rng);\n\n                    changed.clear();\n\n                    long long oldObj = ev.obj;\n                    long long oldK = curK;\n\n                    int len = (int)s[bestSid].size();\n\n                    for (int p = 0; p < len; p++) {\n                        int cell = ev.placementCell(bestSid, idx, p);\n                        int req = s[bestSid][p] - 'A';\n\n                        if (ev.board[cell] != req) {\n                            int old = ev.board[cell];\n                            changed.push_back({cell, old});\n\n                            if (useKmer) curK += ksc.delta(ev.board, cell, req);\n                            ev.applyChange(cell, req);\n                        }\n                    }\n\n                    long long exactD = ev.obj - oldObj;\n                    long long kD = curK - oldK;\n                    long long combD = exactD + kScale * kD;\n\n                    bool accept = false;\n                    if (combD >= 0) accept = true;\n                    else if (exactD > -BIG / 2) {\n                        if (rng.nextDouble() < exp((double)combD / temp)) accept = true;\n                    }\n\n                    if (!accept) {\n                        for (int i = (int)changed.size() - 1; i >= 0; i--) {\n                            int cell = changed[i].first;\n                            int old = changed[i].second;\n\n                            if (useKmer) curK += ksc.delta(ev.board, cell, old);\n                            ev.applyChange(cell, old);\n                        }\n                    } else {\n                        best.update(ev);\n                    }\n                }\n            } else {\n                int cell = rng.nextInt(C);\n                int old = ev.board[cell];\n\n                long long bestComb = 0;\n                long long bestK = 0;\n                int bestChar = old;\n\n                for (int nc = 0; nc < ALPHA; nc++) {\n                    if (nc == old) continue;\n\n                    long long kd = 0;\n                    if (useKmer) kd = ksc.delta(ev.board, cell, nc);\n\n                    long long ed = ev.applyChange(cell, nc);\n                    ev.applyChange(cell, old);\n\n                    long long cd = ed + kScale * kd;\n\n                    if (cd > bestComb) {\n                        bestComb = cd;\n                        bestK = kd;\n                        bestChar = nc;\n                    }\n                }\n\n                if (bestChar != old) {\n                    if (useKmer) curK += bestK;\n                    ev.applyChange(cell, bestChar);\n                    best.update(ev);\n                } else {\n                    int nc = rng.nextInt(ALPHA);\n                    if (nc == old) nc = (nc + 1) % ALPHA;\n\n                    long long kd = 0;\n                    if (useKmer) kd = ksc.delta(ev.board, cell, nc);\n\n                    long long ed = ev.applyChange(cell, nc);\n                    long long cd = ed + kScale * kd;\n\n                    bool accept = false;\n                    if (cd >= 0) accept = true;\n                    else if (ed > -BIG / 2) {\n                        if (rng.nextDouble() < exp((double)cd / temp)) accept = true;\n                    }\n\n                    if (accept) {\n                        if (useKmer) curK += kd;\n                        best.update(ev);\n                    } else {\n                        ev.applyChange(cell, old);\n                    }\n                }\n            }\n\n            iter++;\n        }\n    };\n\n    {\n        Evaluator evExact(s, pre, best.board);\n        doSearch(evExact, false, 1.23);\n    }\n\n    vector<unsigned char> boardKmer(C);\n    for (int i = 0; i < C; i++) boardKmer[i] = randomChar();\n\n    long long kScore = ksc.score(boardKmer);\n\n    while (elapsedSec() < 1.55) {\n        int cell = rng.nextInt(C);\n        int old = boardKmer[cell];\n\n        long long bestD = 0;\n        int bestC = old;\n\n        for (int nc = 0; nc < ALPHA; nc++) {\n            if (nc == old) continue;\n\n            long long d = ksc.delta(boardKmer, cell, nc);\n\n            if (d > bestD) {\n                bestD = d;\n                bestC = nc;\n            }\n        }\n\n        if (bestC != old) {\n            boardKmer[cell] = (unsigned char)bestC;\n            kScore += bestD;\n        } else {\n            int nc = rng.nextInt(ALPHA);\n            if (nc == old) nc = (nc + 1) % ALPHA;\n\n            long long d = ksc.delta(boardKmer, cell, nc);\n\n            if (d >= 0 || rng.nextDouble() < exp((double)d / 30.0)) {\n                boardKmer[cell] = (unsigned char)nc;\n                kScore += d;\n            }\n        }\n    }\n\n    Evaluator evKmer(s, pre, boardKmer);\n    best.update(evKmer);\n\n    vector<unsigned char> startCombined;\n\n    if (evKmer.covered > best.covered ||\n        (evKmer.covered == best.covered && ksc.score(evKmer.board) > ksc.score(best.board))) {\n        startCombined = evKmer.board;\n    } else {\n        startCombined = best.board;\n    }\n\n    Evaluator evCombined(s, pre, startCombined);\n    doSearch(evCombined, true, 2.84);\n\n    if (elapsedSec() < 2.90) {\n        Evaluator evRot2(s, pre, best.board);\n        optimizeLineRotations(evRot2, 2.90, 1);\n        best.update(evRot2);\n    }\n\n    if (elapsedSec() < 2.94) {\n        Evaluator evSwap2(s, pre, best.board);\n        optimizeLineSwaps(evSwap2, 2.94, 1);\n        best.update(evSwap2);\n    }\n\n    if (elapsedSec() < 2.97) {\n        Evaluator evPolish(s, pre, best.board);\n        doSearch(evPolish, false, 2.97);\n    }\n\n    vector<unsigned char> answer = best.board;\n\n    if (best.covered == M) {\n        Evaluator evFinal(s, pre, answer);\n\n        vector<int> cells(C);\n        iota(cells.begin(), cells.end(), 0);\n        shuffle(cells.begin(), cells.end(), mt19937((unsigned)rng.next()));\n\n        for (int cell : cells) {\n            int old = evFinal.board[cell];\n            if (old == 8) continue;\n\n            evFinal.applyChange(cell, 8);\n\n            if (evFinal.covered < M) {\n                evFinal.applyChange(cell, old);\n            }\n        }\n\n        answer = evFinal.board;\n    }\n\n    for (int i = 0; i < N; i++) {\n        string out;\n\n        for (int j = 0; j < N; j++) {\n            int v = answer[i * N + j];\n            if (v == 8) out.push_back('.');\n            else out.push_back(char('A' + v));\n        }\n\n        cout << out << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\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 HopcroftKarp {\n    int nL, nR;\n    vector<vector<int>> adj;\n    vector<int> pairU, pairV, dist;\n\n    HopcroftKarp(int nL_=0, int nR_=0) : nL(nL_), nR(nR_) {\n        adj.assign(nL, {});\n        pairU.assign(nL, -1);\n        pairV.assign(nR, -1);\n        dist.assign(nL, 0);\n    }\n\n    bool bfs() {\n        queue<int> q;\n        bool found = false;\n\n        for (int u = 0; u < nL; u++) {\n            if (pairU[u] == -1) {\n                dist[u] = 0;\n                q.push(u);\n            } else {\n                dist[u] = -1;\n            }\n        }\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (int v : adj[u]) {\n                int u2 = pairV[v];\n                if (u2 == -1) {\n                    found = true;\n                } else if (dist[u2] == -1) {\n                    dist[u2] = dist[u] + 1;\n                    q.push(u2);\n                }\n            }\n        }\n\n        return found;\n    }\n\n    bool dfs(int u) {\n        for (int v : adj[u]) {\n            int u2 = pairV[v];\n            if (u2 == -1 || (dist[u2] == dist[u] + 1 && dfs(u2))) {\n                pairU[u] = v;\n                pairV[v] = u;\n                return true;\n            }\n        }\n        dist[u] = -1;\n        return false;\n    }\n\n    int max_matching() {\n        int matching = 0;\n        while (bfs()) {\n            for (int u = 0; u < nL; u++) {\n                if (pairU[u] == -1 && dfs(u)) matching++;\n            }\n        }\n        return matching;\n    }\n\n    pair<vector<char>, vector<char>> min_vertex_cover() {\n        vector<char> visL(nL, 0), visR(nR, 0);\n        queue<int> q;\n\n        for (int u = 0; u < nL; u++) {\n            if (pairU[u] == -1) {\n                visL[u] = 1;\n                q.push(u);\n            }\n        }\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (int v : adj[u]) {\n                if (pairU[u] == v) continue;\n                if (visR[v]) continue;\n\n                visR[v] = 1;\n                int u2 = pairV[v];\n                if (u2 != -1 && !visL[u2]) {\n                    visL[u2] = 1;\n                    q.push(u2);\n                }\n            }\n        }\n\n        vector<char> coverL(nL, 0), coverR(nR, 0);\n        for (int u = 0; u < nL; u++) coverL[u] = !visL[u];\n        for (int v = 0; v < nR; v++) coverR[v] = visR[v];\n        return {coverL, coverR};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<vector<int>> id(N, vector<int>(N, -1));\n    vector<int> ri, rj, cost;\n\n    int R = 0;\n    int startRid = -1;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                id[i][j] = R++;\n                ri.push_back(i);\n                rj.push_back(j);\n                cost.push_back(grid[i][j] - '0');\n                if (i == si && j == sj) startRid = id[i][j];\n            }\n        }\n    }\n\n    int W = (R + 63) >> 6;\n\n    vector<int> hid(R), vid(R);\n    vector<vector<int>> hCells, vCells;\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n\n            vector<int> cells;\n            while (j < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                j++;\n            }\n\n            int h = (int)hCells.size();\n            for (int x : cells) hid[x] = h;\n            hCells.push_back(cells);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n\n            vector<int> cells;\n            while (i < N && grid[i][j] != '#') {\n                cells.push_back(id[i][j]);\n                i++;\n            }\n\n            int v = (int)vCells.size();\n            for (int x : cells) vid[x] = v;\n            vCells.push_back(cells);\n        }\n    }\n\n    int H = (int)hCells.size();\n    int V = (int)vCells.size();\n\n    vector<uint64_t> coverBits((ll)R * W, 0);\n\n    for (int x = 0; x < R; x++) {\n        uint64_t* bs = &coverBits[(ll)x * W];\n\n        for (int y : hCells[hid[x]]) {\n            bs[y >> 6] |= 1ULL << (y & 63);\n        }\n        for (int y : vCells[vid[x]]) {\n            bs[y >> 6] |= 1ULL << (y & 63);\n        }\n    }\n\n    vector<int> coverWeight(R, 0);\n    for (int x = 0; x < R; x++) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        int s = 0;\n        for (int w = 0; w < W; w++) s += __builtin_popcountll(bs[w]);\n        coverWeight[x] = s;\n    }\n\n    vector<uint64_t> fullMask(W, 0);\n    for (int x = 0; x < R; x++) {\n        fullMask[x >> 6] |= 1ULL << (x & 63);\n    }\n\n    auto is_full_bits = [&](const vector<uint64_t>& bs) -> bool {\n        for (int w = 0; w < W; w++) {\n            if ((bs[w] & fullMask[w]) != fullMask[w]) return false;\n        }\n        return true;\n    };\n\n    auto pop_and = [&](const uint64_t* a, const vector<uint64_t>& b) -> int {\n        int res = 0;\n        for (int w = 0; w < W; w++) {\n            res += __builtin_popcountll(a[w] & b[w]);\n        }\n        return res;\n    };\n\n    auto erase_cover_from_uncovered = [&](vector<uint64_t>& uncovered, int x) {\n        const uint64_t* bs = &coverBits[(ll)x * W];\n        for (int w = 0; w < W; w++) {\n            uncovered[w] &= ~bs[w];\n        }\n    };\n\n    auto reduce_selected = [&](vector<int> selected, bool sortFirst) {\n        if (sortFirst) {\n            sort(selected.begin(), selected.end());\n            selected.erase(unique(selected.begin(), selected.end()), selected.end());\n        } else {\n            vector<char> seen(R, 0);\n            vector<int> tmp;\n            for (int x : selected) {\n                if (!seen[x]) {\n                    seen[x] = 1;\n                    tmp.push_back(x);\n                }\n            }\n            selected.swap(tmp);\n        }\n\n        selected.erase(remove(selected.begin(), selected.end(), startRid), selected.end());\n\n        vector<int> cnt(R, 0);\n\n        auto addCoverCount = [&](int x, int delta) {\n            const uint64_t* bs = &coverBits[(ll)x * W];\n\n            for (int w = 0; w < W; w++) {\n                uint64_t v = bs[w];\n\n                while (v) {\n                    int b = __builtin_ctzll(v);\n                    int y = (w << 6) + b;\n                    if (y < R) cnt[y] += delta;\n                    v &= v - 1;\n                }\n            }\n        };\n\n        addCoverCount(startRid, 1);\n        for (int x : selected) addCoverCount(x, 1);\n\n        vector<int> kept;\n\n        for (int idx = (int)selected.size() - 1; idx >= 0; idx--) {\n            int x = selected[idx];\n            bool removable = true;\n\n            const uint64_t* bs = &coverBits[(ll)x * W];\n\n            for (int w = 0; w < W && removable; w++) {\n                uint64_t v = bs[w];\n\n                while (v) {\n                    int b = __builtin_ctzll(v);\n                    int y = (w << 6) + b;\n\n                    if (y < R && cnt[y] <= 1) {\n                        removable = false;\n                        break;\n                    }\n\n                    v &= v - 1;\n                }\n            }\n\n            if (removable) {\n                addCoverCount(x, -1);\n            } else {\n                kept.push_back(x);\n            }\n        }\n\n        reverse(kept.begin(), kept.end());\n        return kept;\n    };\n\n    auto selected_covers_all = [&](const vector<int>& selected) {\n        vector<uint64_t> bs(W, 0);\n\n        const uint64_t* sbs = &coverBits[(ll)startRid * W];\n        for (int w = 0; w < W; w++) bs[w] |= sbs[w];\n\n        for (int x : selected) {\n            const uint64_t* cbs = &coverBits[(ll)x * W];\n            for (int w = 0; w < W; w++) bs[w] |= cbs[w];\n        }\n\n        return is_full_bits(bs);\n    };\n\n    auto make_greedy_raw = [&](int mode) {\n        vector<int> selected;\n        vector<uint64_t> uncovered = fullMask;\n        erase_cover_from_uncovered(uncovered, startRid);\n\n        vector<char> selectedFlag(R, 0);\n        vector<int> nearDist(R);\n\n        for (int x = 0; x < R; x++) {\n            nearDist[x] = abs(ri[x] - si) + abs(rj[x] - sj);\n        }\n\n        auto anyUncovered = [&]() -> bool {\n            for (uint64_t x : uncovered) {\n                if (x) return true;\n            }\n            return false;\n        };\n\n        while (anyUncovered()) {\n            int best = -1;\n            int bestGain = -1;\n            int bestTie = INT_MIN;\n            ll bestScore = LLONG_MIN;\n\n            for (int x = 0; x < R; x++) {\n                if (selectedFlag[x]) continue;\n\n                const uint64_t* bs = &coverBits[(ll)x * W];\n                int gain = pop_and(bs, uncovered);\n                if (gain <= 0) continue;\n\n                int hLen = (int)hCells[hid[x]].size();\n                int vLen = (int)vCells[vid[x]].size();\n                int segLen = hLen + vLen;\n                int startD = abs(ri[x] - si) + abs(rj[x] - sj);\n                int nd = nearDist[x];\n\n                if (mode == 0) {\n                    int tie =\n                        10 * segLen\n                        - abs(ri[x] - si)\n                        - abs(rj[x] - sj);\n\n                    if (gain > bestGain || (gain == bestGain && tie > bestTie)) {\n                        bestGain = gain;\n                        bestTie = tie;\n                        best = x;\n                    }\n                } else {\n                    ll score;\n                    if (mode == 1) {\n                        score = (ll)gain * 10000 - 70LL * nd + 90LL * segLen - 5LL * startD;\n                    } else if (mode == 2) {\n                        score = (ll)gain * 7500 - 105LL * nd + 120LL * segLen - 8LL * cost[x];\n                    } else if (mode == 3) {\n                        score = (ll)gain * 7000 - 110LL * startD + 100LL * segLen - 35LL * nd;\n                    } else if (mode == 4) {\n                        score = (ll)gain * 8800 - 130LL * nd + 60LL * segLen + 8LL * hLen * vLen;\n                    } else {\n                        score = (ll)gain * 6400 - 65LL * nd - 95LL * startD + 180LL * segLen - 18LL * cost[x];\n                    }\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        best = x;\n                    }\n                }\n            }\n\n            if (best == -1) break;\n\n            selectedFlag[best] = 1;\n            selected.push_back(best);\n            erase_cover_from_uncovered(uncovered, best);\n\n            if (mode != 0) {\n                for (int y = 0; y < R; y++) {\n                    int d = abs(ri[y] - ri[best]) + abs(rj[y] - rj[best]);\n                    if (d < nearDist[y]) nearDist[y] = d;\n                }\n            }\n        }\n\n        return selected;\n    };\n\n    auto make_greedy = [&](int mode, bool sortReduce) {\n        return reduce_selected(make_greedy_raw(mode), sortReduce);\n    };\n\n    vector<int> greedySelected = make_greedy(0, true);\n\n    vector<int> mvcSelected;\n    bool mvcValid = false;\n\n    {\n        int hs = hid[startRid];\n        int vs = vid[startRid];\n\n        HopcroftKarp hk(H, V);\n\n        unordered_map<ll, int> edgeCell;\n        edgeCell.reserve(R * 2 + 10);\n\n        for (int x = 0; x < R; x++) {\n            int h = hid[x], v = vid[x];\n            edgeCell[(ll)h * V + v] = x;\n\n            if (h == hs || v == vs) continue;\n            hk.adj[h].push_back(v);\n        }\n\n        for (int h = 0; h < H; h++) {\n            sort(hk.adj[h].begin(), hk.adj[h].end());\n            hk.adj[h].erase(unique(hk.adj[h].begin(), hk.adj[h].end()), hk.adj[h].end());\n        }\n\n        hk.max_matching();\n        auto [coverH, coverV] = hk.min_vertex_cover();\n\n        HopcroftKarp hk2(H, V);\n        for (int x = 0; x < R; x++) {\n            int h = hid[x], v = vid[x];\n            if (coverH[h] && coverV[v]) {\n                hk2.adj[h].push_back(v);\n            }\n        }\n\n        for (int h = 0; h < H; h++) {\n            sort(hk2.adj[h].begin(), hk2.adj[h].end());\n            hk2.adj[h].erase(unique(hk2.adj[h].begin(), hk2.adj[h].end()), hk2.adj[h].end());\n        }\n\n        hk2.max_matching();\n\n        vector<char> doneH(H, 0), doneV(V, 0);\n\n        for (int h = 0; h < H; h++) {\n            int v = hk2.pairU[h];\n            if (v != -1 && coverH[h] && coverV[v]) {\n                auto it = edgeCell.find((ll)h * V + v);\n                if (it != edgeCell.end()) {\n                    mvcSelected.push_back(it->second);\n                    doneH[h] = 1;\n                    doneV[v] = 1;\n                }\n            }\n        }\n\n        auto best_cell_in_list = [&](const vector<int>& cells) {\n            int best = cells[0];\n            int bestScore = INT_MAX;\n\n            for (int x : cells) {\n                int score =\n                    10 * (abs(ri[x] - si) + abs(rj[x] - sj))\n                    - (int)hCells[hid[x]].size()\n                    - (int)vCells[vid[x]].size();\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = x;\n                }\n            }\n\n            return best;\n        };\n\n        for (int h = 0; h < H; h++) {\n            if (coverH[h] && !doneH[h]) {\n                mvcSelected.push_back(best_cell_in_list(hCells[h]));\n                doneH[h] = 1;\n            }\n        }\n\n        for (int v = 0; v < V; v++) {\n            if (coverV[v] && !doneV[v]) {\n                mvcSelected.push_back(best_cell_in_list(vCells[v]));\n                doneV[v] = 1;\n            }\n        }\n\n        mvcSelected = reduce_selected(mvcSelected, true);\n        mvcValid = selected_covers_all(mvcSelected);\n    }\n\n    vector<vector<int>> candidates;\n    candidates.push_back(greedySelected);\n\n    vector<char> inUnion(R, 0);\n    inUnion[startRid] = 1;\n    int unionCount = 1;\n\n    auto mark_union = [&](const vector<int>& sel) {\n        for (int x : sel) {\n            if (!inUnion[x]) {\n                inUnion[x] = 1;\n                unionCount++;\n            }\n        }\n    };\n\n    mark_union(greedySelected);\n\n    auto same_set = [&](vector<int> a, vector<int> b) {\n        sort(a.begin(), a.end());\n        sort(b.begin(), b.end());\n        return a == b;\n    };\n\n    auto try_add_candidate = [&](const vector<int>& sel, int capUnion, bool sizeGuard) {\n        if (sel.empty()) return;\n        if (!selected_covers_all(sel)) return;\n\n        if (sizeGuard && sel.size() > greedySelected.size() * 3 / 2 + 25) return;\n\n        for (auto& c : candidates) {\n            if (same_set(c, sel)) return;\n        }\n\n        int add = 0;\n        for (int x : sel) {\n            if (!inUnion[x]) add++;\n        }\n\n        if (unionCount + add > capUnion) return;\n\n        candidates.push_back(sel);\n        mark_union(sel);\n    };\n\n    if (mvcValid) {\n        try_add_candidate(mvcSelected, 660, false);\n    }\n\n    for (int mode = 1; mode <= 5 && timer.elapsed() < 0.58; mode++) {\n        vector<int> cand = make_greedy(mode, true);\n        try_add_candidate(cand, 660, true);\n    }\n\n    for (int mode = 0; mode <= 2 && timer.elapsed() < 0.70; mode++) {\n        vector<int> cand = make_greedy(mode, false);\n        try_add_candidate(cand, 660, true);\n    }\n\n    vector<int> nodeRid;\n    nodeRid.push_back(startRid);\n\n    vector<int> ridToNode(R, -1);\n    ridToNode[startRid] = 0;\n\n    for (const auto& selected : candidates) {\n        for (int x : selected) {\n            if (ridToNode[x] == -1) {\n                ridToNode[x] = (int)nodeRid.size();\n                nodeRid.push_back(x);\n            }\n        }\n    }\n\n    int G = (int)nodeRid.size();\n\n    vector<vector<pair<int,int>>> adj(R);\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n\n    for (int x = 0; x < R; x++) {\n        int i = ri[x], j = rj[x];\n\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d];\n            int nj = j + dj[d];\n\n            if (0 <= ni && ni < N && 0 <= nj && nj < N && id[ni][nj] != -1) {\n                int y = id[ni][nj];\n                adj[x].push_back({y, cost[y]});\n            }\n        }\n    }\n\n    const int INF = 1e9;\n\n    vector<vector<int>> distMat(G, vector<int>(G, INF));\n    vector<vector<short>> prevNode(G, vector<short>(R, -1));\n\n    for (int s = 0; s < G; s++) {\n        int src = nodeRid[s];\n\n        vector<int> dist(R, INF);\n        vector<int> pathScore(R, -1);\n        vector<short> pre(R, -1);\n\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n\n        dist[src] = 0;\n        pathScore[src] = coverWeight[src];\n        pq.push({0, src});\n\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top();\n            pq.pop();\n\n            if (cd != dist[v]) continue;\n\n            for (auto [to, w] : adj[v]) {\n                int nd = cd + w;\n                int ns = pathScore[v] + coverWeight[to];\n\n                if (nd < dist[to] || (nd == dist[to] && ns > pathScore[to])) {\n                    dist[to] = nd;\n                    pathScore[to] = ns;\n                    pre[to] = (short)v;\n                    pq.push({nd, to});\n                }\n            }\n        }\n\n        prevNode[s].swap(pre);\n\n        for (int t = 0; t < G; t++) {\n            distMat[s][t] = dist[nodeRid[t]];\n        }\n    }\n\n    vector<int> nodeCost(G);\n    for (int i = 0; i < G; i++) nodeCost[i] = cost[nodeRid[i]];\n\n    auto cycleCost = [&](const vector<int>& cyc) -> ll {\n        ll res = 0;\n        int m = (int)cyc.size();\n\n        for (int i = 0; i < m; i++) {\n            res += distMat[cyc[i]][cyc[(i + 1) % m]];\n        }\n\n        return res;\n    };\n\n    auto symDist = [&](int a, int b) -> int {\n        if (a == b) return 0;\n        return distMat[a][b] + nodeCost[a];\n    };\n\n    auto improve_cycle = [&](vector<int>& cycle, double endTime) {\n        if ((int)cycle.size() > 780) return;\n\n        while (timer.elapsed() < endTime) {\n            int m = (int)cycle.size();\n\n            ll bestDelta = 0;\n            int bestType = 0;\n            int bestL = -1, bestR = -1;\n            int bestI = -1, bestJ = -1, bestPos = -1;\n\n            for (int l = 1; l < m - 1; l++) {\n                if ((l & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                for (int r = l + 1; r < m; r++) {\n                    int a = cycle[l - 1];\n                    int b = cycle[l];\n                    int c = cycle[r];\n                    int d = cycle[(r + 1) % m];\n\n                    ll delta =\n                        (ll)symDist(a, c) + symDist(b, d)\n                        - symDist(a, b) - symDist(c, d);\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 1;\n                        bestL = l;\n                        bestR = r;\n                    }\n                }\n            }\n\n            for (int i = 1; i < m; i++) {\n                if ((i & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                int x = cycle[i];\n                int a = cycle[i - 1];\n                int b = cycle[(i + 1) % m];\n\n                ll removeDelta =\n                    (ll)distMat[a][b]\n                    - distMat[a][x]\n                    - distMat[x][b];\n\n                for (int pos = 0; pos < m; pos++) {\n                    if (pos == i || pos == i - 1) continue;\n\n                    int c = cycle[pos];\n                    int d = cycle[(pos + 1) % m];\n\n                    ll delta =\n                        removeDelta\n                        + (ll)distMat[c][x]\n                        + distMat[x][d]\n                        - distMat[c][d];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 2;\n                        bestI = i;\n                        bestPos = pos;\n                    }\n                }\n            }\n\n            for (int i = 1; i + 1 < m; i++) {\n                if ((i & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                int x = cycle[i];\n                int y = cycle[i + 1];\n                int a = cycle[i - 1];\n                int b = cycle[(i + 2) % m];\n\n                ll removeDelta =\n                    (ll)distMat[a][b]\n                    - distMat[a][x]\n                    - distMat[x][y]\n                    - distMat[y][b];\n\n                for (int pos = 0; pos < m; pos++) {\n                    if (i - 1 <= pos && pos <= i + 1) continue;\n\n                    int c = cycle[pos];\n                    int d = cycle[(pos + 1) % m];\n\n                    ll delta =\n                        removeDelta\n                        + (ll)distMat[c][x]\n                        + distMat[x][y]\n                        + distMat[y][d]\n                        - distMat[c][d];\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 3;\n                        bestI = i;\n                        bestPos = pos;\n                    }\n                }\n            }\n\n            for (int i = 1; i < m; i++) {\n                if ((i & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                for (int j = i + 1; j < m; j++) {\n                    ll delta;\n\n                    if (j == i + 1) {\n                        int a = cycle[i - 1];\n                        int x = cycle[i];\n                        int y = cycle[j];\n                        int b = cycle[(j + 1) % m];\n\n                        delta =\n                            (ll)distMat[a][y]\n                            + distMat[y][x]\n                            + distMat[x][b]\n                            - distMat[a][x]\n                            - distMat[x][y]\n                            - distMat[y][b];\n                    } else {\n                        int a = cycle[i - 1];\n                        int x = cycle[i];\n                        int b = cycle[i + 1];\n\n                        int c = cycle[j - 1];\n                        int y = cycle[j];\n                        int d = cycle[(j + 1) % m];\n\n                        delta =\n                            (ll)distMat[a][y]\n                            + distMat[y][b]\n                            + distMat[c][x]\n                            + distMat[x][d]\n                            - distMat[a][x]\n                            - distMat[x][b]\n                            - distMat[c][y]\n                            - distMat[y][d];\n                    }\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestType = 4;\n                        bestI = i;\n                        bestJ = j;\n                    }\n                }\n            }\n\n            if (bestType == 0) break;\n\n            if (bestType == 1) {\n                reverse(cycle.begin() + bestL, cycle.begin() + bestR + 1);\n            } else if (bestType == 2) {\n                int x = cycle[bestI];\n                cycle.erase(cycle.begin() + bestI);\n\n                int insertIdx;\n                if (bestPos < bestI) insertIdx = bestPos + 1;\n                else insertIdx = bestPos;\n\n                cycle.insert(cycle.begin() + insertIdx, x);\n            } else if (bestType == 3) {\n                int x = cycle[bestI];\n                int y = cycle[bestI + 1];\n\n                cycle.erase(cycle.begin() + bestI, cycle.begin() + bestI + 2);\n\n                int insertIdx;\n                if (bestPos < bestI) insertIdx = bestPos + 1;\n                else insertIdx = bestPos - 1;\n\n                cycle.insert(cycle.begin() + insertIdx, y);\n                cycle.insert(cycle.begin() + insertIdx, x);\n            } else {\n                swap(cycle[bestI], cycle[bestJ]);\n            }\n        }\n    };\n\n    auto construct_cycle = [&](const vector<int>& selected) {\n        vector<int> localNodes;\n        localNodes.push_back(0);\n\n        for (int x : selected) {\n            int g = ridToNode[x];\n            if (g > 0) localNodes.push_back(g);\n        }\n\n        sort(localNodes.begin() + 1, localNodes.end());\n        localNodes.erase(unique(localNodes.begin(), localNodes.end()), localNodes.end());\n\n        int M = (int)localNodes.size();\n        vector<int> cycle;\n\n        if (M == 1) {\n            cycle = {0};\n        } else if (M <= 440) {\n            cycle = {0};\n\n            vector<int> unused;\n            for (int i = 1; i < M; i++) unused.push_back(localNodes[i]);\n\n            while (!unused.empty()) {\n                int bestUIdx = -1;\n                int bestPos = -1;\n                int bestDelta = INF;\n\n                for (int ui = 0; ui < (int)unused.size(); ui++) {\n                    int x = unused[ui];\n                    int m = (int)cycle.size();\n\n                    for (int p = 0; p < m; p++) {\n                        int a = cycle[p];\n                        int b = cycle[(p + 1) % m];\n\n                        int delta =\n                            distMat[a][x]\n                            + distMat[x][b]\n                            - distMat[a][b];\n\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestUIdx = ui;\n                            bestPos = p;\n                        }\n                    }\n                }\n\n                int x = unused[bestUIdx];\n                cycle.insert(cycle.begin() + bestPos + 1, x);\n                unused.erase(unused.begin() + bestUIdx);\n            }\n        } else {\n            vector<char> used(G, 0);\n            cycle = {0};\n            used[0] = 1;\n\n            int cur = 0;\n\n            for (int step = 1; step < M; step++) {\n                int best = -1;\n                int bd = INF;\n\n                for (int x : localNodes) {\n                    if (!used[x] && distMat[cur][x] < bd) {\n                        bd = distMat[cur][x];\n                        best = x;\n                    }\n                }\n\n                used[best] = 1;\n                cycle.push_back(best);\n                cur = best;\n            }\n        }\n\n        return cycle;\n    };\n\n    vector<vector<int>> cycles;\n    cycles.reserve(candidates.size());\n\n    for (const auto& cand : candidates) {\n        cycles.push_back(construct_cycle(cand));\n    }\n\n    if (!cycles.empty()) {\n        improve_cycle(cycles[0], min(1.45, timer.elapsed() + 0.34));\n    }\n    if (cycles.size() >= 2) {\n        improve_cycle(cycles[1], min(1.82, timer.elapsed() + 0.32));\n    }\n    for (int k = 2; k < (int)cycles.size() && timer.elapsed() < 2.02; k++) {\n        improve_cycle(cycles[k], min(2.02, timer.elapsed() + 0.10));\n    }\n\n    int bestIdx = 0;\n    ll bestCost = cycleCost(cycles[0]);\n\n    for (int k = 1; k < (int)cycles.size(); k++) {\n        ll c = cycleCost(cycles[k]);\n        if (c < bestCost) {\n            bestCost = c;\n            bestIdx = k;\n        }\n    }\n\n    vector<int> cycle = cycles[bestIdx];\n\n    improve_cycle(cycle, 2.12);\n\n    auto reconstructPath = [&](int srcNode, int dstNode) {\n        vector<int> path;\n\n        int src = nodeRid[srcNode];\n        int dst = nodeRid[dstNode];\n\n        int cur = dst;\n\n        while (cur != src) {\n            path.push_back(cur);\n            cur = prevNode[srcNode][cur];\n\n            if (cur < 0) break;\n        }\n\n        path.push_back(src);\n        reverse(path.begin(), path.end());\n\n        return path;\n    };\n\n    struct EdgeCache {\n        int G, W, R;\n        const vector<int>& nodeRid;\n        const vector<vector<short>>& prevNode;\n        const vector<uint64_t>& coverBits;\n        vector<uint64_t> data;\n        vector<unsigned char> done;\n\n        EdgeCache(\n            int G_,\n            int W_,\n            int R_,\n            const vector<int>& nodeRid_,\n            const vector<vector<short>>& prevNode_,\n            const vector<uint64_t>& coverBits_\n        )\n            : G(G_), W(W_), R(R_), nodeRid(nodeRid_),\n              prevNode(prevNode_), coverBits(coverBits_) {\n            data.assign((ll)G * G * W, 0);\n            done.assign((ll)G * G, 0);\n        }\n\n        uint64_t* get(int a, int b) {\n            ll idx = (ll)a * G + b;\n            uint64_t* ret = &data[idx * W];\n\n            if (done[idx]) return ret;\n            done[idx] = 1;\n\n            int src = nodeRid[a];\n            int dst = nodeRid[b];\n\n            vector<int> path;\n            int cur = dst;\n\n            while (cur != src) {\n                path.push_back(cur);\n                cur = prevNode[a][cur];\n\n                if (cur < 0) break;\n            }\n\n            path.push_back(src);\n\n            for (int x : path) {\n                const uint64_t* bs = &coverBits[(ll)x * W];\n\n                for (int w = 0; w < W; w++) {\n                    ret[w] |= bs[w];\n                }\n            }\n\n            return ret;\n        }\n    };\n\n    if (G <= 680 && timer.elapsed() < 2.23) {\n        EdgeCache cache(G, W, R, nodeRid, prevNode, coverBits);\n\n        while ((int)cycle.size() > 1 && timer.elapsed() < 2.66) {\n            int m = (int)cycle.size();\n\n            vector<uint64_t> pref((ll)(m + 1) * W, 0);\n            vector<uint64_t> suff((ll)(m + 1) * W, 0);\n            vector<ll> edgePref(m + 1, 0);\n\n            for (int e = 0; e < m; e++) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n\n                for (int w = 0; w < W; w++) {\n                    pref[(ll)(e + 1) * W + w] =\n                        pref[(ll)e * W + w] | ec[w];\n                }\n\n                edgePref[e + 1] =\n                    edgePref[e] + distMat[cycle[e]][cycle[(e + 1) % m]];\n            }\n\n            for (int e = m - 1; e >= 0; e--) {\n                uint64_t* ec = cache.get(cycle[e], cycle[(e + 1) % m]);\n\n                for (int w = 0; w < W; w++) {\n                    suff[(ll)e * W + w] =\n                        suff[(ll)(e + 1) * W + w] | ec[w];\n                }\n            }\n\n            int bestP = -1;\n            int bestQ = -1;\n            ll bestSave = 0;\n            vector<uint64_t> tmp(W);\n\n            int maxBlock = 10;\n\n            for (int p = 1; p < m; p++) {\n                if ((p & 15) == 0 && timer.elapsed() >= 2.66) break;\n\n                for (int len = 1; len <= maxBlock && p + len - 1 < m; len++) {\n                    int q = p + len - 1;\n\n                    int prv = cycle[p - 1];\n                    int nxt = cycle[(q + 1) % m];\n\n                    ll removedCost = edgePref[q + 1] - edgePref[p - 1];\n                    ll save = removedCost - distMat[prv][nxt];\n\n                    if (save <= bestSave) continue;\n\n                    uint64_t* ec = cache.get(prv, nxt);\n\n                    for (int w = 0; w < W; w++) {\n                        tmp[w] =\n                            pref[(ll)(p - 1) * W + w]\n                            | suff[(ll)(q + 1) * W + w]\n                            | ec[w];\n                    }\n\n                    bool ok = true;\n\n                    for (int w = 0; w < W; w++) {\n                        if ((tmp[w] & fullMask[w]) != fullMask[w]) {\n                            ok = false;\n                            break;\n                        }\n                    }\n\n                    if (ok) {\n                        bestSave = save;\n                        bestP = p;\n                        bestQ = q;\n                    }\n                }\n            }\n\n            if (bestP == -1) break;\n\n            cycle.erase(cycle.begin() + bestP, cycle.begin() + bestQ + 1);\n        }\n    }\n\n    auto cycle_nodes_cover_all = [&]() {\n        vector<uint64_t> bs(W, 0);\n\n        for (int g : cycle) {\n            int rid = nodeRid[g];\n            const uint64_t* cbs = &coverBits[(ll)rid * W];\n\n            for (int w = 0; w < W; w++) {\n                bs[w] |= cbs[w];\n            }\n        }\n\n        return is_full_bits(bs);\n    };\n\n    if (timer.elapsed() < 2.76 && cycle_nodes_cover_all()) {\n        improve_cycle(cycle, 2.80);\n    }\n\n    auto buildFullPath = [&]() {\n        vector<int> fp;\n        fp.push_back(startRid);\n\n        int m = (int)cycle.size();\n\n        for (int e = 0; e < m; e++) {\n            int a = cycle[e];\n            int b = cycle[(e + 1) % m];\n\n            vector<int> path = reconstructPath(a, b);\n\n            for (int k = 1; k < (int)path.size(); k++) {\n                fp.push_back(path[k]);\n            }\n        }\n\n        return fp;\n    };\n\n    vector<int> fullPath = buildFullPath();\n\n    auto simplifyFullPathLoops = [&](vector<int>& path, double endTime) {\n        while ((int)path.size() > 1 && timer.elapsed() < endTime) {\n            int L = (int)path.size();\n\n            vector<uint64_t> pref((ll)(L + 1) * W, 0);\n            vector<uint64_t> suff((ll)(L + 1) * W, 0);\n            vector<ll> edgePref(L, 0);\n\n            for (int i = 0; i < L; i++) {\n                const uint64_t* bs = &coverBits[(ll)path[i] * W];\n\n                for (int w = 0; w < W; w++) {\n                    pref[(ll)(i + 1) * W + w] =\n                        pref[(ll)i * W + w] | bs[w];\n                }\n\n                if (i > 0) {\n                    edgePref[i] = edgePref[i - 1] + cost[path[i]];\n                }\n            }\n\n            for (int i = L - 1; i >= 0; i--) {\n                const uint64_t* bs = &coverBits[(ll)path[i] * W];\n\n                for (int w = 0; w < W; w++) {\n                    suff[(ll)i * W + w] =\n                        suff[(ll)(i + 1) * W + w] | bs[w];\n                }\n            }\n\n            vector<vector<int>> occ(R);\n            for (int i = 0; i < L; i++) {\n                occ[path[i]].push_back(i);\n            }\n\n            int bestL = -1;\n            int bestR = -1;\n            ll bestSave = 0;\n            vector<uint64_t> tmp(W);\n\n            for (int x = 0; x < R; x++) {\n                auto& v = occ[x];\n                int sz = (int)v.size();\n                if (sz < 2) continue;\n\n                for (int ai = 0; ai + 1 < sz; ai++) {\n                    int l = v[ai];\n\n                    for (int bi = sz - 1; bi > ai; bi--) {\n                        int r = v[bi];\n\n                        if (r <= l + 1) continue;\n\n                        ll save = edgePref[r] - edgePref[l];\n                        if (save <= bestSave) break;\n\n                        for (int w = 0; w < W; w++) {\n                            tmp[w] =\n                                pref[(ll)(l + 1) * W + w]\n                                | suff[(ll)(r + 1) * W + w];\n                        }\n\n                        bool ok = true;\n                        for (int w = 0; w < W; w++) {\n                            if ((tmp[w] & fullMask[w]) != fullMask[w]) {\n                                ok = false;\n                                break;\n                            }\n                        }\n\n                        if (ok) {\n                            bestSave = save;\n                            bestL = l;\n                            bestR = r;\n                            break;\n                        }\n                    }\n\n                    if ((ai & 15) == 0 && timer.elapsed() >= endTime) break;\n                }\n\n                if ((x & 31) == 0 && timer.elapsed() >= endTime) break;\n            }\n\n            if (bestL == -1) break;\n\n            path.erase(path.begin() + bestL + 1, path.begin() + bestR + 1);\n        }\n    };\n\n    auto line_path_between = [&](int a, int b) {\n        vector<int> line;\n        line.push_back(a);\n\n        if (a == b) return line;\n\n        if (hid[a] == hid[b]) {\n            int row = ri[a];\n            int c1 = rj[a], c2 = rj[b];\n            int step = (c2 > c1 ? 1 : -1);\n\n            for (int c = c1 + step; c != c2 + step; c += step) {\n                line.push_back(id[row][c]);\n            }\n        } else if (vid[a] == vid[b]) {\n            int col = rj[a];\n            int r1 = ri[a], r2 = ri[b];\n            int step = (r2 > r1 ? 1 : -1);\n\n            for (int r = r1 + step; r != r2 + step; r += step) {\n                line.push_back(id[r][col]);\n            }\n        } else {\n            line.clear();\n        }\n\n        return line;\n    };\n\n    auto concat_path = [&](const vector<int>& a, const vector<int>& b) {\n        vector<int> res = a;\n        if (res.empty() || b.empty()) {\n            res.clear();\n            return res;\n        }\n        if (res.back() != b.front()) {\n            res.clear();\n            return res;\n        }\n        for (int i = 1; i < (int)b.size(); i++) res.push_back(b[i]);\n        return res;\n    };\n\n    auto path_cost = [&](const vector<int>& p) {\n        ll s = 0;\n        for (int i = 1; i < (int)p.size(); i++) s += cost[p[i]];\n        return s;\n    };\n\n    auto geometric_paths_between = [&](int a, int b) {\n        vector<vector<int>> res;\n\n        vector<int> straight = line_path_between(a, b);\n        if (!straight.empty()) res.push_back(straight);\n\n        int c1i = ri[a], c1j = rj[b];\n        if (0 <= c1i && c1i < N && 0 <= c1j && c1j < N && id[c1i][c1j] != -1) {\n            int c = id[c1i][c1j];\n            vector<int> p1 = line_path_between(a, c);\n            vector<int> p2 = line_path_between(c, b);\n            vector<int> p = concat_path(p1, p2);\n            if (!p.empty()) res.push_back(p);\n        }\n\n        int c2i = ri[b], c2j = rj[a];\n        if (0 <= c2i && c2i < N && 0 <= c2j && c2j < N && id[c2i][c2j] != -1) {\n            int c = id[c2i][c2j];\n            vector<int> p1 = line_path_between(a, c);\n            vector<int> p2 = line_path_between(c, b);\n            vector<int> p = concat_path(p1, p2);\n            if (!p.empty()) res.push_back(p);\n        }\n\n        // New: H-V-H two-bend shortcut.\n        {\n            vector<int> best;\n            ll bestC = LLONG_MAX;\n\n            for (int x1 : hCells[hid[a]]) {\n                int col = rj[x1];\n                int x2 = id[ri[b]][col];\n\n                if (x2 == -1) continue;\n                if (vid[x1] != vid[x2]) continue;\n                if (hid[x2] != hid[b]) continue;\n\n                vector<int> p1 = line_path_between(a, x1);\n                vector<int> p2 = line_path_between(x1, x2);\n                vector<int> p3 = line_path_between(x2, b);\n\n                vector<int> p = concat_path(concat_path(p1, p2), p3);\n\n                if (!p.empty()) {\n                    ll c = path_cost(p);\n                    if (c < bestC) {\n                        bestC = c;\n                        best.swap(p);\n                    }\n                }\n            }\n\n            if (!best.empty()) res.push_back(best);\n        }\n\n        // New: V-H-V two-bend shortcut.\n        {\n            vector<int> best;\n            ll bestC = LLONG_MAX;\n\n            for (int x1 : vCells[vid[a]]) {\n                int row = ri[x1];\n                int x2 = id[row][rj[b]];\n\n                if (x2 == -1) continue;\n                if (hid[x1] != hid[x2]) continue;\n                if (vid[x2] != vid[b]) continue;\n\n                vector<int> p1 = line_path_between(a, x1);\n                vector<int> p2 = line_path_between(x1, x2);\n                vector<int> p3 = line_path_between(x2, b);\n\n                vector<int> p = concat_path(concat_path(p1, p2), p3);\n\n                if (!p.empty()) {\n                    ll c = path_cost(p);\n                    if (c < bestC) {\n                        bestC = c;\n                        best.swap(p);\n                    }\n                }\n            }\n\n            if (!best.empty()) res.push_back(best);\n        }\n\n        return res;\n    };\n\n    auto simplifyGeometricDetours = [&](vector<int>& path, double endTime) {\n        while ((int)path.size() > 2 && timer.elapsed() < endTime) {\n            int L = (int)path.size();\n\n            vector<uint64_t> pref((ll)(L + 1) * W, 0);\n            vector<uint64_t> suff((ll)(L + 1) * W, 0);\n            vector<ll> edgePref(L, 0);\n\n            for (int i = 0; i < L; i++) {\n                const uint64_t* bs = &coverBits[(ll)path[i] * W];\n\n                for (int w = 0; w < W; w++) {\n                    pref[(ll)(i + 1) * W + w] =\n                        pref[(ll)i * W + w] | bs[w];\n                }\n\n                if (i > 0) {\n                    edgePref[i] = edgePref[i - 1] + cost[path[i]];\n                }\n            }\n\n            for (int i = L - 1; i >= 0; i--) {\n                const uint64_t* bs = &coverBits[(ll)path[i] * W];\n\n                for (int w = 0; w < W; w++) {\n                    suff[(ll)i * W + w] =\n                        suff[(ll)(i + 1) * W + w] | bs[w];\n                }\n            }\n\n            int bestL = -1;\n            int bestR = -1;\n            vector<int> bestPath;\n            ll bestSave = 0;\n            vector<uint64_t> tmp(W), pathCover(W);\n\n            int maxSpan = 420;\n\n            for (int l = 0; l + 2 < L; l++) {\n                if ((l & 15) == 0 && timer.elapsed() >= endTime) break;\n\n                int upper = min(L - 1, l + maxSpan);\n\n                for (int r = upper; r >= l + 2; r--) {\n                    int a = path[l];\n                    int b = path[r];\n\n                    ll oldCost = edgePref[r] - edgePref[l];\n\n                    int manhattan = abs(ri[a] - ri[b]) + abs(rj[a] - rj[b]);\n                    if (oldCost <= 5LL * manhattan + bestSave) continue;\n\n                    vector<vector<int>> candPaths = geometric_paths_between(a, b);\n\n                    for (auto& gp : candPaths) {\n                        if ((int)gp.size() <= 1) continue;\n\n                        ll newCost = path_cost(gp);\n                        ll save = oldCost - newCost;\n\n                        if (save <= bestSave) continue;\n\n                        fill(pathCover.begin(), pathCover.end(), 0);\n\n                        for (int x : gp) {\n                            const uint64_t* bs = &coverBits[(ll)x * W];\n                            for (int w = 0; w < W; w++) {\n                                pathCover[w] |= bs[w];\n                            }\n                        }\n\n                        for (int w = 0; w < W; w++) {\n                            tmp[w] =\n                                pref[(ll)(l + 1) * W + w]\n                                | suff[(ll)(r + 1) * W + w]\n                                | pathCover[w];\n                        }\n\n                        bool ok = true;\n                        for (int w = 0; w < W; w++) {\n                            if ((tmp[w] & fullMask[w]) != fullMask[w]) {\n                                ok = false;\n                                break;\n                            }\n                        }\n\n                        if (ok) {\n                            bestSave = save;\n                            bestL = l;\n                            bestR = r;\n                            bestPath = gp;\n                        }\n                    }\n                }\n            }\n\n            if (bestL == -1) break;\n\n            vector<int> nextPath;\n            nextPath.reserve(path.size() - (bestR - bestL) + bestPath.size());\n\n            for (int i = 0; i <= bestL; i++) nextPath.push_back(path[i]);\n            for (int k = 1; k < (int)bestPath.size(); k++) nextPath.push_back(bestPath[k]);\n            for (int i = bestR + 1; i < L; i++) nextPath.push_back(path[i]);\n\n            path.swap(nextPath);\n        }\n    };\n\n    if (timer.elapsed() < 2.82) {\n        simplifyFullPathLoops(fullPath, 2.90);\n    }\n\n    if (timer.elapsed() < 2.90) {\n        simplifyGeometricDetours(fullPath, 2.985);\n    }\n\n    if (timer.elapsed() < 2.985) {\n        simplifyFullPathLoops(fullPath, 2.997);\n    }\n\n    string ans;\n\n    auto moveChar = [&](int a, int b) -> char {\n        int da = ri[b] - ri[a];\n        int db = rj[b] - rj[a];\n\n        if (da == -1) return 'U';\n        if (da == 1) return 'D';\n        if (db == -1) return 'L';\n        return 'R';\n    };\n\n    for (int i = 1; i < (int)fullPath.size(); i++) {\n        ans.push_back(moveChar(fullPath[i - 1], fullPath[i]));\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Record {\n    int task;\n    int dur;\n};\n\nint N, M, K, R;\nvector<vector<int>> D;\nvector<vector<int>> children_;\nvector<int> remdep;\nvector<int> status_; // -1:not started, 0:running, 1:done\n\nvector<vector<int>> skill_est;\nvector<vector<Record>> records_;\nvector<int> member_task;\nvector<int> member_start;\n\nvector<double> bottom_priority;\nvector<double> min_cost, avg_cost;\nvector<double> reach_score;\n\nconst int MAX_SKILL = 70;\n\ndouble base_skill;\nconst double PRIOR_COMP = 0.008;\nconst double PRIOR_NORM = 0.003;\nconst double NORM_TARGET = 40.0;\n\ninline double obsPenalty(int w, int t) {\n    static const double p1[5] = {\n        0.0,\n        -log(4.0 / 7.0),\n        -log(3.0 / 7.0),\n        -log(2.0 / 7.0),\n        -log(1.0 / 7.0)\n    };\n\n    if (t == 1) {\n        if (w <= 4) return p1[w];\n        double x = w - 4;\n        return 3.0 + 2.0 * x * x;\n    } else {\n        if (w == 0) {\n            return 5.0 + 1.0 * t * t;\n        }\n        int lo = max(1, t - 3);\n        int hi = t + 3;\n        if (w < lo) {\n            double x = lo - w;\n            return 2.0 * x * x;\n        }\n        if (w > hi) {\n            double x = w - hi;\n            return 2.0 * x * x;\n        }\n        return 1.0 + 0.04 * abs(w - t);\n    }\n}\n\ninline int calcWTaskSkill(int task, const vector<int>& s) {\n    int w = 0;\n    for (int k = 0; k < K; k++) {\n        if (D[task][k] > s[k]) w += D[task][k] - s[k];\n    }\n    return w;\n}\n\ninline double expectedDurationFromWInt(int w) {\n    if (w == 0) return 1.0;\n    if (w == 1) return 13.0 / 7.0;\n    if (w == 2) return 17.0 / 7.0;\n    if (w == 3) return 22.0 / 7.0;\n    return (double)w;\n}\n\ninline double expectedDurationFromWDouble(double w) {\n    if (w <= 0.0) return 1.0;\n\n    static const double table[5] = {\n        1.0,\n        13.0 / 7.0,\n        17.0 / 7.0,\n        22.0 / 7.0,\n        4.0\n    };\n\n    if (w < 4.0) {\n        int a = (int)floor(w);\n        double f = w - a;\n        return table[a] * (1.0 - f) + table[a + 1] * f;\n    }\n\n    return w;\n}\n\ninline double memberConfidence(int mem) {\n    int c = (int)records_[mem].size();\n\n    // Conservative early, almost fully trusted after sufficient observations.\n    return (double)c / ((double)c + 3.5);\n}\n\ninline double expectedDuration(int task, int mem) {\n    const auto& s = skill_est[mem];\n\n    double conf = memberConfidence(mem);\n    double w = 0.0;\n\n    for (int k = 0; k < K; k++) {\n        double eff_skill = base_skill + conf * ((double)s[k] - base_skill);\n        if ((double)D[task][k] > eff_skill) {\n            w += (double)D[task][k] - eff_skill;\n        }\n    }\n\n    return expectedDurationFromWDouble(w);\n}\n\nvoid optimizeMember(int mem) {\n    auto& recs = records_[mem];\n    if (recs.empty()) return;\n\n    vector<int>& s = skill_est[mem];\n    int Rm = (int)recs.size();\n\n    vector<int> curW(Rm, 0);\n    for (int r = 0; r < Rm; r++) {\n        curW[r] = calcWTaskSkill(recs[r].task, s);\n    }\n\n    double sumsq = 0.0;\n    for (int k = 0; k < K; k++) sumsq += 1.0 * s[k] * s[k];\n\n    int passes = 3;\n    if (Rm >= 12) passes = 4;\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool changed_any = false;\n\n        for (int k = 0; k < K; k++) {\n            int old = s[k];\n\n            double bestObj = 1e100;\n            int bestVal = old;\n\n            for (int val = 0; val <= MAX_SKILL; val++) {\n                double obj = 0.0;\n\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    int oldContrib = max(0, D[task][k] - old);\n                    int newContrib = max(0, D[task][k] - val);\n                    int nw = curW[r] - oldContrib + newContrib;\n                    obj += obsPenalty(nw, recs[r].dur);\n                }\n\n                double compPrior = PRIOR_COMP * (val - base_skill) * (val - base_skill);\n\n                double nsumsq = sumsq - 1.0 * old * old + 1.0 * val * val;\n                double norm = sqrt(nsumsq);\n                double normPrior = PRIOR_NORM * (norm - NORM_TARGET) * (norm - NORM_TARGET);\n\n                obj += compPrior + normPrior;\n\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestVal = val;\n                }\n            }\n\n            if (bestVal != old) {\n                for (int r = 0; r < Rm; r++) {\n                    int task = recs[r].task;\n                    curW[r] -= max(0, D[task][k] - old);\n                    curW[r] += max(0, D[task][k] - bestVal);\n                }\n\n                sumsq = sumsq - 1.0 * old * old + 1.0 * bestVal * bestVal;\n                s[k] = bestVal;\n                changed_any = true;\n            }\n        }\n\n        if (!changed_any) break;\n    }\n}\n\nvoid precomputeReachScore() {\n    vector<double> dp(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        double v = 0.0;\n\n        for (int c : children_[i]) {\n            v += 1.0 + dp[c];\n            if (v > 1e6) {\n                v = 1e6;\n                break;\n            }\n        }\n\n        dp[i] = v;\n    }\n\n    reach_score.assign(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        reach_score[i] = log1p(dp[i]);\n    }\n}\n\nvoid recomputePriorities() {\n    min_cost.assign(N, 0.0);\n    avg_cost.assign(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        if (status_[i] == 1) {\n            min_cost[i] = avg_cost[i] = 0.0;\n            continue;\n        }\n\n        double mn = 1e100;\n        double sum = 0.0;\n\n        for (int j = 0; j < M; j++) {\n            double e = expectedDuration(i, j);\n            mn = min(mn, e);\n            sum += e;\n        }\n\n        min_cost[i] = mn;\n        avg_cost[i] = sum / M;\n    }\n\n    bottom_priority.assign(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        if (status_[i] == 1) {\n            bottom_priority[i] = 0.0;\n            continue;\n        }\n\n        double nodeCost = 0.7 * min_cost[i] + 0.3 * avg_cost[i];\n\n        double mx = 0.0;\n        for (int c : children_[i]) {\n            mx = max(mx, bottom_priority[c]);\n        }\n\n        bottom_priority[i] = nodeCost + mx;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K >> R;\n\n    D.assign(N, vector<int>(K));\n\n    for (int i = 0; i < N; i++) {\n        for (int k = 0; k < K; k++) cin >> D[i][k];\n    }\n\n    children_.assign(N, {});\n    remdep.assign(N, 0);\n\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u;\n        --v;\n\n        children_[u].push_back(v);\n        remdep[v]++;\n    }\n\n    base_skill = 35.0 / sqrt((double)K);\n    int init_skill = max(0, (int)round(base_skill));\n\n    skill_est.assign(M, vector<int>(K, init_skill));\n    records_.assign(M, {});\n\n    status_.assign(N, -1);\n    member_task.assign(M, -1);\n    member_start.assign(M, -1);\n\n    precomputeReachScore();\n\n    for (int day = 1; day <= 2000; day++) {\n        recomputePriorities();\n\n        vector<int> free_members;\n        for (int j = 0; j < M; j++) {\n            if (member_task[j] == -1) free_members.push_back(j);\n        }\n\n        vector<int> ready;\n        for (int i = 0; i < N; i++) {\n            if (status_[i] == -1 && remdep[i] == 0) ready.push_back(i);\n        }\n\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (bottom_priority[a] != bottom_priority[b]) {\n                return bottom_priority[a] > bottom_priority[b];\n            }\n            if (reach_score[a] != reach_score[b]) {\n                return reach_score[a] > reach_score[b];\n            }\n            return a < b;\n        });\n\n        vector<pair<int, int>> assignments;\n\n        while (!free_members.empty()) {\n            int bestFi = -1;\n            int bestTask = -1;\n            double bestScore = -1e100;\n\n            int limit = min((int)ready.size(), 300);\n\n            for (int fi = 0; fi < (int)free_members.size(); fi++) {\n                int mem = free_members[fi];\n\n                for (int idx = 0; idx < limit; idx++) {\n                    int task = ready[idx];\n\n                    if (status_[task] != -1) continue;\n\n                    double pred = expectedDuration(task, mem);\n\n                    double score =\n                        bottom_priority[task]\n                        + 0.15 * reach_score[task]\n                        - 0.70 * pred\n                        + 0.20 * (avg_cost[task] - pred);\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestFi = fi;\n                        bestTask = task;\n                    }\n                }\n            }\n\n            if (bestFi == -1) break;\n\n            int mem = free_members[bestFi];\n\n            status_[bestTask] = 0;\n            member_task[mem] = bestTask;\n            member_start[mem] = day;\n\n            assignments.push_back({mem, bestTask});\n\n            free_members.erase(free_members.begin() + bestFi);\n        }\n\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << mem + 1 << ' ' << task + 1;\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        for (int i = 0; i < cnt; i++) {\n            int f;\n            cin >> f;\n            --f;\n\n            int task = member_task[f];\n            if (task < 0) continue;\n\n            int dur = day - member_start[f] + 1;\n\n            status_[task] = 1;\n            member_task[f] = -1;\n            member_start[f] = -1;\n\n            records_[f].push_back({task, dur});\n            optimizeMember(f);\n\n            for (int c : children_[task]) {\n                remdep[c]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int ax, ay, cx, cy;\n    int score;\n};\n\nstruct Node {\n    int x, y;\n    int id;   // -1 depot\n    int type; // 0 pickup, 1 delivery\n};\n\nstruct InsertInfo {\n    int cost;\n    int pgap;\n    int dgap;\n};\n\nstruct State {\n    vector<Node> route;\n    vector<int> selected;\n    vector<char> used;\n    int cost;\n};\n\nstatic const int N = 1000;\nstatic const int K = 50;\nstatic const int DEP = 400;\nstatic const int INF = 1e9;\n\nvector<Order> ords;\nchrono::steady_clock::time_point start_time;\n\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\ninline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline int ndist(const Node& a, const Node& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\ninline Node pickupNode(int id) {\n    return Node{ords[id].ax, ords[id].ay, id, 0};\n}\n\ninline Node deliveryNode(int id) {\n    return Node{ords[id].cx, ords[id].cy, id, 1};\n}\n\nint routeCost(const vector<Node>& route) {\n    int res = 0;\n    for (int i = 0; i + 1 < (int)route.size(); i++) {\n        res += ndist(route[i], route[i + 1]);\n    }\n    return res;\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    double nextDouble() {\n        return (next() + 0.5) / 4294967296.0;\n    }\n\n    int randint(int l, int r) {\n        return l + (int)(next() % (uint32_t)(r - l + 1));\n    }\n};\n\nXorShift rng;\n\n// O(route length) best insertion.\n// Pickup and delivery in same gap is handled separately.\n// For different gaps, pickup insertion cost + best suffix delivery insertion cost.\nInsertInfo bestInsert(const vector<Node>& route, int oid) {\n    const int L = (int)route.size();\n    const int G = L - 1; // number of gaps, indexed 0..G-1\n\n    const int px = ords[oid].ax;\n    const int py = ords[oid].ay;\n    const int dx = ords[oid].cx;\n    const int dy = ords[oid].cy;\n\n    int addD[128];\n    int suffCost[129];\n    int suffIdx[129];\n\n    for (int j = 0; j < G; j++) {\n        const Node& C = route[j];\n        const Node& D = route[j + 1];\n\n        addD[j] = mdist(C.x, C.y, dx, dy)\n                + mdist(dx, dy, D.x, D.y)\n                - ndist(C, D);\n    }\n\n    suffCost[G] = INF;\n    suffIdx[G] = -1;\n\n    for (int j = G - 1; j >= 0; j--) {\n        if (addD[j] <= suffCost[j + 1]) {\n            suffCost[j] = addD[j];\n            suffIdx[j] = j;\n        } else {\n            suffCost[j] = suffCost[j + 1];\n            suffIdx[j] = suffIdx[j + 1];\n        }\n    }\n\n    int best = INF;\n    int bestP = -1;\n    int bestD = -1;\n\n    for (int i = 0; i < G; i++) {\n        const Node& A = route[i];\n        const Node& B = route[i + 1];\n\n        int directAB = ndist(A, B);\n\n        // pickup and delivery inserted into same gap\n        int same = mdist(A.x, A.y, px, py)\n                 + mdist(px, py, dx, dy)\n                 + mdist(dx, dy, B.x, B.y)\n                 - directAB;\n\n        if (same < best) {\n            best = same;\n            bestP = i;\n            bestD = i;\n        }\n\n        // pickup at gap i, delivery at some later gap j > i\n        if (i + 1 < G) {\n            int addP = mdist(A.x, A.y, px, py)\n                     + mdist(px, py, B.x, B.y)\n                     - directAB;\n\n            int val = addP + suffCost[i + 1];\n\n            if (val < best) {\n                best = val;\n                bestP = i;\n                bestD = suffIdx[i + 1];\n            }\n        }\n    }\n\n    return InsertInfo{best, bestP, bestD};\n}\n\nvoid applyInsert(vector<Node>& route, int oid, const InsertInfo& ins) {\n    vector<Node> nr;\n    nr.reserve(route.size() + 2);\n\n    Node P = pickupNode(oid);\n    Node D = deliveryNode(oid);\n\n    for (int i = 0; i < (int)route.size(); i++) {\n        nr.push_back(route[i]);\n\n        if (i == ins.pgap) {\n            nr.push_back(P);\n            if (ins.dgap == ins.pgap) {\n                nr.push_back(D);\n            }\n        }\n\n        if (ins.dgap > ins.pgap && i == ins.dgap) {\n            nr.push_back(D);\n        }\n    }\n\n    route.swap(nr);\n}\n\nvector<Node> removeOrder(const vector<Node>& route, int oid) {\n    vector<Node> nr;\n    nr.reserve(route.size() - 2);\n    for (const auto& v : route) {\n        if (v.id != oid) nr.push_back(v);\n    }\n    return nr;\n}\n\nvoid buildPos(const State& st, int p[], int d[]) {\n    for (int oid : st.selected) {\n        p[oid] = -1;\n        d[oid] = -1;\n    }\n\n    for (int i = 1; i <= (int)st.route.size() - 2; i++) {\n        const Node& v = st.route[i];\n        if (v.type == 0) p[v.id] = i;\n        else d[v.id] = i;\n    }\n}\n\ninline bool feasibleReverseFast(const State& st, int l, int r, const int p[], const int d[]) {\n    for (int oid : st.selected) {\n        if (l <= p[oid] && d[oid] <= r) return false;\n    }\n    return true;\n}\n\ninline bool feasibleSwapFast(const State& st, int i, int j, const int p[], const int d[]) {\n    const Node& A = st.route[i];\n    const Node& B = st.route[j];\n\n    if (A.id == B.id) return false;\n\n    int idA = A.id;\n    int idB = B.id;\n\n    int pa = p[idA];\n    int da = d[idA];\n\n    if (A.type == 0) pa = j;\n    else da = j;\n\n    if (pa >= da) return false;\n\n    int pb = p[idB];\n    int db = d[idB];\n\n    if (B.type == 0) pb = i;\n    else db = i;\n\n    if (pb >= db) return false;\n\n    return true;\n}\n\nbool pairReinsertOptimize(State& st, double limitTime, int maxPass = 4) {\n    bool any = false;\n\n    for (int pass = 0; pass < maxPass && elapsed() < limitTime; pass++) {\n        bool improved = false;\n\n        for (int oid : st.selected) {\n            if (elapsed() >= limitTime) break;\n\n            vector<Node> rem = removeOrder(st.route, oid);\n            int remCost = routeCost(rem);\n\n            InsertInfo ins = bestInsert(rem, oid);\n            int newCost = remCost + ins.cost;\n\n            if (newCost < st.cost) {\n                st.route.swap(rem);\n                applyInsert(st.route, oid, ins);\n                st.cost = newCost;\n                improved = true;\n                any = true;\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nbool twoOptOptimize(State& st, double limitTime) {\n    bool any = false;\n    int n = (int)st.route.size();\n\n    static int p[N], d[N];\n\n    while (elapsed() < limitTime) {\n        buildPos(st, p, d);\n\n        int bestDelta = 0;\n        int bestL = -1;\n        int bestR = -1;\n\n        for (int l = 1; l <= n - 3; l++) {\n            for (int r = l + 1; r <= n - 2; r++) {\n                int delta = ndist(st.route[l - 1], st.route[r])\n                          + ndist(st.route[l], st.route[r + 1])\n                          - ndist(st.route[l - 1], st.route[l])\n                          - ndist(st.route[r], st.route[r + 1]);\n\n                if (delta < bestDelta && feasibleReverseFast(st, l, r, p, d)) {\n                    bestDelta = delta;\n                    bestL = l;\n                    bestR = r;\n                }\n            }\n        }\n\n        if (bestDelta >= 0) break;\n\n        reverse(st.route.begin() + bestL, st.route.begin() + bestR + 1);\n        st.cost += bestDelta;\n        any = true;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nbool swapOptimize(State& st, double limitTime) {\n    bool any = false;\n    int n = (int)st.route.size();\n\n    static int p[N], d[N];\n\n    while (elapsed() < limitTime) {\n        buildPos(st, p, d);\n\n        int bestDelta = 0;\n        int bestI = -1;\n        int bestJ = -1;\n\n        for (int i = 1; i <= n - 3; i++) {\n            for (int j = i + 1; j <= n - 2; j++) {\n                int delta;\n\n                if (i + 1 == j) {\n                    delta = ndist(st.route[i - 1], st.route[j])\n                          + ndist(st.route[j], st.route[i])\n                          + ndist(st.route[i], st.route[j + 1])\n                          - ndist(st.route[i - 1], st.route[i])\n                          - ndist(st.route[i], st.route[j])\n                          - ndist(st.route[j], st.route[j + 1]);\n                } else {\n                    delta = ndist(st.route[i - 1], st.route[j])\n                          + ndist(st.route[j], st.route[i + 1])\n                          + ndist(st.route[j - 1], st.route[i])\n                          + ndist(st.route[i], st.route[j + 1])\n                          - ndist(st.route[i - 1], st.route[i])\n                          - ndist(st.route[i], st.route[i + 1])\n                          - ndist(st.route[j - 1], st.route[j])\n                          - ndist(st.route[j], st.route[j + 1]);\n                }\n\n                if (delta < bestDelta && feasibleSwapFast(st, i, j, p, d)) {\n                    bestDelta = delta;\n                    bestI = i;\n                    bestJ = j;\n                }\n            }\n        }\n\n        if (bestDelta >= 0) break;\n\n        swap(st.route[bestI], st.route[bestJ]);\n        st.cost += bestDelta;\n        any = true;\n    }\n\n    st.cost = routeCost(st.route);\n    return any;\n}\n\nvoid routeLocalOptimize(State& st, double limitTime, bool heavy) {\n    while (elapsed() < limitTime) {\n        int before = st.cost;\n\n        pairReinsertOptimize(st, limitTime, 3);\n        twoOptOptimize(st, limitTime);\n\n        if (heavy) {\n            swapOptimize(st, limitTime);\n            twoOptOptimize(st, limitTime);\n            pairReinsertOptimize(st, limitTime, 2);\n        }\n\n        st.cost = routeCost(st.route);\n\n        if (st.cost >= before) break;\n    }\n}\n\nState constructGreedy(const vector<int>& pool, int randomTop) {\n    Node depot{DEP, DEP, -1, -1};\n\n    State st;\n    st.route = {depot, depot};\n    st.used.assign(N, 0);\n    st.selected.clear();\n    st.cost = 0;\n\n    struct Choice {\n        int cost;\n        int oid;\n        InsertInfo ins;\n    };\n\n    for (int step = 0; step < K; step++) {\n        vector<Choice> top;\n        top.reserve(randomTop);\n\n        for (int oid : pool) {\n            if (st.used[oid]) continue;\n\n            InsertInfo ins = bestInsert(st.route, oid);\n            Choice ch{ins.cost, oid, ins};\n\n            if ((int)top.size() < randomTop) {\n                top.push_back(ch);\n            } else {\n                int worst = 0;\n                for (int i = 1; i < (int)top.size(); i++) {\n                    if (top[i].cost > top[worst].cost) worst = i;\n                }\n                if (ch.cost < top[worst].cost) top[worst] = ch;\n            }\n        }\n\n        sort(top.begin(), top.end(), [](const Choice& a, const Choice& b) {\n            return a.cost < b.cost;\n        });\n\n        int idx = 0;\n        if (randomTop > 1 && (int)top.size() > 1) {\n            int lim = (int)top.size();\n            double u = rng.nextDouble();\n            idx = min(lim - 1, (int)(u * u * lim));\n        }\n\n        Choice ch = top[idx];\n\n        applyInsert(st.route, ch.oid, ch.ins);\n        st.used[ch.oid] = 1;\n        st.selected.push_back(ch.oid);\n        st.cost += ch.ins.cost;\n    }\n\n    st.cost = routeCost(st.route);\n    return st;\n}\n\nvector<int> makeClusterPool(int cx, int cy, int M) {\n    vector<pair<int, int>> v;\n    v.reserve(N);\n\n    for (int i = 0; i < N; i++) {\n        int cluster = mdist(ords[i].ax, ords[i].ay, cx, cy)\n                    + mdist(ords[i].cx, ords[i].cy, cx, cy);\n\n        int center = mdist(ords[i].ax, ords[i].ay, DEP, DEP)\n                   + mdist(ords[i].cx, ords[i].cy, DEP, DEP);\n\n        int paird = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        int sc = cluster * 10 + center * 3 + paird;\n        v.push_back({sc, i});\n    }\n\n    if (M < N) {\n        nth_element(v.begin(), v.begin() + M, v.end());\n        v.resize(M);\n    }\n\n    sort(v.begin(), v.end());\n\n    vector<int> pool;\n    pool.reserve(v.size());\n    for (auto [_, id] : v) pool.push_back(id);\n\n    return pool;\n}\n\nvoid replaceOptimize(State& st, const vector<int>& candList, double limitTime) {\n    while (elapsed() < limitTime) {\n        int bestNewCost = st.cost;\n        int bestRemove = -1;\n        int bestAdd = -1;\n\n        int checks = 0;\n        bool timeout = false;\n\n        for (int remOid : st.selected) {\n            vector<Node> remRoute = removeOrder(st.route, remOid);\n            int remCost = routeCost(remRoute);\n\n            for (int addOid : candList) {\n                if (st.used[addOid]) continue;\n\n                InsertInfo ins = bestInsert(remRoute, addOid);\n                int newCost = remCost + ins.cost;\n\n                if (newCost < bestNewCost) {\n                    bestNewCost = newCost;\n                    bestRemove = remOid;\n                    bestAdd = addOid;\n                }\n\n                if ((++checks & 511) == 0 && elapsed() > limitTime) {\n                    timeout = true;\n                    break;\n                }\n            }\n\n            if (timeout) break;\n        }\n\n        if (bestRemove == -1) break;\n\n        vector<Node> remRoute = removeOrder(st.route, bestRemove);\n        InsertInfo ins = bestInsert(remRoute, bestAdd);\n\n        st.route.swap(remRoute);\n        applyInsert(st.route, bestAdd, ins);\n\n        st.used[bestRemove] = 0;\n        st.used[bestAdd] = 1;\n\n        for (int& x : st.selected) {\n            if (x == bestRemove) {\n                x = bestAdd;\n                break;\n            }\n        }\n\n        st.cost = routeCost(st.route);\n        routeLocalOptimize(st, min(limitTime, elapsed() + 0.08), false);\n\n        if (timeout) break;\n    }\n\n    st.cost = routeCost(st.route);\n}\n\nvoid destroyRepairOptimize(State& best, const vector<int>& candList, double limitTime) {\n    vector<int> cand;\n    int lim = min((int)candList.size(), 850);\n    cand.reserve(lim);\n\n    for (int i = 0; i < lim; i++) {\n        cand.push_back(candList[i]);\n    }\n\n    while (elapsed() < limitTime) {\n        State cur = best;\n\n        int q = rng.randint(2, 5);\n\n        vector<pair<int, int>> saving;\n        saving.reserve(K);\n\n        for (int oid : cur.selected) {\n            vector<Node> rem = removeOrder(cur.route, oid);\n            int rc = routeCost(rem);\n            saving.push_back({cur.cost - rc, oid});\n        }\n\n        sort(saving.begin(), saving.end(), greater<pair<int, int>>());\n\n        vector<int> removed;\n        vector<char> remFlag(N, 0);\n\n        int topRange = min((int)saving.size(), 18);\n\n        for (int t = 0; t < q; t++) {\n            int idx;\n            if (rng.nextDouble() < 0.70) {\n                idx = rng.randint(0, topRange - 1);\n            } else {\n                idx = rng.randint(0, (int)saving.size() - 1);\n            }\n\n            int oid = saving[idx].second;\n\n            if (remFlag[oid]) {\n                t--;\n                continue;\n            }\n\n            remFlag[oid] = 1;\n            removed.push_back(oid);\n        }\n\n        vector<Node> nr;\n        nr.reserve(cur.route.size() - 2 * removed.size());\n\n        for (const Node& v : cur.route) {\n            if (v.id != -1 && remFlag[v.id]) continue;\n            nr.push_back(v);\n        }\n\n        cur.route.swap(nr);\n\n        vector<int> ns;\n        ns.reserve(K);\n\n        for (int oid : cur.selected) {\n            if (!remFlag[oid]) {\n                ns.push_back(oid);\n            } else {\n                cur.used[oid] = 0;\n            }\n        }\n\n        cur.selected.swap(ns);\n        cur.cost = routeCost(cur.route);\n\n        while ((int)cur.selected.size() < K && elapsed() < limitTime) {\n            int bestAdd = -1;\n            InsertInfo bestIns{INF, -1, -1};\n\n            for (int oid : cand) {\n                if (cur.used[oid]) continue;\n\n                InsertInfo ins = bestInsert(cur.route, oid);\n\n                if (ins.cost < bestIns.cost) {\n                    bestIns = ins;\n                    bestAdd = oid;\n                }\n            }\n\n            if (bestAdd == -1) break;\n\n            applyInsert(cur.route, bestAdd, bestIns);\n            cur.used[bestAdd] = 1;\n            cur.selected.push_back(bestAdd);\n            cur.cost += bestIns.cost;\n        }\n\n        if ((int)cur.selected.size() != K) continue;\n\n        cur.cost = routeCost(cur.route);\n        routeLocalOptimize(cur, min(limitTime, elapsed() + 0.05), false);\n\n        if (cur.cost < best.cost) {\n            best = cur;\n        }\n    }\n\n    best.cost = routeCost(best.route);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    ords.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> ords[i].ax >> ords[i].ay >> ords[i].cx >> ords[i].cy;\n\n        int centerSum = mdist(DEP, DEP, ords[i].ax, ords[i].ay)\n                      + mdist(DEP, DEP, ords[i].cx, ords[i].cy);\n\n        int pairDist = mdist(ords[i].ax, ords[i].ay, ords[i].cx, ords[i].cy);\n\n        ords[i].score = centerSum + pairDist / 2;\n    }\n\n    vector<int> allIds(N);\n    iota(allIds.begin(), allIds.end(), 0);\n\n    vector<int> sortedIds = allIds;\n\n    sort(sortedIds.begin(), sortedIds.end(), [](int a, int b) {\n        return ords[a].score < ords[b].score;\n    });\n\n    State best = constructGreedy(allIds, 1);\n    routeLocalOptimize(best, 0.35, true);\n\n    vector<int> centerPool;\n    centerPool.reserve(750);\n\n    for (int i = 0; i < 750; i++) {\n        centerPool.push_back(sortedIds[i]);\n    }\n\n    int iter = 0;\n\n    while (elapsed() < 1.05) {\n        vector<int> pool;\n\n        if (iter % 4 == 0) {\n            int base = sortedIds[rng.randint(0, 499)];\n\n            int cx = (ords[base].ax + ords[base].cx) / 2 + rng.randint(-80, 80);\n            int cy = (ords[base].ay + ords[base].cy) / 2 + rng.randint(-80, 80);\n\n            cx = max(150, min(650, cx));\n            cy = max(150, min(650, cy));\n\n            pool = makeClusterPool(cx, cy, 450);\n        } else if (iter % 4 == 1) {\n            pool = makeClusterPool(\n                400 + rng.randint(-160, 160),\n                400 + rng.randint(-160, 160),\n                450\n            );\n        } else {\n            pool = centerPool;\n        }\n\n        State cur = constructGreedy(pool, 7);\n        routeLocalOptimize(cur, min(1.20, elapsed() + 0.05), false);\n\n        if (cur.cost < best.cost) {\n            best = cur;\n        }\n\n        iter++;\n    }\n\n    routeLocalOptimize(best, 1.35, true);\n\n    vector<int> replaceCand;\n    replaceCand.reserve(N);\n\n    for (int i = 0; i < N; i++) {\n        replaceCand.push_back(sortedIds[i]);\n    }\n\n    replaceOptimize(best, replaceCand, 1.80);\n\n    destroyRepairOptimize(best, replaceCand, 1.93);\n\n    routeLocalOptimize(best, 1.975, true);\n\n    cout << K;\n    for (int oid : best.selected) {\n        cout << ' ' << oid + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (const Node& v : best.route) {\n        cout << ' ' << v.x << ' ' << v.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 400;\nstatic constexpr int M = 1995;\nstatic constexpr int SAMPLES = 96;\n\n// Fractional bias, approximately 2.17 per sample.\n// bias=2 was best so far, bias=3 was too aggressive.\n// This tests a very small increase over bias=2.\nstatic constexpr long long ACCEPT_THRESHOLD = 208;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n};\n\nstruct DSU {\n    int16_t p[N];\n    int16_t sz[N];\n\n    inline void init() {\n        for (int i = 0; i < N; i++) {\n            p[i] = i;\n            sz[i] = 1;\n        }\n    }\n\n    inline int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    inline bool same(int a, int b) {\n        return find(a) == find(b);\n    }\n\n    inline bool unite(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n\n        if (ra == rb) return false;\n\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n\n        return true;\n    }\n};\n\nstruct SmallDSU {\n    int16_t p[N];\n    int16_t sz[N];\n\n    inline void init(int n) {\n        for (int i = 0; i < n; i++) {\n            p[i] = i;\n            sz[i] = 1;\n        }\n    }\n\n    inline int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    inline bool same(int a, int b) {\n        return find(a) == find(b);\n    }\n\n    inline bool unite(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n\n        if (ra == rb) return false;\n\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n\n        return true;\n    }\n};\n\nstatic uint16_t sampled_w[SAMPLES][M];\nstatic int16_t nxt_edge[SAMPLES][M];\nstatic int16_t prv_edge[SAMPLES][M];\nstatic int16_t head_edge[SAMPLES];\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> x(N), y(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<int16_t> u(M), v(M);\n    vector<int> d(M);\n\n    for (int i = 0; i < M; i++) {\n        int a, b;\n        cin >> a >> b;\n\n        u[i] = int16_t(a);\n        v[i] = int16_t(b);\n\n        long long dx = x[a] - x[b];\n        long long dy = y[a] - y[b];\n\n        d[i] = int(floor(sqrt(double(dx * dx + dy * dy)) + 0.5));\n    }\n\n    XorShift rng;\n\n    // Plain random Monte Carlo samples.\n    for (int s = 0; s < SAMPLES; s++) {\n        for (int i = 0; i < M; i++) {\n            sampled_w[s][i] = uint16_t(rng.randint(d[i], 3 * d[i]));\n        }\n    }\n\n    /*\n        For each sample scenario, keep future edges sorted by sampled weight.\n        During the online process, the current edge is removed from all lists.\n    */\n    for (int s = 0; s < SAMPLES; s++) {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (sampled_w[s][a] != sampled_w[s][b]) {\n                return sampled_w[s][a] < sampled_w[s][b];\n            }\n            return a < b;\n        });\n\n        head_edge[s] = int16_t(ord[0]);\n\n        for (int i = 0; i < M; i++) {\n            int e = ord[i];\n\n            prv_edge[s][e] = int16_t(i == 0 ? -1 : ord[i - 1]);\n            nxt_edge[s][e] = int16_t(i + 1 == M ? -1 : ord[i + 1]);\n        }\n    }\n\n    DSU accepted;\n    accepted.init();\n\n    static int16_t root_to_cid[N];\n    static int16_t vertex_cid[N];\n\n    static int16_t edge_a[M];\n    static int16_t edge_b[M];\n\n    for (int cur = 0; cur < M; cur++) {\n        int len;\n        cin >> len;\n\n        // Remove current edge from every future-edge sorted linked list.\n        for (int s = 0; s < SAMPLES; s++) {\n            int p = prv_edge[s][cur];\n            int n = nxt_edge[s][cur];\n\n            if (p == -1) {\n                head_edge[s] = int16_t(n);\n            } else {\n                nxt_edge[s][p] = int16_t(n);\n            }\n\n            if (n != -1) {\n                prv_edge[s][n] = int16_t(p);\n            }\n        }\n\n        int answer = 0;\n\n        if (!accepted.same(u[cur], v[cur])) {\n            fill(root_to_cid, root_to_cid + N, int16_t(-1));\n\n            int comp_count = 0;\n\n            for (int i = 0; i < N; i++) {\n                int r = accepted.find(i);\n\n                if (root_to_cid[r] == -1) {\n                    root_to_cid[r] = int16_t(comp_count++);\n                }\n\n                vertex_cid[i] = root_to_cid[r];\n            }\n\n            int start_comp = vertex_cid[u[cur]];\n            int goal_comp = vertex_cid[v[cur]];\n\n            // Contract endpoints of all edges once for this decision.\n            for (int e = 0; e < M; e++) {\n                int a = vertex_cid[u[e]];\n                int b = vertex_cid[v[e]];\n\n                if (a == b) {\n                    edge_a[e] = -1;\n                    edge_b[e] = -1;\n                } else {\n                    edge_a[e] = int16_t(a);\n                    edge_b[e] = int16_t(b);\n                }\n            }\n\n            /*\n                Safety check.\n\n                If accepted edges plus all future edges excluding current\n                cannot connect the graph, current edge is mandatory.\n            */\n            bool reject_possible = true;\n\n            {\n                SmallDSU reach;\n                reach.init(comp_count);\n\n                int c = comp_count;\n\n                for (int e = cur + 1; e < M; e++) {\n                    int a = edge_a[e];\n                    if (a == -1) continue;\n\n                    int b = edge_b[e];\n\n                    if (reach.unite(a, b)) {\n                        c--;\n\n                        if (c == 1) break;\n                    }\n                }\n\n                if (c > 1) {\n                    reject_possible = false;\n                }\n            }\n\n            if (!reject_possible) {\n                answer = 1;\n            } else {\n                long long sum_delta = 0;\n\n                /*\n                    For each sampled future world:\n                    Run Kruskal after rejecting current edge, but stop as soon\n                    as the two endpoint components become connected.\n\n                    The connection weight equals the maximum edge weight on\n                    their path in the reject-MST.\n\n                    Forcing current edge changes sampled completion cost by:\n\n                        len - connection_weight\n                */\n                for (int s = 0; s < SAMPLES; s++) {\n                    SmallDSU dsu;\n                    dsu.init(comp_count);\n\n                    int connect_weight = 0;\n\n                    for (int e = head_edge[s]; e != -1; e = nxt_edge[s][e]) {\n                        int a = edge_a[e];\n\n                        if (a == -1) continue;\n\n                        int b = edge_b[e];\n\n                        if (dsu.unite(a, b)) {\n                            if (dsu.same(start_comp, goal_comp)) {\n                                connect_weight = sampled_w[s][e];\n                                break;\n                            }\n                        }\n                    }\n\n                    sum_delta += (long long)len - connect_weight;\n                }\n\n                if (sum_delta < ACCEPT_THRESHOLD) {\n                    answer = 1;\n                }\n            }\n\n            if (answer) {\n                accepted.unite(u[cur], v[cur]);\n            }\n        }\n\n        cout << answer << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nstruct Task {\n    int sx, sy;\n    int wx, wy;\n};\n\nstruct Plan {\n    // kind:\n    // 0 = corner rectangle\n    // 1 = full edge strip\n    // 2 = edge-middle rectangle\n    int kind = 0;\n    int ori = 0;\n    int H = 10;\n    int W = 10;\n    int ax = 1;\n    int ay = 1;\n    int plannedPets = 0;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\n\nbool wall_[31][31];\n\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char mvChar[4] = {'U', 'D', 'L', 'R'};\nconst char buildChar[4] = {'u', 'd', 'l', 'r'};\n\nPlan plan_;\nint x1_, x2_, y1_, y2_;\nvector<Task> tasks;\n\nbool inBoard(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nbool passable(int x, int y) {\n    return inBoard(x, y) && !wall_[x][y];\n}\n\nvoid getBoundsParam(const Plan &p, int &x1, int &x2, int &y1, int &y2) {\n    if (p.kind == 0) {\n        int H = p.H;\n        int W = p.W;\n\n        if (p.ori == 0) {\n            x1 = 1;\n            x2 = H;\n            y1 = 1;\n            y2 = W;\n        } else if (p.ori == 1) {\n            x1 = 1;\n            x2 = H;\n            y1 = 31 - W;\n            y2 = 30;\n        } else if (p.ori == 2) {\n            x1 = 31 - H;\n            x2 = 30;\n            y1 = 1;\n            y2 = W;\n        } else {\n            x1 = 31 - H;\n            x2 = 30;\n            y1 = 31 - W;\n            y2 = 30;\n        }\n    } else if (p.kind == 1) {\n        int S = p.H;\n\n        if (p.ori == 0) {\n            x1 = 1;\n            x2 = S;\n            y1 = 1;\n            y2 = 30;\n        } else if (p.ori == 1) {\n            x1 = 31 - S;\n            x2 = 30;\n            y1 = 1;\n            y2 = 30;\n        } else if (p.ori == 2) {\n            x1 = 1;\n            x2 = 30;\n            y1 = 1;\n            y2 = S;\n        } else {\n            x1 = 1;\n            x2 = 30;\n            y1 = 31 - S;\n            y2 = 30;\n        }\n    } else {\n        x1 = p.ax;\n        x2 = p.ax + p.H - 1;\n        y1 = p.ay;\n        y2 = p.ay + p.W - 1;\n    }\n}\n\nvoid setRegionBounds() {\n    getBoundsParam(plan_, x1_, x2_, y1_, y2_);\n}\n\nbool insideRegion(int x, int y) {\n    return x1_ <= x && x <= x2_ && y1_ <= y && y <= y2_;\n}\n\nbool insideParam(int x, int y, const Plan &p) {\n    int a, b, c, d;\n    getBoundsParam(p, a, b, c, d);\n    return a <= x && x <= b && c <= y && y <= d;\n}\n\nint areaOfPlan(const Plan &p) {\n    if (p.kind == 1) return p.H * 30;\n    return p.H * p.W;\n}\n\nint taskCountOfPlan(const Plan &p) {\n    if (p.kind == 0) return p.H + p.W;\n    if (p.kind == 1) return 30;\n\n    // edge-middle rectangle\n    if (p.ori == 0 || p.ori == 1) return p.W + 2 * p.H;\n    return p.H + 2 * p.W;\n}\n\nint distToRegion(int x, int y, const Plan &p) {\n    int a, b, c, d;\n    getBoundsParam(p, a, b, c, d);\n\n    int res = 0;\n    if (x < a) res += a - x;\n    if (x > b) res += x - b;\n    if (y < c) res += c - y;\n    if (y > d) res += y - d;\n    return res;\n}\n\nint petsInsidePlan(const Plan &p) {\n    int cnt = 0;\n    for (auto &pet : pets) {\n        if (insideParam(pet.x, pet.y, p)) cnt++;\n    }\n    return cnt;\n}\n\nint petsInsideCurrent() {\n    int cnt = 0;\n    for (auto &pet : pets) {\n        if (insideRegion(pet.x, pet.y)) cnt++;\n    }\n    return cnt;\n}\n\nint humansInsideCurrent() {\n    int cnt = 0;\n    for (auto &h : humans) {\n        if (insideRegion(h.x, h.y)) cnt++;\n    }\n    return cnt;\n}\n\nvoid makeTasks() {\n    tasks.clear();\n    setRegionBounds();\n\n    if (plan_.kind == 0) {\n        int H = plan_.H;\n        int W = plan_.W;\n\n        if (plan_.ori == 0) {\n            for (int c = 1; c <= W; c++) tasks.push_back({H, c, H + 1, c});\n            for (int r = 1; r <= H; r++) tasks.push_back({r, W, r, W + 1});\n        } else if (plan_.ori == 1) {\n            int L = 31 - W;\n            for (int c = L; c <= 30; c++) tasks.push_back({H, c, H + 1, c});\n            for (int r = 1; r <= H; r++) tasks.push_back({r, L, r, L - 1});\n        } else if (plan_.ori == 2) {\n            int U = 31 - H;\n            for (int c = 1; c <= W; c++) tasks.push_back({U, c, U - 1, c});\n            for (int r = U; r <= 30; r++) tasks.push_back({r, W, r, W + 1});\n        } else {\n            int U = 31 - H;\n            int L = 31 - W;\n            for (int c = L; c <= 30; c++) tasks.push_back({U, c, U - 1, c});\n            for (int r = U; r <= 30; r++) tasks.push_back({r, L, r, L - 1});\n        }\n    } else if (plan_.kind == 1) {\n        int S = plan_.H;\n\n        if (plan_.ori == 0) {\n            for (int c = 1; c <= 30; c++) tasks.push_back({S, c, S + 1, c});\n        } else if (plan_.ori == 1) {\n            int U = 31 - S;\n            for (int c = 1; c <= 30; c++) tasks.push_back({U, c, U - 1, c});\n        } else if (plan_.ori == 2) {\n            for (int r = 1; r <= 30; r++) tasks.push_back({r, S, r, S + 1});\n        } else {\n            int L = 31 - S;\n            for (int r = 1; r <= 30; r++) tasks.push_back({r, L, r, L - 1});\n        }\n    } else {\n        int a = x1_, b = x2_, c = y1_, d = y2_;\n\n        if (plan_.ori == 0) {\n            // touching top edge: bottom + left + right\n            for (int y = c; y <= d; y++) tasks.push_back({b, y, b + 1, y});\n            for (int x = a; x <= b; x++) {\n                tasks.push_back({x, c, x, c - 1});\n                tasks.push_back({x, d, x, d + 1});\n            }\n        } else if (plan_.ori == 1) {\n            // touching bottom edge: top + left + right\n            for (int y = c; y <= d; y++) tasks.push_back({a, y, a - 1, y});\n            for (int x = a; x <= b; x++) {\n                tasks.push_back({x, c, x, c - 1});\n                tasks.push_back({x, d, x, d + 1});\n            }\n        } else if (plan_.ori == 2) {\n            // touching left edge: right + top + bottom\n            for (int x = a; x <= b; x++) tasks.push_back({x, d, x, d + 1});\n            for (int y = c; y <= d; y++) {\n                tasks.push_back({a, y, a - 1, y});\n                tasks.push_back({b, y, b + 1, y});\n            }\n        } else {\n            // touching right edge: left + top + bottom\n            for (int x = a; x <= b; x++) tasks.push_back({x, c, x, c - 1});\n            for (int y = c; y <= d; y++) {\n                tasks.push_back({a, y, a - 1, y});\n                tasks.push_back({b, y, b + 1, y});\n            }\n        }\n    }\n}\n\ndouble evaluatePlan(const Plan &p, bool conservativeStripPenalty) {\n    int pcnt = petsInsidePlan(p);\n\n    double avgDist = 0;\n    for (auto &h : humans) {\n        avgDist += distToRegion(h.x, h.y, p);\n    }\n    avgDist /= M;\n\n    int area = areaOfPlan(p);\n    int taskCnt = taskCountOfPlan(p);\n\n    double val = area * pow(0.5, pcnt)\n               - 1.8 * avgDist\n               - 0.35 * taskCnt;\n\n    if (p.kind == 1 && conservativeStripPenalty) {\n        val -= 25.0;\n        if (pcnt >= 3) val -= 100.0;\n    }\n\n    if (p.kind == 2) {\n        val -= 18.0;\n        val -= 0.15 * taskCnt;\n    }\n\n    return val;\n}\n\nvoid selectPlan(bool allowAdvanced) {\n    Plan bestSquare;\n    double bestSquareVal = -1e100;\n\n    for (int ori = 0; ori < 4; ori++) {\n        for (int S = 8; S <= 18; S++) {\n            Plan p;\n            p.kind = 0;\n            p.ori = ori;\n            p.H = S;\n            p.W = S;\n            p.plannedPets = petsInsidePlan(p);\n\n            double val = evaluatePlan(p, false);\n\n            if (val > bestSquareVal) {\n                bestSquareVal = val;\n                bestSquare = p;\n            }\n        }\n    }\n\n    Plan best = bestSquare;\n    double bestVal = bestSquareVal;\n\n    if (allowAdvanced) {\n        for (int ori = 0; ori < 4; ori++) {\n            for (int H = 6; H <= 18; H++) {\n                for (int W = 6; W <= 18; W++) {\n                    int mn = min(H, W);\n                    int mx = max(H, W);\n                    if (mn * 2 < mx) continue;\n\n                    Plan p;\n                    p.kind = 0;\n                    p.ori = ori;\n                    p.H = H;\n                    p.W = W;\n                    p.plannedPets = petsInsidePlan(p);\n\n                    double val = evaluatePlan(p, false);\n\n                    if (val > bestVal + 18.0) {\n                        bestVal = val;\n                        best = p;\n                    }\n                }\n            }\n        }\n\n        for (int ori = 0; ori < 4; ori++) {\n            for (int S = 8; S <= 22; S++) {\n                Plan p;\n                p.kind = 1;\n                p.ori = ori;\n                p.H = S;\n                p.W = 30;\n                p.plannedPets = petsInsidePlan(p);\n\n                if (p.plannedPets > 2) continue;\n\n                double val = evaluatePlan(p, true);\n\n                if (val > bestVal + 40.0) {\n                    bestVal = val;\n                    best = p;\n                }\n            }\n        }\n\n        // Conservative edge-middle rectangle fallback.\n        // Choose only if initially pet-free and clearly better.\n        for (int ori = 0; ori < 4; ori++) {\n            if (ori == 0 || ori == 1) {\n                // top / bottom edge: H is depth, W is horizontal length\n                for (int H = 5; H <= 13; H++) {\n                    for (int W = 8; W <= 22; W++) {\n                        int taskCnt = W + 2 * H;\n                        if (taskCnt > 44) continue;\n\n                        for (int L = 2; L + W - 1 <= 29; L++) {\n                            Plan p;\n                            p.kind = 2;\n                            p.ori = ori;\n                            p.H = H;\n                            p.W = W;\n                            p.ax = (ori == 0 ? 1 : 31 - H);\n                            p.ay = L;\n                            p.plannedPets = petsInsidePlan(p);\n\n                            if (p.plannedPets != 0) continue;\n\n                            double val = evaluatePlan(p, false);\n                            if (val > bestVal + 52.0) {\n                                bestVal = val;\n                                best = p;\n                            }\n                        }\n                    }\n                }\n            } else {\n                // left / right edge: H is vertical length, W is depth\n                for (int H = 8; H <= 22; H++) {\n                    for (int W = 5; W <= 13; W++) {\n                        int taskCnt = H + 2 * W;\n                        if (taskCnt > 44) continue;\n\n                        for (int U = 2; U + H - 1 <= 29; U++) {\n                            Plan p;\n                            p.kind = 2;\n                            p.ori = ori;\n                            p.H = H;\n                            p.W = W;\n                            p.ax = U;\n                            p.ay = (ori == 2 ? 1 : 31 - W);\n                            p.plannedPets = petsInsidePlan(p);\n\n                            if (p.plannedPets != 0) continue;\n\n                            double val = evaluatePlan(p, false);\n                            if (val > bestVal + 52.0) {\n                                bestVal = val;\n                                best = p;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    best.plannedPets = petsInsidePlan(best);\n    plan_ = best;\n    makeTasks();\n}\n\nbool allHumansInside() {\n    return humansInsideCurrent() == M;\n}\n\nbool allTasksDone() {\n    for (auto &t : tasks) {\n        if (!wall_[t.wx][t.wy]) return false;\n    }\n    return true;\n}\n\nchar dirFromTo(int x1, int y1, int x2, int y2, bool build) {\n    for (int d = 0; d < 4; d++) {\n        if (x1 + dx[d] == x2 && y1 + dy[d] == y2) {\n            return build ? buildChar[d] : mvChar[d];\n        }\n    }\n    return '.';\n}\n\nbool validBuildTarget(\n    int x,\n    int y,\n    const bool occH[31][31],\n    const bool occP[31][31]\n) {\n    if (!inBoard(x, y)) return false;\n    if (occH[x][y]) return false;\n    if (occP[x][y]) return false;\n\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n\n        if (inBoard(nx, ny) && occP[nx][ny]) return false;\n    }\n\n    return true;\n}\n\nvoid bfsAll(\n    int sx,\n    int sy,\n    const bool avoid[31][31],\n    bool restrictInside,\n    int dist[31][31],\n    char first[31][31]\n) {\n    for (int i = 1; i <= 30; i++) {\n        for (int j = 1; j <= 30; j++) {\n            dist[i][j] = -1;\n            first[i][j] = '.';\n        }\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();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d];\n            int ny = y + dy[d];\n\n            if (!inBoard(nx, ny)) continue;\n            if (!passable(nx, ny)) continue;\n            if (avoid[nx][ny]) continue;\n            if (restrictInside && !insideRegion(nx, ny)) continue;\n            if (dist[nx][ny] != -1) continue;\n\n            dist[nx][ny] = dist[x][y] + 1;\n            first[nx][ny] = (x == sx && y == sy) ? mvChar[d] : first[x][y];\n            q.push({nx, ny});\n        }\n    }\n}\n\nchar bfsMove(\n    int sx,\n    int sy,\n    const vector<pair<int,int>> &targets,\n    const bool avoid[31][31],\n    bool restrictInside\n) {\n    if (targets.empty()) return '.';\n\n    bool isTarget[31][31] = {};\n    for (auto [x, y] : targets) {\n        if (!inBoard(x, y)) continue;\n        if (!passable(x, y)) continue;\n        if (restrictInside && !insideRegion(x, y)) continue;\n        isTarget[x][y] = true;\n    }\n\n    if (isTarget[sx][sy]) return '.';\n\n    int dist[31][31];\n    char first[31][31];\n    bfsAll(sx, sy, avoid, restrictInside, dist, first);\n\n    int bestD = 1e9;\n    char bestC = '.';\n\n    for (int x = 1; x <= 30; x++) {\n        for (int y = 1; y <= 30; y++) {\n            if (!isTarget[x][y]) continue;\n            if (dist[x][y] == -1) continue;\n\n            if (dist[x][y] < bestD) {\n                bestD = dist[x][y];\n                bestC = first[x][y];\n            }\n        }\n    }\n\n    return bestC;\n}\n\nvector<pair<int,int>> insideCells() {\n    vector<pair<int,int>> res;\n\n    for (int x = x1_; x <= x2_; x++) {\n        for (int y = y1_; y <= y2_; y++) {\n            if (passable(x, y)) res.push_back({x, y});\n        }\n    }\n\n    return res;\n}\n\npair<int,int> centerCell() {\n    return {(x1_ + x2_) / 2, (y1_ + y2_) / 2};\n}\n\nvoid assignMovesByDP(\n    string &ans,\n    const vector<pair<int,int>> &targetsRaw,\n    const bool avoid[31][31]\n) {\n    vector<pair<int,int>> targets;\n    bool seen[31][31] = {};\n\n    for (auto [x, y] : targetsRaw) {\n        if (!inBoard(x, y)) continue;\n        if (!passable(x, y)) continue;\n        if (!insideRegion(x, y)) continue;\n        if (seen[x][y]) continue;\n\n        seen[x][y] = true;\n        targets.push_back({x, y});\n    }\n\n    if (targets.empty()) return;\n\n    vector<int> ids;\n    for (int i = 0; i < M; i++) {\n        if (ans[i] == '.' && insideRegion(humans[i].x, humans[i].y)) {\n            ids.push_back(i);\n        }\n    }\n\n    int K = ids.size();\n    int T = targets.size();\n\n    if (K == 0) return;\n\n    vector<vector<int>> distHT(K, vector<int>(T, -1));\n    vector<vector<char>> firstHT(K, vector<char>(T, '.'));\n\n    for (int i = 0; i < K; i++) {\n        int hid = ids[i];\n\n        int dist[31][31];\n        char first[31][31];\n\n        bfsAll(\n            humans[hid].x,\n            humans[hid].y,\n            avoid,\n            true,\n            dist,\n            first\n        );\n\n        for (int j = 0; j < T; j++) {\n            auto [tx, ty] = targets[j];\n            distHT[i][j] = dist[tx][ty];\n            firstHT[i][j] = first[tx][ty];\n        }\n    }\n\n    const int INF = 1e9;\n    int FULL = 1 << K;\n\n    vector<vector<int>> dp(T + 1, vector<int>(FULL, INF));\n    vector<vector<int>> parMask(T + 1, vector<int>(FULL, -1));\n    vector<vector<int>> parHuman(T + 1, vector<int>(FULL, -2));\n\n    dp[0][0] = 0;\n\n    for (int t = 0; t < T; t++) {\n        for (int mask = 0; mask < FULL; mask++) {\n            if (dp[t][mask] >= INF) continue;\n\n            if (dp[t][mask] < dp[t + 1][mask]) {\n                dp[t + 1][mask] = dp[t][mask];\n                parMask[t + 1][mask] = mask;\n                parHuman[t + 1][mask] = -1;\n            }\n\n            for (int h = 0; h < K; h++) {\n                if (mask >> h & 1) continue;\n                if (distHT[h][t] == -1) continue;\n\n                int nmask = mask | (1 << h);\n                int nd = dp[t][mask] + distHT[h][t];\n\n                if (nd < dp[t + 1][nmask]) {\n                    dp[t + 1][nmask] = nd;\n                    parMask[t + 1][nmask] = mask;\n                    parHuman[t + 1][nmask] = h;\n                }\n            }\n        }\n    }\n\n    int bestMask = 0;\n    int bestPop = -1;\n    int bestCost = INF;\n\n    for (int mask = 0; mask < FULL; mask++) {\n        if (dp[T][mask] >= INF) continue;\n\n        int pc = __builtin_popcount((unsigned)mask);\n\n        if (pc > bestPop || (pc == bestPop && dp[T][mask] < bestCost)) {\n            bestPop = pc;\n            bestCost = dp[T][mask];\n            bestMask = mask;\n        }\n    }\n\n    vector<int> assignedTarget(K, -1);\n    int mask = bestMask;\n\n    for (int t = T; t >= 1; t--) {\n        int ph = parHuman[t][mask];\n        int pm = parMask[t][mask];\n\n        if (ph >= 0) {\n            assignedTarget[ph] = t - 1;\n        }\n\n        if (pm == -1) break;\n        mask = pm;\n    }\n\n    for (int h = 0; h < K; h++) {\n        int hid = ids[h];\n\n        if (assignedTarget[h] != -1) {\n            int t = assignedTarget[h];\n            ans[hid] = firstHT[h][t];\n        } else {\n            ans[hid] = bfsMove(\n                humans[hid].x,\n                humans[hid].y,\n                targets,\n                avoid,\n                true\n            );\n        }\n    }\n}\n\nbool enoughHumansForBuild(int turn) {\n    if (allHumansInside()) return true;\n\n    int cnt = humansInsideCurrent();\n\n    if (plan_.kind == 1 && cnt >= M - 1) {\n        if (M >= 7 && turn >= 45) return true;\n        if (turn >= 70) return true;\n    }\n\n    return false;\n}\n\nvoid applyHumanActions(const string &ans) {\n    for (int i = 0; i < M; i++) {\n        char a = ans[i];\n\n        if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n            for (int d = 0; d < 4; d++) {\n                if (a == mvChar[d]) {\n                    humans[i].x += dx[d];\n                    humans[i].y += dy[d];\n                }\n            }\n        } else if (a == 'u' || a == 'd' || a == 'l' || a == 'r') {\n            for (int d = 0; d < 4; d++) {\n                if (a == buildChar[d]) {\n                    int wx = humans[i].x + dx[d];\n                    int wy = humans[i].y + dy[d];\n\n                    if (inBoard(wx, wy)) {\n                        wall_[wx][wy] = true;\n                    }\n                }\n            }\n        }\n    }\n}\n\nvoid readPetMoves() {\n    for (int i = 0; i < N; i++) {\n        string s;\n        if (!(cin >> s)) exit(0);\n\n        if (s == \".\") continue;\n\n        for (char c : s) {\n            if (c == 'U') pets[i].x--;\n            else if (c == 'D') pets[i].x++;\n            else if (c == 'L') pets[i].y--;\n            else if (c == 'R') pets[i].y++;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pets.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    }\n\n    cin >> M;\n    humans.resize(M);\n\n    for (int i = 0; i < M; i++) {\n        cin >> humans[i].x >> humans[i].y;\n    }\n\n    memset(wall_, false, sizeof(wall_));\n\n    selectPlan(true);\n\n    bool startedBuild = false;\n    bool replanned = false;\n\n    for (int turn = 0; turn < 300; turn++) {\n        bool occH[31][31] = {};\n        bool occP[31][31] = {};\n\n        for (auto &h : humans) occH[h.x][h.y] = true;\n        for (auto &p : pets) occP[p.x][p.y] = true;\n\n        string ans(M, '.');\n        bool avoid[31][31] = {};\n\n        if (\n            !startedBuild &&\n            !replanned &&\n            turn >= 80 &&\n            enoughHumansForBuild(turn) &&\n            petsInsideCurrent() >= 2\n        ) {\n            replanned = true;\n            selectPlan(true);\n        }\n\n        if (!startedBuild && !enoughHumansForBuild(turn)) {\n            auto targets = insideCells();\n\n            for (int i = 0; i < M; i++) {\n                ans[i] = bfsMove(\n                    humans[i].x,\n                    humans[i].y,\n                    targets,\n                    avoid,\n                    false\n                );\n            }\n        } else {\n            if (!startedBuild) {\n                int curPets = petsInsideCurrent();\n\n                if (plan_.plannedPets == 0) {\n                    if (curPets == 0 || turn >= 105) {\n                        startedBuild = true;\n                    }\n                } else {\n                    if (turn >= 35 || curPets <= plan_.plannedPets) {\n                        startedBuild = true;\n                    }\n                }\n            }\n\n            if (!startedBuild) {\n                auto c = centerCell();\n                vector<pair<int,int>> centerTargets = {c};\n                auto insideTargets = insideCells();\n\n                for (int i = 0; i < M; i++) {\n                    if (insideRegion(humans[i].x, humans[i].y)) {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            centerTargets,\n                            avoid,\n                            true\n                        );\n                    } else {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            insideTargets,\n                            avoid,\n                            false\n                        );\n                    }\n                }\n            } else if (!allTasksDone()) {\n                bool scheduledWall[31][31] = {};\n\n                for (int i = 0; i < M; i++) {\n                    int hx = humans[i].x;\n                    int hy = humans[i].y;\n\n                    for (auto &t : tasks) {\n                        if (wall_[t.wx][t.wy]) continue;\n                        if (scheduledWall[t.wx][t.wy]) continue;\n                        if (t.sx != hx || t.sy != hy) continue;\n                        if (!validBuildTarget(t.wx, t.wy, occH, occP)) continue;\n\n                        ans[i] = dirFromTo(hx, hy, t.wx, t.wy, true);\n                        scheduledWall[t.wx][t.wy] = true;\n                        avoid[t.wx][t.wy] = true;\n                        break;\n                    }\n                }\n\n                vector<pair<int,int>> goodTargets;\n                vector<pair<int,int>> fallbackTargets;\n\n                for (auto &t : tasks) {\n                    if (wall_[t.wx][t.wy]) continue;\n                    if (scheduledWall[t.wx][t.wy]) continue;\n\n                    fallbackTargets.push_back({t.sx, t.sy});\n\n                    if (validBuildTarget(t.wx, t.wy, occH, occP)) {\n                        goodTargets.push_back({t.sx, t.sy});\n                    }\n                }\n\n                if (goodTargets.empty()) goodTargets = fallbackTargets;\n\n                auto insideTargets = insideCells();\n\n                for (int i = 0; i < M; i++) {\n                    if (ans[i] != '.') continue;\n\n                    if (!insideRegion(humans[i].x, humans[i].y)) {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            insideTargets,\n                            avoid,\n                            false\n                        );\n                    }\n                }\n\n                assignMovesByDP(ans, goodTargets, avoid);\n            } else {\n                auto c = centerCell();\n                vector<pair<int,int>> centerTargets = {c};\n                auto insideTargets = insideCells();\n\n                for (int i = 0; i < M; i++) {\n                    if (insideRegion(humans[i].x, humans[i].y)) {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            centerTargets,\n                            avoid,\n                            true\n                        );\n                    } else {\n                        ans[i] = bfsMove(\n                            humans[i].x,\n                            humans[i].y,\n                            insideTargets,\n                            avoid,\n                            false\n                        );\n                    }\n                }\n            }\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        applyHumanActions(ans);\n        readPetMoves();\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int V = 400;\nstatic constexpr int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble p_fail, p_succ;\nstring hwall[20], vwall[19];\n\nint start_id, target_id;\nint nxt_cell[4][V];\nint dist_to_t[V];\n\nusing PotTable = array<array<float, V>, MAXL + 1>;\nPotTable pot_nb, pot_mean;\n\nconst string DIRS = \"UDLR\";\n\nstatic double F[MAXL + 1][V];\nstatic double B[MAXL + 1][V];\nstatic double pref_score[MAXL + 1];\n\nint id(int i, int j) { return i * N + j; }\n\npair<int, int> pos_of(int x) { return {x / N, x % N}; }\n\nint dir_id(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\nstruct Node {\n    array<float, V> prob;\n    array<char, MAXL> path;\n    float score;\n    float eval;\n};\n\nvoid build_graph() {\n    for (int x = 0; x < V; x++) {\n        auto [i, j] = pos_of(x);\n\n        if (i == 0 || vwall[i - 1][j] == '1') nxt_cell[0][x] = x;\n        else nxt_cell[0][x] = id(i - 1, j);\n\n        if (i == N - 1 || vwall[i][j] == '1') nxt_cell[1][x] = x;\n        else nxt_cell[1][x] = id(i + 1, j);\n\n        if (j == 0 || hwall[i][j - 1] == '1') nxt_cell[2][x] = x;\n        else nxt_cell[2][x] = id(i, j - 1);\n\n        if (j == N - 1 || hwall[i][j] == '1') nxt_cell[3][x] = x;\n        else nxt_cell[3][x] = id(i, j + 1);\n    }\n}\n\nvoid bfs_distance() {\n    const int INF = 1e9;\n    fill(dist_to_t, dist_to_t + V, INF);\n\n    queue<int> q;\n    dist_to_t[target_id] = 0;\n    q.push(target_id);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int to = nxt_cell[d][v];\n            if (to == v) continue;\n\n            if (dist_to_t[to] > dist_to_t[v] + 1) {\n                dist_to_t[to] = dist_to_t[v] + 1;\n                q.push(to);\n            }\n        }\n    }\n}\n\nvoid build_mean_potential() {\n    for (int t = 0; t <= MAXL; t++) {\n        int rem = MAXL - t;\n\n        for (int c = 0; c < V; c++) {\n            int d = dist_to_t[c];\n\n            if (d > rem) {\n                pot_mean[t][c] = 0.0f;\n            } else {\n                double val = 401.0 - t - d / p_succ;\n                pot_mean[t][c] = (float)max(0.0, val);\n            }\n        }\n    }\n}\n\nvoid build_nb_potential() {\n    static double hit_prob[MAXL + 1][MAXL + 1];\n    static double hit_ksum[MAXL + 1][MAXL + 1];\n\n    for (int rem = 0; rem <= MAXL; rem++) {\n        hit_prob[rem][0] = 1.0;\n        hit_ksum[rem][0] = 0.0;\n\n        for (int d = 1; d <= rem; d++) {\n            double pr = pow(p_succ, d);\n            double psum = 0.0;\n            double ksum = 0.0;\n\n            for (int k = d; k <= rem; k++) {\n                psum += pr;\n                ksum += pr * k;\n\n                if (k < rem) {\n                    pr *= (double)k / (double)(k - d + 1) * p_fail;\n                }\n            }\n\n            hit_prob[rem][d] = psum;\n            hit_ksum[rem][d] = ksum;\n        }\n    }\n\n    for (int t = 0; t <= MAXL; t++) {\n        int rem = MAXL - t;\n\n        for (int c = 0; c < V; c++) {\n            int d = dist_to_t[c];\n\n            if (d > rem) {\n                pot_nb[t][c] = 0.0f;\n                continue;\n            }\n\n            double finite = (401.0 - t) * hit_prob[rem][d] - hit_ksum[rem][d];\n\n            double mean = 401.0 - t - d / p_succ;\n            mean = max(0.0, mean);\n\n            double val = 0.82 * finite + 0.18 * mean;\n            pot_nb[t][c] = (float)max(0.0, val);\n        }\n    }\n}\n\ndouble evaluate_string(const string& s) {\n    static double cur[V], nxt[V];\n\n    fill(cur, cur + V, 0.0);\n    cur[start_id] = 1.0;\n\n    double score = 0.0;\n\n    for (int t = 0; t < (int)s.size(); t++) {\n        int dir = dir_id(s[t]);\n        fill(nxt, nxt + V, 0.0);\n\n        double arrive = 0.0;\n        double remain = 0.0;\n\n        for (int c = 0; c < V; c++) {\n            double pr = cur[c];\n            if (pr < 1e-18) continue;\n\n            int to = nxt_cell[dir][c];\n\n            if (to == target_id) {\n                arrive += pr * p_succ;\n                nxt[c] += pr * p_fail;\n            } else if (to == c) {\n                nxt[c] += pr;\n            } else {\n                nxt[c] += pr * p_fail;\n                nxt[to] += pr * p_succ;\n            }\n        }\n\n        score += arrive * (400 - t);\n\n        for (int i = 0; i < V; i++) {\n            cur[i] = nxt[i];\n            remain += cur[i];\n        }\n\n        if (remain < 1e-18) break;\n    }\n\n    return score;\n}\n\nstring beam_search(const PotTable& pot, int beam_width) {\n    vector<Node> beam;\n    beam.reserve(beam_width);\n\n    Node init;\n    init.prob.fill(0.0f);\n    init.prob[start_id] = 1.0f;\n    init.score = 0.0f;\n    init.eval = pot[0][start_id];\n    beam.push_back(init);\n\n    for (int depth = 0; depth < MAXL; depth++) {\n        vector<Node> cand;\n        cand.reserve(beam.size() * 4);\n\n        for (const Node& par : beam) {\n            for (int dir = 0; dir < 4; dir++) {\n                Node ch;\n                ch.prob.fill(0.0f);\n\n                if (depth > 0) memcpy(ch.path.data(), par.path.data(), depth);\n                ch.path[depth] = DIRS[dir];\n\n                float arrive = 0.0f;\n\n                for (int c = 0; c < V; c++) {\n                    float pr = par.prob[c];\n                    if (pr < 1e-12f) continue;\n\n                    int to = nxt_cell[dir][c];\n\n                    if (to == target_id) {\n                        arrive += pr * (float)p_succ;\n                        ch.prob[c] += pr * (float)p_fail;\n                    } else if (to == c) {\n                        ch.prob[c] += pr;\n                    } else {\n                        ch.prob[c] += pr * (float)p_fail;\n                        ch.prob[to] += pr * (float)p_succ;\n                    }\n                }\n\n                int nt = depth + 1;\n                ch.score = par.score + arrive * (400 - depth);\n\n                double future = 0.0;\n                for (int c = 0; c < V; c++) {\n                    float pr = ch.prob[c];\n                    if (pr < 1e-12f) continue;\n                    future += pr * pot[nt][c];\n                }\n\n                ch.eval = (float)(ch.score + future);\n                cand.push_back(std::move(ch));\n            }\n        }\n\n        if ((int)cand.size() > beam_width) {\n            nth_element(\n                cand.begin(),\n                cand.begin() + beam_width,\n                cand.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            );\n            cand.resize(beam_width);\n        }\n\n        beam.swap(cand);\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)beam.size(); i++) {\n        if (beam[i].score > beam[best].score) best = i;\n    }\n\n    string res;\n    res.reserve(MAXL);\n    for (int i = 0; i < MAXL; i++) res.push_back(beam[best].path[i]);\n    return res;\n}\n\nstring shortest_path_by_order(const vector<int>& order) {\n    string res;\n    int cur = start_id;\n\n    while (cur != target_id && (int)res.size() < MAXL) {\n        bool moved = false;\n\n        for (int d : order) {\n            int to = nxt_cell[d][cur];\n\n            if (to != cur && dist_to_t[to] == dist_to_t[cur] - 1) {\n                res.push_back(DIRS[d]);\n                cur = to;\n                moved = true;\n                break;\n            }\n        }\n\n        if (!moved) break;\n    }\n\n    return res;\n}\n\nstring random_shortest_path(mt19937& rng) {\n    string res;\n    int cur = start_id;\n\n    while (cur != target_id && (int)res.size() < MAXL) {\n        vector<int> ds;\n\n        for (int d = 0; d < 4; d++) {\n            int to = nxt_cell[d][cur];\n            if (to != cur && dist_to_t[to] == dist_to_t[cur] - 1) {\n                ds.push_back(d);\n            }\n        }\n\n        if (ds.empty()) break;\n\n        int d = ds[rng() % ds.size()];\n        res.push_back(DIRS[d]);\n        cur = nxt_cell[d][cur];\n    }\n\n    return res;\n}\n\nstring repeat_pattern(const string& pat) {\n    string s;\n    s.reserve(MAXL);\n\n    while ((int)s.size() < MAXL) {\n        for (char c : pat) {\n            if ((int)s.size() >= MAXL) break;\n            s.push_back(c);\n        }\n    }\n\n    return s;\n}\n\nstring make_cycle_pattern(const string& base) {\n    if (base.empty()) return string(MAXL, 'D');\n\n    string s;\n    s.reserve(MAXL);\n\n    int k = 0;\n    while ((int)s.size() < MAXL) {\n        s.push_back(base[k]);\n        k++;\n        if (k == (int)base.size()) k = 0;\n    }\n\n    return s;\n}\n\nstring make_repeat_each_pattern(const string& base, int rep) {\n    if (base.empty()) return string(MAXL, 'D');\n\n    string s;\n    s.reserve(MAXL);\n\n    while ((int)s.size() < MAXL) {\n        for (char c : base) {\n            for (int r = 0; r < rep && (int)s.size() < MAXL; r++) {\n                s.push_back(c);\n            }\n            if ((int)s.size() >= MAXL) break;\n        }\n    }\n\n    return s;\n}\n\nstring greedy_with_potential(const PotTable& pot) {\n    array<float, V> cur{}, nxt{};\n    cur.fill(0.0f);\n    cur[start_id] = 1.0f;\n\n    string s;\n    s.reserve(MAXL);\n\n    double score = 0.0;\n\n    for (int t = 0; t < MAXL; t++) {\n        int best_dir = 0;\n        double best_eval = -1e100;\n\n        for (int dir = 0; dir < 4; dir++) {\n            nxt.fill(0.0f);\n            double arrive = 0.0;\n\n            for (int c = 0; c < V; c++) {\n                float pr = cur[c];\n                if (pr < 1e-12f) continue;\n\n                int to = nxt_cell[dir][c];\n\n                if (to == target_id) {\n                    arrive += pr * p_succ;\n                    nxt[c] += pr * (float)p_fail;\n                } else if (to == c) {\n                    nxt[c] += pr;\n                } else {\n                    nxt[c] += pr * (float)p_fail;\n                    nxt[to] += pr * (float)p_succ;\n                }\n            }\n\n            double future = 0.0;\n            for (int c = 0; c < V; c++) {\n                if (nxt[c] < 1e-12f) continue;\n                future += nxt[c] * pot[t + 1][c];\n            }\n\n            double ev = score + arrive * (400 - t) + future;\n\n            if (ev > best_eval) {\n                best_eval = ev;\n                best_dir = dir;\n            }\n        }\n\n        s.push_back(DIRS[best_dir]);\n\n        nxt.fill(0.0f);\n        double arrive = 0.0;\n\n        for (int c = 0; c < V; c++) {\n            float pr = cur[c];\n            if (pr < 1e-12f) continue;\n\n            int to = nxt_cell[best_dir][c];\n\n            if (to == target_id) {\n                arrive += pr * p_succ;\n                nxt[c] += pr * (float)p_fail;\n            } else if (to == c) {\n                nxt[c] += pr;\n            } else {\n                nxt[c] += pr * (float)p_fail;\n                nxt[to] += pr * (float)p_succ;\n            }\n        }\n\n        score += arrive * (400 - t);\n        cur = nxt;\n    }\n\n    return s;\n}\n\nvector<string> generate_path_candidates() {\n    vector<string> cand;\n\n    vector<int> perm = {0, 1, 2, 3};\n\n    do {\n        string p = shortest_path_by_order(perm);\n        if (p.empty()) continue;\n\n        cand.push_back(make_cycle_pattern(p));\n\n        for (int r = 2; r <= 7; r++) {\n            cand.push_back(make_repeat_each_pattern(p, r));\n        }\n    } while (next_permutation(perm.begin(), perm.end()));\n\n    mt19937 rng(\n        987654321u\n        ^ (unsigned)(si_ * 100000 + sj_ * 10000 + ti_ * 1000 + tj_ * 100)\n        ^ (unsigned)(p_fail * 10000)\n    );\n\n    for (int k = 0; k < 60; k++) {\n        string p = random_shortest_path(rng);\n        if (p.empty()) continue;\n\n        cand.push_back(make_cycle_pattern(p));\n\n        int r = 2 + (rng() % 6);\n        cand.push_back(make_repeat_each_pattern(p, r));\n    }\n\n    cand.push_back(repeat_pattern(\"DR\"));\n    cand.push_back(repeat_pattern(\"RD\"));\n    cand.push_back(repeat_pattern(\"DDRR\"));\n    cand.push_back(repeat_pattern(\"RRDD\"));\n    cand.push_back(repeat_pattern(\"DRDRR\"));\n    cand.push_back(repeat_pattern(\"RDRDD\"));\n\n    return cand;\n}\n\ndouble step_value(int t, int c, int dir, const double* next_val) {\n    int to = nxt_cell[dir][c];\n\n    if (to == target_id) {\n        return p_succ * (400 - t) + p_fail * next_val[c];\n    } else if (to == c) {\n        return next_val[c];\n    } else {\n        return p_fail * next_val[c] + p_succ * next_val[to];\n    }\n}\n\nvoid rebuild_forward_backward(const string& ans) {\n    int L = ans.size();\n\n    for (int t = 0; t <= L; t++) {\n        fill(F[t], F[t] + V, 0.0);\n        fill(B[t], B[t] + V, 0.0);\n    }\n\n    F[0][start_id] = 1.0;\n    pref_score[0] = 0.0;\n\n    for (int t = 0; t < L; t++) {\n        int dir = dir_id(ans[t]);\n        double arrive = 0.0;\n\n        for (int c = 0; c < V; c++) {\n            double pr = F[t][c];\n            if (pr < 1e-18) continue;\n\n            int to = nxt_cell[dir][c];\n\n            if (to == target_id) {\n                arrive += pr * p_succ;\n                F[t + 1][c] += pr * p_fail;\n            } else if (to == c) {\n                F[t + 1][c] += pr;\n            } else {\n                F[t + 1][c] += pr * p_fail;\n                F[t + 1][to] += pr * p_succ;\n            }\n        }\n\n        pref_score[t + 1] = pref_score[t] + arrive * (400 - t);\n    }\n\n    fill(B[L], B[L] + V, 0.0);\n\n    for (int t = L - 1; t >= 0; t--) {\n        int dir = dir_id(ans[t]);\n        for (int c = 0; c < V; c++) {\n            B[t][c] = step_value(t, c, dir, B[t + 1]);\n        }\n    }\n}\n\nbool scan_block_size(\n    string& ans,\n    int K,\n    double& best_score,\n    int& best_pos,\n    int& best_mask,\n    chrono::steady_clock::time_point start_time,\n    double deadline\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    static double va[V], vb[V];\n\n    int L = ans.size();\n    int total = 1 << (2 * K);\n    bool found = false;\n\n    for (int pos = 0; pos + K <= L; pos++) {\n        if (elapsed() > deadline) break;\n\n        int original = 0;\n        for (int i = 0; i < K; i++) {\n            original |= dir_id(ans[pos + i]) << (2 * i);\n        }\n\n        for (int mask = 0; mask < total; mask++) {\n            if (mask == original) continue;\n\n            for (int c = 0; c < V; c++) va[c] = B[pos + K][c];\n\n            for (int r = K - 1; r >= 0; r--) {\n                int d = (mask >> (2 * r)) & 3;\n\n                for (int c = 0; c < V; c++) {\n                    vb[c] = step_value(pos + r, c, d, va);\n                }\n\n                for (int c = 0; c < V; c++) va[c] = vb[c];\n            }\n\n            double sc = pref_score[pos];\n\n            for (int c = 0; c < V; c++) {\n                double pr = F[pos][c];\n                if (pr < 1e-18) continue;\n                sc += pr * va[c];\n            }\n\n            if (sc > best_score + 1e-11) {\n                best_score = sc;\n                best_pos = pos;\n                best_mask = mask;\n                found = true;\n            }\n        }\n    }\n\n    return found;\n}\n\nvoid exact_local_limited(\n    string& ans,\n    chrono::steady_clock::time_point start_time,\n    double deadline,\n    int max_iter,\n    bool use3,\n    bool use4,\n    bool use5\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    for (int iter = 0; iter < max_iter && elapsed() < deadline; iter++) {\n        rebuild_forward_backward(ans);\n\n        double best_score = pref_score[ans.size()];\n        int best_pos = -1;\n        int best_mask = -1;\n        int best_k = 0;\n\n        if (scan_block_size(ans, 1, best_score, best_pos, best_mask, start_time, deadline)) {\n            best_k = 1;\n        }\n\n        if (scan_block_size(ans, 2, best_score, best_pos, best_mask, start_time, deadline)) {\n            best_k = 2;\n        }\n\n        if (best_k == 0 && use3) {\n            if (scan_block_size(ans, 3, best_score, best_pos, best_mask, start_time, deadline)) {\n                best_k = 3;\n            }\n        }\n\n        if (best_k == 0 && use4) {\n            if (scan_block_size(ans, 4, best_score, best_pos, best_mask, start_time, deadline)) {\n                best_k = 4;\n            }\n        }\n\n        if (best_k == 0 && use5) {\n            if (scan_block_size(ans, 5, best_score, best_pos, best_mask, start_time, deadline)) {\n                best_k = 5;\n            }\n        }\n\n        if (best_k == 0) break;\n\n        for (int i = 0; i < best_k; i++) {\n            int d = (best_mask >> (2 * i)) & 3;\n            ans[best_pos + i] = DIRS[d];\n        }\n    }\n}\n\nvoid random_escape(string& ans, chrono::steady_clock::time_point start_time, double deadline) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    double best_score = evaluate_string(ans);\n\n    mt19937 rng(\n        1234567u\n        ^ (unsigned)(si_ * 100000 + sj_ * 10000 + ti_ * 1000 + tj_ * 100)\n        ^ (unsigned)(p_fail * 1000)\n    );\n\n    while (elapsed() < deadline) {\n        int a = rng() % ans.size();\n        int b = rng() % ans.size();\n        if (a == b) continue;\n\n        char oa = ans[a], ob = ans[b];\n\n        char na = DIRS[rng() % 4];\n        char nb = DIRS[rng() % 4];\n\n        if (na == oa && nb == ob) continue;\n\n        ans[a] = na;\n        ans[b] = nb;\n\n        double sc = evaluate_string(ans);\n\n        if (sc > best_score + 1e-11) {\n            best_score = sc;\n        } else {\n            ans[a] = oa;\n            ans[b] = ob;\n        }\n    }\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    cin >> si_ >> sj_ >> ti_ >> tj_ >> p_fail;\n    p_succ = 1.0 - p_fail;\n\n    for (int i = 0; i < 20; i++) cin >> hwall[i];\n    for (int i = 0; i < 19; i++) cin >> vwall[i];\n\n    start_id = id(si_, sj_);\n    target_id = id(ti_, tj_);\n\n    build_graph();\n    bfs_distance();\n\n    build_nb_potential();\n    build_mean_potential();\n\n    vector<string> candidates;\n\n    string main_beam = beam_search(pot_nb, 320);\n    candidates.push_back(main_beam);\n\n    candidates.push_back(greedy_with_potential(pot_nb));\n    candidates.push_back(greedy_with_potential(pot_mean));\n\n    vector<string> path_cand = generate_path_candidates();\n    for (auto& s : path_cand) candidates.push_back(std::move(s));\n\n    vector<pair<double, string>> scored;\n    scored.reserve(candidates.size());\n\n    for (string& s : candidates) {\n        if ((int)s.size() > MAXL) s.resize(MAXL);\n        while ((int)s.size() < MAXL) s.push_back('D');\n\n        scored.push_back({evaluate_string(s), s});\n    }\n\n    sort(scored.begin(), scored.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n\n    vector<string> local_cands;\n    local_cands.push_back(main_beam);\n\n    for (int i = 0; i < (int)scored.size() && (int)local_cands.size() < 4; i++) {\n        bool same = false;\n\n        for (const string& s : local_cands) {\n            if (s == scored[i].second) {\n                same = true;\n                break;\n            }\n        }\n\n        if (!same) local_cands.push_back(scored[i].second);\n    }\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    double phase_deadline = 1.70;\n    vector<pair<double, string>> improved;\n\n    for (int i = 0; i < (int)local_cands.size(); i++) {\n        if (elapsed() > phase_deadline) break;\n\n        string s = local_cands[i];\n\n        if ((int)s.size() > MAXL) s.resize(MAXL);\n        while ((int)s.size() < MAXL) s.push_back('D');\n\n        exact_local_limited(s, start_time, phase_deadline, 4, false, false, false);\n        improved.push_back({evaluate_string(s), s});\n    }\n\n    if (improved.empty()) {\n        improved.push_back(scored[0]);\n    }\n\n    sort(improved.begin(), improved.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n\n    string ans = improved[0].second;\n\n    // Main exact local phase.\n    exact_local_limited(ans, start_time, 1.92, 100, true, true, true);\n\n    // Short random escape.\n    random_escape(ans, start_time, 1.955);\n\n    // Final exact 1/2-block polish after random mutations.\n    exact_local_limited(ans, start_time, 1.985, 20, false, false, false);\n\n    if ((int)ans.size() > MAXL) ans.resize(MAXL);\n    while ((int)ans.size() < MAXL) ans.push_back('D');\n\n    cout << ans << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int MAXP = 2000;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nconst int di[4] = {0, -1, 0, 1};\nconst int dj[4] = {-1, 0, 1, 0};\n\nconst int pieceCntOf[8] = {1,1,1,1,2,2,1,1};\n\nconst int A[8][2] = {\n    {0, -1},\n    {0, -1},\n    {2, -1},\n    {1, -1},\n    {0, 2},\n    {0, 1},\n    {0, -1},\n    {1, -1},\n};\n\nconst int B[8][2] = {\n    {1, -1},\n    {3, -1},\n    {3, -1},\n    {2, -1},\n    {1, 3},\n    {3, 2},\n    {2, -1},\n    {3, -1},\n};\n\nint parent_[MAXP], sz_[MAXP], open_[MAXP];\nint sidePid[V][4];\n\nint findp(int x) {\n    while (parent_[x] != x) {\n        parent_[x] = parent_[parent_[x]];\n        x = parent_[x];\n    }\n    return x;\n}\n\nvoid unite(int a, int b) {\n    int ra = findp(a), rb = findp(b);\n    if (ra == rb) return;\n    if (sz_[ra] < sz_[rb]) swap(ra, rb);\n    parent_[rb] = ra;\n    sz_[ra] += sz_[rb];\n}\n\nstruct Eval {\n    long long actual = 0;\n    int l1 = 0;\n    int l2 = 0;\n    double energy = 0;\n};\n\nEval evaluate(const uint8_t state[V]) {\n    for (int k = 0; k < V; k++) {\n        sidePid[k][0] = sidePid[k][1] = sidePid[k][2] = sidePid[k][3] = -1;\n    }\n\n    int pc = 0;\n\n    for (int k = 0; k < V; k++) {\n        int t = state[k];\n        int c = pieceCntOf[t];\n\n        for (int p = 0; p < c; p++) {\n            int id = pc++;\n            parent_[id] = id;\n            sz_[id] = 1;\n            open_[id] = 0;\n\n            int a = A[t][p];\n            int b = B[t][p];\n            sidePid[k][a] = id;\n            sidePid[k][b] = id;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            if (j + 1 < N) {\n                int a = sidePid[k][2];\n                int b = sidePid[k + 1][0];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n\n            if (i + 1 < N) {\n                int a = sidePid[k][3];\n                int b = sidePid[k + N][1];\n                if (a != -1 && b != -1) unite(a, b);\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n\n            for (int d = 0; d < 4; d++) {\n                int id = sidePid[k][d];\n                if (id == -1) continue;\n\n                int ni = i + di[d];\n                int nj = j + dj[d];\n\n                bool bad = false;\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    bad = true;\n                } else {\n                    int nk = ni * N + nj;\n                    int od = (d + 2) & 3;\n                    if (sidePid[nk][od] == -1) bad = true;\n                }\n\n                if (bad) open_[findp(id)]++;\n            }\n        }\n    }\n\n    Eval res;\n    double potential = 0.0;\n\n    for (int id = 0; id < pc; id++) {\n        int r = findp(id);\n        if (r != id) continue;\n\n        int s = sz_[r];\n        int op = open_[r];\n\n        if (op == 0) {\n            if (s > res.l1) {\n                res.l2 = res.l1;\n                res.l1 = s;\n            } else if (s > res.l2) {\n                res.l2 = s;\n            }\n        } else {\n            potential += (double)s * s / (op + 1);\n        }\n    }\n\n    if (res.l2 > 0) res.actual = 1LL * res.l1 * res.l2;\n\n    res.energy =\n        55.0 * res.actual\n        + 2.0 * res.l1 * res.l1\n        + 4.5 * res.l2 * res.l2\n        + 0.75 * potential;\n\n    return res;\n}\n\nint rotateTile(int t, int r) {\n    if (t < 4) return (t + r) & 3;\n    if (t < 6) return 4 + ((t - 4 + r) & 1);\n    return 6 + ((t - 6 + r) & 1);\n}\n\nint outsideCountState(int k, int t) {\n    int i = k / N;\n    int j = k % N;\n\n    bool has[4] = {};\n    for (int p = 0; p < pieceCntOf[t]; p++) {\n        has[A[t][p]] = true;\n        has[B[t][p]] = true;\n    }\n\n    int cnt = 0;\n    for (int d = 0; d < 4; d++) {\n        if (!has[d]) continue;\n        int ni = i + di[d];\n        int nj = j + dj[d];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) cnt++;\n    }\n    return cnt;\n}\n\nint stateForPair(int base, int d1, int d2) {\n    if (d1 > d2) swap(d1, d2);\n\n    if (base >= 6) {\n        if (d1 == 0 && d2 == 2) return 6;\n        return 7;\n    }\n\n    bool dbl = (base >= 4);\n\n    int s = 0;\n    if (d1 == 0 && d2 == 1) s = 0;\n    else if (d1 == 0 && d2 == 3) s = 1;\n    else if (d1 == 2 && d2 == 3) s = 2;\n    else s = 3;\n\n    if (!dbl) return s;\n\n    if (s == 0 || s == 2) return 4;\n    return 5;\n}\n\nstruct Cycle {\n    vector<int> cells;\n    vector<uint8_t> states;\n    array<uint64_t, 15> mask{};\n    int len = 0;\n};\n\nvoid buildMask(Cycle& c) {\n    c.mask.fill(0);\n    for (int k : c.cells) {\n        c.mask[k >> 6] |= 1ULL << (k & 63);\n    }\n}\n\nbool disjointCycle(const Cycle& a, const Cycle& b) {\n    for (int i = 0; i < 15; i++) {\n        if (a.mask[i] & b.mask[i]) return false;\n    }\n    return true;\n}\n\nstruct PairCand {\n    long long prod;\n    int i;\n    int j;\n    bool operator<(const PairCand& other) const {\n        return prod > other.prod;\n    }\n};\n\nstruct MinCycleEntry {\n    int len;\n    int idx;\n    int ver;\n    bool operator<(const MinCycleEntry& other) const {\n        return len > other.len;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto timeStart = chrono::steady_clock::now();\n\n    string input[N];\n    for (int i = 0; i < N; i++) cin >> input[i];\n\n    uint64_t seed = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        for (char c : input[i]) {\n            seed ^= (uint64_t)c;\n            seed *= 1099511628211ULL;\n        }\n    }\n\n    XorShift rng(seed);\n\n    uint8_t base[V];\n    int dom[V][4], domCnt[V];\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int k = i * N + j;\n            int t = input[i][j] - '0';\n            base[k] = t;\n\n            vector<int> states;\n            if (t < 4) states = {0, 1, 2, 3};\n            else if (t < 6) states = {4, 5};\n            else states = {6, 7};\n\n            bool border = (i == 0 || i == N - 1 || j == 0 || j == N - 1);\n\n            if (border) {\n                int bestOut = 100;\n                for (int s : states) bestOut = min(bestOut, outsideCountState(k, s));\n\n                vector<int> filtered;\n                for (int s : states) {\n                    if (outsideCountState(k, s) == bestOut) filtered.push_back(s);\n                }\n                states = filtered;\n            }\n\n            domCnt[k] = (int)states.size();\n            for (int x = 0; x < domCnt[k]; x++) dom[k][x] = states[x];\n        }\n    }\n\n    vector<Cycle> cycles;\n    cycles.reserve(1800);\n\n    vector<int> cycleVer;\n    cycleVer.reserve(1800);\n    priority_queue<MinCycleEntry> minCycleHeap;\n\n    static int posStamp[V * 4], posIdx[V * 4];\n    static int cellStamp[V];\n\n    static int ks[1300], ds[1300], es[1300];\n\n    int stamp = 1;\n    const int MAX_CYCLES = 1600;\n\n    auto addCycle = [&](Cycle&& c) {\n        if ((int)cycles.size() < MAX_CYCLES) {\n            int idx = (int)cycles.size();\n            cycles.push_back(std::move(c));\n            cycleVer.push_back(0);\n            minCycleHeap.push({cycles[idx].len, idx, 0});\n            return;\n        }\n\n        while (!minCycleHeap.empty()) {\n            auto e = minCycleHeap.top();\n            if (\n                e.idx >= (int)cycles.size()\n                || e.ver != cycleVer[e.idx]\n                || e.len != cycles[e.idx].len\n            ) {\n                minCycleHeap.pop();\n            } else {\n                break;\n            }\n        }\n\n        if (minCycleHeap.empty()) return;\n\n        auto e = minCycleHeap.top();\n        if (c.len <= e.len) return;\n\n        minCycleHeap.pop();\n        int idx = e.idx;\n        cycles[idx] = std::move(c);\n        cycleVer[idx]++;\n        minCycleHeap.push({cycles[idx].len, idx, cycleVer[idx]});\n    };\n\n    auto collectEnd = timeStart + chrono::milliseconds(430);\n    int attempt = 0;\n\n    while (true) {\n        attempt++;\n        if ((attempt & 63) == 0 && chrono::steady_clock::now() >= collectEnd) break;\n\n        stamp++;\n        if (stamp > 1000000000) {\n            memset(posStamp, 0, sizeof(posStamp));\n            memset(cellStamp, 0, sizeof(cellStamp));\n            stamp = 1;\n        }\n\n        int k = rng.nextInt(V);\n        int d = rng.nextInt(4);\n\n        int pathLen = 0;\n        int esLen = 0;\n\n        for (int step = 0; step < 1200; step++) {\n            int node = k * 4 + d;\n\n            if (posStamp[node] == stamp) break;\n\n            posStamp[node] = stamp;\n            posIdx[node] = pathLen;\n            cellStamp[k] = stamp;\n\n            ks[pathLen] = k;\n            ds[pathLen] = d;\n            pathLen++;\n\n            int t = base[k];\n\n            int cand[2];\n            int cc = 0;\n\n            if (t >= 6) {\n                cand[cc++] = (d + 2) & 3;\n            } else {\n                cand[cc++] = (d + 1) & 3;\n                cand[cc++] = (d + 3) & 3;\n                if (rng.nextInt(2)) swap(cand[0], cand[1]);\n            }\n\n            int chosen = -1;\n            int chosenNextK = -1;\n            int chosenNextD = -1;\n\n            for (int ci = 0; ci < cc; ci++) {\n                int e = cand[ci];\n\n                int ni = k / N + di[e];\n                int nj = k % N + dj[e];\n\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n\n                int nk = ni * N + nj;\n                int nd = (e + 2) & 3;\n                int nn = nk * 4 + nd;\n\n                if (posStamp[nn] == stamp) {\n                    int p = posIdx[nn];\n                    int len = pathLen - p;\n\n                    if (len >= 8) {\n                        chosen = e;\n                        chosenNextK = nk;\n                        chosenNextD = nd;\n                        break;\n                    }\n                }\n\n                if (cellStamp[nk] == stamp) continue;\n\n                if (chosen == -1 || rng.nextInt(2)) {\n                    chosen = e;\n                    chosenNextK = nk;\n                    chosenNextD = nd;\n                }\n            }\n\n            if (chosen == -1) break;\n\n            es[esLen++] = chosen;\n\n            int nextNode = chosenNextK * 4 + chosenNextD;\n\n            if (posStamp[nextNode] == stamp) {\n                int p = posIdx[nextNode];\n                int q = pathLen;\n                int len = q - p;\n\n                if (len >= 8) {\n                    Cycle c;\n                    c.len = len;\n                    c.cells.reserve(len);\n                    c.states.reserve(len);\n\n                    bool ok = true;\n                    static int usedCell[V];\n                    static int usedStamp = 1;\n                    usedStamp++;\n\n                    for (int idx = p; idx < q; idx++) {\n                        int ck = ks[idx];\n\n                        if (usedCell[ck] == usedStamp) {\n                            ok = false;\n                            break;\n                        }\n\n                        usedCell[ck] = usedStamp;\n\n                        int cd = ds[idx];\n                        int ce = es[idx];\n                        int cb = base[ck];\n\n                        if (cb >= 6) {\n                            if (((cd + 2) & 3) != ce) {\n                                ok = false;\n                                break;\n                            }\n                        } else {\n                            if (((cd + 2) & 3) == ce || cd == ce) {\n                                ok = false;\n                                break;\n                            }\n                        }\n\n                        c.cells.push_back(ck);\n                        c.states.push_back((uint8_t)stateForPair(cb, cd, ce));\n                    }\n\n                    if (ok) {\n                        buildMask(c);\n                        addCycle(std::move(c));\n                    }\n                }\n\n                break;\n            }\n\n            k = chosenNextK;\n            d = chosenNextD;\n        }\n    }\n\n    uint8_t cur[V], best[V], startState[V];\n\n    Eval bestEval;\n    bestEval.actual = -1;\n\n    Eval bestEnergyEval;\n    bestEnergyEval.energy = -1e100;\n\n    auto registerCandidate = [&](const uint8_t s[V]) {\n        Eval ev = evaluate(s);\n\n        if (ev.energy > bestEnergyEval.energy) {\n            bestEnergyEval = ev;\n            memcpy(startState, s, V);\n        }\n\n        if (\n            ev.actual > bestEval.actual ||\n            (ev.actual == bestEval.actual && ev.energy > bestEval.energy)\n        ) {\n            bestEval = ev;\n            memcpy(best, s, V);\n        }\n    };\n\n    if (!cycles.empty()) {\n        sort(cycles.begin(), cycles.end(), [](const Cycle& a, const Cycle& b) {\n            return a.len > b.len;\n        });\n\n        priority_queue<PairCand> pq;\n        const int KEEP_PAIRS = 25;\n\n        int C = (int)cycles.size();\n\n        for (int i = 0; i < C; i++) {\n            if (\n                !pq.empty()\n                && (int)pq.size() >= KEEP_PAIRS\n                && 1LL * cycles[i].len * cycles[i].len <= pq.top().prod\n            ) {\n                break;\n            }\n\n            for (int j = i + 1; j < C; j++) {\n                long long p = 1LL * cycles[i].len * cycles[j].len;\n\n                if (!pq.empty() && (int)pq.size() >= KEEP_PAIRS && p <= pq.top().prod) {\n                    break;\n                }\n\n                if (!disjointCycle(cycles[i], cycles[j])) continue;\n\n                if ((int)pq.size() < KEEP_PAIRS) {\n                    pq.push({p, i, j});\n                } else if (p > pq.top().prod) {\n                    pq.pop();\n                    pq.push({p, i, j});\n                }\n            }\n        }\n\n        vector<PairCand> pairs;\n        while (!pq.empty()) {\n            pairs.push_back(pq.top());\n            pq.pop();\n        }\n\n        sort(pairs.begin(), pairs.end(), [](const PairCand& a, const PairCand& b) {\n            return a.prod > b.prod;\n        });\n\n        for (int pi = 0; pi < (int)pairs.size(); pi++) {\n            auto pr = pairs[pi];\n\n            int reps = 2;\n            if (pi < 8) reps = 3;\n\n            for (int rep = 0; rep < reps; rep++) {\n                for (int k = 0; k < V; k++) {\n                    cur[k] = dom[k][rng.nextInt(domCnt[k])];\n                }\n\n                for (int x = 0; x < cycles[pr.i].len; x++) {\n                    cur[cycles[pr.i].cells[x]] = cycles[pr.i].states[x];\n                }\n\n                for (int x = 0; x < cycles[pr.j].len; x++) {\n                    cur[cycles[pr.j].cells[x]] = cycles[pr.j].states[x];\n                }\n\n                registerCandidate(cur);\n            }\n        }\n\n        int lim = min<int>(45, cycles.size());\n\n        for (int cidx = 0; cidx < lim; cidx++) {\n            for (int k = 0; k < V; k++) {\n                cur[k] = dom[k][rng.nextInt(domCnt[k])];\n            }\n\n            for (int x = 0; x < cycles[cidx].len; x++) {\n                cur[cycles[cidx].cells[x]] = cycles[cidx].states[x];\n            }\n\n            registerCandidate(cur);\n        }\n    }\n\n    constexpr int INIT_TRIALS = 500;\n\n    for (int tr = 0; tr < INIT_TRIALS; tr++) {\n        for (int k = 0; k < V; k++) {\n            cur[k] = dom[k][rng.nextInt(domCnt[k])];\n        }\n\n        registerCandidate(cur);\n    }\n\n    memcpy(cur, best, V);\n    Eval curEval = evaluate(cur);\n\n    const double TL = 1.93;\n    const double T0 = 2500.0;\n    const double T1 = 1.0;\n\n    double temp = T0;\n    int iter = 0;\n\n    while (true) {\n        iter++;\n\n        if ((iter & 511) == 0) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - timeStart).count();\n\n            if (elapsed >= TL) break;\n\n            double progress = elapsed / TL;\n            temp = T0 * pow(T1 / T0, progress);\n        }\n\n        int m = 1;\n        int r = rng.nextInt(100);\n\n        if (r < 8) m = 2;\n        if (r == 0) m = 3;\n\n        int pos[3];\n        uint8_t oldVal[3];\n\n        bool okMove = true;\n\n        for (int x = 0; x < m; x++) {\n            int k = -1;\n\n            for (int tries = 0; tries < 50; tries++) {\n                int cand = rng.nextInt(V);\n\n                if (domCnt[cand] <= 1) continue;\n\n                bool used = false;\n                for (int y = 0; y < x; y++) {\n                    if (pos[y] == cand) used = true;\n                }\n\n                if (!used) {\n                    k = cand;\n                    break;\n                }\n            }\n\n            if (k == -1) {\n                okMove = false;\n                break;\n            }\n\n            pos[x] = k;\n            oldVal[x] = cur[k];\n\n            int nd;\n\n            do {\n                nd = dom[k][rng.nextInt(domCnt[k])];\n            } while (nd == cur[k]);\n\n            cur[k] = nd;\n        }\n\n        if (!okMove) {\n            for (int x = 0; x < m; x++) {\n                cur[pos[x]] = oldVal[x];\n            }\n            continue;\n        }\n\n        Eval ne = evaluate(cur);\n        double diff = ne.energy - curEval.energy;\n\n        bool accept = false;\n\n        if (diff >= 0) {\n            accept = true;\n        } else {\n            double p = exp(diff / temp);\n            if (rng.nextDouble() < p) accept = true;\n        }\n\n        if (\n            ne.actual > bestEval.actual ||\n            (ne.actual == bestEval.actual && ne.energy > bestEval.energy)\n        ) {\n            bestEval = ne;\n            memcpy(best, cur, V);\n        }\n\n        if (accept) {\n            curEval = ne;\n        } else {\n            for (int x = 0; x < m; x++) {\n                cur[pos[x]] = oldVal[x];\n            }\n        }\n    }\n\n    string ans;\n    ans.reserve(V);\n\n    for (int k = 0; k < V; k++) {\n        int b = base[k];\n        int target = best[k];\n\n        int rr = 0;\n        for (int r = 0; r < 4; r++) {\n            if (rotateTile(b, r) == target) {\n                rr = r;\n                break;\n            }\n        }\n\n        ans.push_back(char('0' + rr));\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint N, T, M, FULLV;\nchrono::steady_clock::time_point START_TIME;\narray<vector<int>, 100> ADJ;\null zob[100][16];\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nint hexval(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return c - 'a' + 10;\n}\n\nvoid build_adj() {\n    for (int p = 0; p < M; p++) {\n        int r = p / N;\n        int c = p % N;\n        if (r > 0) ADJ[p].push_back(p - N);\n        if (r + 1 < N) ADJ[p].push_back(p + N);\n        if (c > 0) ADJ[p].push_back(p - 1);\n        if (c + 1 < N) ADJ[p].push_back(p + 1);\n    }\n}\n\nchar move_char_from_blank_to_tile(int blank, int tile) {\n    if (tile == blank - N) return 'U';\n    if (tile == blank + N) return 'D';\n    if (tile == blank - 1) return 'L';\n    return 'R';\n}\n\nint move_blank_pos(int blank, char c) {\n    if (c == 'U') return blank - N;\n    if (c == 'D') return blank + N;\n    if (c == 'L') return blank - 1;\n    return blank + 1;\n}\n\nbool legal_move(int blank, char c) {\n    int r = blank / N;\n    int col = blank % N;\n    if (c == 'U') return r > 0;\n    if (c == 'D') return r + 1 < N;\n    if (c == 'L') return col > 0;\n    return col + 1 < N;\n}\n\nvoid apply_move(array<unsigned char, 100>& b, int& blank, char c) {\n    int nb = move_blank_pos(blank, c);\n    swap(b[blank], b[nb]);\n    blank = nb;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Evaluation                                                                  */\n/* -------------------------------------------------------------------------- */\n\nstruct Eval {\n    int s;\n    int maxComp;\n    int cyc;\n};\n\nstruct DSU {\n    int p[100], sz[100], ed[100];\n\n    void init(const array<unsigned char, 100>& b) {\n        for (int i = 0; i < M; i++) {\n            if (b[i]) {\n                p[i] = i;\n                sz[i] = 1;\n                ed[i] = 0;\n            } else {\n                p[i] = -1;\n                sz[i] = 0;\n                ed[i] = 0;\n            }\n        }\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    void add_edge(int a, int b) {\n        int ra = find(a);\n        int rb = find(b);\n\n        if (ra == rb) {\n            ed[ra]++;\n            return;\n        }\n\n        if (sz[ra] < sz[rb]) swap(ra, rb);\n\n        p[rb] = ra;\n        sz[ra] += sz[rb];\n        ed[ra] += ed[rb] + 1;\n    }\n};\n\nEval eval_board(const array<unsigned char, 100>& b) {\n    DSU d;\n    d.init(b);\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            if (b[p] == 0) continue;\n\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) d.add_edge(p, p + 1);\n            }\n\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) d.add_edge(p, p + N);\n            }\n        }\n    }\n\n    Eval ev{0, 0, 0};\n\n    for (int i = 0; i < M; i++) {\n        if (b[i] == 0) continue;\n        if (d.find(i) != i) continue;\n\n        ev.maxComp = max(ev.maxComp, d.sz[i]);\n\n        if (d.ed[i] == d.sz[i] - 1) {\n            ev.s = max(ev.s, d.sz[i]);\n        } else if (d.ed[i] >= d.sz[i]) {\n            ev.cyc += d.ed[i] - d.sz[i] + 1;\n        }\n    }\n\n    return ev;\n}\n\nint estimated_score(int S, int K) {\n    if (S < FULLV) {\n        return (int)llround(500000.0 * S / FULLV);\n    } else {\n        return (int)llround(500000.0 * (2.0 - (double)K / T));\n    }\n}\n\npair<int, int> eval_answer(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    const string& ans\n) {\n    array<unsigned char, 100> b = init;\n    int blank = initBlank;\n\n    for (char c : ans) {\n        if (!legal_move(blank, c)) return {-1, -1};\n        apply_move(b, blank, c);\n    }\n\n    Eval ev = eval_board(b);\n    return {ev.s, estimated_score(ev.s, (int)ans.size())};\n}\n\n/* -------------------------------------------------------------------------- */\n/* Target reconstruction                                                       */\n/* -------------------------------------------------------------------------- */\n\nstruct Edge {\n    int a, b;\n    int ba, bb;\n};\n\nint dir_bit(int from, int to) {\n    if (to == from - 1) return 1;\n    if (to == from - N) return 2;\n    if (to == from + 1) return 4;\n    return 8;\n}\n\nstruct SmallDSU {\n    vector<int> p, sz;\n\n    SmallDSU(int n = 0) : p(n), sz(n, 1) {\n        iota(p.begin(), p.end(), 0);\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n\n        if (a == b) return false;\n\n        if (sz[a] < sz[b]) swap(a, b);\n\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct ReconState {\n    vector<int> mask;\n    vector<int> cnt;\n    vector<char> tree;\n    vector<vector<pair<int, int>>> adj;\n    int diff;\n};\n\nvoid adj_add(vector<vector<pair<int, int>>>& adj, int u, int v, int eid) {\n    adj[u].push_back({v, eid});\n    adj[v].push_back({u, eid});\n}\n\nvoid adj_remove(vector<vector<pair<int, int>>>& adj, int u, int v, int eid) {\n    auto erase_one = [&](int x, int y) {\n        auto& vec = adj[x];\n\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i].first == y && vec[i].second == eid) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n\n    erase_one(u, v);\n    erase_one(v, u);\n}\n\nbool reconstruct_target_any(\n    const vector<int>& targetCnt,\n    array<unsigned char, 100>& target,\n    double time_limit\n) {\n    int emptyPos = M - 1;\n\n    vector<int> posToVid(M, -1);\n    vector<int> vidToPos;\n\n    for (int p = 0; p < M; p++) {\n        if (p == emptyPos) continue;\n        posToVid[p] = (int)vidToPos.size();\n        vidToPos.push_back(p);\n    }\n\n    int V = (int)vidToPos.size();\n\n    vector<Edge> edges;\n\n    for (int p = 0; p < M; p++) {\n        if (p == emptyPos) continue;\n\n        int r = p / N;\n        int c = p % N;\n\n        if (c + 1 < N && p + 1 != emptyPos) {\n            int q = p + 1;\n            edges.push_back({posToVid[p], posToVid[q], dir_bit(p, q), dir_bit(q, p)});\n        }\n\n        if (r + 1 < N && p + N != emptyPos) {\n            int q = p + N;\n            edges.push_back({posToVid[p], posToVid[q], dir_bit(p, q), dir_bit(q, p)});\n        }\n    }\n\n    int E = (int)edges.size();\n    mt19937 rng(712367821);\n\n    auto calc_diff = [&](const vector<int>& cnt) {\n        int d = 0;\n        for (int i = 0; i < 16; i++) d += abs(cnt[i] - targetCnt[i]);\n        return d;\n    };\n\n    auto build_random_tree = [&]() {\n        ReconState st;\n\n        st.mask.assign(V, 0);\n        st.cnt.assign(16, 0);\n        st.tree.assign(E, 0);\n        st.adj.assign(V, {});\n\n        vector<int> ord(E);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n\n        SmallDSU dsu(V);\n        int used = 0;\n\n        for (int id : ord) {\n            auto& e = edges[id];\n\n            if (dsu.unite(e.a, e.b)) {\n                st.tree[id] = 1;\n                st.mask[e.a] |= e.ba;\n                st.mask[e.b] |= e.bb;\n                adj_add(st.adj, e.a, e.b, id);\n\n                used++;\n                if (used == V - 1) break;\n            }\n        }\n\n        for (int x : st.mask) st.cnt[x]++;\n        st.diff = calc_diff(st.cnt);\n\n        return st;\n    };\n\n    ReconState best;\n    best.diff = INT_MAX;\n\n    while (elapsed_sec() < time_limit) {\n        ReconState st = build_random_tree();\n\n        if (st.diff < best.diff) best = st;\n\n        if (st.diff == 0) {\n            best = st;\n            break;\n        }\n\n        double local_start = elapsed_sec();\n\n        while (elapsed_sec() < time_limit) {\n            double progress = (elapsed_sec() - local_start) / max(0.001, time_limit - local_start);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 3.5 * (1.0 - progress) + 0.03 * progress;\n\n            int addId = -1;\n\n            for (int tries = 0; tries < 25; tries++) {\n                int id = rng() % E;\n\n                if (!st.tree[id]) {\n                    addId = id;\n                    break;\n                }\n            }\n\n            if (addId == -1) continue;\n\n            int s = edges[addId].a;\n            int g = edges[addId].b;\n\n            vector<int> par(V, -1), parEdge(V, -1);\n            queue<int> q;\n\n            q.push(s);\n            par[s] = s;\n\n            while (!q.empty() && par[g] == -1) {\n                int v = q.front();\n                q.pop();\n\n                for (auto [to, eid] : st.adj[v]) {\n                    if (par[to] == -1) {\n                        par[to] = v;\n                        parEdge[to] = eid;\n                        q.push(to);\n                    }\n                }\n            }\n\n            vector<int> pathEdges;\n            int cur = g;\n\n            while (cur != s) {\n                pathEdges.push_back(parEdge[cur]);\n                cur = par[cur];\n            }\n\n            int remId = pathEdges[rng() % pathEdges.size()];\n\n            vector<int> nmask = st.mask;\n            vector<int> ncnt = st.cnt;\n\n            auto& ae = edges[addId];\n            auto& re = edges[remId];\n\n            nmask[ae.a] |= ae.ba;\n            nmask[ae.b] |= ae.bb;\n            nmask[re.a] &= ~re.ba;\n            nmask[re.b] &= ~re.bb;\n\n            int affected[4] = {ae.a, ae.b, re.a, re.b};\n            sort(affected, affected + 4);\n\n            int len = unique(affected, affected + 4) - affected;\n\n            int ndiff = st.diff;\n\n            for (int i = 0; i < len; i++) {\n                int v = affected[i];\n\n                int oldm = st.mask[v];\n                int newm = nmask[v];\n\n                if (oldm == newm) continue;\n\n                ndiff -= abs(ncnt[oldm] - targetCnt[oldm]);\n                ncnt[oldm]--;\n                ndiff += abs(ncnt[oldm] - targetCnt[oldm]);\n\n                ndiff -= abs(ncnt[newm] - targetCnt[newm]);\n                ncnt[newm]++;\n                ndiff += abs(ncnt[newm] - targetCnt[newm]);\n            }\n\n            bool accept = false;\n\n            if (ndiff <= st.diff) {\n                accept = true;\n            } else {\n                double prob = exp((double)(st.diff - ndiff) / temp);\n                double rr = (double)rng() / (double)UINT_MAX;\n\n                if (rr < prob) accept = true;\n            }\n\n            if (accept) {\n                st.diff = ndiff;\n                st.mask.swap(nmask);\n                st.cnt.swap(ncnt);\n\n                st.tree[addId] = 1;\n                st.tree[remId] = 0;\n\n                adj_add(st.adj, ae.a, ae.b, addId);\n                adj_remove(st.adj, re.a, re.b, remId);\n\n                if (st.diff < best.diff) best = st;\n\n                if (st.diff == 0) {\n                    best = st;\n                    goto finish_reconstruction;\n                }\n            }\n        }\n    }\n\nfinish_reconstruction:\n    if (best.diff == INT_MAX) return false;\n\n    target.fill(0);\n    target[emptyPos] = 0;\n\n    for (int v = 0; v < V; v++) {\n        target[vidToPos[v]] = (unsigned char)best.mask[v];\n    }\n\n    return best.diff == 0;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Greedy target placement                                                     */\n/* -------------------------------------------------------------------------- */\n\nbool find_path_to_place(\n    const array<unsigned char, 100>& board,\n    int blank,\n    const vector<char>& fixed,\n    int pos,\n    int val,\n    string& path\n) {\n    path.clear();\n\n    if (board[pos] == val) return true;\n\n    int total = M * M;\n\n    vector<int> pre(total, -2);\n    vector<char> prem(total, 0);\n\n    queue<int> q;\n\n    for (int p = 0; p < M; p++) {\n        if (fixed[p]) continue;\n        if (p == blank) continue;\n\n        if (board[p] == val) {\n            int id = p * M + blank;\n            pre[id] = -1;\n            q.push(id);\n        }\n    }\n\n    int goal = -1;\n\n    while (!q.empty()) {\n        int id = q.front();\n        q.pop();\n\n        int tile = id / M;\n        int z = id % M;\n\n        if (tile == pos) {\n            goal = id;\n            break;\n        }\n\n        for (int nb : ADJ[z]) {\n            if (fixed[nb]) continue;\n\n            int ntile = tile;\n\n            if (nb == tile) ntile = z;\n\n            int nz = nb;\n            int nid = ntile * M + nz;\n\n            if (pre[nid] != -2) continue;\n\n            pre[nid] = id;\n            prem[nid] = move_char_from_blank_to_tile(z, nb);\n\n            q.push(nid);\n        }\n    }\n\n    if (goal == -1) return false;\n\n    int cur = goal;\n\n    while (pre[cur] != -1) {\n        path.push_back(prem[cur]);\n        cur = pre[cur];\n    }\n\n    reverse(path.begin(), path.end());\n\n    return true;\n}\n\nuint64_t encode9(const array<unsigned char, 100>& b, const vector<int>& cells) {\n    uint64_t x = 0;\n\n    for (int i = 0; i < 9; i++) {\n        x |= (uint64_t)b[cells[i]] << (4 * i);\n    }\n\n    return x;\n}\n\nint zero_index9(uint64_t x) {\n    for (int i = 0; i < 9; i++) {\n        if (((x >> (4 * i)) & 15) == 0) return i;\n    }\n\n    return -1;\n}\n\nuint64_t swap_nibble(uint64_t x, int a, int b) {\n    uint64_t va = (x >> (4 * a)) & 15;\n    uint64_t vb = (x >> (4 * b)) & 15;\n\n    x &= ~(15ULL << (4 * a));\n    x &= ~(15ULL << (4 * b));\n\n    x |= va << (4 * b);\n    x |= vb << (4 * a);\n\n    return x;\n}\n\nbool solve_final_3x3(\n    array<unsigned char, 100>& board,\n    int& blank,\n    const array<unsigned char, 100>& target,\n    string& ans\n) {\n    vector<int> cells;\n\n    for (int r = N - 3; r < N; r++) {\n        for (int c = N - 3; c < N; c++) {\n            cells.push_back(r * N + c);\n        }\n    }\n\n    bool blankInside = false;\n\n    for (int p : cells) {\n        if (p == blank) blankInside = true;\n    }\n\n    if (!blankInside) return false;\n\n    uint64_t start = encode9(board, cells);\n    uint64_t goal = encode9(target, cells);\n\n    if (start == goal) return true;\n\n    unordered_map<uint64_t, pair<uint64_t, char>> pre;\n    pre.reserve(400000);\n\n    queue<uint64_t> q;\n    q.push(start);\n    pre[start] = {UINT64_MAX, 0};\n\n    bool ok = false;\n    uint64_t found = 0;\n\n    while (!q.empty()) {\n        uint64_t x = q.front();\n        q.pop();\n\n        int zi = zero_index9(x);\n        int zr = zi / 3;\n        int zc = zi % 3;\n\n        const int dr[4] = {-1, 1, 0, 0};\n        const int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = zr + dr[k];\n            int nc = zc + dc[k];\n\n            if (nr < 0 || nr >= 3 || nc < 0 || nc >= 3) continue;\n\n            int ni = nr * 3 + nc;\n            uint64_t y = swap_nibble(x, zi, ni);\n\n            if (pre.count(y)) continue;\n\n            char mv = move_char_from_blank_to_tile(cells[zi], cells[ni]);\n            pre[y] = {x, mv};\n\n            if (y == goal) {\n                found = y;\n                ok = true;\n                while (!q.empty()) q.pop();\n                break;\n            }\n\n            q.push(y);\n        }\n    }\n\n    if (!ok) return false;\n\n    string path;\n    uint64_t cur = found;\n\n    while (pre[cur].first != UINT64_MAX) {\n        path.push_back(pre[cur].second);\n        cur = pre[cur].first;\n    }\n\n    reverse(path.begin(), path.end());\n\n    if ((int)ans.size() + (int)path.size() > T) return false;\n\n    for (char c : path) {\n        apply_move(board, blank, c);\n        ans.push_back(c);\n    }\n\n    return true;\n}\n\nstring partial_solve_to_target(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    const array<unsigned char, 100>& target\n) {\n    array<unsigned char, 100> board = init;\n    int blank = initBlank;\n\n    vector<char> fixed(M, 0);\n\n    string ans;\n    string bestAns;\n\n    Eval ev0 = eval_board(board);\n    int bestScore = estimated_score(ev0.s, 0);\n\n    vector<int> order;\n\n    for (int r = 0; r < N - 3; r++) {\n        for (int c = 0; c < N; c++) {\n            order.push_back(r * N + c);\n        }\n    }\n\n    for (int r = N - 3; r < N; r++) {\n        for (int c = 0; c < N - 3; c++) {\n            order.push_back(r * N + c);\n        }\n    }\n\n    for (int pos : order) {\n        int val = target[pos];\n\n        if (val == 0) break;\n\n        string path;\n\n        if (!find_path_to_place(board, blank, fixed, pos, val, path)) break;\n        if ((int)ans.size() + (int)path.size() > T) break;\n\n        for (char c : path) {\n            apply_move(board, blank, c);\n            ans.push_back(c);\n        }\n\n        if (board[pos] != val) break;\n\n        fixed[pos] = 1;\n\n        Eval ev = eval_board(board);\n        int sc = estimated_score(ev.s, (int)ans.size());\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestAns = ans;\n        }\n\n        if (ev.s == FULLV) return ans;\n    }\n\n    {\n        array<unsigned char, 100> b2 = board;\n        int z2 = blank;\n        string a2 = ans;\n\n        if (solve_final_3x3(b2, z2, target, a2)) {\n            Eval ev = eval_board(b2);\n            int sc = estimated_score(ev.s, (int)a2.size());\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestAns = a2;\n            }\n        }\n    }\n\n    return bestAns;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Beam search                                                                 */\n/* -------------------------------------------------------------------------- */\n\ninline bool edge_adj(const array<unsigned char, 100>& b, int x, int y) {\n    if (y == x - 1) return (b[x] & 1) && (b[y] & 4);\n    if (y == x + 1) return (b[x] & 4) && (b[y] & 1);\n    if (y == x - N) return (b[x] & 2) && (b[y] & 8);\n    if (y == x + N) return (b[x] & 8) && (b[y] & 2);\n    return false;\n}\n\nint local_edges(const array<unsigned char, 100>& b, int a, int c) {\n    int cells[2] = {a, c};\n    int keys[8];\n    int kc = 0;\n    int res = 0;\n\n    for (int ii = 0; ii < 2; ii++) {\n        int x = cells[ii];\n\n        for (int y : ADJ[x]) {\n            int u = min(x, y);\n            int v = max(x, y);\n            int key = u * 100 + v;\n\n            bool seen = false;\n\n            for (int t = 0; t < kc; t++) {\n                if (keys[t] == key) {\n                    seen = true;\n                    break;\n                }\n            }\n\n            if (seen) continue;\n\n            keys[kc++] = key;\n\n            if (edge_adj(b, x, y)) res++;\n        }\n    }\n\n    return res;\n}\n\nint total_edges(const array<unsigned char, 100>& b) {\n    int e = 0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n\n            if (b[p] == 0) continue;\n\n            if (c + 1 < N && b[p + 1] != 0) {\n                if ((b[p] & 4) && (b[p + 1] & 1)) e++;\n            }\n\n            if (r + 1 < N && b[p + N] != 0) {\n                if ((b[p] & 8) && (b[p + N] & 2)) e++;\n            }\n        }\n    }\n\n    return e;\n}\n\nstruct Node {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    short depth;\n    unsigned char prev;\n    ull hash;\n};\n\nstruct Cand {\n    array<unsigned char, 100> b;\n    int parent;\n    short blank;\n    short e;\n    short s;\n    short maxComp;\n    short cyc;\n    short depth;\n    unsigned char prev;\n    ull hash;\n    long long h;\n};\n\nchar inv_move(char c) {\n    if (c == 'U') return 'D';\n    if (c == 'D') return 'U';\n    if (c == 'L') return 'R';\n    if (c == 'R') return 'L';\n    return 0;\n}\n\nstring restore_path(const vector<Node>& pool, int idx) {\n    string res;\n\n    while (pool[idx].parent != -1) {\n        res.push_back((char)pool[idx].prev);\n        idx = pool[idx].parent;\n    }\n\n    reverse(res.begin(), res.end());\n\n    return res;\n}\n\nbool add_seed_path(\n    vector<Node>& pool,\n    vector<int>& beam,\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    ull initHash,\n    const string& prefix,\n    int& bestIdx,\n    int& bestScore\n) {\n    if (prefix.empty() || (int)prefix.size() > T) return false;\n\n    array<unsigned char, 100> b = init;\n    int blank = initBlank;\n    ull h = initHash;\n    int parent = 0;\n\n    for (int i = 0; i < (int)prefix.size(); i++) {\n        char c = prefix[i];\n\n        if (!legal_move(blank, c)) return false;\n\n        int nb = move_blank_pos(blank, c);\n        unsigned char tile = b[nb];\n\n        h ^= zob[blank][0];\n        h ^= zob[nb][tile];\n        h ^= zob[blank][tile];\n        h ^= zob[nb][0];\n\n        swap(b[blank], b[nb]);\n        blank = nb;\n\n        Node nd;\n        nd.b = b;\n        nd.parent = parent;\n        nd.blank = blank;\n        nd.e = 0;\n        nd.s = 0;\n        nd.depth = i + 1;\n        nd.prev = (unsigned char)c;\n        nd.hash = h;\n\n        pool.push_back(nd);\n        parent = (int)pool.size() - 1;\n    }\n\n    Node& last = pool[parent];\n    last.e = total_edges(last.b);\n\n    Eval ev = eval_board(last.b);\n    last.s = ev.s;\n\n    int sc = estimated_score(ev.s, last.depth);\n\n    if (sc > bestScore) {\n        bestScore = sc;\n        bestIdx = parent;\n    }\n\n    if (last.depth < T) beam.push_back(parent);\n\n    return true;\n}\n\nstring beam_search(\n    const array<unsigned char, 100>& init,\n    int initBlank,\n    ull initHash,\n    const string& seedPath\n) {\n    int W;\n\n    if (N == 6) W = 2600;\n    else if (N == 7) W = 1850;\n    else if (N == 8) W = 1250;\n    else if (N == 9) W = 850;\n    else W = 600;\n\n    vector<Node> pool;\n    pool.reserve((size_t)W * min(T + 2, 900) + T + 10);\n\n    Node root;\n    root.b = init;\n    root.parent = -1;\n    root.blank = initBlank;\n    root.e = total_edges(init);\n    root.prev = 0;\n    root.hash = initHash;\n    root.depth = 0;\n\n    Eval rootEv = eval_board(init);\n    root.s = rootEv.s;\n\n    pool.push_back(root);\n\n    if (rootEv.s == FULLV) return \"\";\n\n    vector<int> beam{0};\n\n    int bestIdx = 0;\n    int bestScore = estimated_score(rootEv.s, 0);\n\n    if (!seedPath.empty()) {\n        add_seed_path(pool, beam, init, initBlank, initHash, seedPath, bestIdx, bestScore);\n    }\n\n    const char mvChar[4] = {'U', 'D', 'L', 'R'};\n\n    for (int iter = 1; iter <= T; iter++) {\n        if (elapsed_sec() > 2.87) break;\n\n        vector<Cand> cand;\n        cand.reserve(beam.size() * 3 + 10);\n\n        for (int idx : beam) {\n            const Node& nd = pool[idx];\n\n            if (nd.depth >= T) continue;\n\n            int z = nd.blank;\n\n            for (int dir = 0; dir < 4; dir++) {\n                char mc = mvChar[dir];\n\n                if (nd.prev && inv_move((char)nd.prev) == mc) continue;\n                if (!legal_move(z, mc)) continue;\n\n                int nz = move_blank_pos(z, mc);\n\n                Cand x;\n                x.b = nd.b;\n\n                int before = local_edges(x.b, z, nz);\n\n                unsigned char tile = x.b[nz];\n                x.b[z] = tile;\n                x.b[nz] = 0;\n\n                int after = local_edges(x.b, z, nz);\n\n                x.e = nd.e - before + after;\n                x.parent = idx;\n                x.blank = nz;\n                x.prev = (unsigned char)mc;\n                x.s = 0;\n                x.maxComp = 0;\n                x.cyc = 0;\n                x.depth = nd.depth + 1;\n\n                ull h = nd.hash;\n                h ^= zob[z][0];\n                h ^= zob[nz][tile];\n                h ^= zob[z][tile];\n                h ^= zob[nz][0];\n\n                x.hash = h;\n\n                cand.push_back(std::move(x));\n            }\n        }\n\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.hash != b.hash) return a.hash < b.hash;\n            if (a.e != b.e) return a.e > b.e;\n            return a.depth < b.depth;\n        });\n\n        int write = 0;\n\n        for (int i = 0; i < (int)cand.size();) {\n            int j = i + 1;\n            int best = i;\n\n            while (j < (int)cand.size() && cand[j].hash == cand[i].hash) {\n                if (cand[j].e > cand[best].e ||\n                    (cand[j].e == cand[best].e && cand[j].depth < cand[best].depth)) {\n                    best = j;\n                }\n                j++;\n            }\n\n            cand[write++] = std::move(cand[best]);\n            i = j;\n        }\n\n        cand.resize(write);\n\n        int preLimit = min((int)cand.size(), max(W, 3 * W / 2));\n\n        if ((int)cand.size() > preLimit) {\n            nth_element(\n                cand.begin(),\n                cand.begin() + preLimit,\n                cand.end(),\n                [](const Cand& a, const Cand& b) {\n                    return a.e > b.e;\n                }\n            );\n\n            cand.resize(preLimit);\n        }\n\n        for (Cand& x : cand) {\n            Eval ev = eval_board(x.b);\n\n            x.s = ev.s;\n            x.maxComp = ev.maxComp;\n            x.cyc = ev.cyc;\n\n            x.h = 0;\n            x.h += 135000LL * x.s;\n            x.h += 1500LL * x.s * x.s;\n            x.h += 8200LL * x.e;\n            x.h += 900LL * x.maxComp;\n            x.h -= 21000LL * x.cyc;\n            x.h += (long long)(x.hash & 4095ULL);\n\n            int sc = estimated_score(x.s, x.depth);\n\n            if (sc > bestScore) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n                tmp.depth = x.depth;\n\n                pool.push_back(tmp);\n\n                bestIdx = (int)pool.size() - 1;\n                bestScore = sc;\n            }\n\n            if (x.s == FULLV) {\n                Node tmp;\n                tmp.b = x.b;\n                tmp.parent = x.parent;\n                tmp.blank = x.blank;\n                tmp.e = x.e;\n                tmp.s = x.s;\n                tmp.prev = x.prev;\n                tmp.hash = x.hash;\n                tmp.depth = x.depth;\n\n                pool.push_back(tmp);\n\n                return restore_path(pool, (int)pool.size() - 1);\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.h != b.h) return a.h > b.h;\n            if (a.e != b.e) return a.e > b.e;\n            return a.depth < b.depth;\n        });\n\n        int keep = min(W, (int)cand.size());\n\n        vector<int> nextBeam;\n        nextBeam.reserve(keep);\n\n        for (int i = 0; i < keep; i++) {\n            Node nd;\n            nd.b = cand[i].b;\n            nd.parent = cand[i].parent;\n            nd.blank = cand[i].blank;\n            nd.e = cand[i].e;\n            nd.s = cand[i].s;\n            nd.prev = cand[i].prev;\n            nd.hash = cand[i].hash;\n            nd.depth = cand[i].depth;\n\n            pool.push_back(nd);\n\n            int ni = (int)pool.size() - 1;\n\n            if (nd.depth < T) nextBeam.push_back(ni);\n\n            int sc = estimated_score(nd.s, nd.depth);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestIdx = ni;\n            }\n        }\n\n        beam.swap(nextBeam);\n    }\n\n    return restore_path(pool, bestIdx);\n}\n\n/* -------------------------------------------------------------------------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    cin >> N >> T;\n\n    M = N * N;\n    FULLV = M - 1;\n\n    build_adj();\n\n    mt19937_64 rng(123456789);\n\n    for (int i = 0; i < 100; i++) {\n        for (int v = 0; v < 16; v++) {\n            zob[i][v] = rng();\n        }\n    }\n\n    array<unsigned char, 100> init{};\n    int initBlank = -1;\n    ull initHash = 0;\n\n    vector<int> targetCnt(16, 0);\n\n    for (int r = 0; r < N; r++) {\n        string s;\n        cin >> s;\n\n        for (int c = 0; c < N; c++) {\n            int p = r * N + c;\n            int v = hexval(s[c]);\n\n            init[p] = (unsigned char)v;\n\n            if (v == 0) {\n                initBlank = p;\n            } else {\n                targetCnt[v]++;\n            }\n\n            initHash ^= zob[p][v];\n        }\n    }\n\n    string bestAns = \"\";\n    string seedAns = \"\";\n\n    Eval initEval = eval_board(init);\n    int initS = initEval.s;\n    int bestScore = estimated_score(initEval.s, 0);\n\n    array<unsigned char, 100> target{};\n\n    double reconLimit;\n\n    if (N <= 7) reconLimit = 0.62;\n    else if (N == 8) reconLimit = 0.72;\n    else reconLimit = 0.82;\n\n    bool haveTarget = reconstruct_target_any(targetCnt, target, reconLimit);\n\n    if (haveTarget || elapsed_sec() < 1.05) {\n        string targetAns = partial_solve_to_target(init, initBlank, target);\n\n        auto [S, sc] = eval_answer(init, initBlank, targetAns);\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestAns = targetAns;\n        }\n\n        // Key change: avoid using clearly bad target-greedy states as beam seeds.\n        if (!targetAns.empty() && S >= max(1, initS - 2)) {\n            seedAns = targetAns;\n        }\n\n        if (S == FULLV && (int)targetAns.size() <= T) {\n            cout << targetAns << '\\n';\n            return 0;\n        }\n    }\n\n    string beamAns = beam_search(init, initBlank, initHash, seedAns);\n\n    if ((int)beamAns.size() > T) beamAns.resize(T);\n\n    auto [beamS, beamScore] = eval_answer(init, initBlank, beamAns);\n\n    if (beamScore > bestScore) {\n        bestScore = beamScore;\n        bestAns = beamAns;\n    }\n\n    if ((int)bestAns.size() > T) bestAns.resize(T);\n\n    cout << bestAns << '\\n';\n\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Line {\n    double a, b, c;\n};\n\nstruct EvalResult {\n    int matched;\n    int diff;\n    array<int, 11> hist;\n    long long value() const {\n        return 100000LL * matched - diff;\n    }\n};\n\nstruct GridCand {\n    double theta;\n    vector<double> cu, cv;\n    long long val;\n};\n\nstruct Key {\n    uint64_t lo, hi;\n    bool operator==(const Key& o) const {\n        return lo == o.lo && hi == o.hi;\n    }\n};\n\nstruct KeyHash {\n    size_t operator()(const Key& k) const {\n        uint64_t x = k.lo ^ (k.hi + 0x9e3779b97f4a7c15ULL + (k.lo << 6) + (k.lo >> 2));\n        x ^= x >> 30;\n        x *= 0xbf58476d1ce4e5b9ULL;\n        x ^= x >> 27;\n        x *= 0x94d049bb133111ebULL;\n        x ^= x >> 31;\n        return (size_t)x;\n    }\n};\n\nstruct Partition {\n    vector<int> pid;\n    vector<int> cnt;\n    vector<vector<int>> members;\n    array<int, 11> hist;\n    EvalResult eval;\n    long long largeSq;\n};\n\nstruct CandidateLine {\n    Line line;\n    double priority;\n    int staticIndex;\n};\n\nstatic const double PI = acos(-1.0);\nstatic const double R = 10000.0;\n\nint N, K;\narray<int, 11> targetA;\nvector<Point> pts;\nchrono::steady_clock::time_point st;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n}\n\nlong long large_contrib(int c) {\n    return c > 10 ? 1LL * c * c : 0LL;\n}\n\nEvalResult make_eval_from_hist(const array<int, 11>& hist) {\n    EvalResult res;\n    res.hist = hist;\n    res.matched = 0;\n    res.diff = 0;\n    for (int d = 1; d <= 10; d++) {\n        res.matched += min(targetA[d], hist[d]);\n        res.diff += abs(targetA[d] - hist[d]);\n    }\n    return res;\n}\n\nEvalResult eval_grid(double theta, const vector<double>& cu, const vector<double>& cv) {\n    int gx = (int)cu.size() + 1;\n    int gy = (int)cv.size() + 1;\n    vector<int> cnt(gx * gy, 0);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double u = p.x * cs + p.y * sn;\n        double v = -p.x * sn + p.y * cs;\n        int ix = int(upper_bound(cu.begin(), cu.end(), u) - cu.begin());\n        int iy = int(upper_bound(cv.begin(), cv.end(), v) - cv.begin());\n        cnt[ix * gy + iy]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n    for (int c : cnt) {\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n    return make_eval_from_hist(hist);\n}\n\nEvalResult eval_lines(const vector<Line>& lines) {\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(N * 2);\n\n    int L = (int)lines.size();\n\n    for (const auto& p : pts) {\n        uint64_t lo = 0, hi = 0;\n\n        for (int i = 0; i < L; i++) {\n            double v = lines[i].a * p.x + lines[i].b * p.y - lines[i].c;\n            if (v > 0) {\n                if (i < 64) lo |= 1ULL << i;\n                else hi |= 1ULL << (i - 64);\n            }\n        }\n\n        mp[{lo, hi}]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n\n    for (auto& kv : mp) {\n        int c = kv.second;\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n\n    return make_eval_from_hist(hist);\n}\n\nPartition build_partition(const vector<Line>& lines, bool needMembers) {\n    Partition part;\n    part.pid.assign(N, -1);\n    part.cnt.clear();\n    part.members.clear();\n    part.hist.fill(0);\n    part.largeSq = 0;\n\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(N * 2);\n\n    int L = (int)lines.size();\n\n    for (int i = 0; i < N; i++) {\n        const auto& p = pts[i];\n\n        uint64_t lo = 0, hi = 0;\n\n        for (int j = 0; j < L; j++) {\n            double v = lines[j].a * p.x + lines[j].b * p.y - lines[j].c;\n            if (v > 0) {\n                if (j < 64) lo |= 1ULL << j;\n                else hi |= 1ULL << (j - 64);\n            }\n        }\n\n        Key key{lo, hi};\n        auto it = mp.find(key);\n\n        int id;\n        if (it == mp.end()) {\n            id = (int)part.cnt.size();\n            mp[key] = id;\n            part.cnt.push_back(0);\n            if (needMembers) part.members.emplace_back();\n        } else {\n            id = it->second;\n        }\n\n        part.pid[i] = id;\n        part.cnt[id]++;\n        if (needMembers) part.members[id].push_back(i);\n    }\n\n    for (int c : part.cnt) {\n        if (1 <= c && c <= 10) part.hist[c]++;\n        part.largeSq += large_contrib(c);\n    }\n\n    part.eval = make_eval_from_hist(part.hist);\n    return part;\n}\n\nvector<Line> build_grid_lines(double theta, const vector<double>& cu, const vector<double>& cv) {\n    vector<Line> lines;\n    lines.reserve(cu.size() + cv.size());\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (double c : cu) lines.push_back({cs, sn, c});\n    for (double c : cv) lines.push_back({-sn, cs, c});\n\n    return lines;\n}\n\nvector<double> uniform_cuts(int g) {\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    for (int i = 1; i < g; i++) {\n        cuts.push_back(-R + 2.0 * R * i / g);\n    }\n\n    return cuts;\n}\n\nvector<double> projection_quantile_cuts(double theta, int g, bool second_axis) {\n    vector<double> vals;\n    vals.reserve(N);\n\n    double cs = cos(theta), sn = sin(theta);\n\n    for (const auto& p : pts) {\n        double z;\n        if (!second_axis) z = p.x * cs + p.y * sn;\n        else z = -p.x * sn + p.y * cs;\n        vals.push_back(z);\n    }\n\n    sort(vals.begin(), vals.end());\n\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    for (int i = 1; i < g; i++) {\n        int r = (long long)N * i / g;\n        r = min(max(r, 1), N - 1);\n\n        double c = (vals[r - 1] + vals[r]) * 0.5;\n        if (fabs(vals[r] - vals[r - 1]) < 1e-9) c = vals[r] + 1e-7;\n\n        c = max(-R + 1e-6, min(R - 1e-6, c));\n        cuts.push_back(c);\n    }\n\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nvector<double> random_dirichlet_cuts(int g, double alpha, mt19937& rng) {\n    vector<double> w(g);\n\n    if (alpha > 500.0) {\n        for (int i = 0; i < g; i++) w[i] = 1.0;\n    } else {\n        gamma_distribution<double> gd(alpha, 1.0);\n        for (int i = 0; i < g; i++) w[i] = max(1e-12, gd(rng));\n    }\n\n    double sum = accumulate(w.begin(), w.end(), 0.0);\n\n    vector<double> cuts;\n    cuts.reserve(max(0, g - 1));\n\n    double cur = -R;\n    for (int i = 0; i + 1 < g; i++) {\n        cur += 2.0 * R * w[i] / sum;\n        cuts.push_back(cur);\n    }\n\n    sort(cuts.begin(), cuts.end());\n    return cuts;\n}\n\nlong long local_split_value(const Partition& part, int c, int p) {\n    if (p <= 0 || p >= c) return LLONG_MIN / 4;\n\n    int q = c - p;\n\n    array<int, 11> hist = part.hist;\n\n    if (1 <= c && c <= 10) hist[c]--;\n    if (1 <= p && p <= 10) hist[p]++;\n    if (1 <= q && q <= 10) hist[q]++;\n\n    return make_eval_from_hist(hist).value() - part.eval.value();\n}\n\nvector<CandidateLine> generate_cell_candidate_lines(const Partition& part, mt19937& rng, int maxCand) {\n    vector<int> ids(part.cnt.size());\n    iota(ids.begin(), ids.end(), 0);\n\n    auto cell_priority = [&](int id) {\n        int c = part.cnt[id];\n        int pr = 0;\n\n        if (c > 10) pr += 100000 + c * c;\n        else if (part.hist[c] > targetA[c]) pr += 50000 + c;\n        else pr += c;\n\n        return pr;\n    };\n\n    sort(ids.begin(), ids.end(), [&](int x, int y) {\n        return cell_priority(x) > cell_priority(y);\n    });\n\n    vector<double> angles;\n    for (int i = 0; i < 18; i++) angles.push_back(PI * i / 18.0);\n\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n    for (int i = 0; i < 8; i++) angles.push_back(ur01(rng) * PI);\n\n    vector<CandidateLine> cand;\n    cand.reserve(maxCand * 2);\n\n    int usedCells = 0;\n\n    for (int id : ids) {\n        int c = part.cnt[id];\n        if (c <= 1) continue;\n\n        bool interesting = false;\n        if (c > 10) interesting = true;\n        if (c <= 10 && part.hist[c] > targetA[c]) interesting = true;\n        if (!interesting && usedCells >= 10) continue;\n\n        usedCells++;\n        if (usedCells > 50) break;\n\n        vector<int> ranks;\n\n        for (int d = 1; d <= 10; d++) {\n            if (targetA[d] > part.hist[d]) {\n                if (1 <= d && d < c) ranks.push_back(d);\n                if (1 <= c - d && c - d < c) ranks.push_back(c - d);\n            }\n        }\n\n        for (int d = 1; d <= min(10, c - 1); d++) {\n            ranks.push_back(d);\n            ranks.push_back(c - d);\n        }\n\n        if (c > 20) {\n            vector<double> fracs = {0.20, 0.25, 0.30, 0.333333333, 0.40, 0.50,\n                                    0.60, 0.666666667, 0.70, 0.75, 0.80};\n            for (double f : fracs) {\n                int r = (int)llround(c * f);\n                if (1 <= r && r < c) ranks.push_back(r);\n            }\n\n            int step = max(3, c / 12);\n            for (int r = step; r < c; r += step) {\n                if (1 <= r && r < c) ranks.push_back(r);\n            }\n        }\n\n        if (c <= 24) {\n            for (int r = 1; r < c; r++) {\n                if (local_split_value(part, c, r) >= -100000) ranks.push_back(r);\n            }\n        }\n\n        sort(ranks.begin(), ranks.end());\n        ranks.erase(unique(ranks.begin(), ranks.end()), ranks.end());\n\n        if (ranks.empty()) continue;\n\n        for (double th : angles) {\n            double a = cos(th), b = sin(th);\n\n            vector<double> proj;\n            proj.reserve(c);\n\n            for (int idx : part.members[id]) {\n                const auto& p = pts[idx];\n                proj.push_back(a * p.x + b * p.y);\n            }\n\n            sort(proj.begin(), proj.end());\n\n            for (int r : ranks) {\n                if (r <= 0 || r >= c) continue;\n                if (fabs(proj[r] - proj[r - 1]) < 1e-9) continue;\n\n                double cc = (proj[r - 1] + proj[r]) * 0.5;\n\n                long long lv1 = local_split_value(part, c, r);\n                long long lv2 = local_split_value(part, c, c - r);\n                long long lv = max(lv1, lv2);\n\n                long long oldLarge = large_contrib(c);\n                long long newLarge = large_contrib(r) + large_contrib(c - r);\n                long long largeGain = oldLarge - newLarge;\n\n                double priority = (double)lv * 10.0 + largeGain * 0.02 + (c > 10 ? 30000.0 : 0.0) + c;\n\n                cand.push_back({{a, b, cc}, priority, -1});\n            }\n        }\n    }\n\n    sort(cand.begin(), cand.end(), [](const CandidateLine& x, const CandidateLine& y) {\n        return x.priority > y.priority;\n    });\n\n    if ((int)cand.size() > maxCand) cand.resize(maxCand);\n    return cand;\n}\n\nvector<Line> generate_static_extra_candidate_lines(mt19937& rng) {\n    vector<Line> cand;\n\n    int nang = 30;\n    int nq = 70;\n\n    for (int ai = 0; ai < nang; ai++) {\n        double theta = PI * ai / nang;\n        double a = cos(theta), b = sin(theta);\n\n        vector<double> vals;\n        vals.reserve(N);\n\n        for (const auto& p : pts) vals.push_back(a * p.x + b * p.y);\n        sort(vals.begin(), vals.end());\n\n        for (int q = 1; q < nq; q++) {\n            int r = (long long)N * q / nq;\n            r = min(max(r, 1), N - 1);\n\n            double c = (vals[r - 1] + vals[r]) * 0.5;\n            if (fabs(vals[r] - vals[r - 1]) < 1e-9) c = vals[r] + 1e-7;\n\n            cand.push_back({a, b, c});\n        }\n\n        for (int u = 1; u < 35; u++) {\n            double c = -R + 2.0 * R * u / 35.0;\n            cand.push_back({a, b, c});\n        }\n    }\n\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n\n    for (int t = 0; t < 500; t++) {\n        double theta = ur01(rng) * PI;\n        double a = cos(theta), b = sin(theta);\n\n        int id1 = rng() % N;\n        int id2 = rng() % N;\n\n        double c1 = a * pts[id1].x + b * pts[id1].y;\n        double c2 = a * pts[id2].x + b * pts[id2].y;\n        double c = (c1 + c2) * 0.5;\n        c = max(-R + 1e-6, min(R - 1e-6, c));\n\n        cand.push_back({a, b, c});\n    }\n\n    return cand;\n}\n\npair<long long, long long> eval_add_line_full(const Line& ln, const Partition& part, vector<int>& pos, vector<int>& touched) {\n    touched.clear();\n\n    for (int i = 0; i < N; i++) {\n        const auto& p = pts[i];\n        double v = ln.a * p.x + ln.b * p.y - ln.c;\n\n        if (v > 0) {\n            int id = part.pid[i];\n            if (pos[id] == 0) touched.push_back(id);\n            pos[id]++;\n        }\n    }\n\n    array<int, 11> hist = part.hist;\n    long long largeSq = part.largeSq;\n\n    for (int id : touched) {\n        int p = pos[id];\n        int c = part.cnt[id];\n        int q = c - p;\n\n        if (p != 0 && q != 0) {\n            if (1 <= c && c <= 10) hist[c]--;\n            if (1 <= p && p <= 10) hist[p]++;\n            if (1 <= q && q <= 10) hist[q]++;\n\n            largeSq -= large_contrib(c);\n            largeSq += large_contrib(p) + large_contrib(q);\n        }\n\n        pos[id] = 0;\n    }\n\n    return {make_eval_from_hist(hist).value(), largeSq};\n}\n\nvoid greedy_add_lines(vector<Line>& lines, long long& bestValue, double timeLimit, mt19937& rng, vector<Line>& bestGreedyLines) {\n    if ((int)lines.size() >= K) return;\n\n    vector<Line> staticCand = generate_static_extra_candidate_lines(rng);\n    vector<char> staticUsed(staticCand.size(), 0);\n\n    bestGreedyLines = lines;\n    long long bestGreedyValue = eval_lines(lines).value();\n\n    int neutralUsed = 0;\n    const int neutralLimit = 10;\n\n    while ((int)lines.size() < K && elapsed_sec() < timeLimit) {\n        Partition part = build_partition(lines, true);\n        long long curVal = part.eval.value();\n        long long curLarge = part.largeSq;\n\n        int dynamicLimit = 3000;\n        vector<CandidateLine> cand = generate_cell_candidate_lines(part, rng, dynamicLimit);\n\n        for (int i = 0; i < (int)staticCand.size(); i++) {\n            if (!staticUsed[i]) cand.push_back({staticCand[i], 0.0, i});\n        }\n\n        vector<int> pos(part.cnt.size(), 0);\n        vector<int> touched;\n        touched.reserve(part.cnt.size());\n\n        long long bestCandVal = curVal;\n        long long bestCandLarge = curLarge;\n        int bestIdx = -1;\n\n        long long bestNeutralLarge = curLarge;\n        int bestNeutralIdx = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (elapsed_sec() > timeLimit) break;\n\n            auto [v, lg] = eval_add_line_full(cand[i].line, part, pos, touched);\n\n            if (v > bestCandVal || (v == bestCandVal && lg < bestCandLarge)) {\n                bestCandVal = v;\n                bestCandLarge = lg;\n                bestIdx = i;\n            }\n\n            if (v == curVal && lg < bestNeutralLarge) {\n                bestNeutralLarge = lg;\n                bestNeutralIdx = i;\n            }\n        }\n\n        int chosen = -1;\n        bool neutral = false;\n\n        if (bestIdx != -1 && bestCandVal > curVal) {\n            chosen = bestIdx;\n        } else if (neutralUsed < neutralLimit && bestNeutralIdx != -1 && bestNeutralLarge < curLarge) {\n            chosen = bestNeutralIdx;\n            neutral = true;\n        } else {\n            break;\n        }\n\n        lines.push_back(cand[chosen].line);\n\n        if (cand[chosen].staticIndex >= 0) {\n            staticUsed[cand[chosen].staticIndex] = 1;\n        }\n\n        if (neutral) {\n            neutralUsed++;\n        } else {\n            neutralUsed = max(0, neutralUsed - 1);\n            bestValue = max(bestValue, bestCandVal);\n\n            if (bestCandVal > bestGreedyValue) {\n                bestGreedyValue = bestCandVal;\n                bestGreedyLines = lines;\n            }\n        }\n    }\n\n    bestValue = max(bestValue, bestGreedyValue);\n}\n\nlong long extgcd(long long a, long long b, long long& x, long long& y) {\n    if (b == 0) {\n        x = (a >= 0 ? 1 : -1);\n        y = 0;\n        return llabs(a);\n    }\n\n    long long x1, y1;\n    long long g = extgcd(b, a % b, x1, y1);\n\n    x = y1;\n    y = x1 - (a / b) * y1;\n\n    return g;\n}\n\nbool collinear_any_coeff(long long A, long long B, long long C) {\n    for (const auto& p : pts) {\n        __int128 v = (__int128)A * p.x + (__int128)B * p.y;\n        if (v == C) return true;\n    }\n    return false;\n}\n\nbool has_point_x(long long x) {\n    for (const auto& p : pts) if (p.x == x) return true;\n    return false;\n}\n\nbool has_point_y(long long y) {\n    for (const auto& p : pts) if (p.y == y) return true;\n    return false;\n}\n\nlong long nearest_safe_coord(double v, bool isX) {\n    long long base = llround(v);\n\n    for (long long d = 0; d <= 20000; d++) {\n        long long a = base + d;\n        if (a >= -1000000000LL && a <= 1000000000LL && !(isX ? has_point_x(a) : has_point_y(a))) return a;\n\n        long long b = base - d;\n        if (d && b >= -1000000000LL && b <= 1000000000LL && !(isX ? has_point_x(b) : has_point_y(b))) return b;\n    }\n\n    return base;\n}\n\narray<long long, 4> line_to_integer_points_scaled(const Line& ln, long long SCALE) {\n    const long long LIM = 1000000000LL;\n    const long long BIG = 100000000LL;\n\n    double norm = hypot(ln.a, ln.b);\n    double aa = ln.a / norm;\n    double bb = ln.b / norm;\n    double cc = ln.c / norm;\n\n    if (fabs(bb) < 1e-11) {\n        long long x = nearest_safe_coord(cc / aa, true);\n        return {x, -BIG, x, BIG};\n    }\n\n    if (fabs(aa) < 1e-11) {\n        long long y = nearest_safe_coord(cc / bb, false);\n        return {-BIG, y, BIG, y};\n    }\n\n    long long A = llround(aa * SCALE);\n    long long B = llround(bb * SCALE);\n\n    if (A == 0 && B == 0) A = 1;\n    if (A == 0) A = (aa >= 0 ? 1 : -1);\n    if (B == 0) B = (bb >= 0 ? 1 : -1);\n\n    for (int t = 0; std::gcd(llabs(A), llabs(B)) != 1 && t < 20; t++) {\n        if (llabs(A) < llabs(B)) A += (A >= 0 ? 1 : -1);\n        else B += (B >= 0 ? 1 : -1);\n    }\n\n    if (std::gcd(llabs(A), llabs(B)) != 1) {\n        A += (A >= 0 ? 1 : -1);\n        while (std::gcd(llabs(A), llabs(B)) != 1) A += (A >= 0 ? 1 : -1);\n    }\n\n    long double len = sqrt((long double)A * A + (long double)B * B);\n    long long C = llround((long double)cc * len);\n\n    for (int t = 0; t < 80 && collinear_any_coeff(A, B, C); t++) {\n        if (t % 2 == 0) C += 1 + t / 2;\n        else C -= 1 + t / 2;\n    }\n\n    long long xg, yg;\n    extgcd(llabs(A), llabs(B), xg, yg);\n\n    if (A < 0) xg = -xg;\n    if (B < 0) yg = -yg;\n\n    __int128 x0 = (__int128)xg * C;\n    __int128 y0 = (__int128)yg * C;\n\n    long double px = aa * cc;\n    long double py = bb * cc;\n\n    long double dx = B;\n    long double dy = -A;\n    long double denom = dx * dx + dy * dy;\n\n    long double tr = ((px - (long double)x0) * dx + (py - (long double)y0) * dy) / denom;\n    long long t0 = llround(tr);\n\n    __int128 x1b = x0 + (__int128)t0 * B;\n    __int128 y1b = y0 - (__int128)t0 * A;\n\n    long long x1 = (long long)x1b;\n    long long y1 = (long long)y1b;\n\n    long long stepMax = max(llabs(A), llabs(B));\n    long long T = max(1LL, min(900LL, (LIM - 1000000LL) / max(1LL, stepMax)));\n\n    long long x2 = x1 + B * T;\n    long long y2 = y1 - A * T;\n\n    if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) {\n        x2 = x1 - B * T;\n        y2 = y1 + A * T;\n    }\n\n    while ((x1 < -LIM || x1 > LIM || y1 < -LIM || y1 > LIM ||\n            x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) && T > 1) {\n        T /= 2;\n\n        x2 = x1 + B * T;\n        y2 = y1 - A * T;\n\n        if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) {\n            x2 = x1 - B * T;\n            y2 = y1 + A * T;\n        }\n    }\n\n    if (x1 < -LIM || x1 > LIM || y1 < -LIM || y1 > LIM ||\n        x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM ||\n        (x1 == x2 && y1 == y2)) {\n        double px0 = aa * cc;\n        double py0 = bb * cc;\n        double ux = -bb, uy = aa;\n\n        x1 = llround(px0 + BIG * ux);\n        y1 = llround(py0 + BIG * uy);\n        x2 = llround(px0 - BIG * ux);\n        y2 = llround(py0 - BIG * uy);\n\n        x1 = max(-LIM, min(LIM, x1));\n        y1 = max(-LIM, min(LIM, y1));\n        x2 = max(-LIM, min(LIM, x2));\n        y2 = max(-LIM, min(LIM, y2));\n    }\n\n    if (x1 == x2 && y1 == y2) {\n        if (x2 < LIM) x2++;\n        else x2--;\n    }\n\n    return {x1, y1, x2, y2};\n}\n\nEvalResult eval_output_segments(const vector<array<long long, 4>>& segs) {\n    unordered_map<Key, int, KeyHash> mp;\n    mp.reserve(N * 2);\n\n    int L = (int)segs.size();\n\n    for (const auto& p : pts) {\n        uint64_t lo = 0, hi = 0;\n        bool cut = false;\n\n        for (int i = 0; i < L; i++) {\n            long long x1 = segs[i][0], y1 = segs[i][1], x2 = segs[i][2], y2 = segs[i][3];\n\n            __int128 cross = (__int128)(x2 - x1) * (p.y - y1) - (__int128)(y2 - y1) * (p.x - x1);\n\n            if (cross == 0) {\n                cut = true;\n                break;\n            }\n\n            if (cross > 0) {\n                if (i < 64) lo |= 1ULL << i;\n                else hi |= 1ULL << (i - 64);\n            }\n        }\n\n        if (!cut) mp[{lo, hi}]++;\n    }\n\n    array<int, 11> hist{};\n    hist.fill(0);\n\n    for (auto& kv : mp) {\n        int c = kv.second;\n        if (1 <= c && c <= 10) hist[c]++;\n    }\n\n    return make_eval_from_hist(hist);\n}\n\nvector<Line> remove_improving_lines(vector<Line> lines, double deadline) {\n    long long cur = eval_lines(lines).value();\n\n    bool improved = true;\n\n    while (improved && elapsed_sec() < deadline) {\n        improved = false;\n        int bestIdx = -1;\n        long long bestVal = cur;\n\n        for (int i = 0; i < (int)lines.size(); i++) {\n            if (elapsed_sec() > deadline) break;\n\n            vector<Line> tmp = lines;\n            tmp.erase(tmp.begin() + i);\n\n            long long v = eval_lines(tmp).value();\n\n            if (v > bestVal) {\n                bestVal = v;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx >= 0) {\n            lines.erase(lines.begin() + bestIdx);\n            cur = bestVal;\n            improved = true;\n        }\n    }\n\n    return lines;\n}\n\nvector<array<long long, 4>> remove_output_improving_segments(vector<array<long long, 4>> segs, double deadline) {\n    long long cur = eval_output_segments(segs).value();\n\n    while (elapsed_sec() < deadline) {\n        int bestIdx = -1;\n        long long bestVal = cur;\n\n        for (int i = 0; i < (int)segs.size(); i++) {\n            if (elapsed_sec() > deadline) break;\n\n            vector<array<long long, 4>> tmp = segs;\n            tmp.erase(tmp.begin() + i);\n\n            long long v = eval_output_segments(tmp).value();\n\n            if (v > bestVal) {\n                bestVal = v;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx == -1) break;\n\n        segs.erase(segs.begin() + bestIdx);\n        cur = bestVal;\n    }\n\n    return segs;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st = chrono::steady_clock::now();\n\n    cin >> N >> K;\n    targetA.fill(0);\n\n    int M = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> targetA[d];\n        M += targetA[d];\n    }\n\n    pts.resize(N);\n    for (int i = 0; i < N; i++) cin >> pts[i].x >> pts[i].y;\n\n    mt19937 rng(1234567);\n    uniform_real_distribution<double> ur01(0.0, 1.0);\n\n    vector<Line> bestLines;\n    long long bestValue = LLONG_MIN;\n\n    vector<GridCand> topGrids;\n\n    auto register_grid = [&](double theta, const vector<double>& cu, const vector<double>& cv) {\n        if ((int)cu.size() + (int)cv.size() > K) return;\n\n        EvalResult er = eval_grid(theta, cu, cv);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = build_grid_lines(theta, cu, cv);\n        }\n\n        topGrids.push_back({theta, cu, cv, val});\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n\n        if ((int)topGrids.size() > 18) topGrids.pop_back();\n    };\n\n    auto register_lines = [&](const vector<Line>& lines) {\n        if ((int)lines.size() > K) return;\n\n        EvalResult er = eval_lines(lines);\n        long long val = er.value();\n\n        if (val > bestValue) {\n            bestValue = val;\n            bestLines = lines;\n        }\n    };\n\n    double baseUniformProduct = 4.0 * M / PI;\n\n    vector<double> factors = {0.45, 0.55, 0.65, 0.78, 0.90, 1.00, 1.12, 1.28, 1.50, 1.75, 2.05};\n    vector<double> aspects = {0.50, 0.62, 0.75, 0.88, 1.00, 1.15, 1.33, 1.60, 2.00};\n\n    vector<double> thetas;\n    for (int i = 0; i < 12; i++) thetas.push_back(PI * i / 24.0);\n\n    for (double fac : factors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, baseUniformProduct * fac);\n\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            auto cu = uniform_cuts(gx);\n            auto cv = uniform_cuts(gy);\n\n            for (double th : thetas) register_grid(th, cu, cv);\n        }\n    }\n\n    vector<double> qFactors = {0.50, 0.62, 0.75, 0.88, 1.00, 1.15, 1.32, 1.55, 1.85};\n\n    for (double fac : qFactors) {\n        for (double asp : aspects) {\n            double prod = max(1.0, M * fac);\n\n            int gx = max(1, (int)llround(sqrt(prod * asp)));\n            int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n            while (gx + gy - 2 > K) {\n                if (gx > gy) gx--;\n                else gy--;\n            }\n\n            for (double th : thetas) {\n                auto cu = projection_quantile_cuts(th, gx, false);\n                auto cv = projection_quantile_cuts(th, gy, true);\n                register_grid(th, cu, cv);\n            }\n        }\n    }\n\n    for (int rep = 0; rep < 40 && elapsed_sec() < 1.1; rep++) {\n        double hbase = sqrt(max(1.0, M / 3.0));\n        double scale = 0.55 + 0.035 * rep;\n\n        int g = max(2, (int)llround(hbase * scale));\n        g = min(g, 34);\n\n        double th0 = (rep % 15) * PI / 45.0;\n\n        vector<Line> lines;\n\n        for (int f = 0; f < 3; f++) {\n            double th = th0 + f * PI / 3.0;\n            double a = cos(th), b = sin(th);\n\n            auto cuts = uniform_cuts(g);\n\n            for (double c : cuts) lines.push_back({a, b, c});\n        }\n\n        register_lines(lines);\n    }\n\n    vector<double> alphaList = {0.25, 0.35, 0.50, 0.75, 1.00, 1.50, 2.50, 5.00, 1000.0};\n\n    while (elapsed_sec() < 1.40) {\n        double logFac = log(0.45) + ur01(rng) * (log(2.15) - log(0.45));\n        double logAsp = log(0.45) + ur01(rng) * (log(2.20) - log(0.45));\n\n        double fac = exp(logFac);\n        double asp = exp(logAsp);\n\n        double prod = max(1.0, baseUniformProduct * fac);\n\n        int gx = max(1, (int)llround(sqrt(prod * asp)));\n        int gy = max(1, (int)llround(sqrt(prod / asp)));\n\n        while (gx + gy - 2 > K) {\n            if (gx > gy) gx--;\n            else gy--;\n        }\n\n        double ax = alphaList[rng() % alphaList.size()];\n        double ay = alphaList[rng() % alphaList.size()];\n\n        auto cu = random_dirichlet_cuts(gx, ax, rng);\n        auto cv = random_dirichlet_cuts(gy, ay, rng);\n\n        double th = ur01(rng) * PI / 2.0;\n\n        register_grid(th, cu, cv);\n    }\n\n    auto improve_grid = [&](GridCand start, double timeLimit) {\n        GridCand cur = start;\n        GridCand best = start;\n\n        double begin = elapsed_sec();\n\n        while (elapsed_sec() < timeLimit) {\n            double now = elapsed_sec();\n            double progress = (now - begin) / max(1e-9, timeLimit - begin);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 30000.0 * (1.0 - progress) + 300.0;\n\n            GridCand nxt = cur;\n            int typ = rng() % 10;\n\n            if ((typ < 4 && !nxt.cu.empty()) || nxt.cv.empty()) {\n                int m = nxt.cu.size();\n                int id = rng() % m;\n\n                double lo = (id == 0 ? -R + 1e-6 : nxt.cu[id - 1] + 1e-6);\n                double hi = (id + 1 == m ? R - 1e-6 : nxt.cu[id + 1] - 1e-6);\n                double width = hi - lo;\n\n                double nv;\n                if (typ == 0) {\n                    normal_distribution<double> nd(0.0, width * 0.08);\n                    nv = nxt.cu[id] + nd(rng);\n                } else {\n                    nv = lo + ur01(rng) * width;\n                }\n\n                nxt.cu[id] = max(lo, min(hi, nv));\n            } else if (typ < 8 && !nxt.cv.empty()) {\n                int m = nxt.cv.size();\n                int id = rng() % m;\n\n                double lo = (id == 0 ? -R + 1e-6 : nxt.cv[id - 1] + 1e-6);\n                double hi = (id + 1 == m ? R - 1e-6 : nxt.cv[id + 1] - 1e-6);\n                double width = hi - lo;\n\n                double nv;\n                if (typ == 4) {\n                    normal_distribution<double> nd(0.0, width * 0.08);\n                    nv = nxt.cv[id] + nd(rng);\n                } else {\n                    nv = lo + ur01(rng) * width;\n                }\n\n                nxt.cv[id] = max(lo, min(hi, nv));\n            } else if (typ == 8) {\n                normal_distribution<double> nd(0.0, 0.015 * (1.0 - progress) + 0.002);\n\n                nxt.theta += nd(rng);\n                while (nxt.theta < 0) nxt.theta += PI;\n                while (nxt.theta >= PI) nxt.theta -= PI;\n            } else {\n                bool axis = rng() & 1;\n                double scale = exp((ur01(rng) - 0.5) * 0.12 * (1.0 - progress));\n\n                vector<double>& arr = axis ? nxt.cu : nxt.cv;\n\n                for (double& x : arr) x = max(-R + 1e-6, min(R - 1e-6, x * scale));\n\n                sort(arr.begin(), arr.end());\n\n                for (int i = 1; i < (int)arr.size(); i++) {\n                    if (arr[i] <= arr[i - 1] + 1e-6) arr[i] = arr[i - 1] + 1e-6;\n                }\n\n                for (double& x : arr) x = max(-R + 1e-6, min(R - 1e-6, x));\n            }\n\n            EvalResult er = eval_grid(nxt.theta, nxt.cu, nxt.cv);\n            nxt.val = er.value();\n\n            long long delta = nxt.val - cur.val;\n\n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else {\n                double prob = exp((double)delta / temp);\n                if (ur01(rng) < prob) accept = true;\n            }\n\n            if (accept) cur = nxt;\n\n            if (nxt.val > best.val) {\n                best = nxt;\n\n                if (nxt.val > bestValue) {\n                    bestValue = nxt.val;\n                    bestLines = build_grid_lines(nxt.theta, nxt.cu, nxt.cv);\n                }\n            }\n        }\n\n        return best;\n    };\n\n    int idx = 0;\n\n    while (elapsed_sec() < 2.32 && idx < (int)topGrids.size()) {\n        double remaining = 2.32 - elapsed_sec();\n        int left = (int)topGrids.size() - idx;\n\n        double slice = min(0.19, max(0.035, remaining / max(1, left)));\n\n        GridCand improved = improve_grid(topGrids[idx], min(2.32, elapsed_sec() + slice));\n        topGrids[idx] = improved;\n\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n\n        idx++;\n    }\n\n    while (elapsed_sec() < 2.40 && !topGrids.empty()) {\n        GridCand improved = improve_grid(topGrids[0], min(2.40, elapsed_sec() + 0.05));\n        topGrids[0] = improved;\n\n        sort(topGrids.begin(), topGrids.end(), [](const GridCand& a, const GridCand& b) {\n            return a.val > b.val;\n        });\n    }\n\n    vector<Line> beforeGreedyLines = bestLines;\n    vector<Line> bestGreedyLines = bestLines;\n\n    greedy_add_lines(bestLines, bestValue, 2.865, rng, bestGreedyLines);\n\n    vector<vector<Line>> candidateSets;\n    candidateSets.push_back(bestLines);\n    candidateSets.push_back(bestGreedyLines);\n    candidateSets.push_back(beforeGreedyLines);\n\n    for (int i = 0; i < min(5, (int)topGrids.size()); i++) {\n        candidateSets.push_back(build_grid_lines(topGrids[i].theta, topGrids[i].cu, topGrids[i].cv));\n    }\n\n    if (elapsed_sec() < 2.91) {\n        candidateSets.push_back(remove_improving_lines(bestLines, 2.915));\n    }\n\n    if (elapsed_sec() < 2.925) {\n        candidateSets.push_back(remove_improving_lines(bestGreedyLines, 2.93));\n    }\n\n    if (bestLines.empty()) {\n        auto cu = uniform_cuts(25);\n        auto cv = uniform_cuts(25);\n        bestLines = build_grid_lines(0.01, cu, cv);\n        candidateSets.push_back(bestLines);\n    }\n\n    long long bestOutVal = LLONG_MIN;\n    vector<array<long long, 4>> bestSegs;\n\n    vector<long long> scales = {10007LL, 100003LL, 1000003LL, 10000019LL, 100000007LL};\n\n    for (auto lines : candidateSets) {\n        if ((int)lines.size() > K) lines.resize(K);\n\n        for (long long sc : scales) {\n            if (elapsed_sec() > 2.965) break;\n\n            vector<array<long long, 4>> segs;\n            segs.reserve(lines.size());\n\n            for (const auto& ln : lines) {\n                segs.push_back(line_to_integer_points_scaled(ln, sc));\n            }\n\n            long long v = eval_output_segments(segs).value();\n\n            if (v > bestOutVal) {\n                bestOutVal = v;\n                bestSegs = segs;\n            }\n        }\n    }\n\n    if (elapsed_sec() < 2.975 && !bestSegs.empty()) {\n        auto improvedSegs = remove_output_improving_segments(bestSegs, 2.985);\n        long long v = eval_output_segments(improvedSegs).value();\n        if (v >= bestOutVal) {\n            bestOutVal = v;\n            bestSegs = improvedSegs;\n        }\n    }\n\n    if ((int)bestSegs.size() > K) bestSegs.resize(K);\n\n    cout << bestSegs.size() << '\\n';\n\n    for (const auto& e : bestSegs) {\n        cout << e[0] << ' ' << e[1] << ' ' << e[2] << ' ' << e[3] << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 61;\n\nint N, M;\nint Weight[MAXN][MAXN];\nint maxWeightGlobal;\nint centerCoord;\nvector<pair<int,int>> initialDots;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int mod) {\n        if (mod <= 0) return 0;\n        return int(next() % mod);\n    }\n};\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nint dx8[8] = {1, 0, -1, 0, 1, -1, -1, 1};\nint dy8[8] = {0, 1, 0, -1, 1, 1, -1, -1};\n\npair<int,int> dirPairs[8] = {\n    {0, 1}, {1, 2}, {2, 3}, {3, 0},\n    {4, 5}, {5, 6}, {6, 7}, {7, 4}\n};\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ninline int enc(int x, int y) {\n    return x * N + y;\n}\n\ninline int stepLen(int ax, int ay, int bx, int by) {\n    return max(abs(ax - bx), abs(ay - by));\n}\n\ninline int movePerim(const Move &m) {\n    return stepLen(m.x1, m.y1, m.x2, m.y2)\n         + stepLen(m.x2, m.y2, m.x3, m.y3)\n         + stepLen(m.x3, m.y3, m.x4, m.y4)\n         + stepLen(m.x4, m.y4, m.x1, m.y1);\n}\n\nstruct State {\n    bool dot[MAXN][MAXN];\n    bool seg[4][MAXN][MAXN];\n    vector<Move> ops;\n    long long totalWeight;\n\n    void init() {\n        memset(dot, 0, sizeof(dot));\n        memset(seg, 0, sizeof(seg));\n        ops.clear();\n        ops.reserve(N * N);\n        totalWeight = 0;\n\n        for (auto [x, y] : initialDots) {\n            dot[x][y] = true;\n            totalWeight += Weight[x][y];\n        }\n    }\n\n    bool edgeFree(int ax, int ay, int bx, int by) const {\n        if (ay == by) {\n            int y = ay;\n            int l = min(ax, bx), r = max(ax, bx);\n            for (int x = l; x < r; x++) {\n                if (seg[0][x][y]) return false;\n            }\n            return true;\n        }\n\n        if (ax == bx) {\n            int x = ax;\n            int l = min(ay, by), r = max(ay, by);\n            for (int y = l; y < r; y++) {\n                if (seg[1][x][y]) return false;\n            }\n            return true;\n        }\n\n        if ((bx - ax) == (by - ay)) {\n            int x = ax, y = ay;\n            if (x > bx) {\n                x = bx;\n                y = by;\n            }\n            int len = abs(bx - ax);\n            for (int i = 0; i < len; i++) {\n                if (seg[2][x + i][y + i]) return false;\n            }\n            return true;\n        }\n\n        {\n            int x = ax, y = ay;\n            if (x > bx) {\n                x = bx;\n                y = by;\n            }\n            int len = abs(bx - ax);\n            for (int i = 0; i < len; i++) {\n                if (seg[3][x + i][y - i - 1]) return false;\n            }\n            return true;\n        }\n    }\n\n    void markEdge(int ax, int ay, int bx, int by) {\n        if (ay == by) {\n            int y = ay;\n            int l = min(ax, bx), r = max(ax, bx);\n            for (int x = l; x < r; x++) seg[0][x][y] = true;\n            return;\n        }\n\n        if (ax == bx) {\n            int x = ax;\n            int l = min(ay, by), r = max(ay, by);\n            for (int y = l; y < r; y++) seg[1][x][y] = true;\n            return;\n        }\n\n        if ((bx - ax) == (by - ay)) {\n            int x = ax, y = ay;\n            if (x > bx) {\n                x = bx;\n                y = by;\n            }\n            int len = abs(bx - ax);\n            for (int i = 0; i < len; i++) seg[2][x + i][y + i] = true;\n            return;\n        }\n\n        {\n            int x = ax, y = ay;\n            if (x > bx) {\n                x = bx;\n                y = by;\n            }\n            int len = abs(bx - ax);\n            for (int i = 0; i < len; i++) seg[3][x + i][y - i - 1] = true;\n        }\n    }\n\n    bool rectEdgesFree(const Move &m) const {\n        return edgeFree(m.x1, m.y1, m.x2, m.y2)\n            && edgeFree(m.x2, m.y2, m.x3, m.y3)\n            && edgeFree(m.x3, m.y3, m.x4, m.y4)\n            && edgeFree(m.x4, m.y4, m.x1, m.y1);\n    }\n\n    bool isAllowedDotOnPerimeter(int x, int y, const Move &m) const {\n        return (x == m.x2 && y == m.y2)\n            || (x == m.x3 && y == m.y3)\n            || (x == m.x4 && y == m.y4);\n    }\n\n    bool edgeDotsOk(int ax, int ay, int bx, int by, const Move &m) const {\n        int dx = (bx > ax) - (bx < ax);\n        int dy = (by > ay) - (by < ay);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int i = 0; i <= len; i++) {\n            if (dot[x][y] && !isAllowedDotOnPerimeter(x, y, m)) return false;\n            x += dx;\n            y += dy;\n        }\n        return true;\n    }\n\n    bool validMove(const Move &m) const {\n        if (!inside(m.x1, m.y1) || !inside(m.x2, m.y2)\n         || !inside(m.x3, m.y3) || !inside(m.x4, m.y4)) return false;\n\n        if (dot[m.x1][m.y1]) return false;\n        if (!dot[m.x2][m.y2] || !dot[m.x3][m.y3] || !dot[m.x4][m.y4]) return false;\n\n        int ax = m.x2 - m.x1;\n        int ay = m.y2 - m.y1;\n        int bx = m.x4 - m.x1;\n        int by = m.y4 - m.y1;\n\n        if (ax == 0 && ay == 0) return false;\n        if (bx == 0 && by == 0) return false;\n\n        if (m.x3 != m.x2 + m.x4 - m.x1) return false;\n        if (m.y3 != m.y2 + m.y4 - m.y1) return false;\n\n        if (ax * bx + ay * by != 0) return false;\n\n        auto allowedVec = [](int x, int y) {\n            if (x == 0 && y != 0) return true;\n            if (y == 0 && x != 0) return true;\n            if (abs(x) == abs(y) && x != 0) return true;\n            return false;\n        };\n\n        if (!allowedVec(ax, ay) || !allowedVec(bx, by)) return false;\n        if (!rectEdgesFree(m)) return false;\n\n        if (!edgeDotsOk(m.x1, m.y1, m.x2, m.y2, m)) return false;\n        if (!edgeDotsOk(m.x2, m.y2, m.x3, m.y3, m)) return false;\n        if (!edgeDotsOk(m.x3, m.y3, m.x4, m.y4, m)) return false;\n        if (!edgeDotsOk(m.x4, m.y4, m.x1, m.y1, m)) return false;\n\n        return true;\n    }\n\n    void apply(const Move &m) {\n        markEdge(m.x1, m.y1, m.x2, m.y2);\n        markEdge(m.x2, m.y2, m.x3, m.y3);\n        markEdge(m.x3, m.y3, m.x4, m.y4);\n        markEdge(m.x4, m.y4, m.x1, m.y1);\n\n        dot[m.x1][m.y1] = true;\n        totalWeight += Weight[m.x1][m.y1];\n        ops.push_back(m);\n    }\n};\n\nstruct Param {\n    int wcoef;\n    int pcoef;\n    int qcoef;\n    int dcoef;\n    int ocoef;\n    int acoef;\n    int rcoef;\n    int dircoef;\n    int noise;\n    int topR;\n    int phase;\n};\n\nstruct Result {\n    long long score;\n    vector<Move> ops;\n};\n\nstruct Candidate {\n    long long key;\n    Move mv;\n};\n\nvoid insertTop(vector<Candidate> &top, int R, const Candidate &cand) {\n    if ((int)top.size() < R) {\n        top.push_back(cand);\n        return;\n    }\n\n    int worst = 0;\n    for (int i = 1; i < R; i++) {\n        if (top[i].key < top[worst].key) worst = i;\n    }\n\n    if (cand.key > top[worst].key) top[worst] = cand;\n}\n\nState greedyFill(State st, const Param &param, XorShift &rng, const Timer &timer, double deadline) {\n    static short nearestDot[8][MAXN][MAXN];\n\n    int dirx = 0, diry = 0;\n    if (param.dircoef != 0) {\n        int k = rng.nextInt(8);\n        dirx = dx8[k];\n        diry = dy8[k];\n    }\n\n    while (true) {\n        if (timer.elapsed() > deadline) break;\n\n        for (int d = 0; d < 8; d++) {\n            int xs = dx8[d] > 0 ? N - 1 : 0;\n            int xe = dx8[d] > 0 ? -1 : N;\n            int xi = dx8[d] > 0 ? -1 : 1;\n\n            int ys = dy8[d] > 0 ? N - 1 : 0;\n            int ye = dy8[d] > 0 ? -1 : N;\n            int yi = dy8[d] > 0 ? -1 : 1;\n\n            for (int x = xs; x != xe; x += xi) {\n                for (int y = ys; y != ye; y += yi) {\n                    int nx = x + dx8[d];\n                    int ny = y + dy8[d];\n\n                    if (!inside(nx, ny)) {\n                        nearestDot[d][x][y] = -1;\n                    } else if (st.dot[nx][ny]) {\n                        nearestDot[d][x][y] = enc(nx, ny);\n                    } else {\n                        nearestDot[d][x][y] = nearestDot[d][nx][ny];\n                    }\n                }\n            }\n        }\n\n        bool found = false;\n        Move bestMove{};\n        long long bestKey = LLONG_MIN;\n        vector<Candidate> top;\n\n        if (param.topR > 1) top.reserve(param.topR);\n\n        int opCount = (int)st.ops.size();\n\n        long long pEff = param.pcoef;\n        if (param.phase == 1) {\n            pEff = 1LL * param.pcoef * 260 / (260 + opCount);\n        } else if (param.phase == 2) {\n            pEff = 1LL * param.pcoef * (120 + min(opCount, 400)) / 120;\n        }\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                if (st.dot[x][y]) continue;\n\n                int degree = 0;\n                if (param.dcoef != 0) {\n                    for (int d = 0; d < 8; d++) {\n                        if (nearestDot[d][x][y] >= 0) degree++;\n                    }\n                }\n\n                int opp = 0;\n                if (param.ocoef != 0) {\n                    for (auto [d1, d2] : dirPairs) {\n                        if (nearestDot[d1][x][y] >= 0 && nearestDot[d2][x][y] >= 0) opp++;\n                    }\n                }\n\n                for (auto [d1, d2] : dirPairs) {\n                    int e2 = nearestDot[d1][x][y];\n                    int e4 = nearestDot[d2][x][y];\n\n                    if (e2 < 0 || e4 < 0) continue;\n\n                    int x2 = e2 / N;\n                    int y2 = e2 % N;\n                    int x4 = e4 / N;\n                    int y4 = e4 % N;\n\n                    int x3 = x2 + x4 - x;\n                    int y3 = y2 + y4 - y;\n\n                    if (!inside(x3, y3)) continue;\n                    if (!st.dot[x3][y3]) continue;\n\n                    int e3 = enc(x3, y3);\n                    if (nearestDot[d2][x2][y2] != e3) continue;\n                    if (nearestDot[d1][x4][y4] != e3) continue;\n\n                    Move mv{x, y, x2, y2, x3, y3, x4, y4};\n                    if (!st.rectEdgesFree(mv)) continue;\n\n                    int perim = movePerim(mv);\n                    int area = abs((x2 - x) * (y4 - y) - (y2 - y) * (x4 - x));\n\n                    long long key = 0;\n                    key += 1LL * Weight[x][y] * param.wcoef;\n                    key -= 1LL * perim * pEff;\n                    key -= 1LL * perim * perim * param.qcoef;\n                    key += 1LL * degree * param.dcoef;\n                    key += 1LL * opp * param.ocoef;\n                    key += 1LL * area * param.acoef;\n\n                    if (param.rcoef != 0) {\n                        key += 1LL * param.rcoef * (10000LL * Weight[x][y] / (perim + 4));\n                    }\n\n                    if (param.dircoef != 0) {\n                        int proj = dirx * (x - centerCoord) + diry * (y - centerCoord);\n                        key += 1LL * param.dircoef * proj;\n                    }\n\n                    if (param.noise > 0) key += rng.nextInt(param.noise);\n\n                    if (param.topR <= 1) {\n                        if (!found || key > bestKey || (key == bestKey && rng.nextInt(2))) {\n                            found = true;\n                            bestKey = key;\n                            bestMove = mv;\n                        }\n                    } else {\n                        insertTop(top, param.topR, Candidate{key, mv});\n                    }\n                }\n            }\n        }\n\n        if (param.topR > 1) {\n            if (top.empty()) break;\n\n            sort(top.begin(), top.end(), [](const Candidate &a, const Candidate &b) {\n                return a.key > b.key;\n            });\n\n            int r = (int)top.size();\n            int idx;\n\n            if (r == 1) {\n                idx = 0;\n            } else {\n                int a = rng.nextInt(r);\n                int b = rng.nextInt(r);\n                idx = 1LL * a * b / r;\n                if (idx >= r) idx = r - 1;\n            }\n\n            bestMove = top[idx].mv;\n            found = true;\n        }\n\n        if (!found) break;\n        st.apply(bestMove);\n    }\n\n    return st;\n}\n\nState makePerturbedState(const vector<Move> &baseOps, XorShift &rng, int mode) {\n    State st;\n    st.init();\n\n    int K = (int)baseOps.size();\n\n    int prefix = K;\n    int blockL = K + 1;\n    int blockR = K + 1;\n    int dropPct = 0;\n\n    int sx = 0, sy = 0, threshold = 0;\n    int cx = 0, cy = 0, rad2 = 0;\n\n    if (mode == 0) {\n        dropPct = 4 + rng.nextInt(16);\n    } else if (mode == 1) {\n        prefix = K * (35 + rng.nextInt(55)) / 100;\n    } else if (mode == 2) {\n        if (K > 0) {\n            blockL = rng.nextInt(K);\n            int len = max(1, K * (5 + rng.nextInt(22)) / 100);\n            blockR = min(K, blockL + len);\n        }\n    } else if (mode == 6) {\n        int d = rng.nextInt(8);\n        sx = dx8[d];\n        sy = dy8[d];\n        threshold = -N / 6 + rng.nextInt(max(1, N / 3 + 1));\n    } else if (mode == 7) {\n        cx = rng.nextInt(N);\n        cy = rng.nextInt(N);\n        int r = max(3, N * (10 + rng.nextInt(18)) / 100);\n        rad2 = r * r;\n    } else if (mode == 8) {\n        // Gentle suffix destruction: useful in the extra phase.\n        prefix = K * (75 + rng.nextInt(21)) / 100;\n    }\n\n    for (int i = 0; i < K; i++) {\n        bool keep = true;\n        const Move &m = baseOps[i];\n\n        if (mode == 0) {\n            if (rng.nextInt(100) < dropPct) keep = false;\n        } else if (mode == 1) {\n            if (i >= prefix) keep = false;\n        } else if (mode == 2) {\n            if (blockL <= i && i < blockR) keep = false;\n        } else if (mode == 3) {\n            int w = Weight[m.x1][m.y1];\n            int low = maxWeightGlobal - w;\n            int prob = 3 + 28 * low / max(1, maxWeightGlobal);\n            if (rng.nextInt(100) < prob) keep = false;\n        } else if (mode == 4) {\n            int p = movePerim(m);\n            int prob = 2 + 45 * p / max(1, 4 * N);\n            if (rng.nextInt(100) < prob) keep = false;\n        } else if (mode == 5) {\n            int p = movePerim(m);\n            int w = Weight[m.x1][m.y1];\n            int bad = max(0, maxWeightGlobal - w) + p * 8;\n            int prob = 2 + min(40, bad * 35 / max(1, maxWeightGlobal + 4 * N));\n            if (rng.nextInt(100) < prob) keep = false;\n        } else if (mode == 6) {\n            int proj = sx * (m.x1 - centerCoord) + sy * (m.y1 - centerCoord);\n            if (proj >= threshold && rng.nextInt(100) < 35) keep = false;\n            else if (proj >= threshold - 4 && rng.nextInt(100) < 12) keep = false;\n        } else if (mode == 7) {\n            int dx = m.x1 - cx;\n            int dy = m.y1 - cy;\n            if (dx * dx + dy * dy <= rad2 && rng.nextInt(100) < 45) keep = false;\n        } else {\n            if (i >= prefix) keep = false;\n        }\n\n        if (!keep) continue;\n\n        if (st.validMove(m)) st.apply(m);\n    }\n\n    return st;\n}\n\nvoid updateElites(vector<Result> &elites, const Result &cand) {\n    elites.push_back(cand);\n\n    sort(elites.begin(), elites.end(), [](const Result &a, const Result &b) {\n        if (a.score != b.score) return a.score > b.score;\n        return a.ops.size() > b.ops.size();\n    });\n\n    vector<Result> filtered;\n    for (auto &e : elites) {\n        bool dup = false;\n        for (auto &f : filtered) {\n            if (e.score == f.score && e.ops.size() == f.ops.size()) {\n                dup = true;\n                break;\n            }\n        }\n\n        if (!dup) filtered.push_back(e);\n        if ((int)filtered.size() >= 7) break;\n    }\n\n    elites.swap(filtered);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    initialDots.resize(M);\n    for (int i = 0; i < M; i++) {\n        cin >> initialDots[i].first >> initialDots[i].second;\n    }\n\n    centerCoord = (N - 1) / 2;\n    maxWeightGlobal = 0;\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            Weight[x][y] = (x - centerCoord) * (x - centerCoord)\n                         + (y - centerCoord) * (y - centerCoord) + 1;\n            maxWeightGlobal = max(maxWeightGlobal, Weight[x][y]);\n        }\n    }\n\n    Timer timer;\n\n    const double PHASE1_DEADLINE = 4.72;\n    const double FINAL_DEADLINE = 4.84;\n\n    vector<Param> params = {\n        {1000,    0,   0,     0,     0,    0, 0,    0,      0,  1, 0},\n        {1000,   20,   0,     0,     0,    0, 0,    0,  20000,  1, 0},\n        {1000,   80,   0,     0,     0,    0, 0,    0,  50000,  1, 0},\n        {1000,  200,   0,     0,     0,    0, 0,    0, 100000,  1, 0},\n        {1000,  -20,   0,     0,     0,    0, 0,    0,  50000,  1, 0},\n        {1000,  -80,   0,     0,     0,    0, 0,    0, 100000,  1, 0},\n        {1000,    0,   0,     0,     0,    0, 0,    0, 200000,  1, 0},\n        {1000,  400,   0,     0,     0,    0, 0,    0, 200000,  1, 0},\n\n        {1000, 1000,   0,     0,     0,    0, 0,    0,  50000,  4, 1},\n        {1000, 1800,   0,     0,     0,  -15, 0,    0,  80000,  6, 1},\n        {1000, 3000,   0,     0,     0,  -30, 0,    0, 100000,  8, 1},\n        { 950, 4500,   0,     0,     0,  -45, 0,    0, 120000, 10, 1},\n\n        {1000, 1000,   0, 10000,  8000,    0, 0,    0,  70000,  6, 1},\n        {1000, 2000,   0, 20000, 12000,  -15, 0,    0, 100000,  8, 1},\n        { 900, 3500,   0, 35000, 18000,  -30, 0,    0, 130000, 12, 1},\n        { 800, 5000,   0, 50000, 25000,  -45, 0,    0, 160000, 16, 1},\n\n        { 900,  500,  10, 10000, 10000,    0, 2,    0,  80000,  6, 1},\n        { 800,  800,  18, 20000, 15000,  -10, 3,    0, 100000,  8, 1},\n        { 750, 1200,  25, 30000, 20000,  -20, 4,    0, 130000, 10, 1},\n        { 700, 1600,  35, 40000, 25000,  -30, 5,    0, 150000, 12, 1},\n\n        {1000,  300,   0,  8000,  8000,   10, 0, 2500, 100000,  8, 0},\n        {1000,  800,   0, 12000, 12000,    0, 1, 3500, 120000, 10, 1},\n        { 900, 1200,  12, 20000, 16000,  -15, 2, 4500, 140000, 12, 1},\n\n        {1000, -300,   0,     0,     0,   20, 0,    0,  80000,  5, 0},\n        {1000, -800,   0,     0,     0,   45, 0,    0, 120000,  8, 0},\n\n        {1000,  800,   0, 10000,  8000,    0, 0,    0,  70000,  6, 2},\n        {1000, 1600,   0, 25000, 15000,  -15, 0,    0, 100000, 10, 2},\n    };\n\n    vector<Param> repairParams = {\n        {1000,    0,   0,     0,     0,    0, 0,    0, 100000,  1, 0},\n        {1000, 1000,   0, 10000, 10000,    0, 0,    0,  70000,  6, 1},\n        {1000, 2000,   0, 20000, 12000,  -15, 0,    0, 100000,  8, 1},\n        { 900, 3500,   0, 35000, 18000,  -30, 0,    0, 130000, 12, 1},\n        {1000, -300,   0,     0,     0,   20, 0,    0, 100000,  6, 0},\n        { 850,  800,  15, 20000, 15000,  -10, 3,    0, 110000,  8, 1},\n        { 750, 1300,  25, 30000, 20000,  -25, 4,    0, 140000, 12, 1},\n        {1000,  500,   0, 12000, 10000,   10, 1, 3000, 120000, 10, 1},\n        { 900, 1200,  12, 25000, 18000,  -15, 2, 4200, 140000, 12, 1},\n    };\n\n    Result best{-1, {}};\n    vector<Result> elites;\n\n    int iter = 0;\n    int normalIter = 0;\n    int repairIter = 0;\n\n    auto runOne = [&](double deadline, bool extraPhase) {\n        uint64_t seed = 123456789ULL\n                      + 1000003ULL * iter\n                      + 998244353ULL * N\n                      + 19260817ULL * M\n                      + (extraPhase ? 777777777ULL : 0ULL);\n\n        XorShift rng(seed);\n\n        State start;\n        Param p;\n\n        bool doRepair = false;\n        if (!extraPhase) {\n            if (!elites.empty() && normalIter >= (int)params.size() && iter % 2 == 1) {\n                doRepair = true;\n            }\n        } else {\n            doRepair = !elites.empty();\n        }\n\n        if (!doRepair) {\n            start.init();\n            p = params[normalIter % params.size()];\n            normalIter++;\n        } else {\n            int eliteIndex = 0;\n\n            // In the extra phase, focus more strongly on the best elite.\n            int randomThreshold = extraPhase ? 75 : 60;\n            if ((int)elites.size() >= 2 && rng.nextInt(100) >= randomThreshold) {\n                eliteIndex = rng.nextInt((int)elites.size());\n            }\n\n            int mode = extraPhase ? rng.nextInt(9) : rng.nextInt(6);\n            start = makePerturbedState(elites[eliteIndex].ops, rng, mode);\n            p = repairParams[repairIter % repairParams.size()];\n            repairIter++;\n        }\n\n        State fin = greedyFill(std::move(start), p, rng, timer, deadline);\n\n        Result cand{fin.totalWeight, fin.ops};\n\n        if (cand.score > best.score) {\n            best = cand;\n        }\n\n        updateElites(elites, cand);\n        iter++;\n    };\n\n    while (timer.elapsed() < PHASE1_DEADLINE) {\n        runOne(PHASE1_DEADLINE, false);\n    }\n\n    while (timer.elapsed() < FINAL_DEADLINE) {\n        runOne(FINAL_DEADLINE, true);\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (const auto &m : best.ops) {\n        cout << m.x1 << ' ' << m.y1 << ' '\n             << m.x2 << ' ' << m.y2 << ' '\n             << m.x3 << ' ' << m.y3 << ' '\n             << m.x4 << ' ' << m.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed = 2463534242u) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n};\n\nusing Board = array<unsigned char, 100>;\n\nint F[101];\nint cntFlavor[4];\n\nint anchorR[4], anchorC[4];\nint distCell[4][100];\nint targetCell[100];\n\nint neighs[100][4];\nint degs[100];\n\nconst int cornerR[4] = {0, 0, 9, 9};\nconst int cornerC[4] = {0, 9, 0, 9};\n\nchar dirChar[4] = {'F', 'B', 'L', 'R'};\n\nvoid initNeighbors() {\n    for (int id = 0; id < 100; id++) {\n        int r = id / 10;\n        int c = id % 10;\n        degs[id] = 0;\n        if (r > 0) neighs[id][degs[id]++] = id - 10;\n        if (r < 9) neighs[id][degs[id]++] = id + 10;\n        if (c > 0) neighs[id][degs[id]++] = id - 1;\n        if (c < 9) neighs[id][degs[id]++] = id + 1;\n    }\n}\n\nBoard tiltBoard(const Board& b, int dir) {\n    Board nb{};\n    nb.fill(0);\n\n    if (dir == 0) { // F\n        for (int c = 0; c < 10; c++) {\n            int w = 0;\n            for (int r = 0; r < 10; r++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w++ * 10 + c] = v;\n            }\n        }\n    } else if (dir == 1) { // B\n        for (int c = 0; c < 10; c++) {\n            int w = 9;\n            for (int r = 9; r >= 0; r--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[w-- * 10 + c] = v;\n            }\n        }\n    } else if (dir == 2) { // L\n        for (int r = 0; r < 10; r++) {\n            int w = 0;\n            for (int c = 0; c < 10; c++) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w++] = v;\n            }\n        }\n    } else { // R\n        for (int r = 0; r < 10; r++) {\n            int w = 9;\n            for (int c = 9; c >= 0; c--) {\n                unsigned char v = b[r * 10 + c];\n                if (v) nb[r * 10 + w--] = v;\n            }\n        }\n    }\n\n    return nb;\n}\n\nvoid placeCandyByP(Board& b, int p, int flavor) {\n    int k = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            k++;\n            if (k == p) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n        }\n    }\n}\n\nvoid placeRandomCandy(Board& b, int emptyCnt, int flavor, XorShift& rng) {\n    int k = rng.randint(emptyCnt);\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) {\n            if (k == 0) {\n                b[i] = (unsigned char)flavor;\n                return;\n            }\n            k--;\n        }\n    }\n}\n\nlong long componentRawScore(const Board& b) {\n    bool vis[100] = {};\n    long long res = 0;\n    int q[100];\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            for (int i = 0; i < degs[v]; i++) {\n                int ni = neighs[v][i];\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        res += 1LL * sz * sz;\n    }\n\n    return res;\n}\n\nlong long evalBoard(const Board& b) {\n    bool vis[100] = {};\n    long long comp = 0;\n    int q[100];\n\n    for (int s = 0; s < 100; s++) {\n        if (b[s] == 0 || vis[s]) continue;\n\n        int flav = b[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            for (int i = 0; i < degs[v]; i++) {\n                int ni = neighs[v][i];\n                if (!vis[ni] && b[ni] == flav) {\n                    vis[ni] = true;\n                    q[tail++] = ni;\n                }\n            }\n        }\n\n        comp += 1LL * sz * sz;\n    }\n\n    int sameAdj = 0;\n    int diffAdj = 0;\n    int pref = 0;\n    int targetMatch = 0;\n\n    for (int r = 0; r < 10; r++) {\n        for (int c = 0; c < 10; c++) {\n            int id = r * 10 + c;\n            int fl = b[id];\n            if (fl == 0) continue;\n\n            pref += 18 - distCell[fl][id];\n            if (targetCell[id] == fl) targetMatch++;\n\n            if (r + 1 < 10) {\n                int fl2 = b[(r + 1) * 10 + c];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n            if (c + 1 < 10) {\n                int fl2 = b[r * 10 + c + 1];\n                if (fl2) {\n                    if (fl2 == fl) sameAdj++;\n                    else diffAdj++;\n                }\n            }\n        }\n    }\n\n    return comp * 100\n         + sameAdj * 220\n         - diffAdj * 60\n         + pref * 28\n         + targetMatch * 300;\n}\n\nvoid buildTarget() {\n    for (int fl = 1; fl <= 3; fl++) {\n        for (int id = 0; id < 100; id++) {\n            int r = id / 10;\n            int c = id % 10;\n            distCell[fl][id] = abs(r - anchorR[fl]) + abs(c - anchorC[fl]);\n        }\n    }\n\n    fill(targetCell, targetCell + 100, 0);\n\n    struct Item {\n        int dist;\n        int fl;\n        int id;\n    };\n\n    vector<Item> items;\n    items.reserve(300);\n\n    for (int id = 0; id < 100; id++) {\n        for (int fl = 1; fl <= 3; fl++) {\n            items.push_back({distCell[fl][id], fl, id});\n        }\n    }\n\n    sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n        if (a.dist != b.dist) return a.dist < b.dist;\n        if (a.fl != b.fl) return a.fl < b.fl;\n        return a.id < b.id;\n    });\n\n    int rem[4];\n    for (int fl = 1; fl <= 3; fl++) rem[fl] = cntFlavor[fl];\n\n    for (auto& it : items) {\n        if (targetCell[it.id] == 0 && rem[it.fl] > 0) {\n            targetCell[it.id] = it.fl;\n            rem[it.fl]--;\n        }\n    }\n}\n\nint choosePolicyDir(const Board& b) {\n    int bestDir = 0;\n    long long bestVal = LLONG_MIN;\n\n    for (int d = 0; d < 4; d++) {\n        Board nb = tiltBoard(b, d);\n        long long val = evalBoard(nb);\n        if (val > bestVal) {\n            bestVal = val;\n            bestDir = d;\n        }\n    }\n\n    return bestDir;\n}\n\nlong long simulatePolicyGame(uint32_t seed) {\n    XorShift rng(seed);\n    Board b{};\n    b.fill(0);\n\n    for (int t = 1; t <= 100; t++) {\n        placeRandomCandy(b, 101 - t, F[t], rng);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long simulateRollout(Board b, int nextT, uint32_t seed) {\n    XorShift rng(seed);\n\n    for (int t = nextT; t <= 100; t++) {\n        placeRandomCandy(b, 101 - t, F[t], rng);\n\n        if (t < 100) {\n            int d = choosePolicyDir(b);\n            b = tiltBoard(b, d);\n        }\n    }\n\n    return componentRawScore(b);\n}\n\nlong long exactOneStepLookahead(const Board& b, int currentT) {\n    if (currentT >= 100) return evalBoard(b);\n\n    int nt = currentT + 1;\n    int fl = F[nt];\n\n    vector<int> emp;\n    emp.reserve(100);\n\n    for (int i = 0; i < 100; i++) {\n        if (b[i] == 0) emp.push_back(i);\n    }\n\n    long long sum = 0;\n\n    for (int id : emp) {\n        Board tmp = b;\n        tmp[id] = (unsigned char)fl;\n\n        if (nt == 100) {\n            // True final objective is better than heuristic at the last placement.\n            sum += componentRawScore(tmp) * 100;\n        } else {\n            long long best = LLONG_MIN;\n            for (int d = 0; d < 4; d++) {\n                Board nb = tiltBoard(tmp, d);\n                best = max(best, evalBoard(nb));\n            }\n            sum += best;\n        }\n    }\n\n    return sum / max(1, (int)emp.size());\n}\n\nvoid selectCornerAssignment() {\n    double bestScore = -1.0;\n    int bestCorner[4] = {0, 0, 1, 2};\n\n    vector<uint32_t> seeds;\n    for (int i = 0; i < 5; i++) {\n        seeds.push_back(1234567u + i * 1000003u);\n    }\n\n    for (int mask = 0; mask < (1 << 4); mask++) {\n        if (__builtin_popcount((unsigned)mask) != 3) continue;\n\n        vector<int> cs;\n        for (int i = 0; i < 4; i++) {\n            if (mask >> i & 1) cs.push_back(i);\n        }\n\n        sort(cs.begin(), cs.end());\n\n        do {\n            for (int fl = 1; fl <= 3; fl++) {\n                int cid = cs[fl - 1];\n                anchorR[fl] = cornerR[cid];\n                anchorC[fl] = cornerC[cid];\n            }\n\n            buildTarget();\n\n            long long sum = 0;\n            for (uint32_t seed : seeds) {\n                sum += simulatePolicyGame(seed);\n            }\n\n            double avg = (double)sum / seeds.size();\n\n            if (avg > bestScore) {\n                bestScore = avg;\n                for (int fl = 1; fl <= 3; fl++) {\n                    bestCorner[fl] = cs[fl - 1];\n                }\n            }\n\n        } while (next_permutation(cs.begin(), cs.end()));\n    }\n\n    for (int fl = 1; fl <= 3; fl++) {\n        int cid = bestCorner[fl];\n        anchorR[fl] = cornerR[cid];\n        anchorC[fl] = cornerC[cid];\n    }\n\n    buildTarget();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    initNeighbors();\n\n    auto startTime = chrono::steady_clock::now();\n\n    for (int i = 1; i <= 100; i++) {\n        cin >> F[i];\n        cntFlavor[F[i]]++;\n    }\n\n    selectCornerAssignment();\n\n    Board board{};\n    board.fill(0);\n\n    XorShift rolloutRng(987654321u);\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        if (!(cin >> p)) return 0;\n\n        placeCandyByP(board, p, F[t]);\n\n        Board cand[4];\n        long long baseEval[4];\n        long long lookEval[4];\n\n        for (int d = 0; d < 4; d++) {\n            cand[d] = tiltBoard(board, d);\n            baseEval[d] = evalBoard(cand[d]);\n        }\n\n        bool canLook = true;\n        {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - startTime).count();\n            if (elapsed > 1.72) canLook = false;\n        }\n\n        for (int d = 0; d < 4; d++) {\n            if (canLook && t < 100) lookEval[d] = exactOneStepLookahead(cand[d], t);\n            else lookEval[d] = baseEval[d];\n        }\n\n        long long rolloutTotal[4] = {};\n        int samples = 0;\n\n        if (t < 100) {\n            double ratio = (double)t / 100.0;\n            double targetTime = 0.03 + 1.77 * pow(ratio, 1.25);\n            const double HARD_LIMIT = 1.86;\n\n            while (true) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - startTime).count();\n\n                if (elapsed > HARD_LIMIT) break;\n                if (elapsed > targetTime && samples >= 1) break;\n\n                uint32_t seed = rolloutRng.next();\n\n                for (int d = 0; d < 4; d++) {\n                    rolloutTotal[d] += simulateRollout(cand[d], t + 1, seed);\n                }\n\n                samples++;\n\n                if (samples >= 250) break;\n            }\n        }\n\n        int bestDir = 0;\n        double bestScore = -1e100;\n\n        for (int d = 0; d < 4; d++) {\n            double score;\n\n            if (samples > 0) {\n                double rolloutAvg = (double)rolloutTotal[d] / samples;\n                double lookPseudoRaw = (double)lookEval[d] / 100.0;\n                double basePseudoRaw = (double)baseEval[d] / 100.0;\n\n                score = rolloutAvg + 0.12 * lookPseudoRaw + 0.03 * basePseudoRaw;\n            } else {\n                score = (double)lookEval[d] + 0.1 * (double)baseEval[d];\n            }\n\n            if (score > bestScore) {\n                bestScore = score;\n                bestDir = d;\n            }\n        }\n\n        board = cand[bestDir];\n\n        cout << dirChar[bestDir] << endl;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing U64 = uint64_t;\nusing Row = array<U64, 2>;\n\nstruct FastRNG {\n    uint64_t x;\n    FastRNG(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nstatic inline bool bitRow(const vector<Row>& rows, int i, int j) {\n    return (rows[i][j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline bool bitRowArr(const array<Row, 100>& rows, int i, int j) {\n    return (rows[i][j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline void setRow(vector<Row>& rows, int i, int j) {\n    rows[i][j >> 6] |= 1ULL << (j & 63);\n    rows[j][i >> 6] |= 1ULL << (i & 63);\n}\n\nstatic inline void setRowArr(array<Row, 100>& rows, int i, int j) {\n    rows[i][j >> 6] |= 1ULL << (j & 63);\n    rows[j][i >> 6] |= 1ULL << (i & 63);\n}\n\nstruct Candidate {\n    array<unsigned char, 100> deg{};\n    array<unsigned char, 100> origDeg{};\n    array<unsigned char, 100> ord{};\n    array<uint64_t, 2> mask{};\n    array<Row, 100> sortedRows{};\n    int edges = 0;\n};\n\nstruct Codebook {\n    int M = 0;\n    int N = 0;\n    double eps = 0.0;\n    vector<Candidate> code;\n    vector<string> out;\n};\n\nstatic inline bool getMaskBitRaw(const array<uint64_t, 2>& mask, int j) {\n    return (mask[j >> 6] >> (j & 63)) & 1ULL;\n}\n\nstatic inline bool getMaskBit(const Candidate& c, int j) {\n    return (c.mask[j >> 6] >> (j & 63)) & 1ULL;\n}\n\nCandidate makeCandidate(int N, const array<uint64_t, 2>& mask) {\n    Candidate c;\n    c.mask = mask;\n\n    int suf[105];\n    suf[N] = 0;\n    for (int i = N - 1; i >= 0; i--) {\n        suf[i] = suf[i + 1] + (i == 0 ? 0 : (getMaskBitRaw(mask, i) ? 1 : 0));\n    }\n\n    vector<int> d(N);\n    int edges = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool b = (i == 0 ? false : getMaskBitRaw(mask, i));\n        d[i] = suf[i + 1] + (b ? i : 0);\n        c.origDeg[i] = (unsigned char)d[i];\n        if (b) edges += i;\n    }\n\n    vector<int> p(N);\n    iota(p.begin(), p.end(), 0);\n    sort(p.begin(), p.end(), [&](int a, int b) {\n        if (d[a] != d[b]) return d[a] < d[b];\n        return a < b;\n    });\n\n    for (int i = 0; i < N; i++) {\n        c.ord[i] = (unsigned char)p[i];\n        c.deg[i] = (unsigned char)d[p[i]];\n    }\n\n    for (int i = 0; i < 100; i++) c.sortedRows[i] = Row{0ULL, 0ULL};\n\n    for (int a = 0; a < N; a++) {\n        int va = p[a];\n        for (int b = a + 1; b < N; b++) {\n            int vb = p[b];\n            bool e = getMaskBitRaw(mask, max(va, vb));\n            if (e) setRowArr(c.sortedRows, a, b);\n        }\n    }\n\n    c.edges = edges;\n    return c;\n}\n\nstring thresholdGraphString(const Candidate& c, int N) {\n    string s;\n    s.reserve(N * (N - 1) / 2);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            s.push_back(getMaskBit(c, j) ? '1' : '0');\n        }\n    }\n\n    return s;\n}\n\nint ceilLog2Int(int x) {\n    int p = 1, r = 0;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\ndouble degreeDistanceMetric(const Candidate& a, const Candidate& b, int N) {\n    double ss = 0.0;\n    double sum = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double v = (double)a.deg[i] - (double)b.deg[i];\n        ss += v * v;\n        sum += v;\n    }\n\n    double score = ss - (sum * sum) / max(1.0, 2.0 * N - 2.0);\n    if (score < 0) score = 0;\n    return score;\n}\n\nvector<Candidate> generatePool(int N, int M, double eps, FastRNG& rng) {\n    int target = max(400, min(2400, 20 * M + 350));\n\n    vector<Candidate> pool;\n    pool.reserve(target + 10);\n\n    unordered_set<string> seen;\n    seen.reserve(target * 3);\n\n    auto addCandidate = [&](const array<uint64_t, 2>& mask) {\n        Candidate c = makeCandidate(N, mask);\n\n        string key;\n        key.resize(N);\n        for (int i = 0; i < N; i++) key[i] = (char)c.deg[i];\n\n        if (seen.insert(key).second) {\n            pool.push_back(c);\n        }\n    };\n\n    if (N - 1 <= 20) {\n        uint64_t total = 1ULL << (N - 1);\n        if ((int)total <= target) {\n            for (uint64_t m = 0; m < total; m++) {\n                array<uint64_t, 2> mask{0ULL, 0ULL};\n                mask[0] = m << 1;\n                addCandidate(mask);\n            }\n            return pool;\n        }\n    }\n\n    {\n        array<uint64_t, 2> emptyMask{0ULL, 0ULL};\n        addCandidate(emptyMask);\n\n        array<uint64_t, 2> fullMask{0ULL, 0ULL};\n        for (int j = 1; j < N; j++) {\n            fullMask[j >> 6] |= 1ULL << (j & 63);\n        }\n        addCandidate(fullMask);\n    }\n\n    int attempts = 0;\n    while ((int)pool.size() < target && attempts < target * 70) {\n        attempts++;\n\n        array<uint64_t, 2> mask{0ULL, 0ULL};\n        int mode = rng.nextInt(6);\n\n        if (mode == 0) {\n            double p = rng.nextDouble();\n            for (int j = 1; j < N; j++) {\n                if (rng.nextDouble() < p) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        } else if (mode == 1) {\n            int need = rng.nextInt(N);\n            int rem = N - 1;\n            for (int j = 1; j < N; j++) {\n                if (need > 0 && rng.nextInt(rem) < need) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                    need--;\n                }\n                rem--;\n            }\n        } else if (mode == 2) {\n            int cut = 1 + rng.nextInt(N - 1);\n            for (int j = cut; j < N; j++) {\n                mask[j >> 6] |= 1ULL << (j & 63);\n            }\n            for (int t = 0; t < N / 7 + 1; t++) {\n                int j = 1 + rng.nextInt(N - 1);\n                mask[j >> 6] ^= 1ULL << (j & 63);\n            }\n        } else if (mode == 3) {\n            double p;\n            int r = rng.nextInt(7);\n            if (r == 0) p = 0.04;\n            else if (r == 1) p = 0.10;\n            else if (r == 2) p = 0.22;\n            else if (r == 3) p = 0.50;\n            else if (r == 4) p = 0.78;\n            else if (r == 5) p = 0.90;\n            else p = 0.96;\n\n            for (int j = 1; j < N; j++) {\n                if (rng.nextDouble() < p) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        } else if (mode == 4) {\n            int blocks = 2 + rng.nextInt(6);\n            bool cur = rng.nextInt(2);\n            int pos = 1;\n            for (int b = 0; b < blocks && pos < N; b++) {\n                int denom = max(1, blocks - b);\n                int len = 1 + rng.nextInt(max(1, (N - pos) / denom));\n                int to = min(N, pos + len);\n                for (int j = pos; j < to; j++) {\n                    if (cur) mask[j >> 6] |= 1ULL << (j & 63);\n                }\n                cur = !cur;\n                pos = to;\n            }\n            for (int j = pos; j < N; j++) {\n                if (cur) mask[j >> 6] |= 1ULL << (j & 63);\n            }\n        } else {\n            double x = rng.nextDouble();\n            double drift = (rng.nextDouble() - 0.5) * 0.08;\n            for (int j = 1; j < N; j++) {\n                x += drift + (rng.nextDouble() - 0.5) * 0.18;\n                if (x < 0) x = -x;\n                if (x > 1) x = 2 - x;\n                if (rng.nextDouble() < x) {\n                    mask[j >> 6] |= 1ULL << (j & 63);\n                }\n            }\n        }\n\n        addCandidate(mask);\n    }\n\n    return pool;\n}\n\nCodebook buildCodebook(int M, int N, double eps, FastRNG& rng) {\n    vector<Candidate> pool = generatePool(N, M, eps, rng);\n    int K = (int)pool.size();\n\n    Codebook book;\n    book.M = M;\n    book.N = N;\n    book.eps = eps;\n\n    if (K < M) return book;\n\n    vector<int> starts;\n\n    int minEdge = 0, maxEdge = 0;\n    for (int i = 1; i < K; i++) {\n        if (pool[i].edges < pool[minEdge].edges) minEdge = i;\n        if (pool[i].edges > pool[maxEdge].edges) maxEdge = i;\n    }\n\n    starts.push_back(minEdge);\n    starts.push_back(maxEdge);\n    for (int t = 0; t < 3 && K > 0; t++) starts.push_back(rng.nextInt(K));\n\n    double bestMinDist = -1.0;\n    vector<Candidate> bestCode;\n\n    for (int st : starts) {\n        vector<char> used(K, 0);\n        vector<double> mind(K, 1e100);\n        vector<Candidate> cur;\n        cur.reserve(M);\n\n        for (int it = 0; it < M; it++) {\n            int best = -1;\n\n            if (it == 0) {\n                best = st;\n            } else {\n                double bv = -1;\n                for (int i = 0; i < K; i++) {\n                    if (!used[i] && mind[i] > bv) {\n                        bv = mind[i];\n                        best = i;\n                    }\n                }\n            }\n\n            used[best] = 1;\n            Candidate chosen = pool[best];\n\n            for (int i = 0; i < K; i++) {\n                if (!used[i]) {\n                    double d = degreeDistanceMetric(chosen, pool[i], N);\n                    if (d < mind[i]) mind[i] = d;\n                }\n            }\n\n            cur.push_back(chosen);\n        }\n\n        double md = 1e100;\n        for (int i = 0; i < M; i++) {\n            for (int j = i + 1; j < M; j++) {\n                md = min(md, degreeDistanceMetric(cur[i], cur[j], N));\n            }\n        }\n\n        if (md > bestMinDist) {\n            bestMinDist = md;\n            bestCode = std::move(cur);\n        }\n    }\n\n    book.code = std::move(bestCode);\n    book.out.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        book.out[k] = thresholdGraphString(book.code[k], N);\n    }\n\n    return book;\n}\n\nstruct ParsedGraph {\n    vector<Row> rows;\n    vector<int> deg;\n    vector<int> sortedDeg;\n    vector<int> ord;\n};\n\nParsedGraph parseGraph(const string& s, int N) {\n    ParsedGraph g;\n    g.rows.assign(N, Row{0ULL, 0ULL});\n    g.deg.assign(N, 0);\n\n    int idx = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++, idx++) {\n            if (s[idx] == '1') {\n                setRow(g.rows, i, j);\n                g.deg[i]++;\n                g.deg[j]++;\n            }\n        }\n    }\n\n    vector<int> ndSum(N, 0);\n    for (int i = 0; i < N; i++) {\n        int sum = 0;\n        for (int j = 0; j < N; j++) {\n            if (i != j && bitRow(g.rows, i, j)) sum += g.deg[j];\n        }\n        ndSum[i] = sum;\n    }\n\n    g.ord.resize(N);\n    iota(g.ord.begin(), g.ord.end(), 0);\n    sort(g.ord.begin(), g.ord.end(), [&](int a, int b) {\n        if (g.deg[a] != g.deg[b]) return g.deg[a] < g.deg[b];\n        if (ndSum[a] != ndSum[b]) return ndSum[a] < ndSum[b];\n        return a < b;\n    });\n\n    g.sortedDeg.resize(N);\n    for (int i = 0; i < N; i++) g.sortedDeg[i] = g.deg[g.ord[i]];\n\n    return g;\n}\n\ndouble scoreLambda(int N, double eps) {\n    if (eps <= 1e-12) return 0.0;\n\n    double var = max(1e-9, (N - 1) * eps * (1.0 - eps));\n    double logodds = log((1.0 - eps) / eps);\n    logodds = max(0.15, logodds);\n\n    double lambda = 1.0 / (2.0 * var * logodds);\n\n    if (lambda < 0.025) lambda = 0.025;\n    if (lambda > 0.18) lambda = 0.18;\n    return lambda;\n}\n\ndouble degreeScore(const Codebook& book, const Candidate& c, const vector<int>& obsSorted) {\n    int N = book.N;\n    double eps = book.eps;\n    double base = eps * (N - 1);\n    double scale = 1.0 - 2.0 * eps;\n\n    double ss = 0.0;\n    double sum = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double mu = base + scale * (double)c.deg[i];\n        double diff = obsSorted[i] - mu;\n        ss += diff * diff;\n        sum += diff;\n    }\n\n    if (eps <= 1e-12) return ss;\n\n    double score = ss - (sum * sum) / max(1.0, 2.0 * N - 2.0);\n    if (score < 0) score = 0;\n    return score;\n}\n\nint initialAdjCost(const ParsedGraph& h, const Candidate& c, const vector<int>& order, int N) {\n    int cost = 0;\n    for (int i = 0; i < N; i++) {\n        int vi = order[i];\n        for (int j = i + 1; j < N; j++) {\n            bool x = bitRow(h.rows, vi, order[j]);\n            bool y = bitRowArr(c.sortedRows, i, j);\n            cost += (x != y);\n        }\n    }\n    return cost;\n}\n\nint deltaSwap(const ParsedGraph& h, const Candidate& c, const vector<int>& order, int a, int b, int N) {\n    if (a == b) return 0;\n    if (a > b) swap(a, b);\n\n    int va = order[a];\n    int vb = order[b];\n\n    int oldCost = 0;\n    int newCost = 0;\n\n    for (int k = 0; k < N; k++) {\n        if (k == a || k == b) continue;\n\n        int vk = order[k];\n\n        bool h_ak = bitRow(h.rows, va, vk);\n        bool h_bk = bitRow(h.rows, vb, vk);\n\n        bool g_ak = bitRowArr(c.sortedRows, min(a, k), max(a, k));\n        bool g_bk = bitRowArr(c.sortedRows, min(b, k), max(b, k));\n\n        oldCost += (h_ak != g_ak);\n        oldCost += (h_bk != g_bk);\n\n        newCost += (h_bk != g_ak);\n        newCost += (h_ak != g_bk);\n    }\n\n    return newCost - oldCost;\n}\n\nint localAdjCost(const ParsedGraph& h, const Candidate& c, int N) {\n    vector<int> order = h.ord;\n    int cost = initialAdjCost(h, c, order, N);\n\n    int window;\n    if (N <= 30) window = 10;\n    else if (N <= 70) window = 8;\n    else window = 6;\n\n    int passes = (N <= 40 ? 4 : 3);\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool improved = false;\n\n        for (int i = 0; i + 1 < N; i++) {\n            int d = deltaSwap(h, c, order, i, i + 1, N);\n            if (d < 0) {\n                swap(order[i], order[i + 1]);\n                cost += d;\n                improved = true;\n            }\n        }\n\n        for (int i = N - 2; i >= 0; i--) {\n            int d = deltaSwap(h, c, order, i, i + 1, N);\n            if (d < 0) {\n                swap(order[i], order[i + 1]);\n                cost += d;\n                improved = true;\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            int bestJ = -1;\n            int bestD = 0;\n            int lim = min(N, i + window + 1);\n\n            for (int j = i + 2; j < lim; j++) {\n                int d = deltaSwap(h, c, order, i, j, N);\n                if (d < bestD) {\n                    bestD = d;\n                    bestJ = j;\n                }\n            }\n\n            if (bestJ != -1) {\n                swap(order[i], order[bestJ]);\n                cost += bestD;\n                improved = true;\n            }\n        }\n\n        if (!improved) break;\n    }\n\n    return cost;\n}\n\nint decode(const Codebook& book, const ParsedGraph& h) {\n    int M = book.M;\n    int N = book.N;\n\n    vector<double> dscore(M);\n    vector<int> ham0(M);\n\n    double lambda = scoreLambda(N, book.eps);\n\n    for (int k = 0; k < M; k++) {\n        dscore[k] = degreeScore(book, book.code[k], h.sortedDeg);\n    }\n\n    if (book.eps <= 1e-12) {\n        int best = 0;\n        for (int k = 1; k < M; k++) {\n            if (dscore[k] < dscore[best]) best = k;\n        }\n        return best;\n    }\n\n    for (int k = 0; k < M; k++) {\n        ham0[k] = initialAdjCost(h, book.code[k], h.ord, N);\n    }\n\n    vector<int> cand;\n    vector<char> used(M, 0);\n\n    auto addTopBy = [&](auto valueFunc, int cnt) {\n        vector<int> v(M);\n        iota(v.begin(), v.end(), 0);\n        int c = min(cnt, M);\n\n        if (c < M) {\n            nth_element(v.begin(), v.begin() + c, v.end(), [&](int a, int b) {\n                return valueFunc(a) < valueFunc(b);\n            });\n        }\n\n        sort(v.begin(), v.begin() + c, [&](int a, int b) {\n            return valueFunc(a) < valueFunc(b);\n        });\n\n        for (int i = 0; i < c; i++) {\n            int k = v[i];\n            if (!used[k]) {\n                used[k] = 1;\n                cand.push_back(k);\n            }\n        }\n    };\n\n    int topD, topC, topH;\n    if (book.eps <= 0.05) {\n        topD = 6;\n        topC = 8;\n        topH = 4;\n    } else if (book.eps <= 0.20) {\n        topD = 8;\n        topC = 10;\n        topH = 5;\n    } else {\n        topD = 10;\n        topC = 13;\n        topH = 6;\n    }\n\n    addTopBy([&](int k) { return dscore[k]; }, topD);\n    addTopBy([&](int k) { return (double)ham0[k] + lambda * dscore[k]; }, topC);\n    addTopBy([&](int k) { return (double)ham0[k]; }, topH);\n\n    int best = cand.empty() ? 0 : cand[0];\n    double bestFinal = 1e100;\n\n    for (int k : cand) {\n        int ham = localAdjCost(h, book.code[k], N);\n        double finalScore = (double)ham + lambda * dscore[k];\n\n        finalScore += 0.03 * ((double)ham0[k] + lambda * dscore[k]);\n\n        if (finalScore < bestFinal) {\n            bestFinal = finalScore;\n            best = k;\n        }\n    }\n\n    return best;\n}\n\nvector<int> simulateNoisyDegrees(const Candidate& c, int N, double eps, FastRNG& rng) {\n    vector<int> deg(N, 0);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = getMaskBit(c, j);\n            if (rng.nextDouble() < eps) e = !e;\n            if (e) {\n                deg[i]++;\n                deg[j]++;\n            }\n        }\n    }\n\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint decodeDegreeOnly(const Codebook& book, const vector<int>& obsSorted) {\n    int best = 0;\n    double bestScore = 1e100;\n\n    for (int k = 0; k < book.M; k++) {\n        double sc = degreeScore(book, book.code[k], obsSorted);\n        if (sc < bestScore) {\n            bestScore = sc;\n            best = k;\n        }\n    }\n\n    return best;\n}\n\nint simulateErrorsDegreeOnly(const Codebook& book, int T, FastRNG& rng) {\n    int err = 0;\n\n    for (int t = 0; t < T; t++) {\n        int s = rng.nextInt(book.M);\n        vector<int> obs = simulateNoisyDegrees(book.code[s], book.N, book.eps, rng);\n        int pred = decodeDegreeOnly(book, obs);\n        if (pred != s) err++;\n    }\n\n    return err;\n}\n\nvector<int> candidateNs(int M, double eps) {\n    int minN = max(4, ceilLog2Int(M) + 1);\n    vector<int> ns;\n\n    if (eps <= 1e-12) {\n        ns.push_back(minN);\n        return ns;\n    }\n\n    int maxN;\n    if (eps <= 0.01) maxN = min(100, minN + 15);\n    else if (eps <= 0.05) maxN = min(100, minN + 40);\n    else if (eps <= 0.15) maxN = 85;\n    else maxN = 100;\n\n    for (int n = minN; n <= maxN; ) {\n        ns.push_back(n);\n\n        int step;\n        if (eps <= 0.05) {\n            if (n < 30) step = 1;\n            else if (n < 60) step = 3;\n            else step = 5;\n        } else {\n            if (n < 30) step = 2;\n            else if (n < 70) step = 5;\n            else step = 10;\n        }\n\n        n += step;\n    }\n\n    if (ns.empty() || ns.back() != maxN) ns.push_back(maxN);\n    if (eps >= 0.18 && ns.back() != 100) ns.push_back(100);\n\n    sort(ns.begin(), ns.end());\n    ns.erase(unique(ns.begin(), ns.end()), ns.end());\n    return ns;\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 epsInt = (int)llround(eps * 100);\n    FastRNG rng(123456789ULL + 10007ULL * M + 1000003ULL * epsInt);\n\n    Codebook bestBook;\n    double bestValue = -1.0;\n\n    vector<int> ns = candidateNs(M, eps);\n\n    for (int N : ns) {\n        Codebook book = buildCodebook(M, N, eps, rng);\n        if ((int)book.code.size() != M) continue;\n\n        double value;\n\n        if (eps <= 1e-12) {\n            value = 1.0 / N;\n        } else {\n            int T;\n            if (eps <= 0.03) T = 260;\n            else if (eps <= 0.15) T = 210;\n            else T = 170;\n\n            int err = simulateErrorsDegreeOnly(book, T, rng);\n            double p = (err + 0.25) / (T + 0.5);\n\n            // Degree-only simulation is pessimistic because the real decoder also\n            // uses adjacency matching. Discount it slightly at noisy settings.\n            if (eps >= 0.25) p *= 0.75;\n            else if (eps >= 0.15) p *= 0.85;\n\n            value = exp(100.0 * log(max(1e-12, 1.0 - 0.1 * p))) / N;\n        }\n\n        if (value > bestValue) {\n            bestValue = value;\n            bestBook = std::move(book);\n        }\n    }\n\n    if ((int)bestBook.code.size() != M) {\n        int N = max(4, ceilLog2Int(M) + 1);\n        bestBook = buildCodebook(M, N, eps, rng);\n    }\n\n    cout << bestBook.N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << bestBook.out[k] << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        ParsedGraph h = parseGraph(H, bestBook.N);\n        int ans = decode(bestBook, h);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF = (1LL << 60);\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n\n    int root(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = root(a);\n        b = root(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    int mx, my;\n    ll len2;\n};\n\nstruct Adj {\n    int to, w, id;\n};\n\nint N, M, D, K;\nvector<Edge> edges;\nvector<vector<Adj>> g;\nvector<int> X, Y;\nvector<int> degv;\n\nmt19937 rng(1234567);\n\nuint64_t morton_key(int x, int y) {\n    uint64_t r = 0;\n    for (int i = 0; i < 12; i++) {\n        r |= uint64_t((x >> i) & 1) << (2 * i);\n        r |= uint64_t((y >> i) & 1) << (2 * i + 1);\n    }\n    return r;\n}\n\nvoid dijkstra_fill(int s, const vector<int>* assign, int ban_day, vector<ll>& dist) {\n    fill(dist.begin(), dist.end(), INF);\n\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\n    while (!pq.empty()) {\n        auto [du, u] = pq.top();\n        pq.pop();\n\n        if (du != dist[u]) continue;\n\n        for (const auto& e : g[u]) {\n            if (assign && (*assign)[e.id] == ban_day) continue;\n\n            ll nd = du + e.w;\n            if (nd < dist[e.to]) {\n                dist[e.to] = nd;\n                pq.push({nd, e.to});\n            }\n        }\n    }\n}\n\nbool connected_day(const vector<int>& assign, int day) {\n    DSU uf(N);\n\n    for (int i = 0; i < M; i++) {\n        if (assign[i] != day) {\n            uf.unite(edges[i].u, edges[i].v);\n        }\n    }\n\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n\n    return true;\n}\n\nbool all_connected(const vector<int>& assign) {\n    for (int d = 0; d < D; d++) {\n        if (!connected_day(assign, d)) return false;\n    }\n    return true;\n}\n\nbool can_add_removal_keep_connected(const vector<int>& assign, int day, int eid) {\n    DSU uf(N);\n\n    for (int i = 0; i < M; i++) {\n        if (assign[i] == day || i == eid) continue;\n        uf.unite(edges[i].u, edges[i].v);\n    }\n\n    int r = uf.root(0);\n    for (int i = 1; i < N; i++) {\n        if (uf.root(i) != r) return false;\n    }\n\n    return true;\n}\n\nvoid repair_isolated(vector<int>& assign) {\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n\n    for (int i = 0; i < M; i++) {\n        int d = assign[i];\n        load[d]++;\n        vc[edges[i].u][d]++;\n        vc[edges[i].v][d]++;\n    }\n\n    bool changed = true;\n\n    for (int loop = 0; changed && loop < 20; loop++) {\n        changed = false;\n\n        for (int v = 0; v < N; v++) {\n            for (int d = 0; d < D; d++) {\n                if (vc[v][d] < degv[v]) continue;\n\n                int eid = -1;\n                for (auto& a : g[v]) {\n                    if (assign[a.id] == d) {\n                        eid = a.id;\n                        break;\n                    }\n                }\n\n                if (eid == -1) continue;\n\n                int u = edges[eid].u;\n                int w = edges[eid].v;\n                int best = -1;\n\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == d) continue;\n                    if (load[nd] >= K) continue;\n                    if (vc[u][nd] + 1 >= degv[u]) continue;\n                    if (vc[w][nd] + 1 >= degv[w]) continue;\n\n                    best = nd;\n                    break;\n                }\n\n                if (best == -1) {\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd != d && load[nd] < K) {\n                            best = nd;\n                            break;\n                        }\n                    }\n                }\n\n                if (best != -1) {\n                    assign[eid] = best;\n                    load[d]--;\n                    load[best]++;\n                    vc[u][d]--;\n                    vc[w][d]--;\n                    vc[u][best]++;\n                    vc[w][best]++;\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\nvoid repair_connectivity(vector<int>& assign, const Timer& timer, double limit_time) {\n    vector<int> load(D, 0);\n    for (int x : assign) load[x]++;\n\n    for (int iter = 0; iter < 200 && timer.elapsed() < limit_time; iter++) {\n        bool changed = false;\n\n        for (int day = 0; day < D && timer.elapsed() < limit_time; day++) {\n            DSU uf(N);\n\n            for (int i = 0; i < M; i++) {\n                if (assign[i] != day) {\n                    uf.unite(edges[i].u, edges[i].v);\n                }\n            }\n\n            int r0 = uf.root(0);\n            bool ok = true;\n\n            for (int i = 1; i < N; i++) {\n                if (uf.root(i) != r0) {\n                    ok = false;\n                    break;\n                }\n            }\n\n            if (ok) continue;\n\n            vector<int> cand;\n            cand.reserve(load[day]);\n\n            for (int i = 0; i < M; i++) {\n                if (assign[i] == day && uf.root(edges[i].u) != uf.root(edges[i].v)) {\n                    cand.push_back(i);\n                }\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            bool moved = false;\n\n            for (int eid : cand) {\n                int best_day = -1;\n                int best_cost = INT_MAX;\n\n                for (int nd = 0; nd < D; nd++) {\n                    if (nd == day) continue;\n                    if (load[nd] >= K) continue;\n\n                    int cost = load[nd];\n                    if (!can_add_removal_keep_connected(assign, nd, eid)) {\n                        cost += 1000000;\n                    }\n\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_day = nd;\n                    }\n                }\n\n                if (best_day != -1) {\n                    assign[eid] = best_day;\n                    load[day]--;\n                    load[best_day]++;\n                    changed = true;\n                    moved = true;\n                    break;\n                }\n            }\n\n            if (moved) break;\n        }\n\n        if (!changed) break;\n        if (all_connected(assign)) break;\n    }\n}\n\nvector<int> make_order(int type) {\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    if (type == 0) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) < morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 1) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return morton_key(edges[a].mx, edges[a].my) > morton_key(edges[b].mx, edges[b].my);\n        });\n    } else if (type == 2) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].mx != edges[b].mx) return edges[a].mx < edges[b].mx;\n            return edges[a].my < edges[b].my;\n        });\n    } else if (type == 3) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].my != edges[b].my) return edges[a].my < edges[b].my;\n            return edges[a].mx < edges[b].mx;\n        });\n    } else if (type == 4) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx + edges[a].my < edges[b].mx + edges[b].my;\n        });\n    } else if (type == 5) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].mx - edges[a].my < edges[b].mx - edges[b].my;\n        });\n    } else if (type == 6) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].len2 > edges[b].len2;\n        });\n    } else {\n        int A = uniform_int_distribution<int>(-1000, 1000)(rng);\n        int B = uniform_int_distribution<int>(-1000, 1000)(rng);\n\n        if (A == 0 && B == 0) A = 1;\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ll va = 1LL * A * edges[a].mx + 1LL * B * edges[a].my;\n            ll vb = 1LL * A * edges[b].mx + 1LL * B * edges[b].my;\n\n            if (va != vb) return va < vb;\n            return a < b;\n        });\n    }\n\n    return ord;\n}\n\nvector<int> construct_cyclic(int type) {\n    vector<int> ord = make_order(type);\n\n    vector<int> perm(D);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n\n    int shift = uniform_int_distribution<int>(0, D - 1)(rng);\n\n    vector<int> assign(M);\n\n    for (int i = 0; i < M; i++) {\n        assign[ord[i]] = perm[(i + shift) % D];\n    }\n\n    repair_isolated(assign);\n    return assign;\n}\n\nvector<int> construct_greedy(int type) {\n    vector<int> ord;\n\n    if (type == 100) {\n        ord.resize(M);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n    } else {\n        ord = make_order(type);\n    }\n\n    vector<int> target(D, M / D);\n    for (int i = 0; i < M % D; i++) target[i]++;\n    shuffle(target.begin(), target.end(), rng);\n\n    vector<int> assign(M, -1);\n    vector<int> load(D, 0);\n    vector<vector<int>> vc(N, vector<int>(D, 0));\n\n    const int G = 18;\n    vector<vector<int>> cell(D, vector<int>(G * G, 0));\n\n    auto cid = [&](int eid) {\n        int cx = min(G - 1, max(0, edges[eid].mx * G / 2001));\n        int cy = min(G - 1, max(0, edges[eid].my * G / 2001));\n        return pair<int,int>(cx, cy);\n    };\n\n    for (int eid : ord) {\n        int u = edges[eid].u;\n        int v = edges[eid].v;\n\n        auto [cx, cy] = cid(eid);\n\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int pass = 0; pass < 2; pass++) {\n            best = -1;\n            best_cost = INT_MAX;\n\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= target[d]) continue;\n\n                if (pass == 0) {\n                    if (vc[u][d] + 1 >= degv[u]) continue;\n                    if (vc[v][d] + 1 >= degv[v]) continue;\n                }\n\n                int near = 0;\n\n                for (int dx = -1; dx <= 1; dx++) {\n                    for (int dy = -1; dy <= 1; dy++) {\n                        int nx = cx + dx;\n                        int ny = cy + dy;\n\n                        if (0 <= nx && nx < G && 0 <= ny && ny < G) {\n                            near += cell[d][nx * G + ny];\n                        }\n                    }\n                }\n\n                int cost = 0;\n                cost += (vc[u][d] + vc[v][d]) * 100000;\n                cost += near * 700;\n                cost += load[d] * 5;\n                cost += uniform_int_distribution<int>(0, 999)(rng);\n\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best = d;\n                }\n            }\n\n            if (best != -1) break;\n        }\n\n        if (best == -1) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] < target[d]) {\n                    best = d;\n                    break;\n                }\n            }\n        }\n\n        assign[eid] = best;\n        load[best]++;\n        vc[u][best]++;\n        vc[v][best]++;\n        cell[best][cx * G + cy]++;\n    }\n\n    repair_isolated(assign);\n    return assign;\n}\n\nll score_one_day(\n    const vector<int>& assign,\n    int day,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist\n) {\n    ll score = 0;\n    vector<ll> dist(N);\n\n    for (int si = 0; si < S; si++) {\n        int s = sources[si];\n\n        dijkstra_fill(s, &assign, day, dist);\n\n        const auto& bd = base_dist[si];\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n\n            if (dist[v] >= INF / 2) {\n                score += 1000000000LL - bd[v];\n            } else {\n                score += dist[v] - bd[v];\n            }\n        }\n    }\n\n    return score;\n}\n\nll evaluate_schedule(\n    const vector<int>& assign,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist\n) {\n    vector<int> load(D, 0);\n\n    for (int x : assign) {\n        if (x < 0 || x >= D) return (ll)4e18;\n        load[x]++;\n    }\n\n    for (int d = 0; d < D; d++) {\n        if (load[d] > K) return (ll)4e18;\n    }\n\n    if (!all_connected(assign)) {\n        return (ll)3e18;\n    }\n\n    ll score = 0;\n\n    for (int day = 0; day < D; day++) {\n        score += score_one_day(assign, day, S, sources, base_dist);\n    }\n\n    return score;\n}\n\nvector<int> make_sources(int Smax) {\n    vector<int> sources;\n    vector<char> used(N, 0);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return morton_key(X[a], Y[a]) < morton_key(X[b], Y[b]);\n    });\n\n    int strat = min(Smax, min(N, Smax * 2 / 3));\n\n    for (int i = 0; i < strat; i++) {\n        int idx = (ll)(2 * i + 1) * N / (2 * strat);\n        idx = min(N - 1, max(0, idx));\n\n        int v = ord[idx];\n        if (!used[v]) {\n            used[v] = 1;\n            sources.push_back(v);\n        }\n    }\n\n    vector<int> rest(N);\n    iota(rest.begin(), rest.end(), 0);\n    shuffle(rest.begin(), rest.end(), rng);\n\n    for (int v : rest) {\n        if ((int)sources.size() >= Smax) break;\n        if (!used[v]) {\n            used[v] = 1;\n            sources.push_back(v);\n        }\n    }\n\n    return sources;\n}\n\nvoid sampled_local_search(\n    vector<int>& assign,\n    int S,\n    const vector<int>& sources,\n    const vector<vector<ll>>& base_dist,\n    const Timer& timer,\n    double limit_time\n) {\n    if (!all_connected(assign)) return;\n\n    vector<vector<int>> byday(D);\n    vector<int> pos(M, -1);\n    vector<int> load(D, 0);\n\n    for (int i = 0; i < M; i++) {\n        int d = assign[i];\n        pos[i] = (int)byday[d].size();\n        byday[d].push_back(i);\n        load[d]++;\n    }\n\n    vector<ll> day_cost(D, 0);\n\n    for (int d = 0; d < D; d++) {\n        if (timer.elapsed() > limit_time) return;\n        day_cost[d] = score_one_day(assign, d, S, sources, base_dist);\n    }\n\n    auto choose_high_day = [&]() {\n        int a = uniform_int_distribution<int>(0, D - 1)(rng);\n        for (int t = 0; t < 4; t++) {\n            int x = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (day_cost[x] > day_cost[a]) a = x;\n        }\n        return a;\n    };\n\n    auto choose_low_day = [&](int forbid, bool need_capacity) {\n        int b = uniform_int_distribution<int>(0, D - 1)(rng);\n\n        for (int tries = 0; tries < 20 && (b == forbid || (need_capacity && load[b] >= K)); tries++) {\n            b = uniform_int_distribution<int>(0, D - 1)(rng);\n        }\n\n        for (int t = 0; t < 4; t++) {\n            int x = uniform_int_distribution<int>(0, D - 1)(rng);\n            if (x == forbid) continue;\n            if (need_capacity && load[x] >= K) continue;\n            if (b == forbid || (need_capacity && load[b] >= K) || day_cost[x] < day_cost[b]) b = x;\n        }\n\n        return b;\n    };\n\n    int trials = 0;\n\n    while (timer.elapsed() < limit_time && trials < 100000) {\n        trials++;\n\n        bool do_move = (uniform_int_distribution<int>(0, 99)(rng) < 55);\n\n        if (do_move) {\n            int a = choose_high_day();\n            if (byday[a].empty()) continue;\n\n            int b = choose_low_day(a, true);\n            if (b == a || b < 0 || b >= D || load[b] >= K) continue;\n\n            int ia = uniform_int_distribution<int>(0, (int)byday[a].size() - 1)(rng);\n            int e = byday[a][ia];\n\n            assign[e] = b;\n\n            if (!connected_day(assign, b)) {\n                assign[e] = a;\n                continue;\n            }\n\n            ll old_cost = day_cost[a] + day_cost[b];\n\n            ll ca = score_one_day(assign, a, S, sources, base_dist);\n            if (timer.elapsed() >= limit_time) {\n                assign[e] = a;\n                return;\n            }\n\n            ll cb = score_one_day(assign, b, S, sources, base_dist);\n            ll new_cost = ca + cb;\n\n            if (new_cost < old_cost) {\n                day_cost[a] = ca;\n                day_cost[b] = cb;\n\n                int last = byday[a].back();\n                byday[a][ia] = last;\n                pos[last] = ia;\n                byday[a].pop_back();\n\n                pos[e] = (int)byday[b].size();\n                byday[b].push_back(e);\n\n                load[a]--;\n                load[b]++;\n            } else {\n                assign[e] = a;\n            }\n        } else {\n            int a = choose_high_day();\n            int b = choose_low_day(a, false);\n\n            if (a == b) continue;\n            if (byday[a].empty() || byday[b].empty()) continue;\n\n            int ia = uniform_int_distribution<int>(0, (int)byday[a].size() - 1)(rng);\n            int ib = uniform_int_distribution<int>(0, (int)byday[b].size() - 1)(rng);\n\n            int e1 = byday[a][ia];\n            int e2 = byday[b][ib];\n\n            assign[e1] = b;\n            assign[e2] = a;\n\n            bool ok = connected_day(assign, a) && connected_day(assign, b);\n\n            if (!ok) {\n                assign[e1] = a;\n                assign[e2] = b;\n                continue;\n            }\n\n            ll old_cost = day_cost[a] + day_cost[b];\n\n            ll ca = score_one_day(assign, a, S, sources, base_dist);\n            if (timer.elapsed() >= limit_time) {\n                assign[e1] = a;\n                assign[e2] = b;\n                return;\n            }\n\n            ll cb = score_one_day(assign, b, S, sources, base_dist);\n            ll new_cost = ca + cb;\n\n            if (new_cost < old_cost) {\n                day_cost[a] = ca;\n                day_cost[b] = cb;\n\n                byday[a][ia] = e2;\n                byday[b][ib] = e1;\n                pos[e1] = ib;\n                pos[e2] = ia;\n            } else {\n                assign[e1] = a;\n                assign[e2] = b;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> D >> K;\n\n    edges.resize(M);\n    g.assign(N, {});\n    degv.assign(N, 0);\n\n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n\n        g[u].push_back({v, w, i});\n        g[v].push_back({u, w, i});\n\n        degv[u]++;\n        degv[v]++;\n    }\n\n    X.resize(N);\n    Y.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> X[i] >> Y[i];\n    }\n\n    for (int i = 0; i < M; i++) {\n        int u = edges[i].u;\n        int v = edges[i].v;\n\n        edges[i].mx = X[u] + X[v];\n        edges[i].my = Y[u] + Y[v];\n\n        ll dx = X[u] - X[v];\n        ll dy = Y[u] - Y[v];\n\n        edges[i].len2 = dx * dx + dy * dy;\n    }\n\n    int Smax = min(N, 96);\n    int Ssmall = min(Smax, (D >= 20 ? 24 : 32));\n    int Sfinal = min(Smax, 80);\n    int Slocal = min(Smax, (D >= 20 ? 7 : 9));\n\n    vector<int> sources = make_sources(Smax);\n\n    vector<vector<ll>> base_dist(Smax, vector<ll>(N));\n\n    for (int i = 0; i < Smax; i++) {\n        dijkstra_fill(sources[i], nullptr, -1, base_dist[i]);\n    }\n\n    vector<pair<ll, vector<int>>> top;\n\n    auto add_candidate = [&](vector<int> assign) {\n        if (!all_connected(assign) && timer.elapsed() < 4.45) {\n            repair_connectivity(assign, timer, 4.60);\n        }\n\n        ll sc = evaluate_schedule(assign, Ssmall, sources, base_dist);\n\n        if ((int)top.size() < 10) {\n            top.push_back({sc, assign});\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        } else if (sc < top.back().first) {\n            top.back() = {sc, assign};\n            sort(top.begin(), top.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n        }\n    };\n\n    for (int t = 0; t < 10 && timer.elapsed() < 4.05; t++) {\n        add_candidate(construct_cyclic(t % 8));\n    }\n\n    for (int t = 0; t < 10 && timer.elapsed() < 4.25; t++) {\n        add_candidate(construct_greedy(t % 8));\n    }\n\n    int iter = 0;\n\n    while (timer.elapsed() < 4.50) {\n        vector<int> cand;\n\n        if (iter % 3 == 0) {\n            cand = construct_greedy(100);\n        } else if (iter % 3 == 1) {\n            cand = construct_greedy(8 + iter);\n        } else {\n            cand = construct_cyclic(8 + iter);\n        }\n\n        add_candidate(std::move(cand));\n        iter++;\n    }\n\n    if (top.empty()) {\n        vector<int> fallback(M);\n        for (int i = 0; i < M; i++) fallback[i] = i % D;\n        repair_isolated(fallback);\n        top.push_back({0, fallback});\n    }\n\n    vector<int> best = top[0].second;\n    ll best_score = (ll)4e18;\n\n    for (auto& p : top) {\n        if (timer.elapsed() > 5.30) break;\n\n        ll sc = evaluate_schedule(p.second, Sfinal, sources, base_dist);\n\n        if (sc < best_score) {\n            best_score = sc;\n            best = p.second;\n        }\n    }\n\n    if (best_score >= (ll)4e18 / 2) {\n        best = top[0].second;\n        best_score = evaluate_schedule(best, Ssmall, sources, base_dist);\n    }\n\n    vector<int> before_local = best;\n    ll before_score = best_score;\n\n    vector<int> improved = best;\n\n    if (timer.elapsed() < 5.35 && all_connected(improved)) {\n        sampled_local_search(improved, Slocal, sources, base_dist, timer, 5.68);\n    }\n\n    if (timer.elapsed() < 5.88) {\n        ll imp_score = evaluate_schedule(improved, Sfinal, sources, base_dist);\n\n        // Small margin to suppress noisy overfitted local-search changes.\n        // Equivalent to requiring about 0.1% improvement.\n        if (imp_score + before_score / 1000 < before_score) {\n            best = improved;\n            best_score = imp_score;\n        } else {\n            best = before_local;\n            best_score = before_score;\n        }\n    }\n\n    if (!all_connected(best) && timer.elapsed() < 5.78) {\n        repair_connectivity(best, timer, 5.88);\n    }\n\n    vector<int> load(D, 0);\n    for (int x : best) load[x]++;\n\n    for (int i = 0; i < M; i++) {\n        if (load[best[i]] <= K) continue;\n\n        for (int d = 0; d < D; d++) {\n            if (load[d] < K) {\n                load[best[i]]--;\n                best[i] = d;\n                load[d]++;\n                break;\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << best[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nstring F[2][14], Rg[2][14];\nauto START_TIME = chrono::steady_clock::now();\n\nbool time_ok(double lim = 5.45) {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count() < lim;\n}\n\ninline int idx3(int x, int y, int z) {\n    return x * D * D + y * D + z;\n}\n\ninline void xyz(int id, int& x, int& y, int& z) {\n    x = id / (D * D);\n    int t = id % (D * D);\n    y = t / D;\n    z = t % D;\n}\n\nuint32_t hash32(uint32_t x) {\n    x ^= x >> 16;\n    x *= 0x7feb352dU;\n    x ^= x >> 15;\n    x *= 0x846ca68bU;\n    x ^= x >> 16;\n    return x;\n}\n\nint hrand(uint32_t seed, int x, int y, int z, int mod) {\n    uint32_t v = seed;\n    v ^= (uint32_t)(x + 17) * 1000003U;\n    v ^= (uint32_t)(y + 31) * 1000033U;\n    v ^= (uint32_t)(z + 47) * 1000037U;\n    return (int)(hash32(v) % mod);\n}\n\nstruct Candidate {\n    vector<unsigned char> occ;\n    int volume = 0;\n};\n\nstruct Rod {\n    vector<int> cells;\n};\n\nstruct LineDec {\n    vector<Rod> rods;\n    vector<int> lens;\n    int volume = 0;\n};\n\nstruct Cuboid {\n    vector<int> cells;\n    int dx, dy, dz, key, vol;\n};\n\nstruct CubDec {\n    vector<Cuboid> cubs;\n    vector<pair<int, vector<int>>> groups;\n    int volume = 0;\n};\n\nstruct Params {\n    int extra, contW, futW, randAmp, reverse, favor, commonBonus;\n    uint32_t seed;\n};\n\nint cuboid_key(int a, int b, int c) {\n    int v[3] = {a, b, c};\n    sort(v, v + 3);\n    return v[0] * 256 + v[1] * 16 + v[2];\n}\n\nint cuboid_volume_from_key(int key) {\n    int a = key / 256;\n    int b = (key / 16) % 16;\n    int c = key % 16;\n    return a * b * c;\n}\n\nvoid make_groups(CubDec& d) {\n    vector<int> ord(d.cubs.size());\n    iota(ord.begin(), ord.end(), 0);\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return d.cubs[a].key < d.cubs[b].key;\n    });\n\n    for (int id : ord) {\n        int k = d.cubs[id].key;\n        if (d.groups.empty() || d.groups.back().first != k) {\n            d.groups.push_back({k, {}});\n        }\n        d.groups.back().second.push_back(id);\n    }\n}\n\nvector<pair<int,int>> solve_cover(const vector<int>& X, const vector<int>& Y, int w[14][14]) {\n    int nx = X.size();\n    int ny = Y.size();\n    vector<pair<int,int>> res;\n    const int NEG = -1000000000;\n\n    if (nx >= ny) {\n        int A = nx, B = ny, M = 1 << B;\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[i]][Y[j]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[i + 1][nm] = mask;\n                        ch[i + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int i = A; i >= 1; i--) {\n            int j = ch[i][mask];\n            int pm = pre[i][mask];\n            res.push_back({X[i - 1], Y[j]});\n            mask = pm;\n        }\n    } else {\n        int A = ny, B = nx, M = 1 << B;\n        vector<int> dp(M, NEG), ndp(M, NEG);\n        vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n        vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n        dp[0] = 0;\n        for (int i = 0; i < A; i++) {\n            fill(ndp.begin(), ndp.end(), NEG);\n            for (int mask = 0; mask < M; mask++) {\n                if (dp[mask] <= NEG / 2) continue;\n                for (int j = 0; j < B; j++) {\n                    int nm = mask | (1 << j);\n                    int val = dp[mask] + w[X[j]][Y[i]];\n                    if (val > ndp[nm]) {\n                        ndp[nm] = val;\n                        pre[i + 1][nm] = mask;\n                        ch[i + 1][nm] = j;\n                    }\n                }\n            }\n            dp.swap(ndp);\n        }\n\n        int mask = M - 1;\n        for (int i = A; i >= 1; i--) {\n            int j = ch[i][mask];\n            int pm = pre[i][mask];\n            res.push_back({X[j], Y[i - 1]});\n            mask = pm;\n        }\n    }\n\n    return res;\n}\n\nCandidate build_candidate(int id, const Params& p) {\n    Candidate c;\n    c.occ.assign(D * D * D, 0);\n\n    bool prev[14][14] = {};\n    vector<int> zs;\n\n    if (!p.reverse) {\n        for (int z = 0; z < D; z++) zs.push_back(z);\n    } else {\n        for (int z = D - 1; z >= 0; z--) zs.push_back(z);\n    }\n\n    int other = id ^ 1;\n\n    for (int ord = 0; ord < D; ord++) {\n        int z = zs[ord];\n        int zn = (ord + 1 < D ? zs[ord + 1] : -1);\n\n        vector<int> X, Y;\n        for (int x = 0; x < D; x++) if (F[id][z][x] == '1') X.push_back(x);\n        for (int y = 0; y < D; y++) if (Rg[id][z][y] == '1') Y.push_back(y);\n\n        int w[14][14] = {};\n        for (int x : X) {\n            for (int y : Y) {\n                int val = 0;\n                if (prev[x][y]) val += p.contW;\n                if (zn != -1 && F[id][zn][x] == '1' && Rg[id][zn][y] == '1') val += p.futW;\n                if (F[other][z][x] == '1' && Rg[other][z][y] == '1') val += p.commonBonus;\n                if (p.randAmp > 0) val += hrand(p.seed, x, y, z, p.randAmp);\n                w[x][y] = val;\n            }\n        }\n\n        auto base = solve_cover(X, Y, w);\n\n        bool sel[14][14] = {};\n        int cnt = 0;\n\n        for (auto [x, y] : base) {\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        int target = min(\n            (int)X.size() * (int)Y.size(),\n            max((int)X.size(), (int)Y.size()) + p.extra\n        );\n\n        vector<tuple<int,int,int>> add;\n\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) continue;\n\n                int sc = 0;\n                if (prev[x][y]) sc += 100000;\n                if (zn != -1 && F[id][zn][x] == '1' && Rg[id][zn][y] == '1') sc += 20000;\n                if (F[other][z][x] == '1' && Rg[other][z][y] == '1') sc += p.commonBonus;\n\n                if (p.favor == 1 || p.favor == 3) {\n                    if (x > 0 && sel[x - 1][y]) sc += 8000;\n                    if (x + 1 < D && sel[x + 1][y]) sc += 8000;\n                }\n                if (p.favor == 2 || p.favor == 3) {\n                    if (y > 0 && sel[x][y - 1]) sc += 8000;\n                    if (y + 1 < D && sel[x][y + 1]) sc += 8000;\n                }\n\n                sc += hrand(p.seed ^ 0x9e3779b9U, x, y, z, 1000);\n                add.push_back({sc, x, y});\n            }\n        }\n\n        sort(add.rbegin(), add.rend());\n\n        for (auto [sc, x, y] : add) {\n            if (cnt >= target) break;\n            if (!sel[x][y]) {\n                sel[x][y] = true;\n                cnt++;\n            }\n        }\n\n        memset(prev, 0, sizeof(prev));\n\n        for (int x : X) {\n            for (int y : Y) {\n                if (sel[x][y]) {\n                    c.occ[idx3(x, y, z)] = 1;\n                    prev[x][y] = true;\n                }\n            }\n        }\n    }\n\n    for (unsigned char v : c.occ) c.volume += v;\n    return c;\n}\n\nLineDec decompose_lines_occ(const vector<unsigned char>& occ, int volume, int axis) {\n    LineDec d;\n    d.volume = volume;\n\n    if (axis == 0) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                int x = 0;\n                while (x < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        x++;\n                        continue;\n                    }\n                    Rod r;\n                    while (x < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        x++;\n                    }\n                    d.lens.push_back(r.cells.size());\n                    d.rods.push_back(move(r));\n                }\n            }\n        }\n    } else if (axis == 1) {\n        for (int x = 0; x < D; x++) {\n            for (int z = 0; z < D; z++) {\n                int y = 0;\n                while (y < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        y++;\n                        continue;\n                    }\n                    Rod r;\n                    while (y < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        y++;\n                    }\n                    d.lens.push_back(r.cells.size());\n                    d.rods.push_back(move(r));\n                }\n            }\n        }\n    } else {\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                int z = 0;\n                while (z < D) {\n                    if (!occ[idx3(x, y, z)]) {\n                        z++;\n                        continue;\n                    }\n                    Rod r;\n                    while (z < D && occ[idx3(x, y, z)]) {\n                        r.cells.push_back(idx3(x, y, z));\n                        z++;\n                    }\n                    d.lens.push_back(r.cells.size());\n                    d.rods.push_back(move(r));\n                }\n            }\n        }\n    }\n\n    return d;\n}\n\nLineDec decompose_lines(const Candidate& c, int axis) {\n    return decompose_lines_occ(c.occ, c.volume, axis);\n}\n\nlong double eval_lines(const LineDec& A, const LineDec& B) {\n    priority_queue<int> p, q;\n\n    for (int x : A.lens) p.push(x);\n    for (int x : B.lens) q.push(x);\n\n    long double score = 0;\n\n    for (int len = D; len >= 1; len--) {\n        while (!p.empty() && !q.empty() && p.top() >= len && q.top() >= len) {\n            int a = p.top(); p.pop();\n            int b = q.top(); q.pop();\n\n            score += 1.0L / len;\n\n            if (a - len > 0) p.push(a - len);\n            if (b - len > 0) q.push(b - len);\n        }\n    }\n\n    while (!p.empty()) {\n        score += p.top();\n        p.pop();\n    }\n    while (!q.empty()) {\n        score += q.top();\n        q.pop();\n    }\n\n    return score;\n}\n\nbool box_free(const vector<unsigned char>& occ, const vector<unsigned char>& used, int lo[3], int hi[3]) {\n    for (int x = lo[0]; x < hi[0]; x++) {\n        for (int y = lo[1]; y < hi[1]; y++) {\n            for (int z = lo[2]; z < hi[2]; z++) {\n                int id = idx3(x, y, z);\n                if (!occ[id] || used[id]) return false;\n            }\n        }\n    }\n    return true;\n}\n\nCubDec decompose_cuboids_occ(const vector<unsigned char>& occ, int volume, array<int,3> ord) {\n    CubDec d;\n    d.volume = volume;\n    vector<unsigned char> used(D * D * D, 0);\n\n    for (int x0 = 0; x0 < D; x0++) {\n        for (int y0 = 0; y0 < D; y0++) {\n            for (int z0 = 0; z0 < D; z0++) {\n                int start = idx3(x0, y0, z0);\n                if (!occ[start] || used[start]) continue;\n\n                int lo[3] = {x0, y0, z0};\n                int hi[3] = {x0 + 1, y0 + 1, z0 + 1};\n\n                for (int ax : ord) {\n                    while (hi[ax] < D) {\n                        int nlo[3] = {lo[0], lo[1], lo[2]};\n                        int nhi[3] = {hi[0], hi[1], hi[2]};\n                        nhi[ax]++;\n                        if (box_free(occ, used, nlo, nhi)) hi[ax]++;\n                        else break;\n                    }\n                }\n\n                Cuboid c;\n                c.dx = hi[0] - lo[0];\n                c.dy = hi[1] - lo[1];\n                c.dz = hi[2] - lo[2];\n                c.vol = c.dx * c.dy * c.dz;\n                c.key = cuboid_key(c.dx, c.dy, c.dz);\n\n                for (int x = lo[0]; x < hi[0]; x++) {\n                    for (int y = lo[1]; y < hi[1]; y++) {\n                        for (int z = lo[2]; z < hi[2]; z++) {\n                            int id = idx3(x, y, z);\n                            used[id] = 1;\n                            c.cells.push_back(id);\n                        }\n                    }\n                }\n\n                d.cubs.push_back(move(c));\n            }\n        }\n    }\n\n    make_groups(d);\n    return d;\n}\n\nCubDec decompose_cuboids_candidate(const Candidate& c, array<int,3> ord) {\n    return decompose_cuboids_occ(c.occ, c.volume, ord);\n}\n\nstruct HybridEval {\n    long double score;\n    int ax0, ax1;\n};\n\nHybridEval eval_cuboid_hybrid(const CubDec& A, const CubDec& B) {\n    vector<unsigned char> usedA(A.cubs.size(), 0), usedB(B.cubs.size(), 0);\n    long double base = 0;\n\n    int ia = 0, ib = 0;\n    while (ia < (int)A.groups.size() && ib < (int)B.groups.size()) {\n        int ka = A.groups[ia].first;\n        int kb = B.groups[ib].first;\n\n        if (ka < kb) ia++;\n        else if (ka > kb) ib++;\n        else {\n            int vol = cuboid_volume_from_key(ka);\n            if (vol > 1) {\n                auto& va = A.groups[ia].second;\n                auto& vb = B.groups[ib].second;\n                int m = min((int)va.size(), (int)vb.size());\n\n                for (int i = 0; i < m; i++) {\n                    usedA[va[i]] = 1;\n                    usedB[vb[i]] = 1;\n                    base += 1.0L / vol;\n                }\n            }\n            ia++;\n            ib++;\n        }\n    }\n\n    vector<unsigned char> remA(D * D * D, 0), remB(D * D * D, 0);\n    int volA = 0, volB = 0;\n\n    for (int i = 0; i < (int)A.cubs.size(); i++) {\n        if (usedA[i]) continue;\n        for (int id : A.cubs[i].cells) {\n            remA[id] = 1;\n            volA++;\n        }\n    }\n\n    for (int i = 0; i < (int)B.cubs.size(); i++) {\n        if (usedB[i]) continue;\n        for (int id : B.cubs[i].cells) {\n            remB[id] = 1;\n            volB++;\n        }\n    }\n\n    array<LineDec, 3> la, lb;\n    for (int ax = 0; ax < 3; ax++) {\n        la[ax] = decompose_lines_occ(remA, volA, ax);\n        lb[ax] = decompose_lines_occ(remB, volB, ax);\n    }\n\n    HybridEval ret{1e100L, 0, 0};\n\n    for (int a = 0; a < 3; a++) {\n        for (int b = 0; b < 3; b++) {\n            long double sc = base + eval_lines(la[a], lb[b]);\n            if (sc < ret.score) {\n                ret.score = sc;\n                ret.ax0 = a;\n                ret.ax1 = b;\n            }\n        }\n    }\n\n    return ret;\n}\n\nvector<vector<int>> components_of_occ(const vector<unsigned char>& occ) {\n    int N = D * D * D;\n    vector<unsigned char> vis(N, 0);\n    vector<vector<int>> comps;\n\n    const int dx[6] = {1, -1, 0, 0, 0, 0};\n    const int dy[6] = {0, 0, 1, -1, 0, 0};\n    const int dz[6] = {0, 0, 0, 0, 1, -1};\n\n    for (int s = 0; s < N; s++) {\n        if (vis[s] || !occ[s]) continue;\n\n        vector<int> comp;\n        queue<int> q;\n        q.push(s);\n        vis[s] = 1;\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            comp.push_back(v);\n\n            int x, y, z;\n            xyz(v, x, y, z);\n\n            for (int d = 0; d < 6; d++) {\n                int nx = x + dx[d];\n                int ny = y + dy[d];\n                int nz = z + dz[d];\n\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n\n                int ni = idx3(nx, ny, nz);\n                if (vis[ni] || !occ[ni]) continue;\n\n                vis[ni] = 1;\n                q.push(ni);\n            }\n        }\n\n        comps.push_back(move(comp));\n    }\n\n    return comps;\n}\n\nlong long component_cover_score(const vector<int>& comp) {\n    bool zx[14][14] = {};\n    bool zy[14][14] = {};\n    int cnt = 0;\n\n    for (int id : comp) {\n        int x, y, z;\n        xyz(id, x, y, z);\n        if (!zx[z][x]) {\n            zx[z][x] = true;\n            cnt++;\n        }\n        if (!zy[z][y]) {\n            zy[z][y] = true;\n            cnt++;\n        }\n    }\n\n    return (long long)comp.size() * 1000 + (long long)cnt * 200;\n}\n\nstruct CommonCore {\n    vector<vector<int>> comps;\n    vector<unsigned char> rem[2];\n    int vol[2] = {0, 0};\n    long double baseCost = 0;\n};\n\nvoid add_partial_cover(\n    int obj,\n    int z,\n    const vector<unsigned char>& usedCommon,\n    vector<unsigned char>& rem,\n    bool prev[14][14],\n    uint32_t seed,\n    int residualExtra\n) {\n    bool preX[14] = {}, preY[14] = {};\n\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            if (usedCommon[idx3(x, y, z)]) {\n                preX[x] = true;\n                preY[y] = true;\n            }\n        }\n    }\n\n    vector<int> X, Y, RX, RY;\n\n    for (int x = 0; x < D; x++) {\n        if (F[obj][z][x] == '1') {\n            X.push_back(x);\n            if (!preX[x]) RX.push_back(x);\n        }\n    }\n\n    for (int y = 0; y < D; y++) {\n        if (Rg[obj][z][y] == '1') {\n            Y.push_back(y);\n            if (!preY[y]) RY.push_back(y);\n        }\n    }\n\n    vector<pair<int,int>> edges;\n\n    auto weight = [&](int x, int y) {\n        int w = 0;\n        if (prev[x][y]) w += 100000;\n        if (z + 1 < D && F[obj][z + 1][x] == '1' && Rg[obj][z + 1][y] == '1') w += 20000;\n        if (F[obj ^ 1][z][x] == '1' && Rg[obj ^ 1][z][y] == '1') w += 4000;\n        w += hrand(seed, x, y, z, 1000);\n        return w;\n    };\n\n    if (!(RX.empty() && RY.empty())) {\n        if ((int)RX.size() >= (int)RY.size() && !RX.empty()) {\n            int A = RX.size(), B = RY.size(), M = 1 << B;\n            int bitY[14] = {};\n            for (int i = 0; i < B; i++) bitY[RY[i]] = 1 << i;\n\n            const int NEG = -1000000000;\n            vector<int> dp(M, NEG), ndp(M, NEG);\n            vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n            vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n            dp[0] = 0;\n\n            for (int i = 0; i < A; i++) {\n                fill(ndp.begin(), ndp.end(), NEG);\n                for (int mask = 0; mask < M; mask++) {\n                    if (dp[mask] <= NEG / 2) continue;\n                    for (int y : Y) {\n                        int nm = mask | bitY[y];\n                        int val = dp[mask] + weight(RX[i], y);\n                        if (val > ndp[nm]) {\n                            ndp[nm] = val;\n                            pre[i + 1][nm] = mask;\n                            ch[i + 1][nm] = y;\n                        }\n                    }\n                }\n                dp.swap(ndp);\n            }\n\n            int mask = M - 1;\n            for (int i = A; i >= 1; i--) {\n                int y = ch[i][mask];\n                int pm = pre[i][mask];\n                edges.push_back({RX[i - 1], y});\n                mask = pm;\n            }\n        } else {\n            int A = RY.size(), B = RX.size(), M = 1 << B;\n            int bitX[14] = {};\n            for (int i = 0; i < B; i++) bitX[RX[i]] = 1 << i;\n\n            const int NEG = -1000000000;\n            vector<int> dp(M, NEG), ndp(M, NEG);\n            vector<vector<int>> pre(A + 1, vector<int>(M, -1));\n            vector<vector<short>> ch(A + 1, vector<short>(M, -1));\n\n            dp[0] = 0;\n\n            for (int i = 0; i < A; i++) {\n                fill(ndp.begin(), ndp.end(), NEG);\n                for (int mask = 0; mask < M; mask++) {\n                    if (dp[mask] <= NEG / 2) continue;\n                    for (int x : X) {\n                        int nm = mask | bitX[x];\n                        int val = dp[mask] + weight(x, RY[i]);\n                        if (val > ndp[nm]) {\n                            ndp[nm] = val;\n                            pre[i + 1][nm] = mask;\n                            ch[i + 1][nm] = x;\n                        }\n                    }\n                }\n                dp.swap(ndp);\n            }\n\n            int mask = M - 1;\n            for (int i = A; i >= 1; i--) {\n                int x = ch[i][mask];\n                int pm = pre[i][mask];\n                edges.push_back({x, RY[i - 1]});\n                mask = pm;\n            }\n        }\n    }\n\n    bool sel[14][14] = {};\n    for (auto [x, y] : edges) sel[x][y] = true;\n\n    int maxEdges = (int)X.size() * (int)Y.size();\n    int target = min(maxEdges, (int)edges.size() + residualExtra);\n\n    vector<tuple<int,int,int>> add;\n\n    for (int x : X) {\n        for (int y : Y) {\n            int id = idx3(x, y, z);\n            if (usedCommon[id] || sel[x][y]) continue;\n\n            int sc = weight(x, y);\n            if (x > 0 && sel[x - 1][y]) sc += 4000;\n            if (x + 1 < D && sel[x + 1][y]) sc += 4000;\n            if (y > 0 && sel[x][y - 1]) sc += 4000;\n            if (y + 1 < D && sel[x][y + 1]) sc += 4000;\n\n            add.push_back({sc, x, y});\n        }\n    }\n\n    sort(add.rbegin(), add.rend());\n\n    for (auto [sc, x, y] : add) {\n        if ((int)edges.size() >= target) break;\n        if (!sel[x][y]) {\n            sel[x][y] = true;\n            edges.push_back({x, y});\n        }\n    }\n\n    fill(&prev[0][0], &prev[0][0] + 14 * 14, false);\n\n    for (auto [x, y] : edges) {\n        int id = idx3(x, y, z);\n        if (!usedCommon[id]) {\n            rem[id] = 1;\n            prev[x][y] = true;\n        }\n    }\n}\n\nCommonCore build_common_core(\n    const vector<vector<int>>& allComps,\n    int minSize,\n    int maxCount,\n    int residualExtra\n) {\n    CommonCore cc;\n    vector<unsigned char> used(D * D * D, 0);\n\n    int cnt = 0;\n    for (auto& comp : allComps) {\n        if ((int)comp.size() < minSize) continue;\n        if (cnt >= maxCount) break;\n\n        cc.baseCost += 1.0L / (int)comp.size();\n        cc.comps.push_back(comp);\n\n        for (int id : comp) used[id] = 1;\n        cnt++;\n    }\n\n    cc.rem[0].assign(D * D * D, 0);\n    cc.rem[1].assign(D * D * D, 0);\n\n    bool prev0[14][14] = {};\n    bool prev1[14][14] = {};\n\n    for (int z = 0; z < D; z++) {\n        add_partial_cover(\n            0, z, used, cc.rem[0], prev0,\n            111111U + minSize * 1009U + maxCount * 17U + residualExtra * 99991U,\n            residualExtra\n        );\n        add_partial_cover(\n            1, z, used, cc.rem[1], prev1,\n            222222U + minSize * 1009U + maxCount * 17U + residualExtra * 99991U,\n            residualExtra\n        );\n    }\n\n    for (int i = 0; i < D * D * D; i++) {\n        cc.vol[0] += cc.rem[0][i];\n        cc.vol[1] += cc.rem[1][i];\n    }\n\n    return cc;\n}\n\nstruct CorePlan {\n    long double score = 1e100L;\n    int ax0 = 0, ax1 = 0;\n    bool useCub = false;\n    int strat0 = 0, strat1 = 0;\n};\n\nCorePlan eval_core(const CommonCore& cc, const vector<array<int,3>>& orders) {\n    CorePlan best;\n\n    array<LineDec, 3> la, lb;\n    for (int ax = 0; ax < 3; ax++) {\n        la[ax] = decompose_lines_occ(cc.rem[0], cc.vol[0], ax);\n        lb[ax] = decompose_lines_occ(cc.rem[1], cc.vol[1], ax);\n    }\n\n    for (int a = 0; a < 3; a++) {\n        for (int b = 0; b < 3; b++) {\n            long double sc = cc.baseCost + eval_lines(la[a], lb[b]);\n            if (sc < best.score) {\n                best.score = sc;\n                best.ax0 = a;\n                best.ax1 = b;\n                best.useCub = false;\n            }\n        }\n    }\n\n    vector<CubDec> ca, cb;\n    for (auto ord : orders) {\n        ca.push_back(decompose_cuboids_occ(cc.rem[0], cc.vol[0], ord));\n        cb.push_back(decompose_cuboids_occ(cc.rem[1], cc.vol[1], ord));\n    }\n\n    for (int i = 0; i < (int)ca.size(); i++) {\n        for (int j = 0; j < (int)cb.size(); j++) {\n            HybridEval he = eval_cuboid_hybrid(ca[i], cb[j]);\n            long double sc = cc.baseCost + he.score;\n            if (sc < best.score) {\n                best.score = sc;\n                best.ax0 = he.ax0;\n                best.ax1 = he.ax1;\n                best.useCub = true;\n                best.strat0 = i;\n                best.strat1 = j;\n            }\n        }\n    }\n\n    return best;\n}\n\nstruct Piece {\n    int len, rod, off;\n\n    bool operator<(const Piece& o) const {\n        if (len != o.len) return len < o.len;\n        if (rod != o.rod) return rod < o.rod;\n        return off < o.off;\n    }\n};\n\nvoid mark_line_piece(vector<int>& out, const LineDec& d, const Piece& p, int useLen, int id) {\n    const Rod& r = d.rods[p.rod];\n    for (int i = 0; i < useLen; i++) out[r.cells[p.off + i]] = id;\n}\n\nvoid add_line_solution(vector<int>& Aout, vector<int>& Bout, const LineDec& A, const LineDec& B, int& blockId) {\n    priority_queue<Piece> p, q;\n\n    for (int i = 0; i < (int)A.rods.size(); i++) p.push({(int)A.rods[i].cells.size(), i, 0});\n    for (int i = 0; i < (int)B.rods.size(); i++) q.push({(int)B.rods[i].cells.size(), i, 0});\n\n    for (int len = D; len >= 1; len--) {\n        while (!p.empty() && !q.empty() && p.top().len >= len && q.top().len >= len) {\n            Piece a = p.top(); p.pop();\n            Piece b = q.top(); q.pop();\n\n            blockId++;\n            mark_line_piece(Aout, A, a, len, blockId);\n            mark_line_piece(Bout, B, b, len, blockId);\n\n            if (a.len - len > 0) p.push({a.len - len, a.rod, a.off + len});\n            if (b.len - len > 0) q.push({b.len - len, b.rod, b.off + len});\n        }\n    }\n\n    while (!p.empty()) {\n        Piece a = p.top(); p.pop();\n        blockId++;\n        mark_line_piece(Aout, A, a, a.len, blockId);\n    }\n\n    while (!q.empty()) {\n        Piece b = q.top(); q.pop();\n        blockId++;\n        mark_line_piece(Bout, B, b, b.len, blockId);\n    }\n}\n\nvoid mark_cuboid(vector<int>& out, const Cuboid& c, int id) {\n    for (int v : c.cells) out[v] = id;\n}\n\nvoid add_cuboid_solution(\n    vector<int>& Aout,\n    vector<int>& Bout,\n    const CubDec& A,\n    const CubDec& B,\n    int axA,\n    int axB,\n    int& blockId\n) {\n    vector<unsigned char> usedA(A.cubs.size(), 0), usedB(B.cubs.size(), 0);\n\n    int ia = 0, ib = 0;\n    while (ia < (int)A.groups.size() && ib < (int)B.groups.size()) {\n        int ka = A.groups[ia].first;\n        int kb = B.groups[ib].first;\n\n        if (ka < kb) ia++;\n        else if (ka > kb) ib++;\n        else {\n            int vol = cuboid_volume_from_key(ka);\n            if (vol > 1) {\n                auto& va = A.groups[ia].second;\n                auto& vb = B.groups[ib].second;\n                int m = min((int)va.size(), (int)vb.size());\n\n                for (int i = 0; i < m; i++) {\n                    int ca = va[i], cb = vb[i];\n                    usedA[ca] = 1;\n                    usedB[cb] = 1;\n\n                    blockId++;\n                    mark_cuboid(Aout, A.cubs[ca], blockId);\n                    mark_cuboid(Bout, B.cubs[cb], blockId);\n                }\n            }\n            ia++;\n            ib++;\n        }\n    }\n\n    vector<unsigned char> remA(D * D * D, 0), remB(D * D * D, 0);\n    int volA = 0, volB = 0;\n\n    for (int i = 0; i < (int)A.cubs.size(); i++) {\n        if (usedA[i]) continue;\n        for (int id : A.cubs[i].cells) {\n            remA[id] = 1;\n            volA++;\n        }\n    }\n\n    for (int i = 0; i < (int)B.cubs.size(); i++) {\n        if (usedB[i]) continue;\n        for (int id : B.cubs[i].cells) {\n            remB[id] = 1;\n            volB++;\n        }\n    }\n\n    LineDec la = decompose_lines_occ(remA, volA, axA);\n    LineDec lb = decompose_lines_occ(remB, volB, axB);\n    add_line_solution(Aout, Bout, la, lb, blockId);\n}\n\nvoid print_output(int n, const vector<int>& A, const vector<int>& B) {\n    cout << n << \"\\n\";\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << A[i];\n    }\n    cout << \"\\n\";\n\n    for (int i = 0; i < D * D * D; i++) {\n        if (i) cout << ' ';\n        cout << B[i];\n    }\n    cout << \"\\n\";\n}\n\nvoid output_line(const LineDec& A, const LineDec& B) {\n    vector<int> Aout(D * D * D, 0), Bout(D * D * D, 0);\n    int blockId = 0;\n    add_line_solution(Aout, Bout, A, B, blockId);\n    print_output(blockId, Aout, Bout);\n}\n\nvoid output_cuboid(const CubDec& A, const CubDec& B, int axA, int axB) {\n    vector<int> Aout(D * D * D, 0), Bout(D * D * D, 0);\n    int blockId = 0;\n    add_cuboid_solution(Aout, Bout, A, B, axA, axB, blockId);\n    print_output(blockId, Aout, Bout);\n}\n\nvoid output_core(const CommonCore& cc, const CorePlan& plan, const vector<array<int,3>>& orders) {\n    vector<int> Aout(D * D * D, 0), Bout(D * D * D, 0);\n    int blockId = 0;\n\n    for (auto& comp : cc.comps) {\n        blockId++;\n        for (int id : comp) {\n            Aout[id] = blockId;\n            Bout[id] = blockId;\n        }\n    }\n\n    if (!plan.useCub) {\n        LineDec la = decompose_lines_occ(cc.rem[0], cc.vol[0], plan.ax0);\n        LineDec lb = decompose_lines_occ(cc.rem[1], cc.vol[1], plan.ax1);\n        add_line_solution(Aout, Bout, la, lb, blockId);\n    } else {\n        CubDec ca = decompose_cuboids_occ(cc.rem[0], cc.vol[0], orders[plan.strat0]);\n        CubDec cb = decompose_cuboids_occ(cc.rem[1], cc.vol[1], orders[plan.strat1]);\n        add_cuboid_solution(Aout, Bout, ca, cb, plan.ax0, plan.ax1, blockId);\n    }\n\n    print_output(blockId, Aout, Bout);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D;\n\n    for (int i = 0; i < 2; i++) {\n        for (int z = 0; z < D; z++) cin >> F[i][z];\n        for (int z = 0; z < D; z++) cin >> Rg[i][z];\n    }\n\n    vector<Params> params;\n    vector<int> extras = {0, 1, 2, 4, 7, 12, 1000};\n    uint32_t baseSeed = 246813579U;\n\n    for (int e : extras) {\n        for (int rev = 0; rev < 2; rev++) {\n            for (int rep = 0; rep < 2; rep++) {\n                Params p;\n                p.extra = e;\n                p.contW = 1000 + rep * 400;\n                p.futW = 80 + rep * 80;\n                p.randAmp = 60;\n                p.reverse = rev;\n                p.favor = rep + 1;\n                p.commonBonus = 0;\n                p.seed = baseSeed + e * 10007U + rev * 1000003U + rep * 9176U;\n                params.push_back(p);\n            }\n        }\n    }\n\n    for (int e : {0, 2, 4, 7, 12, 1000}) {\n        for (int rev = 0; rev < 2; rev++) {\n            Params p;\n            p.extra = e;\n            p.contW = 1400;\n            p.futW = 160;\n            p.randAmp = 50;\n            p.reverse = rev;\n            p.favor = 3;\n            p.commonBonus = 900;\n            p.seed = baseSeed ^ (0xabcdefU + e * 31337U + rev * 99991U);\n            params.push_back(p);\n        }\n    }\n\n    if (D <= 12) {\n        for (int e : {0, 2, 7, 1000}) {\n            for (int rev = 0; rev < 2; rev++) {\n                Params p;\n                p.extra = e;\n                p.contW = 1500;\n                p.futW = 180;\n                p.randAmp = 45;\n                p.reverse = rev;\n                p.favor = 3;\n                p.commonBonus = 3000;\n                p.seed = baseSeed ^ (0x13579bU + e * 27183U + rev * 99991U + 3000U * 17U);\n                params.push_back(p);\n            }\n        }\n    }\n\n    if (D <= 10) {\n        for (int e : {0, 4, 1000}) {\n            for (int rev = 0; rev < 2; rev++) {\n                Params p;\n                p.extra = e;\n                p.contW = 1600;\n                p.futW = 200;\n                p.randAmp = 40;\n                p.reverse = rev;\n                p.favor = 3;\n                p.commonBonus = 10000;\n                p.seed = baseSeed ^ (0x2468acU + e * 31415U + rev * 88888U + 10000U * 13U);\n                params.push_back(p);\n            }\n        }\n    }\n\n    vector<Candidate> cand[2];\n\n    for (int id = 0; id < 2; id++) {\n        for (auto p : params) {\n            cand[id].push_back(build_candidate(id, p));\n        }\n    }\n\n    int n0 = cand[0].size();\n    int n1 = cand[1].size();\n\n    vector<array<LineDec, 3>> lines[2];\n    lines[0].resize(n0);\n    lines[1].resize(n1);\n\n    for (int id = 0; id < 2; id++) {\n        int n = cand[id].size();\n        for (int i = 0; i < n; i++) {\n            for (int ax = 0; ax < 3; ax++) {\n                lines[id][i][ax] = decompose_lines(cand[id][i], ax);\n            }\n        }\n    }\n\n    vector<array<int,3>> orders = {\n        array<int,3>{0, 1, 2},\n        array<int,3>{0, 2, 1},\n        array<int,3>{1, 0, 2},\n        array<int,3>{1, 2, 0},\n        array<int,3>{2, 0, 1},\n        array<int,3>{2, 1, 0}\n    };\n\n    struct CubRef {\n        CubDec dec;\n    };\n\n    vector<CubRef> cubs[2];\n\n    for (int id = 0; id < 2; id++) {\n        for (int i = 0; i < (int)cand[id].size(); i++) {\n            for (auto ord : orders) {\n                CubRef cr;\n                cr.dec = decompose_cuboids_candidate(cand[id][i], ord);\n                cubs[id].push_back(move(cr));\n            }\n        }\n    }\n\n    vector<unsigned char> feasible(D * D * D, 0);\n\n    for (int x = 0; x < D; x++) {\n        for (int y = 0; y < D; y++) {\n            for (int z = 0; z < D; z++) {\n                if (\n                    F[0][z][x] == '1' &&\n                    F[1][z][x] == '1' &&\n                    Rg[0][z][y] == '1' &&\n                    Rg[1][z][y] == '1'\n                ) {\n                    feasible[idx3(x, y, z)] = 1;\n                }\n            }\n        }\n    }\n\n    auto commonComps = components_of_occ(feasible);\n\n    vector<vector<vector<int>>> compOrders;\n\n    sort(commonComps.begin(), commonComps.end(), [](const vector<int>& a, const vector<int>& b) {\n        return a.size() > b.size();\n    });\n    compOrders.push_back(commonComps);\n\n    auto covOrder = commonComps;\n    sort(covOrder.begin(), covOrder.end(), [](const vector<int>& a, const vector<int>& b) {\n        long long sa = component_cover_score(a);\n        long long sb = component_cover_score(b);\n        if (sa != sb) return sa > sb;\n        return a.size() > b.size();\n    });\n    compOrders.push_back(covOrder);\n\n    struct CoreCfg {\n        int orderId, minSize, maxCount, resExtra;\n    };\n\n    vector<CoreCfg> coreCfgs;\n    set<tuple<int,int,int,int>> usedCfg;\n    const int INF = 1000000;\n\n    auto add_cfg = [&](int orderId, int a, int b, int c) {\n        auto t = make_tuple(orderId, a, b, c);\n        if (usedCfg.insert(t).second) {\n            coreCfgs.push_back({orderId, a, b, c});\n        }\n    };\n\n    for (int th : {1, 2, 3, 4, 5, 6, 8, 10, 14, 20, 28}) {\n        add_cfg(0, th, INF, 0);\n    }\n\n    for (int k : {1, 2, 3, 4, 5, 8, 12, 16, 24}) {\n        for (int th : {1, 2, 3, 4}) {\n            add_cfg(0, th, k, 0);\n            add_cfg(1, th, k, 0);\n        }\n    }\n\n    if (D <= 12) {\n        for (int th : {1, 2, 4, 8}) {\n            add_cfg(0, th, INF, 1);\n            add_cfg(1, th, INF, 1);\n        }\n        for (int k : {1, 4, 8, 16}) {\n            for (int th : {1, 2}) {\n                add_cfg(0, th, k, 1);\n                add_cfg(1, th, k, 1);\n            }\n        }\n\n        for (int th : {1, 2, 4}) {\n            add_cfg(0, th, INF, 2);\n        }\n        for (int k : {1, 4, 8}) {\n            for (int th : {1, 2}) {\n                add_cfg(0, th, k, 2);\n            }\n        }\n    }\n\n    if (D <= 10) {\n        for (int th : {1, 2, 3, 4, 6, 10}) {\n            add_cfg(0, th, INF, 1);\n            add_cfg(0, th, INF, 2);\n        }\n        for (int k : {1, 2, 4, 8, 16}) {\n            for (int th : {1, 2, 3}) {\n                add_cfg(0, th, k, 1);\n                add_cfg(0, th, k, 2);\n            }\n        }\n    }\n\n    if (D <= 9) {\n        for (int th : {1, 2, 4}) {\n            add_cfg(0, th, INF, 3);\n        }\n        for (int k : {1, 4, 8}) {\n            for (int th : {1, 2}) {\n                add_cfg(0, th, k, 3);\n            }\n        }\n\n        for (int th : {1, 2}) {\n            add_cfg(0, th, INF, 4);\n        }\n        for (int k : {1, 4}) {\n            for (int th : {1, 2}) {\n                add_cfg(0, th, k, 4);\n            }\n        }\n    }\n\n    if (D <= 8) {\n        for (int th : {1, 2}) {\n            add_cfg(0, th, INF, 5);\n        }\n        for (int k : {1, 4}) {\n            add_cfg(0, 1, k, 5);\n        }\n    }\n\n    vector<CommonCore> cores;\n    vector<CorePlan> corePlans;\n\n    cores.reserve(coreCfgs.size());\n    corePlans.reserve(coreCfgs.size());\n\n    for (auto cfg : coreCfgs) {\n        if (!time_ok(5.10)) break;\n\n        CommonCore cc = build_common_core(\n            compOrders[cfg.orderId],\n            cfg.minSize,\n            cfg.maxCount,\n            cfg.resExtra\n        );\n        CorePlan cp = eval_core(cc, orders);\n\n        corePlans.push_back(cp);\n        cores.push_back(move(cc));\n    }\n\n    long double bestScore = 1e100L;\n    int bestMode = 0;\n\n    int bestI = 0, bestJ = 0;\n    int bestAx0 = 0, bestAx1 = 0;\n    int bestCubA = 0, bestCubB = 0;\n    int bestCore = 0;\n\n    for (int i = 0; i < n0; i++) {\n        for (int j = 0; j < n1; j++) {\n            for (int a = 0; a < 3; a++) {\n                for (int b = 0; b < 3; b++) {\n                    long double sc = eval_lines(lines[0][i][a], lines[1][j][b]);\n                    if (sc < bestScore) {\n                        bestScore = sc;\n                        bestMode = 0;\n                        bestI = i;\n                        bestJ = j;\n                        bestAx0 = a;\n                        bestAx1 = b;\n                    }\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < (int)cubs[0].size(); i++) {\n        if (!time_ok(5.35)) break;\n\n        for (int j = 0; j < (int)cubs[1].size(); j++) {\n            HybridEval he = eval_cuboid_hybrid(cubs[0][i].dec, cubs[1][j].dec);\n            if (he.score < bestScore) {\n                bestScore = he.score;\n                bestMode = 1;\n                bestCubA = i;\n                bestCubB = j;\n                bestAx0 = he.ax0;\n                bestAx1 = he.ax1;\n            }\n        }\n    }\n\n    for (int i = 0; i < (int)cores.size(); i++) {\n        if (corePlans[i].score < bestScore) {\n            bestScore = corePlans[i].score;\n            bestMode = 2;\n            bestCore = i;\n        }\n    }\n\n    if (bestMode == 0) {\n        output_line(lines[0][bestI][bestAx0], lines[1][bestJ][bestAx1]);\n    } else if (bestMode == 1) {\n        output_cuboid(cubs[0][bestCubA].dec, cubs[1][bestCubB].dec, bestAx0, bestAx1);\n    } else {\n        output_core(cores[bestCore], corePlans[bestCore], orders);\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) x = p[x] = p[p[x]];\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a), b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstatic const long long INF = (1LL << 60);\n\nint N, M, K;\nvector<int> X, Y;\nvector<Edge> edges;\nvector<int> A, RY;\n\nvector<vector<int>> cdist;\nvector<vector<pair<int,int>>> sortedRes;\n\nvector<vector<long long>> fw;\nvector<vector<int>> nxtv;\nvector<vector<int>> directEdge;\n\nchrono::steady_clock::time_point st_time;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - st_time).count();\n}\n\nint ceil_sqrt_ll(long long x) {\n    long long r = sqrt((long double)x);\n    while (r * r < x) ++r;\n    while (r > 0 && (r - 1) * (r - 1) >= x) --r;\n    return (int)r;\n}\n\nvoid add_path_edges(int s, int t, vector<char>& sel) {\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n    }\n}\n\nvoid add_path_edges_mark(int s, int t, vector<char>& sel, vector<char>& inTree) {\n    inTree[s] = 1;\n    while (s != t) {\n        int to = nxtv[s][t];\n        if (to < 0) break;\n        int eid = directEdge[s][to];\n        if (eid < 0) break;\n        sel[eid] = 1;\n        s = to;\n        inTree[s] = 1;\n    }\n}\n\npair<long long, vector<int>> build_best_tree(const vector<int>& P) {\n    long long bestCost = INF;\n    vector<int> bestB(M, 0);\n\n    auto consider = [&](vector<char> sel) {\n        vector<char> terminal(N, 0);\n        terminal[0] = 1;\n        for (int i = 0; i < N; i++) if (P[i] > 0) terminal[i] = 1;\n\n        vector<vector<pair<int,int>>> g(N);\n        vector<int> deg(N, 0);\n\n        for (int e = 0; e < M; e++) if (sel[e]) {\n            int u = edges[e].u, v = edges[e].v;\n            g[u].push_back({v, e});\n            g[v].push_back({u, e});\n            deg[u]++;\n            deg[v]++;\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (!terminal[i] && deg[i] <= 1) q.push(i);\n        }\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            if (terminal[v] || deg[v] != 1) continue;\n\n            for (auto [to, eid] : g[v]) {\n                if (!sel[eid]) continue;\n                sel[eid] = 0;\n                deg[v]--;\n                deg[to]--;\n                if (!terminal[to] && deg[to] == 1) q.push(to);\n                break;\n            }\n        }\n\n        long long cost = 0;\n        vector<int> B(M, 0);\n        for (int e = 0; e < M; e++) {\n            if (sel[e]) {\n                cost += edges[e].w;\n                B[e] = 1;\n            }\n        }\n\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestB = B;\n        }\n    };\n\n    vector<int> terms;\n    terms.push_back(0);\n    for (int i = 1; i < N; i++) if (P[i] > 0) terms.push_back(i);\n\n    int T = (int)terms.size();\n\n    // Metric-closure MST over terminals.\n    {\n        vector<char> sel(M, 0);\n\n        if (T >= 2) {\n            vector<long long> minD(T, INF);\n            vector<int> par(T, -1);\n            vector<char> used(T, 0);\n            minD[0] = 0;\n\n            for (int it = 0; it < T; it++) {\n                int v = -1;\n                for (int i = 0; i < T; i++) {\n                    if (!used[i] && (v == -1 || minD[i] < minD[v])) v = i;\n                }\n\n                if (v == -1) break;\n                used[v] = 1;\n\n                if (par[v] != -1) {\n                    add_path_edges(terms[v], terms[par[v]], sel);\n                }\n\n                for (int to = 0; to < T; to++) {\n                    if (!used[to] && fw[terms[v]][terms[to]] < minD[to]) {\n                        minD[to] = fw[terms[v]][terms[to]];\n                        par[to] = v;\n                    }\n                }\n            }\n        }\n\n        consider(sel);\n    }\n\n    // Union of shortest paths from root.\n    {\n        vector<char> sel(M, 0);\n        for (int i = 1; i < N; i++) {\n            if (P[i] > 0) add_path_edges(0, i, sel);\n        }\n        consider(sel);\n    }\n\n    // Ordinary graph MST, pruned.\n    {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return edges[a].w < edges[b].w;\n        });\n\n        DSU dsu(N);\n        vector<char> sel(M, 0);\n\n        for (int eid : ord) {\n            if (dsu.unite(edges[eid].u, edges[eid].v)) {\n                sel[eid] = 1;\n            }\n        }\n\n        consider(sel);\n    }\n\n    // Incremental Steiner-style candidates.\n    {\n        vector<int> base;\n        for (int i = 1; i < N; i++) if (P[i] > 0) base.push_back(i);\n\n        vector<vector<int>> orders;\n\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return fw[0][a] < fw[0][b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return fw[0][a] > fw[0][b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return P[a] > P[b];\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = base;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return P[a] < P[b];\n            });\n            orders.push_back(v);\n        }\n\n        for (auto ord : orders) {\n            vector<char> sel(M, 0);\n            vector<char> inTree(N, 0);\n            inTree[0] = 1;\n\n            for (int t : ord) {\n                int best = -1;\n                long long bd = INF;\n\n                for (int v = 0; v < N; v++) {\n                    if (inTree[v] && fw[t][v] < bd) {\n                        bd = fw[t][v];\n                        best = v;\n                    }\n                }\n\n                if (best != -1) {\n                    add_path_edges_mark(t, best, sel, inTree);\n                }\n            }\n\n            consider(sel);\n        }\n    }\n\n    return {bestCost, bestB};\n}\n\nlong long total_cost(const vector<int>& P) {\n    long long radio = 0;\n    for (int p : P) radio += 1LL * p * p;\n\n    auto tr = build_best_tree(P);\n    return radio + tr.first;\n}\n\nbool compute_covered(const vector<int>& P, vector<char>& covered) {\n    covered.assign(K, 0);\n    int cnt = 0;\n\n    for (int k = 0; k < K; k++) {\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                covered[k] = 1;\n                cnt++;\n                break;\n            }\n        }\n    }\n\n    return cnt == K;\n}\n\nvoid reduce_powers_order(vector<int>& P, const vector<int>& order) {\n    vector<int> coverCnt(K, 0);\n\n    for (int i = 0; i < N; i++) if (P[i] > 0) {\n        for (int k = 0; k < K; k++) {\n            if (cdist[i][k] <= P[i]) coverCnt[k]++;\n        }\n    }\n\n    bool changed = true;\n    int loop = 0;\n\n    while (changed && loop < 12) {\n        loop++;\n        changed = false;\n\n        for (int i : order) {\n            int old = P[i];\n            if (old == 0) continue;\n\n            int req = 0;\n\n            for (int k = 0; k < K; k++) {\n                if (cdist[i][k] <= old && coverCnt[k] == 1) {\n                    req = max(req, cdist[i][k]);\n                }\n            }\n\n            if (req < old) {\n                for (int k = 0; k < K; k++) {\n                    if (cdist[i][k] <= old && cdist[i][k] > req) {\n                        coverCnt[k]--;\n                    }\n                }\n\n                P[i] = req;\n                changed = true;\n            }\n        }\n    }\n}\n\nvoid reduce_powers(vector<int>& P) {\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    reduce_powers_order(P, order);\n}\n\nint lower_existing_radius(int station, int limit) {\n    int res = 0;\n    for (auto [d, k] : sortedRes[station]) {\n        if (d <= limit) res = d;\n        else break;\n    }\n    return res;\n}\n\nbool greedy_complete(\n    vector<int>& P,\n    double alpha,\n    bool dynamicConn,\n    int capStation = -1,\n    int capRadius = 5000\n) {\n    vector<char> covered(K, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; k++) {\n        bool ok = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                ok = true;\n                break;\n            }\n        }\n\n        covered[k] = ok;\n        if (!ok) uncovered++;\n    }\n\n    vector<int> activeList;\n    activeList.push_back(0);\n    for (int i = 0; i < N; i++) {\n        if (P[i] > 0 && i != 0) activeList.push_back(i);\n    }\n\n    vector<double> rootPen(N, 0.0);\n    for (int i = 0; i < N; i++) rootPen[i] = alpha * (double)fw[0][i];\n\n    while (uncovered > 0) {\n        int bestI = -1;\n        int bestR = -1;\n        int bestGain = 0;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            int old = P[i];\n\n            if (i == capStation && old >= capRadius) continue;\n\n            double connPen = 0.0;\n\n            if (old == 0) {\n                if (dynamicConn) {\n                    long long md = INF;\n                    for (int a : activeList) md = min(md, fw[i][a]);\n                    connPen = alpha * (double)md;\n                } else {\n                    connPen = rootPen[i];\n                }\n            }\n\n            int gain = 0;\n            const auto& vec = sortedRes[i];\n\n            for (int idx = 0; idx < (int)vec.size();) {\n                int r = vec[idx].first;\n\n                if (r > 5000) break;\n                if (i == capStation && r > capRadius) break;\n\n                int add = 0;\n                while (idx < (int)vec.size() && vec[idx].first == r) {\n                    int k = vec[idx].second;\n                    if (r > old && !covered[k]) add++;\n                    idx++;\n                }\n\n                if (r <= old) continue;\n\n                gain += add;\n\n                if (gain > 0) {\n                    double delta = (double)r * r - (double)old * old;\n                    if (old == 0) delta += connPen;\n\n                    double score = delta / gain;\n\n                    if (score < bestScore ||\n                        (abs(score - bestScore) < 1e-9 && gain > bestGain)) {\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestGain = gain;\n                    }\n                }\n            }\n        }\n\n        if (bestI == -1) return false;\n\n        bool wasZero = (P[bestI] == 0);\n        P[bestI] = bestR;\n\n        if (wasZero) activeList.push_back(bestI);\n\n        for (auto [r, k] : sortedRes[bestI]) {\n            if (r > bestR) break;\n            if (!covered[k]) {\n                covered[k] = 1;\n                uncovered--;\n            }\n        }\n    }\n\n    return true;\n}\n\nbool greedy_repair_active_only(vector<int>& P, const vector<char>& allowed, const vector<int>& maxR) {\n    vector<char> covered(K, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; k++) {\n        bool ok = false;\n        for (int i = 0; i < N; i++) {\n            if (P[i] > 0 && cdist[i][k] <= P[i]) {\n                ok = true;\n                break;\n            }\n        }\n        covered[k] = ok;\n        if (!ok) uncovered++;\n    }\n\n    while (uncovered > 0) {\n        int bestI = -1;\n        int bestR = -1;\n        int bestGain = 0;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            if (!allowed[i]) continue;\n\n            int old = P[i];\n            if (old >= maxR[i]) continue;\n\n            int gain = 0;\n            const auto& vec = sortedRes[i];\n\n            for (int idx = 0; idx < (int)vec.size();) {\n                int r = vec[idx].first;\n                if (r > maxR[i]) break;\n\n                int add = 0;\n                while (idx < (int)vec.size() && vec[idx].first == r) {\n                    int k = vec[idx].second;\n                    if (r > old && !covered[k]) add++;\n                    idx++;\n                }\n\n                if (r <= old) continue;\n\n                gain += add;\n\n                if (gain > 0) {\n                    double delta = (double)r * r - (double)old * old;\n                    double score = delta / gain;\n\n                    if (score < bestScore ||\n                        (abs(score - bestScore) < 1e-9 && gain > bestGain)) {\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestGain = gain;\n                    }\n                }\n            }\n        }\n\n        if (bestI == -1) return false;\n\n        P[bestI] = bestR;\n\n        for (auto [r, k] : sortedRes[bestI]) {\n            if (r > bestR) break;\n            if (!covered[k]) {\n                covered[k] = 1;\n                uncovered--;\n            }\n        }\n    }\n\n    return true;\n}\n\nvector<int> initial_nearest_solution() {\n    vector<int> P(N, 0);\n\n    for (int k = 0; k < K; k++) {\n        int bi = -1;\n        int bd = 1e9;\n\n        for (int i = 0; i < N; i++) {\n            if (cdist[i][k] <= 5000 && cdist[i][k] < bd) {\n                bd = cdist[i][k];\n                bi = i;\n            }\n        }\n\n        if (bi == -1) {\n            for (int i = 0; i < N; i++) {\n                if (cdist[i][k] < bd) {\n                    bd = cdist[i][k];\n                    bi = i;\n                }\n            }\n        }\n\n        P[bi] = max(P[bi], bd);\n    }\n\n    reduce_powers(P);\n    return P;\n}\n\nvector<int> initial_weighted_nearest_solution(double lambda) {\n    vector<int> P(N, 0);\n\n    for (int k = 0; k < K; k++) {\n        int bi = -1;\n        long double best = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            int d = cdist[i][k];\n            if (d > 5000) continue;\n\n            long double val = (long double)d * d + lambda * (long double)fw[0][i];\n\n            if (val < best) {\n                best = val;\n                bi = i;\n            }\n        }\n\n        if (bi == -1) {\n            int bd = 1e9;\n            for (int i = 0; i < N; i++) {\n                if (cdist[i][k] < bd) {\n                    bd = cdist[i][k];\n                    bi = i;\n                }\n            }\n        }\n\n        P[bi] = max(P[bi], cdist[bi][k]);\n    }\n\n    reduce_powers(P);\n    return P;\n}\n\nvoid optimize_reduction_orders(vector<int>& bestP, long long& bestS) {\n    vector<vector<int>> orders;\n\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return bestP[a] > bestP[b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return bestP[a] < bestP[b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return fw[0][a] < fw[0][b];\n        });\n        orders.push_back(ord);\n    }\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return fw[0][a] > fw[0][b];\n        });\n        orders.push_back(ord);\n    }\n\n    for (auto& ord : orders) {\n        if (elapsed_sec() > 1.96) break;\n\n        vector<int> P = bestP;\n        reduce_powers_order(P, ord);\n\n        vector<char> covered;\n        if (!compute_covered(P, covered)) continue;\n\n        long long S = total_cost(P);\n        if (S < bestS) {\n            bestS = S;\n            bestP = P;\n        }\n    }\n}\n\nvoid fixed_active_local_search(vector<int>& bestP, long long& bestS, double timeLimit) {\n    while (elapsed_sec() < timeLimit) {\n        bool improved = false;\n        vector<int> nextP = bestP;\n        long long nextS = bestS;\n\n        vector<int> active;\n        vector<char> allowed(N, 0);\n\n        for (int i = 0; i < N; i++) {\n            if (bestP[i] > 0) {\n                active.push_back(i);\n                allowed[i] = 1;\n            }\n        }\n\n        sort(active.begin(), active.end(), [&](int a, int b) {\n            return bestP[a] > bestP[b];\n        });\n\n        for (int s : active) {\n            if (elapsed_sec() > timeLimit) break;\n\n            int old = bestP[s];\n            vector<int> limits;\n\n            limits.push_back(0);\n            limits.push_back(lower_existing_radius(s, old / 5));\n            limits.push_back(lower_existing_radius(s, old / 3));\n            limits.push_back(lower_existing_radius(s, old / 2));\n            limits.push_back(lower_existing_radius(s, old * 2 / 3));\n            limits.push_back(lower_existing_radius(s, old * 4 / 5));\n\n            sort(limits.begin(), limits.end());\n            limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n            for (int lim : limits) {\n                if (elapsed_sec() > timeLimit) break;\n                if (lim >= old) continue;\n\n                vector<int> P = bestP;\n                vector<int> maxR(N, 5000);\n\n                P[s] = lim;\n                maxR[s] = lim;\n\n                bool ok = greedy_repair_active_only(P, allowed, maxR);\n                if (!ok) continue;\n\n                reduce_powers(P);\n\n                vector<char> covered;\n                if (!compute_covered(P, covered)) continue;\n\n                long long S = total_cost(P);\n\n                if (S < nextS) {\n                    nextS = S;\n                    nextP = P;\n                    improved = true;\n                }\n            }\n        }\n\n        if (improved) {\n            bestP = nextP;\n            bestS = nextS;\n        } else {\n            break;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    st_time = chrono::steady_clock::now();\n\n    cin >> N >> M >> K;\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    edges.resize(M);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u;\n        --v;\n        edges[i] = {u, v, w};\n    }\n\n    A.resize(K);\n    RY.resize(K);\n    for (int k = 0; k < K; k++) cin >> A[k] >> RY[k];\n\n    fw.assign(N, vector<long long>(N, INF));\n    nxtv.assign(N, vector<int>(N, -1));\n    directEdge.assign(N, vector<int>(N, -1));\n\n    for (int i = 0; i < N; i++) {\n        fw[i][i] = 0;\n        nxtv[i][i] = i;\n    }\n\n    for (int e = 0; e < M; e++) {\n        int u = edges[e].u;\n        int v = edges[e].v;\n        long long w = edges[e].w;\n\n        if (w < fw[u][v]) {\n            fw[u][v] = fw[v][u] = w;\n            nxtv[u][v] = v;\n            nxtv[v][u] = u;\n            directEdge[u][v] = directEdge[v][u] = e;\n        }\n    }\n\n    for (int k = 0; k < N; k++) {\n        for (int i = 0; i < N; i++) if (fw[i][k] < INF) {\n            for (int j = 0; j < N; j++) if (fw[k][j] < INF) {\n                long long nd = fw[i][k] + fw[k][j];\n\n                if (nd < fw[i][j]) {\n                    fw[i][j] = nd;\n                    nxtv[i][j] = nxtv[i][k];\n                }\n            }\n        }\n    }\n\n    cdist.assign(N, vector<int>(K));\n    sortedRes.assign(N, {});\n\n    for (int i = 0; i < N; i++) {\n        sortedRes[i].reserve(K);\n\n        for (int k = 0; k < K; k++) {\n            long long dx = X[i] - A[k];\n            long long dy = Y[i] - RY[k];\n            int d = ceil_sqrt_ll(dx * dx + dy * dy);\n\n            cdist[i][k] = d;\n\n            if (d <= 5000) {\n                sortedRes[i].push_back({d, k});\n            }\n        }\n\n        sort(sortedRes[i].begin(), sortedRes[i].end());\n    }\n\n    vector<int> bestP = initial_nearest_solution();\n    long long bestS = total_cost(bestP);\n    double bestAlpha = 0.2;\n\n    // Cheap extra initial diversification.\n    for (double lambda : {0.05, 0.12, 0.25, 0.5, 0.9, 1.5, 2.5}) {\n        if (elapsed_sec() > 0.18) break;\n\n        vector<int> P = initial_weighted_nearest_solution(lambda);\n        long long S = total_cost(P);\n\n        if (S < bestS) {\n            bestS = S;\n            bestP = P;\n        }\n    }\n\n    vector<double> alphas = {\n        0.0, 0.02, 0.05, 0.08, 0.12, 0.18,\n        0.27, 0.4, 0.6, 0.9, 1.3\n    };\n\n    // Static and dynamic greedy initial constructions.\n    for (double alpha : alphas) {\n        if (elapsed_sec() > 1.08) break;\n\n        for (int dyn = 0; dyn <= 1; dyn++) {\n            if (elapsed_sec() > 1.18) break;\n\n            vector<int> P(N, 0);\n            bool ok = greedy_complete(P, alpha, dyn == 1);\n\n            if (!ok) continue;\n\n            reduce_powers(P);\n            long long S = total_cost(P);\n\n            if (S < bestS) {\n                bestS = S;\n                bestP = P;\n                bestAlpha = alpha;\n            }\n        }\n    }\n\n    optimize_reduction_orders(bestP, bestS);\n\n    // Fixed-active local search before changing active stations.\n    if (elapsed_sec() < 1.40) {\n        fixed_active_local_search(bestP, bestS, 1.55);\n    }\n\n    vector<double> repairAlphas = {\n        0.0,\n        max(0.05, min(0.7, bestAlpha)),\n        0.25,\n        0.55\n    };\n\n    // Robust global local search.\n    while (elapsed_sec() < 1.86) {\n        bool improved = false;\n        vector<int> nextBestP = bestP;\n        long long nextBestS = bestS;\n\n        vector<int> active;\n        for (int i = 0; i < N; i++) {\n            if (bestP[i] > 0) active.push_back(i);\n        }\n\n        sort(active.begin(), active.end(), [&](int a, int b) {\n            long long ca = 1LL * bestP[a] * bestP[a];\n            long long cb = 1LL * bestP[b] * bestP[b];\n            return ca > cb;\n        });\n\n        for (int s : active) {\n            if (elapsed_sec() > 1.91) break;\n\n            int old = bestP[s];\n            vector<int> limits;\n\n            limits.push_back(0);\n            limits.push_back(lower_existing_radius(s, old / 4));\n            limits.push_back(lower_existing_radius(s, old / 2));\n            limits.push_back(lower_existing_radius(s, old * 3 / 4));\n\n            sort(limits.begin(), limits.end());\n            limits.erase(unique(limits.begin(), limits.end()), limits.end());\n\n            for (int lim : limits) {\n                if (elapsed_sec() > 1.93) break;\n                if (lim >= old) continue;\n\n                for (double ra : repairAlphas) {\n                    if (elapsed_sec() > 1.95) break;\n\n                    vector<int> P = bestP;\n                    P[s] = lim;\n\n                    bool ok = greedy_complete(P, ra, true, s, lim);\n                    if (!ok) continue;\n\n                    reduce_powers(P);\n                    long long S = total_cost(P);\n\n                    if (S < nextBestS) {\n                        nextBestS = S;\n                        nextBestP = P;\n                        improved = true;\n                    }\n                }\n            }\n        }\n\n        if (improved) {\n            bestS = nextBestS;\n            bestP = nextBestP;\n\n            if (elapsed_sec() < 1.88) {\n                optimize_reduction_orders(bestP, bestS);\n            }\n        } else {\n            break;\n        }\n    }\n\n    optimize_reduction_orders(bestP, bestS);\n\n    vector<char> covered;\n    if (!compute_covered(bestP, covered)) {\n        greedy_complete(bestP, 0.0, true);\n        reduce_powers(bestP);\n    }\n\n    auto tree = build_best_tree(bestP);\n    vector<int> ansB = tree.second;\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n\n    for (int e = 0; e < M; e++) {\n        if (e) cout << ' ';\n        cout << ansB[e];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 30;\nconstexpr int M = N * (N + 1) / 2;\nconstexpr int MAX_OPS = 10000;\n\nstruct Op {\n    int u, v;\n    bool operator==(const Op& o) const { return u == o.u && v == o.v; }\n};\n\nint ID[N][N], X[M], Y[M];\narray<int, M> initialA;\n\nvector<pair<int,int>> downEdges;\nvector<vector<int>> incidentDown;\nbool isAdj[M][M];\n\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsedSec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nstruct RNG {\n    uint32_t x;\n    RNG(uint32_t seed = 1) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int range(int l, int r) {\n        return l + (int)(next() % (uint32_t)(r - l + 1));\n    }\n};\n\nuint32_t splitmix32(uint32_t x) {\n    x += 0x9e3779b9;\n    x = (x ^ (x >> 16)) * 0x85ebca6b;\n    x = (x ^ (x >> 13)) * 0xc2b2ae35;\n    x ^= (x >> 16);\n    return x;\n}\n\nint calcE(const array<int, M>& a) {\n    int e = 0;\n    for (auto [p, c] : downEdges) if (a[p] > a[c]) e++;\n    return e;\n}\n\nint calcViolationDiffSum(const array<int, M>& a) {\n    int s = 0;\n    for (auto [p, c] : downEdges) {\n        if (a[p] > a[c]) s += a[p] - a[c];\n    }\n    return s;\n}\n\nbool isValidFinal(const array<int, M>& a) {\n    for (auto [p, c] : downEdges) {\n        if (a[p] > a[c]) return false;\n    }\n    return true;\n}\n\nstruct State {\n    array<int, M> a;\n    vector<Op> ops;\n    int E = 0;\n};\n\nvector<int> parentsOf(int u) {\n    vector<int> ps;\n    int x = X[u], y = Y[u];\n    if (x == 0) return ps;\n    if (y > 0) ps.push_back(ID[x - 1][y - 1]);\n    if (y < x) ps.push_back(ID[x - 1][y]);\n    return ps;\n}\n\nvector<int> childrenOf(int u) {\n    vector<int> cs;\n    int x = X[u], y = Y[u];\n    if (x + 1 >= N) return cs;\n    cs.push_back(ID[x + 1][y]);\n    cs.push_back(ID[x + 1][y + 1]);\n    return cs;\n}\n\nint deltaSwapLocal(const array<int, M>& a, int u, int v) {\n    int ids[16], cnt = 0;\n\n    auto add = [&](int e) {\n        for (int i = 0; i < cnt; i++) if (ids[i] == e) return;\n        ids[cnt++] = e;\n    };\n\n    for (int e : incidentDown[u]) add(e);\n    for (int e : incidentDown[v]) add(e);\n\n    int before = 0, after = 0;\n\n    for (int i = 0; i < cnt; i++) {\n        auto [p, c] = downEdges[ids[i]];\n\n        before += (a[p] > a[c]);\n\n        int vp = a[p], vc = a[c];\n\n        if (p == u) vp = a[v];\n        else if (p == v) vp = a[u];\n\n        if (c == u) vc = a[v];\n        else if (c == v) vc = a[u];\n\n        after += (vp > vc);\n    }\n\n    return before - after;\n}\n\nvoid applySwap(State& s, int u, int v) {\n    s.E -= deltaSwapLocal(s.a, u, v);\n    swap(s.a[u], s.a[v]);\n    s.ops.push_back({u, v});\n}\n\nvoid applySwapWithPos(State& s, array<int, M>& pos, int u, int v) {\n    int au = s.a[u], av = s.a[v];\n    applySwap(s, u, v);\n    pos[au] = v;\n    pos[av] = u;\n}\n\nbool sameEdge(const Op& a, const Op& b) {\n    return (a.u == b.u && a.v == b.v) || (a.u == b.v && a.v == b.u);\n}\n\nbool shareVertex(const Op& a, const Op& b) {\n    return a.u == b.u || a.u == b.v || a.v == b.u || a.v == b.v;\n}\n\nbool triangleReplace(const Op& a, const Op& b, Op& r) {\n    if (!shareVertex(a, b)) return false;\n    if (sameEdge(a, b)) return false;\n\n    int common = -1;\n\n    if (a.u == b.u || a.u == b.v) common = a.u;\n    if (a.v == b.u || a.v == b.v) {\n        if (common != -1) return false;\n        common = a.v;\n    }\n\n    if (common == -1) return false;\n\n    int x = (a.u == common ? a.v : a.u);\n    int y = (b.u == common ? b.v : b.u);\n\n    if (!isAdj[x][y]) return false;\n\n    r = {x, y};\n    return true;\n}\n\nvector<Op> localReduceOps(const vector<Op>& ops) {\n    vector<Op> st;\n    st.reserve(ops.size());\n\n    auto normalizeTail = [&]() {\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n            int n = (int)st.size();\n\n            if (n >= 2 && sameEdge(st[n - 1], st[n - 2])) {\n                st.pop_back();\n                st.pop_back();\n                changed = true;\n                continue;\n            }\n\n            n = (int)st.size();\n\n            if (n >= 3 && sameEdge(st[n - 1], st[n - 3])) {\n                Op r;\n                if (triangleReplace(st[n - 3], st[n - 2], r)) {\n                    st.pop_back();\n                    st.pop_back();\n                    st.pop_back();\n                    st.push_back(r);\n                    changed = true;\n                    continue;\n                }\n            }\n        }\n    };\n\n    for (auto op : ops) {\n        st.push_back(op);\n        normalizeTail();\n    }\n\n    return st;\n}\n\nvector<Op> reduceOps(vector<Op> ops) {\n    ops = localReduceOps(ops);\n\n    for (int pass = 0; pass < 3; pass++) {\n        vector<Op> st;\n        st.reserve(ops.size());\n\n        for (auto op : ops) {\n            bool cancelled = false;\n\n            for (int i = (int)st.size() - 1; i >= 0; i--) {\n                if (sameEdge(st[i], op)) {\n                    st.erase(st.begin() + i);\n                    cancelled = true;\n                    break;\n                }\n\n                if (shareVertex(st[i], op)) break;\n            }\n\n            if (!cancelled) st.push_back(op);\n        }\n\n        st = localReduceOps(st);\n\n        if (st.size() == ops.size()) {\n            ops = move(st);\n            break;\n        }\n\n        ops = move(st);\n    }\n\n    return ops;\n}\n\nbool validateOps(const vector<Op>& ops) {\n    if ((int)ops.size() > MAX_OPS) return false;\n\n    array<int, M> a = initialA;\n\n    for (auto [u, v] : ops) {\n        if (!isAdj[u][v]) return false;\n        swap(a[u], a[v]);\n    }\n\n    return isValidFinal(a);\n}\n\nvector<int> yOrder(int x, int type) {\n    vector<int> ys;\n    for (int y = 0; y <= x; y++) ys.push_back(y);\n\n    if (type == 1) {\n        reverse(ys.begin(), ys.end());\n    } else if (type == 2) {\n        if (x & 1) reverse(ys.begin(), ys.end());\n    } else if (type == 3) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da < db;\n            return a < b;\n        });\n    } else if (type == 4) {\n        sort(ys.begin(), ys.end(), [&](int a, int b) {\n            int da = abs(2 * a - x);\n            int db = abs(2 * b - x);\n            if (da != db) return da > db;\n            return a < b;\n        });\n    }\n\n    return ys;\n}\n\nState runHeapify(State s, int yType) {\n    for (int x = N - 2; x >= 0; x--) {\n        auto ys = yOrder(x, yType);\n\n        for (int sy : ys) {\n            int cur = ID[x][sy];\n\n            while (X[cur] + 1 < N) {\n                int cx = X[cur], cy = Y[cur];\n\n                int c1 = ID[cx + 1][cy];\n                int c2 = ID[cx + 1][cy + 1];\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[cur] > s.a[ch]) {\n                    applySwap(s, cur, ch);\n                    cur = ch;\n                } else {\n                    break;\n                }\n            }\n        }\n    }\n\n    return s;\n}\n\nint estimateSiftUpSteps(array<int, M> a, int u, int p, int val) {\n    swap(a[u], a[p]);\n\n    int cur = p;\n    int cnt = 1;\n\n    while (true) {\n        vector<int> cand;\n        for (int q : parentsOf(cur)) {\n            if (a[q] > val) cand.push_back(q);\n        }\n\n        if (cand.empty()) break;\n\n        int best = cand[0];\n        for (int q : cand) {\n            if (a[q] > a[best]) best = q;\n        }\n\n        swap(a[cur], a[best]);\n        cur = best;\n        cnt++;\n\n        if (cnt > N) break;\n    }\n\n    return cnt;\n}\n\nint exactMinSiftUpDistRec(const array<int, M>& a, int u, int val, array<int, M>& memo) {\n    if (memo[u] != -1) return memo[u];\n\n    int best = 1000000;\n\n    for (int p : parentsOf(u)) {\n        if (a[p] > val) {\n            best = min(best, 1 + exactMinSiftUpDistRec(a, p, val, memo));\n        }\n    }\n\n    if (best == 1000000) best = 0;\n    memo[u] = best;\n    return best;\n}\n\nint exactMinSiftUpDist(const array<int, M>& a, int u, int val) {\n    array<int, M> memo;\n    memo.fill(-1);\n    return exactMinSiftUpDistRec(a, u, val, memo);\n}\n\nint exactMaxSiftUpDistRec(const array<int, M>& a, int u, int val, array<int, M>& memo) {\n    if (memo[u] != -1) return memo[u];\n\n    int best = -1;\n\n    for (int p : parentsOf(u)) {\n        if (a[p] > val) {\n            best = max(best, 1 + exactMaxSiftUpDistRec(a, p, val, memo));\n        }\n    }\n\n    if (best == -1) best = 0;\n    memo[u] = best;\n    return best;\n}\n\nint exactMaxSiftUpDist(const array<int, M>& a, int u, int val) {\n    array<int, M> memo;\n    memo.fill(-1);\n    return exactMaxSiftUpDistRec(a, u, val, memo);\n}\n\nState runSiftUpByLabel(State s, int mode, int uptoLabel, int limitOps) {\n    array<int, M> pos;\n    for (int i = 0; i < M; i++) pos[s.a[i]] = i;\n\n    for (int val = 0; val < uptoLabel; val++) {\n        if ((int)s.ops.size() >= limitOps) break;\n\n        while ((int)s.ops.size() < limitOps) {\n            int u = pos[val];\n\n            vector<int> cand;\n            for (int p : parentsOf(u)) {\n                if (s.a[p] > val) cand.push_back(p);\n            }\n\n            if (cand.empty()) break;\n\n            int best = cand[0];\n            long long bestScore = LLONG_MIN;\n\n            for (int p : cand) {\n                int imp = deltaSwapLocal(s.a, u, p);\n                int est = 0, minDist = 0, maxDist = 0;\n\n                if (mode >= 5 && mode <= 9) {\n                    est = estimateSiftUpSteps(s.a, u, p, val);\n                }\n\n                if (mode >= 10) {\n                    minDist = exactMinSiftUpDist(s.a, p, val);\n                    maxDist = exactMaxSiftUpDist(s.a, p, val);\n                }\n\n                long long score = 0;\n\n                if (mode == 0) score = 100000LL * s.a[p] + imp;\n                else if (mode == 1) score = -100000LL * s.a[p] + imp;\n                else if (mode == 2) score = 100000LL * imp + s.a[p];\n                else if (mode == 3) score = -1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                else if (mode == 4) score = 1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                else if (mode == 5) score = -100000LL * est + 1000LL * imp + s.a[p];\n                else if (mode == 6) score = -100000LL * est + 1000LL * s.a[p] + imp;\n                else if (mode == 7) score = 100000LL * imp - 1000LL * est + s.a[p];\n                else if (mode == 8) score = 10000LL * s.a[p] - 1000LL * abs(2 * Y[p] - X[p]) - est;\n                else if (mode == 9) score = 10000LL * s.a[p] + 1000LL * abs(2 * Y[p] - X[p]) - est;\n                else if (mode == 10) score = -1000000LL * minDist + 1000LL * s.a[p] + imp;\n                else if (mode == 11) score = -1000000LL * minDist + 100000LL * imp + s.a[p];\n                else if (mode == 12) score = -1000000LL * minDist - 1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                else if (mode == 13) score = -1000000LL * minDist + 1000LL * abs(2 * Y[p] - X[p]) + s.a[p];\n                else score = 100000LL * maxDist + 1000LL * imp + s.a[p];\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = p;\n                }\n            }\n\n            applySwapWithPos(s, pos, u, best);\n        }\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nstruct BeamNode {\n    array<int, M> a;\n    array<int, M> pos;\n    vector<Op> ops;\n    int E;\n};\n\nvoid applyBeamSwap(BeamNode& b, int u, int v) {\n    b.E -= deltaSwapLocal(b.a, u, v);\n\n    int au = b.a[u];\n    int av = b.a[v];\n\n    swap(b.a[u], b.a[v]);\n    b.pos[au] = v;\n    b.pos[av] = u;\n    b.ops.push_back({u, v});\n}\n\nlong long beamKey(const BeamNode& b, int mode) {\n    long long k = 1000000LL * b.ops.size();\n\n    if (mode == 0) {\n        k += 2000LL * b.E + calcViolationDiffSum(b.a);\n    } else if (mode == 1) {\n        k += 20000LL * b.E;\n    } else if (mode == 2) {\n        k += 1000LL * b.E + 3LL * calcViolationDiffSum(b.a);\n    } else {\n        k += 5000LL * b.E - 2LL * calcViolationDiffSum(b.a);\n    }\n\n    return k;\n}\n\nvector<BeamNode> settleOneValueBeam(const BeamNode& src, int val, int localW, int limitOps, int mode) {\n    vector<BeamNode> cur = {src};\n    vector<BeamNode> done;\n\n    for (int depth = 0; depth < N && !cur.empty(); depth++) {\n        vector<BeamNode> nxt;\n\n        for (auto& node : cur) {\n            if ((int)node.ops.size() >= limitOps) continue;\n\n            int u = node.pos[val];\n\n            vector<int> cand;\n            for (int p : parentsOf(u)) {\n                if (node.a[p] > val) cand.push_back(p);\n            }\n\n            if (cand.empty()) {\n                done.push_back(node);\n                continue;\n            }\n\n            for (int p : cand) {\n                BeamNode nb = node;\n                applyBeamSwap(nb, u, p);\n                nxt.push_back(move(nb));\n            }\n        }\n\n        auto prune = [&](vector<BeamNode>& v, int w) {\n            sort(v.begin(), v.end(), [&](const BeamNode& a, const BeamNode& b) {\n                long long ka = beamKey(a, mode);\n                long long kb = beamKey(b, mode);\n                if (ka != kb) return ka < kb;\n                return a.ops.size() < b.ops.size();\n            });\n\n            if ((int)v.size() > w) v.resize(w);\n        };\n\n        prune(done, localW);\n        prune(nxt, localW);\n\n        cur.swap(nxt);\n    }\n\n    for (auto& node : cur) {\n        int u = node.pos[val];\n        bool ok = true;\n\n        for (int p : parentsOf(u)) {\n            if (node.a[p] > val) {\n                ok = false;\n                break;\n            }\n        }\n\n        if (ok) done.push_back(node);\n    }\n\n    sort(done.begin(), done.end(), [&](const BeamNode& a, const BeamNode& b) {\n        return beamKey(a, mode) < beamKey(b, mode);\n    });\n\n    if ((int)done.size() > localW) done.resize(localW);\n\n    return done;\n}\n\nvector<State> runBeamSiftUp(State base, int globalW, int localW, int mode, int limitOps, double deadline) {\n    BeamNode init;\n    init.a = base.a;\n    init.ops.clear();\n    init.E = base.E;\n\n    for (int i = 0; i < M; i++) init.pos[init.a[i]] = i;\n\n    vector<BeamNode> beam = {init};\n    int processed = 0;\n\n    for (int val = 0; val < M; val++) {\n        if (elapsedSec() > deadline) break;\n\n        vector<BeamNode> nb;\n\n        for (auto& node : beam) {\n            auto v = settleOneValueBeam(node, val, localW, limitOps, mode);\n            for (auto& x : v) nb.push_back(move(x));\n        }\n\n        if (nb.empty()) break;\n\n        sort(nb.begin(), nb.end(), [&](const BeamNode& a, const BeamNode& b) {\n            long long ka = beamKey(a, mode);\n            long long kb = beamKey(b, mode);\n            if (ka != kb) return ka < kb;\n            return a.ops.size() < b.ops.size();\n        });\n\n        if ((int)nb.size() > globalW) nb.resize(globalW);\n\n        beam.swap(nb);\n        processed = val + 1;\n    }\n\n    vector<State> res;\n\n    for (auto& b : beam) {\n        State s;\n        s.a = b.a;\n        s.ops = move(b.ops);\n        s.E = b.E;\n\n        if (processed < M && (int)s.ops.size() < limitOps) {\n            s = runSiftUpByLabel(s, 10, M, limitOps);\n        } else {\n            s.E = calcE(s.a);\n        }\n\n        res.push_back(move(s));\n    }\n\n    return res;\n}\n\nstruct RandSiftParam {\n    int wp, wi, wd, wc, noise;\n};\n\nState runRandomSiftUp(State s, RandSiftParam rp, uint32_t seed, int limitOps) {\n    RNG rng(seed);\n\n    array<int, M> pos;\n    for (int i = 0; i < M; i++) pos[s.a[i]] = i;\n\n    for (int val = 0; val < M; val++) {\n        if ((int)s.ops.size() >= limitOps) break;\n\n        while ((int)s.ops.size() < limitOps) {\n            int u = pos[val];\n\n            vector<int> cand;\n            for (int p : parentsOf(u)) {\n                if (s.a[p] > val) cand.push_back(p);\n            }\n\n            if (cand.empty()) break;\n\n            int best = cand[0];\n            long long bestScore = LLONG_MIN;\n\n            for (int p : cand) {\n                int imp = deltaSwapLocal(s.a, u, p);\n                int center = abs(2 * Y[p] - X[p]);\n\n                long long score = 0;\n                score += 1LL * rp.wp * s.a[p];\n                score += 1LL * rp.wi * imp;\n                score += 1LL * rp.wd * X[p];\n                score += 1LL * rp.wc * center;\n\n                if (rp.noise > 0) {\n                    score += rng.range(-rp.noise, rp.noise);\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = p;\n                }\n            }\n\n            applySwapWithPos(s, pos, u, best);\n        }\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nState runSiftDownByLabel(State s, int mode, int fromLabel, int limitOps) {\n    array<int, M> pos;\n    for (int i = 0; i < M; i++) pos[s.a[i]] = i;\n\n    for (int val = M - 1; val >= fromLabel; val--) {\n        if ((int)s.ops.size() >= limitOps) break;\n\n        while ((int)s.ops.size() < limitOps) {\n            int u = pos[val];\n\n            vector<int> cand;\n            for (int c : childrenOf(u)) {\n                if (s.a[c] < val) cand.push_back(c);\n            }\n\n            if (cand.empty()) break;\n\n            int best = cand[0];\n            long long bestScore = LLONG_MIN;\n\n            for (int c : cand) {\n                int imp = deltaSwapLocal(s.a, u, c);\n\n                long long score;\n\n                if (mode == 0) score = -100000LL * s.a[c] + imp;\n                else if (mode == 1) score = 100000LL * s.a[c] + imp;\n                else if (mode == 2) score = 100000LL * imp - s.a[c];\n                else if (mode == 3) score = -1000LL * abs(2 * Y[c] - X[c]) - s.a[c];\n                else score = 1000LL * abs(2 * Y[c] - X[c]) - s.a[c];\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = c;\n                }\n            }\n\n            applySwapWithPos(s, pos, u, best);\n        }\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nstruct GreedyParam {\n    int wImp, wDiff, wChild, wParent, wDepth, wCenter, noise;\n};\n\nState runWeightedViolationGreedy(State s, GreedyParam gp, int seed, int limitOps) {\n    int step = 0;\n\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        int bu = -1, bv = -1;\n        long long bestScore = LLONG_MIN;\n\n        for (int ei = 0; ei < (int)downEdges.size(); ei++) {\n            auto [p, c] = downEdges[ei];\n\n            if (s.a[p] <= s.a[c]) continue;\n\n            int imp = deltaSwapLocal(s.a, p, c);\n            int diff = s.a[p] - s.a[c];\n            int center = abs(2 * Y[c] - X[c]);\n\n            long long score = 0;\n            score += 1LL * gp.wImp * imp;\n            score += 1LL * gp.wDiff * diff;\n            score += 1LL * gp.wChild * s.a[c];\n            score += 1LL * gp.wParent * s.a[p];\n            score += 1LL * gp.wDepth * X[p];\n            score += 1LL * gp.wCenter * center;\n\n            if (gp.noise > 0) {\n                uint32_t h = splitmix32(seed ^ (step * 1009u) ^ (ei * 9176u));\n                score += (int)(h % (2 * gp.noise + 1)) - gp.noise;\n            }\n\n            if (score > bestScore) {\n                bestScore = score;\n                bu = p;\n                bv = c;\n            }\n        }\n\n        if (bu == -1) break;\n\n        applySwap(s, bu, bv);\n        step++;\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nState runScanBubble(State s, int rowType, int yType, int limitOps) {\n    while (s.E > 0 && (int)s.ops.size() < limitOps) {\n        bool changed = false;\n\n        vector<int> rows;\n        if (rowType == 0) {\n            for (int x = N - 2; x >= 0; x--) rows.push_back(x);\n        } else {\n            for (int x = 0; x <= N - 2; x++) rows.push_back(x);\n        }\n\n        for (int x : rows) {\n            auto ys = yOrder(x, yType);\n\n            for (int y : ys) {\n                if ((int)s.ops.size() >= limitOps) break;\n\n                int p = ID[x][y];\n                int c1 = ID[x + 1][y];\n                int c2 = ID[x + 1][y + 1];\n\n                int ch = (s.a[c1] < s.a[c2] ? c1 : c2);\n\n                if (s.a[p] > s.a[ch]) {\n                    applySwap(s, p, ch);\n                    changed = true;\n                }\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nint encodePerm(const vector<int>& p, int base) {\n    int code = 0;\n    int mul = 1;\n\n    for (int x : p) {\n        code += x * mul;\n        mul *= base;\n    }\n\n    return code;\n}\n\nvector<int> decodePerm(int code, int k) {\n    vector<int> p(k);\n\n    for (int i = 0; i < k; i++) {\n        p[i] = code % k;\n        code /= k;\n    }\n\n    return p;\n}\n\nbool shortestReplacementBlock(const vector<Op>& ops, int l, int len, vector<Op>& rep) {\n    vector<int> verts;\n\n    auto addv = [&](int v) {\n        for (int x : verts) if (x == v) return;\n        verts.push_back(v);\n    };\n\n    for (int i = 0; i < len; i++) {\n        addv(ops[l + i].u);\n        addv(ops[l + i].v);\n    }\n\n    int k = (int)verts.size();\n    if (k > 7) return false;\n\n    int idx[M];\n    fill(idx, idx + M, -1);\n\n    for (int i = 0; i < k; i++) idx[verts[i]] = i;\n\n    vector<pair<int,int>> edges;\n\n    for (int i = 0; i < k; i++) {\n        for (int j = i + 1; j < k; j++) {\n            if (isAdj[verts[i]][verts[j]]) {\n                edges.push_back({i, j});\n            }\n        }\n    }\n\n    vector<int> target(k);\n    iota(target.begin(), target.end(), 0);\n\n    for (int i = 0; i < len; i++) {\n        int a = idx[ops[l + i].u];\n        int b = idx[ops[l + i].v];\n        swap(target[a], target[b]);\n    }\n\n    vector<int> start(k);\n    iota(start.begin(), start.end(), 0);\n\n    int startCode = encodePerm(start, k);\n    int targetCode = encodePerm(target, k);\n\n    if (startCode == targetCode) {\n        rep.clear();\n        return true;\n    }\n\n    int depthLimit = len - 1;\n\n    queue<int> q;\n    unordered_map<int, int> dist;\n    unordered_map<int, int> parent;\n    unordered_map<int, int> parentEdge;\n\n    dist.reserve(4096);\n    parent.reserve(4096);\n    parentEdge.reserve(4096);\n\n    dist[startCode] = 0;\n    parent[startCode] = -1;\n    q.push(startCode);\n\n    bool found = false;\n\n    while (!q.empty()) {\n        int code = q.front();\n        q.pop();\n\n        int d = dist[code];\n        if (d >= depthLimit) continue;\n\n        vector<int> p = decodePerm(code, k);\n\n        for (int ei = 0; ei < (int)edges.size(); ei++) {\n            auto [a, b] = edges[ei];\n\n            vector<int> np = p;\n            swap(np[a], np[b]);\n\n            int nc = encodePerm(np, k);\n            if (dist.count(nc)) continue;\n\n            dist[nc] = d + 1;\n            parent[nc] = code;\n            parentEdge[nc] = ei;\n\n            if (nc == targetCode) {\n                found = true;\n                q = queue<int>();\n                break;\n            }\n\n            q.push(nc);\n        }\n    }\n\n    if (!found && !dist.count(targetCode)) return false;\n    if (dist[targetCode] >= len) return false;\n\n    vector<Op> rev;\n\n    int cur = targetCode;\n    while (cur != startCode) {\n        int ei = parentEdge[cur];\n        auto [a, b] = edges[ei];\n        rev.push_back({verts[a], verts[b]});\n        cur = parent[cur];\n    }\n\n    reverse(rev.begin(), rev.end());\n    rep = move(rev);\n\n    return true;\n}\n\nvector<Op> peepholeOptimize(vector<Op> ops, double deadline) {\n    ops = reduceOps(ops);\n\n    int i = 0;\n\n    while (i < (int)ops.size() && elapsedSec() < deadline) {\n        bool changed = false;\n\n        int maxLen = min(8, (int)ops.size() - i);\n\n        for (int len = maxLen; len >= 3; len--) {\n            vector<Op> rep;\n\n            if (shortestReplacementBlock(ops, i, len, rep) && (int)rep.size() < len) {\n                ops.erase(ops.begin() + i, ops.begin() + i + len);\n                ops.insert(ops.begin() + i, rep.begin(), rep.end());\n\n                i = max(0, i - 8);\n                changed = true;\n                break;\n            }\n        }\n\n        if (!changed) i++;\n    }\n\n    return reduceOps(ops);\n}\n\nbool validWithoutRange(const vector<Op>& ops, int l, int r) {\n    array<int, M> a = initialA;\n\n    for (int i = 0; i < (int)ops.size(); i++) {\n        if (l <= i && i < r) continue;\n        swap(a[ops[i].u], a[ops[i].v]);\n    }\n\n    return isValidFinal(a);\n}\n\nvector<Op> tinyDeletionPrune(vector<Op> ops, double deadline) {\n    ops = reduceOps(ops);\n\n    if (!validateOps(ops)) return ops;\n\n    for (int len : {1, 2}) {\n        for (int i = 0; i + len <= (int)ops.size();) {\n            if (elapsedSec() > deadline) break;\n\n            if (validWithoutRange(ops, i, i + len)) {\n                ops.erase(ops.begin() + i, ops.begin() + i + len);\n                ops = reduceOps(ops);\n                i = max(0, i - 3);\n            } else {\n                i++;\n            }\n        }\n    }\n\n    return reduceOps(ops);\n}\n\nState stateFromPrefix(const vector<Op>& ops, int cut) {\n    State s;\n    s.a = initialA;\n    s.ops.clear();\n    s.ops.reserve(cut);\n\n    for (int i = 0; i < cut; i++) {\n        auto [u, v] = ops[i];\n        swap(s.a[u], s.a[v]);\n        s.ops.push_back({u, v});\n    }\n\n    s.E = calcE(s.a);\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    int id = 0;\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            ID[x][y] = id;\n            X[id] = x;\n            Y[id] = y;\n            id++;\n        }\n    }\n\n    incidentDown.assign(M, {});\n    memset(isAdj, 0, sizeof(isAdj));\n\n    auto addAdj = [&](int u, int v) {\n        isAdj[u][v] = isAdj[v][u] = true;\n    };\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            int u = ID[x][y];\n\n            if (y + 1 <= x) {\n                int v = ID[x][y + 1];\n                addAdj(u, v);\n            }\n\n            if (x + 1 < N) {\n                int v1 = ID[x + 1][y];\n                int v2 = ID[x + 1][y + 1];\n\n                addAdj(u, v1);\n                addAdj(u, v2);\n\n                int e1 = (int)downEdges.size();\n                downEdges.push_back({u, v1});\n                incidentDown[u].push_back(e1);\n                incidentDown[v1].push_back(e1);\n\n                int e2 = (int)downEdges.size();\n                downEdges.push_back({u, v2});\n                incidentDown[u].push_back(e2);\n                incidentDown[v2].push_back(e2);\n            }\n        }\n    }\n\n    uint32_t inputSeed = 1234567;\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> initialA[ID[x][y]];\n            inputSeed = inputSeed * 1000003u + initialA[ID[x][y]] + 97u;\n        }\n    }\n\n    State base;\n    base.a = initialA;\n    base.E = calcE(initialA);\n\n    vector<Op> bestOps;\n    vector<vector<Op>> candidatePool;\n    bool haveBest = false;\n\n    auto addPool = [&](const vector<Op>& ops) {\n        if (!haveBest) return;\n        if ((int)ops.size() > (int)bestOps.size() + 120) return;\n\n        candidatePool.push_back(ops);\n\n        sort(candidatePool.begin(), candidatePool.end(), [](const vector<Op>& a, const vector<Op>& b) {\n            return a.size() < b.size();\n        });\n\n        vector<vector<Op>> np;\n        np.reserve(14);\n\n        for (auto& v : candidatePool) {\n            bool dup = false;\n\n            for (auto& u : np) {\n                if (u.size() != v.size()) continue;\n                if (u == v) {\n                    dup = true;\n                    break;\n                }\n            }\n\n            if (!dup) np.push_back(move(v));\n            if ((int)np.size() >= 14) break;\n        }\n\n        candidatePool.swap(np);\n    };\n\n    auto tryCandidate = [&](const State& s) {\n        if (s.E != 0) return;\n\n        vector<Op> ops = reduceOps(s.ops);\n\n        if ((int)ops.size() > MAX_OPS) return;\n        if (!validateOps(ops)) return;\n\n        if (!haveBest || ops.size() < bestOps.size()) {\n            bestOps = ops;\n            haveBest = true;\n        }\n\n        addPool(ops);\n    };\n\n    auto makeLimit = [&](int margin) {\n        if (!haveBest) return MAX_OPS;\n        return min(MAX_OPS, (int)bestOps.size() + margin);\n    };\n\n    // 1. Safe heapify fallback.\n    for (int t = 0; t < 5; t++) {\n        State s = runHeapify(base, t);\n        tryCandidate(s);\n    }\n\n    if (!haveBest) {\n        State s = runHeapify(base, 0);\n        bestOps = reduceOps(s.ops);\n        haveBest = true;\n        addPool(bestOps);\n    }\n\n    // 2. Deterministic sift-up candidates.\n    if (elapsedSec() < 0.90) {\n        for (int mode = 0; mode < 15; mode++) {\n            if (elapsedSec() > 1.18) break;\n\n            State s = runSiftUpByLabel(base, mode, M, makeLimit(100));\n            tryCandidate(s);\n        }\n    }\n\n    // 3. Beam sift-up.\n    if (elapsedSec() < 1.18) {\n        for (int mode = 0; mode < 4; mode++) {\n            if (elapsedSec() > 1.44) break;\n\n            auto states = runBeamSiftUp(base, 4, 4, mode, makeLimit(100), 1.44);\n\n            for (auto& s : states) tryCandidate(s);\n        }\n    }\n\n    // 4. Randomized sift-up candidates.\n    vector<RandSiftParam> rparams = {\n        {100000, 1000, 0, 0, 50000},\n        {100000, 3000, 0, -1000, 80000},\n        {100000, 3000, 0, 1000, 80000},\n        {50000, 10000, 0, 0, 100000},\n        {10000, 50000, 0, 0, 100000},\n        {100000, 1000, -500, 0, 60000},\n        {100000, 1000, 500, 0, 60000},\n        {-100000, 1000, 0, 0, 80000},\n        {70000, 5000, -500, -500, 120000},\n        {70000, 5000, 500, 500, 120000},\n        {30000, 30000, 0, -2000, 150000},\n        {30000, 30000, 0, 2000, 150000},\n        {120000, 2000, -1000, 0, 90000},\n        {120000, 2000, 1000, 0, 90000},\n        {40000, 40000, -500, -1500, 180000},\n        {40000, 40000, 500, 1500, 180000}\n    };\n\n    if (elapsedSec() < 1.44) {\n        int run = 0;\n\n        while (elapsedSec() < 1.63) {\n            RandSiftParam rp = rparams[run % rparams.size()];\n            uint32_t seed = splitmix32(inputSeed + 19260817u * run + 998244353u);\n\n            State s = runRandomSiftUp(base, rp, seed, makeLimit(120));\n            tryCandidate(s);\n\n            run++;\n            if (run >= 48) break;\n        }\n    }\n\n    // 5. Large-label sift-down candidates.\n    if (elapsedSec() < 1.63) {\n        for (int mode = 0; mode < 5; mode++) {\n            if (elapsedSec() > 1.70) break;\n\n            State s = runSiftDownByLabel(base, mode, 0, makeLimit(80));\n            tryCandidate(s);\n        }\n    }\n\n    // 6. Weighted global greedy.\n    vector<GreedyParam> params = {\n        {100000, 100, -10, 10, 0, 0, 0},\n        {100000, 10, -100, 20, 0, 0, 0},\n        {50000, 200, -50, 50, 0, 0, 0},\n        {10000, 1000, 0, 0, 0, 0, 0},\n        {10000, 100, -1000, 0, 0, 0, 0},\n        {10000, 100, 0, 1000, 0, 0, 0},\n        {100000, 50, -20, 20, -100, 0, 0},\n        {100000, 50, -20, 20, 100, 0, 0},\n        {100000, 50, -20, 20, 0, -100, 0},\n        {100000, 50, -20, 20, 0, 100, 0},\n        {50000, 100, -100, 100, -50, -50, 200},\n        {50000, 100, -100, 100, 50, 50, 200},\n        {20000, 500, -200, 50, 0, -100, 300},\n        {20000, 500, -50, 200, 0, 100, 300},\n        {100000, 0, -1000, 1000, 0, 0, 500},\n        {80000, 300, -300, 300, -100, 0, 500},\n        {80000, 300, -300, 300, 100, 0, 500},\n        {80000, 300, -300, 300, 0, -100, 500},\n        {80000, 300, -300, 300, 0, 100, 500},\n        {120000, 0, -500, 500, -200, -100, 1000},\n        {120000, 0, -500, 500, 200, 100, 1000},\n        {30000, 1000, -500, 500, 0, 0, 1000}\n    };\n\n    if (elapsedSec() < 1.70) {\n        for (int i = 0; i < (int)params.size(); i++) {\n            if (elapsedSec() > 1.82) break;\n\n            State s = runWeightedViolationGreedy(base, params[i], inputSeed + i * 19260817u, makeLimit(80));\n            tryCandidate(s);\n        }\n    }\n\n    // 7. Prefix sift-up followed by heapify.\n    if (elapsedSec() < 1.82) {\n        vector<int> prefixes = {10, 20, 40, 70, 100, 150, 220, 300};\n\n        for (int p : prefixes) {\n            if (elapsedSec() > 1.89) break;\n\n            for (int mode = 0; mode < 8; mode++) {\n                if (elapsedSec() > 1.91) break;\n\n                State pre = runSiftUpByLabel(base, mode, p, makeLimit(80));\n\n                if ((int)pre.ops.size() >= makeLimit(80)) continue;\n\n                for (int t = 0; t < 5; t++) {\n                    if (elapsedSec() > 1.93) break;\n\n                    State s = runHeapify(pre, t);\n                    tryCandidate(s);\n                }\n            }\n        }\n    }\n\n    // 8. Scan bubble fallback.\n    if (elapsedSec() < 1.90) {\n        for (int rowType = 0; rowType < 2; rowType++) {\n            for (int yType = 0; yType < 5; yType++) {\n                if (elapsedSec() > 1.935) break;\n\n                State s = runScanBubble(base, rowType, yType, makeLimit(60));\n                tryCandidate(s);\n            }\n        }\n    }\n\n    // 9. Stronger suffix re-optimization.\n    if (elapsedSec() < 1.935) {\n        vector<vector<Op>> suffixSources;\n        suffixSources.push_back(bestOps);\n\n        sort(candidatePool.begin(), candidatePool.end(), [](const vector<Op>& a, const vector<Op>& b) {\n            return a.size() < b.size();\n        });\n\n        for (int i = 0; i < (int)candidatePool.size() && (int)suffixSources.size() < 4; i++) {\n            if ((int)candidatePool[i].size() <= (int)bestOps.size() + 80) {\n                suffixSources.push_back(candidatePool[i]);\n            }\n        }\n\n        vector<int> backsMain = {20, 40, 70, 110, 160, 240, 340, 480};\n        vector<int> backsSub = {60, 140, 260, 420};\n\n        int sourceId = 0;\n\n        for (const auto& srcOps : suffixSources) {\n            if (elapsedSec() > 1.965) break;\n\n            const vector<int>& backs = (sourceId == 0 ? backsMain : backsSub);\n\n            for (int back : backs) {\n                if (elapsedSec() > 1.965) break;\n                if ((int)srcOps.size() <= back + 5) continue;\n\n                int cut = (int)srcOps.size() - back;\n                State pref = stateFromPrefix(srcOps, cut);\n\n                for (int t = 0; t < 5; t++) {\n                    if (elapsedSec() > 1.967) break;\n\n                    State s = runHeapify(pref, t);\n                    tryCandidate(s);\n                }\n\n                if (elapsedSec() < 1.967) {\n                    State s = runSiftUpByLabel(pref, 10, M, makeLimit(80));\n                    tryCandidate(s);\n                }\n\n                if (sourceId == 0 && elapsedSec() < 1.967) {\n                    State s = runSiftUpByLabel(pref, 2, M, makeLimit(80));\n                    tryCandidate(s);\n                }\n            }\n\n            sourceId++;\n        }\n    }\n\n    // 10. Final compression of near-best candidates.\n    addPool(bestOps);\n\n    sort(candidatePool.begin(), candidatePool.end(), [](const vector<Op>& a, const vector<Op>& b) {\n        return a.size() < b.size();\n    });\n\n    int checked = 0;\n\n    for (auto cand : candidatePool) {\n        if (elapsedSec() > 1.965) break;\n        if (checked >= 6) break;\n        if ((int)cand.size() > (int)bestOps.size() + 80) continue;\n\n        double dl1 = min(1.975, elapsedSec() + (checked == 0 ? 0.030 : 0.012));\n        vector<Op> opt = peepholeOptimize(cand, dl1);\n\n        if ((int)opt.size() <= MAX_OPS && opt.size() < bestOps.size() && validateOps(opt)) {\n            bestOps = opt;\n        }\n\n        if (elapsedSec() < 1.982) {\n            double dl2 = min(1.988, elapsedSec() + 0.008);\n            vector<Op> opt2 = tinyDeletionPrune(opt, dl2);\n\n            if ((int)opt2.size() <= MAX_OPS && opt2.size() < bestOps.size() && validateOps(opt2)) {\n                bestOps = move(opt2);\n            }\n        }\n\n        checked++;\n    }\n\n    // 11. Last cleanup on selected answer.\n    if (elapsedSec() < 1.965) {\n        vector<Op> opt = peepholeOptimize(bestOps, 1.982);\n        if ((int)opt.size() <= MAX_OPS && opt.size() < bestOps.size() && validateOps(opt)) {\n            bestOps = move(opt);\n        }\n    }\n\n    if (elapsedSec() < 1.982) {\n        vector<Op> opt = tinyDeletionPrune(bestOps, 1.992);\n        if ((int)opt.size() <= MAX_OPS && opt.size() < bestOps.size() && validateOps(opt)) {\n            bestOps = move(opt);\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n\n    for (auto [u, v] : bestOps) {\n        cout << X[u] << ' ' << Y[u] << ' ' << X[v] << ' ' << Y[v] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint D, N;\nint ENT;\nvector<int> freeIds;\nbool obstacleCell[100];\nint labelAt[100];\nint rankOfCell[100];\nbool usedLabel[100];\n\nint nb[100][4];\nint nbcnt[100];\n\nchrono::steady_clock::time_point START_TIME;\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nint id_of(int r, int c) {\n    return r * D + c;\n}\n\npair<int,int> rc_of(int id) {\n    return {id / D, id % D};\n}\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nint elapsed_ms() {\n    auto now = chrono::steady_clock::now();\n    return (int)chrono::duration_cast<chrono::milliseconds>(now - START_TIME).count();\n}\n\nbool time_over(int ms) {\n    return elapsed_ms() >= ms;\n}\n\nvoid build_neighbors() {\n    for (int id = 0; id < D * D; id++) {\n        auto [r, c] = rc_of(id);\n        nbcnt[id] = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc)) {\n                nb[id][nbcnt[id]++] = id_of(nr, nc);\n            }\n        }\n    }\n}\n\ninline void set_bit(ull &lo, ull &hi, int x) {\n    if (x < 64) lo |= 1ULL << x;\n    else hi |= 1ULL << (x - 64);\n}\n\ninline int popcnt2(ull lo, ull hi) {\n    return __builtin_popcountll(lo) + __builtin_popcountll(hi);\n}\n\nstatic inline uint64_t splitmix64(uint64_t x) {\n    x += 0x9e3779b97f4a7c15ULL;\n    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;\n    x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;\n    return x ^ (x >> 31);\n}\n\nstruct FlatHash {\n    int cap, mask;\n    vector<ull> loKey, hiKey;\n    vector<int> val;\n\n    FlatHash(int need = 1) {\n        cap = 1;\n        while (cap < need) cap <<= 1;\n        mask = cap - 1;\n        loKey.assign(cap, 0);\n        hiKey.assign(cap, 0);\n        val.assign(cap, -1);\n    }\n\n    void clear() {\n        fill(val.begin(), val.end(), -1);\n    }\n\n    int find_or_insert(ull lo, ull hi, int insertValue, bool &inserted) {\n        uint64_t h = splitmix64(lo ^ splitmix64(hi + 0x9e3779b97f4a7c15ULL));\n        int p = (int)(h & mask);\n\n        while (true) {\n            if (val[p] == -1) {\n                loKey[p] = lo;\n                hiKey[p] = hi;\n                val[p] = insertValue;\n                inserted = true;\n                return insertValue;\n            }\n            if (loKey[p] == lo && hiKey[p] == hi) {\n                inserted = false;\n                return val[p];\n            }\n            p = (p + 1) & mask;\n        }\n    }\n};\n\nbool legal_fill(int cand) {\n    int totalEmptyAfter = 0;\n    for (int id : freeIds) {\n        if (id != cand && labelAt[id] == -1) totalEmptyAfter++;\n    }\n\n    bool vis[100] = {};\n    int que[100];\n    int head = 0, tail = 0;\n\n    vis[ENT] = true;\n    que[tail++] = ENT;\n\n    int reached = 0;\n\n    while (head < tail) {\n        int v = que[head++];\n\n        for (int z = 0; z < nbcnt[v]; z++) {\n            int to = nb[v][z];\n            if (vis[to]) continue;\n            if (obstacleCell[to]) continue;\n            if (to == cand) continue;\n            if (to != ENT && labelAt[to] != -1) continue;\n\n            vis[to] = true;\n            que[tail++] = to;\n            if (to != ENT) reached++;\n        }\n    }\n\n    return reached == totalEmptyAfter;\n}\n\ninline bool is_accessible_container(int id, const bool emptyCell[]) {\n    for (int z = 0; z < nbcnt[id]; z++) {\n        if (emptyCell[nb[id][z]]) return true;\n    }\n    return false;\n}\n\nint evaluate_candidate(\n    int cand,\n    int t,\n    const vector<int>& emptySorted,\n    const vector<int>& remLabels\n) {\n    int val[100];\n    fill(val, val + 100, -1);\n\n    for (int id : freeIds) {\n        if (labelAt[id] >= 0) val[id] = labelAt[id];\n    }\n    val[cand] = t;\n\n    int p = 0;\n    for (int id : emptySorted) {\n        if (id == cand) continue;\n        val[id] = remLabels[p++];\n    }\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    int seq[100];\n    int M = (int)freeIds.size();\n\n    for (int step = 0; step < M; step++) {\n        int best = -1;\n        int bestVal = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (val[id] < bestVal ||\n                (val[id] == bestVal && (best == -1 || rankOfCell[id] < rankOfCell[best]))) {\n                bestVal = val[id];\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    bestVal = val[id];\n                    break;\n                }\n            }\n        }\n\n        seq[step] = bestVal;\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    int inv = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (seq[i] > seq[j]) inv++;\n        }\n    }\n    return inv;\n}\n\nstruct BeamState {\n    ull lo, hi;\n    ull flo, fhi;\n    int cost;\n    int prev;\n    int add;\n    int score;\n};\n\nstruct SmallBeamState {\n    ull lo, hi;\n    ull flo, fhi;\n    int cost;\n    int score;\n};\n\nint beam_estimate_cost_with_values(const int cellVal[100], int WIDTH) {\n    int M = (int)freeIds.size();\n\n    vector<int> idToIdx(D * D, -1);\n    for (int i = 0; i < M; i++) idToIdx[freeIds[i]] = i;\n\n    vector<int> lab(M);\n    for (int i = 0; i < M; i++) lab[i] = cellVal[freeIds[i]];\n\n    vector<ull> adjLo(M, 0), adjHi(M, 0);\n    ull initLo = 0, initHi = 0;\n\n    for (int i = 0; i < M; i++) {\n        int id = freeIds[i];\n\n        for (int z = 0; z < nbcnt[id]; z++) {\n            int to = nb[id][z];\n\n            if (to == ENT) {\n                set_bit(initLo, initHi, i);\n            } else if (idToIdx[to] != -1) {\n                set_bit(adjLo[i], adjHi[i], idToIdx[to]);\n            }\n        }\n    }\n\n    vector<ull> lessLo(M, 0), lessHi(M, 0);\n    for (int x = 0; x < M; x++) {\n        ull lo = 0, hi = 0;\n        for (int i = 0; i < M; i++) {\n            if (lab[i] < x) set_bit(lo, hi, i);\n        }\n        lessLo[x] = lo;\n        lessHi[x] = hi;\n    }\n\n    auto calc_score = [&](int cost, ull flo, ull fhi) {\n        int mn1 = 100, mn2 = 100;\n\n        ull b = flo;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int x = lab[t];\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n            b &= b - 1;\n        }\n\n        b = fhi;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int idx = 64 + t;\n            int x = lab[idx];\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n            b &= b - 1;\n        }\n\n        return cost * 10000 + mn1 * 100 + mn2;\n    };\n\n    vector<SmallBeamState> cur, nxt;\n    cur.reserve(WIDTH);\n    nxt.reserve(WIDTH * 20);\n\n    SmallBeamState st;\n    st.lo = st.hi = 0;\n    st.flo = initLo;\n    st.fhi = initHi;\n    st.cost = 0;\n    st.score = calc_score(0, initLo, initHi);\n    cur.push_back(st);\n\n    FlatHash fmap(WIDTH * 64);\n\n    for (int depth = 0; depth < M; depth++) {\n        nxt.clear();\n        fmap.clear();\n\n        for (int pi = 0; pi < (int)cur.size(); pi++) {\n            const auto& s = cur[pi];\n\n            auto expand_one = [&](int idx) {\n                ull bitLo = 0, bitHi = 0;\n                set_bit(bitLo, bitHi, idx);\n\n                ull nlo = s.lo | bitLo;\n                ull nhi = s.hi | bitHi;\n\n                int label = lab[idx];\n                int removedLess = popcnt2(s.lo & lessLo[label], s.hi & lessHi[label]);\n                int ncost = s.cost + label - removedLess;\n\n                ull nflo = ((s.flo & ~bitLo) | adjLo[idx]) & ~nlo;\n                ull nfhi = ((s.fhi & ~bitHi) | adjHi[idx]) & ~nhi;\n\n                SmallBeamState ns;\n                ns.lo = nlo;\n                ns.hi = nhi;\n                ns.flo = nflo;\n                ns.fhi = nfhi;\n                ns.cost = ncost;\n                ns.score = calc_score(ncost, nflo, nfhi);\n\n                bool inserted;\n                int pos = fmap.find_or_insert(nlo, nhi, (int)nxt.size(), inserted);\n\n                if (inserted) {\n                    nxt.push_back(ns);\n                } else if (ns.cost < nxt[pos].cost ||\n                           (ns.cost == nxt[pos].cost && ns.score < nxt[pos].score)) {\n                    nxt[pos] = ns;\n                }\n            };\n\n            ull b = s.flo;\n            while (b) {\n                int idx = __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n\n            b = s.fhi;\n            while (b) {\n                int idx = 64 + __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n        }\n\n        if ((int)nxt.size() > WIDTH) {\n            nth_element(\n                nxt.begin(),\n                nxt.begin() + WIDTH,\n                nxt.end(),\n                [](const SmallBeamState& a, const SmallBeamState& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.cost < b.cost;\n                }\n            );\n            nxt.resize(WIDTH);\n        }\n\n        cur.swap(nxt);\n    }\n\n    int best = INT_MAX;\n    for (auto& s : cur) best = min(best, s.cost);\n    return best;\n}\n\nint evaluate_candidate_beam_late(\n    int cand,\n    int t,\n    const vector<int>& emptySorted,\n    const vector<int>& remLabels,\n    int width\n) {\n    int val[100];\n    fill(val, val + 100, -1);\n\n    for (int id : freeIds) {\n        if (labelAt[id] >= 0) val[id] = labelAt[id];\n    }\n    val[cand] = t;\n\n    int p = 0;\n    for (int id : emptySorted) {\n        if (id == cand) continue;\n        val[id] = remLabels[p++];\n    }\n\n    return beam_estimate_cost_with_values(val, width);\n}\n\nvector<int> greedy_removal_order() {\n    int M = (int)freeIds.size();\n\n    bool emptyCell[100] = {};\n    bool occ[100] = {};\n\n    emptyCell[ENT] = true;\n    for (int id : freeIds) occ[id] = true;\n\n    vector<int> order;\n    order.reserve(M);\n\n    for (int step = 0; step < M; step++) {\n        int best = -1;\n        int bestLabel = 1e9;\n\n        for (int id : freeIds) {\n            if (!occ[id]) continue;\n            if (!is_accessible_container(id, emptyCell)) continue;\n\n            if (labelAt[id] < bestLabel) {\n                bestLabel = labelAt[id];\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id : freeIds) {\n                if (occ[id]) {\n                    best = id;\n                    break;\n                }\n            }\n        }\n\n        order.push_back(best);\n        occ[best] = false;\n        emptyCell[best] = true;\n    }\n\n    return order;\n}\n\nint inversion_count_of_order(const vector<int>& order) {\n    int M = (int)order.size();\n    int inv = 0;\n    for (int i = 0; i < M; i++) {\n        for (int j = i + 1; j < M; j++) {\n            if (labelAt[order[i]] > labelAt[order[j]]) inv++;\n        }\n    }\n    return inv;\n}\n\nvector<int> beam_removal_order(int WIDTH) {\n    int M = (int)freeIds.size();\n\n    vector<int> idToIdx(D * D, -1);\n    vector<int> idxToId(M);\n\n    for (int i = 0; i < M; i++) {\n        idToIdx[freeIds[i]] = i;\n        idxToId[i] = freeIds[i];\n    }\n\n    vector<int> lab(M);\n    for (int i = 0; i < M; i++) {\n        lab[i] = labelAt[idxToId[i]];\n    }\n\n    vector<ull> adjLo(M, 0), adjHi(M, 0);\n    ull initLo = 0, initHi = 0;\n\n    for (int i = 0; i < M; i++) {\n        int id = idxToId[i];\n\n        for (int z = 0; z < nbcnt[id]; z++) {\n            int to = nb[id][z];\n\n            if (to == ENT) {\n                set_bit(initLo, initHi, i);\n            } else if (idToIdx[to] != -1) {\n                int j = idToIdx[to];\n                set_bit(adjLo[i], adjHi[i], j);\n            }\n        }\n    }\n\n    vector<ull> lessLo(M, 0), lessHi(M, 0);\n\n    for (int x = 0; x < M; x++) {\n        ull lo = 0, hi = 0;\n        for (int i = 0; i < M; i++) {\n            if (lab[i] < x) set_bit(lo, hi, i);\n        }\n        lessLo[x] = lo;\n        lessHi[x] = hi;\n    }\n\n    auto calc_score = [&](int cost, ull flo, ull fhi) {\n        int mn1 = 100, mn2 = 100;\n\n        ull b = flo;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int x = lab[t];\n\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n\n            b &= b - 1;\n        }\n\n        b = fhi;\n        while (b) {\n            int t = __builtin_ctzll(b);\n            int idx = 64 + t;\n            int x = lab[idx];\n\n            if (x < mn1) {\n                mn2 = mn1;\n                mn1 = x;\n            } else if (x < mn2) {\n                mn2 = x;\n            }\n\n            b &= b - 1;\n        }\n\n        return cost * 10000 + mn1 * 100 + mn2;\n    };\n\n    vector<vector<BeamState>> layers;\n    layers.reserve(M + 1);\n\n    BeamState start;\n    start.lo = start.hi = 0;\n    start.flo = initLo;\n    start.fhi = initHi;\n    start.cost = 0;\n    start.prev = -1;\n    start.add = -1;\n    start.score = calc_score(0, initLo, initHi);\n\n    layers.push_back(vector<BeamState>{start});\n\n    FlatHash fmap(WIDTH * 80);\n\n    for (int depth = 0; depth < M; depth++) {\n        vector<BeamState>& cur = layers.back();\n\n        vector<BeamState> nxt;\n        nxt.reserve(min((int)cur.size() * 24, WIDTH * 55));\n\n        fmap.clear();\n\n        for (int pi = 0; pi < (int)cur.size(); pi++) {\n            const BeamState& s = cur[pi];\n\n            auto expand_one = [&](int idx) {\n                ull bitLo = 0, bitHi = 0;\n                set_bit(bitLo, bitHi, idx);\n\n                ull nlo = s.lo | bitLo;\n                ull nhi = s.hi | bitHi;\n\n                int label = lab[idx];\n                int removedLess = popcnt2(s.lo & lessLo[label], s.hi & lessHi[label]);\n                int ncost = s.cost + label - removedLess;\n\n                ull nflo = ((s.flo & ~bitLo) | adjLo[idx]) & ~nlo;\n                ull nfhi = ((s.fhi & ~bitHi) | adjHi[idx]) & ~nhi;\n\n                BeamState ns;\n                ns.lo = nlo;\n                ns.hi = nhi;\n                ns.flo = nflo;\n                ns.fhi = nfhi;\n                ns.cost = ncost;\n                ns.prev = pi;\n                ns.add = idx;\n                ns.score = calc_score(ncost, nflo, nfhi);\n\n                bool inserted;\n                int pos = fmap.find_or_insert(nlo, nhi, (int)nxt.size(), inserted);\n\n                if (inserted) {\n                    nxt.push_back(ns);\n                } else {\n                    if (ns.cost < nxt[pos].cost ||\n                        (ns.cost == nxt[pos].cost && ns.score < nxt[pos].score)) {\n                        nxt[pos] = ns;\n                    }\n                }\n            };\n\n            ull b = s.flo;\n            while (b) {\n                int idx = __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n\n            b = s.fhi;\n            while (b) {\n                int idx = 64 + __builtin_ctzll(b);\n                expand_one(idx);\n                b &= b - 1;\n            }\n        }\n\n        if ((int)nxt.size() > WIDTH) {\n            nth_element(\n                nxt.begin(),\n                nxt.begin() + WIDTH,\n                nxt.end(),\n                [](const BeamState& a, const BeamState& b) {\n                    if (a.score != b.score) return a.score < b.score;\n                    return a.cost < b.cost;\n                }\n            );\n            nxt.resize(WIDTH);\n        }\n\n        layers.push_back(move(nxt));\n    }\n\n    if (layers.back().empty()) {\n        return greedy_removal_order();\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)layers[M].size(); i++) {\n        if (layers[M][i].cost < layers[M][best].cost) {\n            best = i;\n        }\n    }\n\n    vector<int> idxOrder;\n    idxOrder.reserve(M);\n\n    int curIdx = best;\n    for (int depth = M; depth >= 1; depth--) {\n        const BeamState& s = layers[depth][curIdx];\n        idxOrder.push_back(s.add);\n        curIdx = s.prev;\n    }\n\n    reverse(idxOrder.begin(), idxOrder.end());\n\n    vector<int> order;\n    order.reserve(M);\n\n    for (int idx : idxOrder) {\n        order.push_back(idxToId[idx]);\n    }\n\n    return order;\n}\n\nint main() {\n    START_TIME = chrono::steady_clock::now();\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    build_neighbors();\n\n    ENT = id_of(0, (D - 1) / 2);\n\n    fill(obstacleCell, obstacleCell + 100, false);\n    fill(labelAt, labelAt + 100, -1);\n    fill(usedLabel, usedLabel + 100, false);\n\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        obstacleCell[id_of(r, c)] = true;\n    }\n\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            int id = id_of(r, c);\n            if (id == ENT) continue;\n            if (obstacleCell[id]) continue;\n            freeIds.push_back(id);\n        }\n    }\n\n    int M = (int)freeIds.size();\n\n    const int INF = 1e9;\n    vector<int> dist(D * D, INF);\n\n    int que[100];\n    int head = 0, tail = 0;\n\n    dist[ENT] = 0;\n    que[tail++] = ENT;\n\n    while (head < tail) {\n        int v = que[head++];\n\n        for (int z = 0; z < nbcnt[v]; z++) {\n            int to = nb[v][z];\n            if (obstacleCell[to]) continue;\n            if (dist[to] != INF) continue;\n\n            dist[to] = dist[v] + 1;\n            que[tail++] = to;\n        }\n    }\n\n    int center = (D - 1) / 2;\n\n    sort(freeIds.begin(), freeIds.end(), [&](int a, int b) {\n        auto [ra, ca] = rc_of(a);\n        auto [rb, cb] = rc_of(b);\n\n        tuple<int,int,int,int> ka = {\n            dist[a],\n            abs(ca - center),\n            ra,\n            ca\n        };\n        tuple<int,int,int,int> kb = {\n            dist[b],\n            abs(cb - center),\n            rb,\n            cb\n        };\n\n        return ka < kb;\n    });\n\n    for (int i = 0; i < M; i++) {\n        rankOfCell[freeIds[i]] = i;\n    }\n\n    // Arrival phase.\n    for (int step = 0; step < M; step++) {\n        int t;\n        cin >> t;\n\n        vector<int> emptySorted;\n        emptySorted.reserve(M - step);\n\n        for (int id : freeIds) {\n            if (labelAt[id] == -1) emptySorted.push_back(id);\n        }\n\n        vector<int> remLabels;\n        remLabels.reserve(M - step - 1);\n\n        for (int x = 0; x < M; x++) {\n            if (!usedLabel[x] && x != t) remLabels.push_back(x);\n        }\n\n        vector<int> legal;\n        legal.reserve(emptySorted.size());\n\n        for (int id : emptySorted) {\n            if (legal_fill(id)) legal.push_back(id);\n        }\n\n        if (legal.empty()) {\n            legal = emptySorted;\n        }\n\n        struct CandEval {\n            int cell;\n            int greedyInv;\n        };\n\n        vector<CandEval> evals;\n        evals.reserve(legal.size());\n\n        int bestGreedyInv = INT_MAX;\n\n        for (int cand : legal) {\n            int g = evaluate_candidate(cand, t, emptySorted, remLabels);\n            evals.push_back({cand, g});\n            bestGreedyInv = min(bestGreedyInv, g);\n        }\n\n        int remaining = M - step;\n\n        bool useLateBeamFull = (remaining <= 10 && !time_over(1050));\n        bool useLateBeamExtra = (remaining > 10 && remaining <= 13 && !time_over(800));\n\n        int bestCell = legal[0];\n        long long bestScore = (1LL << 60);\n\n        for (auto ce : evals) {\n            int cand = ce.cell;\n            int greedyInv = ce.greedyInv;\n            int evalInv = greedyInv;\n\n            if (useLateBeamFull) {\n                evalInv = evaluate_candidate_beam_late(cand, t, emptySorted, remLabels, 220);\n            } else if (useLateBeamExtra && greedyInv <= bestGreedyInv + 8) {\n                evalInv = evaluate_candidate_beam_late(cand, t, emptySorted, remLabels, 120);\n            }\n\n            long long mismatch = abs(rankOfCell[cand] - t);\n            long long score = evalInv * 100000LL + greedyInv * 100LL + mismatch;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestCell = cand;\n            }\n        }\n\n        labelAt[bestCell] = t;\n        usedLabel[t] = true;\n\n        auto [r, c] = rc_of(bestCell);\n        cout << r << ' ' << c << endl;\n    }\n\n    // Final removal phase.\n    vector<int> greedyOrder = greedy_removal_order();\n    int greedyInv = inversion_count_of_order(greedyOrder);\n\n    int e = elapsed_ms();\n    int width = 9000;\n\n    if (e < 850) width = 10000;\n    else if (e > 1350) width = 5500;\n    else if (e > 1150) width = 7000;\n\n    vector<int> beamOrder;\n\n    if (!time_over(1650)) {\n        beamOrder = beam_removal_order(width);\n    }\n\n    int beamInv = INT_MAX;\n    if (!beamOrder.empty()) {\n        beamInv = inversion_count_of_order(beamOrder);\n    }\n\n    const vector<int>& finalOrder =\n        (!beamOrder.empty() && beamInv <= greedyInv) ? beamOrder : greedyOrder;\n\n    for (int id : finalOrder) {\n        auto [r, c] = rc_of(id);\n        cout << r << ' ' << c << '\\n';\n    }\n\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXC = 101;\nstatic const int INF = 1e9;\n\nint n, m;\nbool allowedAdj[MAXC][MAXC];\n\nstruct State {\n    vector<vector<int>> g;\n    int cnt[MAXC]{};\n    int edgeCnt[MAXC][MAXC]{};\n    int stamp[MAXN][MAXN]{};\n    int curStamp = 1;\n\n    State() {\n        g.assign(n, vector<int>(n, 0));\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(stamp, 0, sizeof(stamp));\n    }\n\n    static void normPair(int &a, int &b) {\n        if (a > b) swap(a, b);\n    }\n\n    bool inside(int r, int c) const {\n        return 0 <= r && r < n && 0 <= c && c < n;\n    }\n\n    void addEdgeCount(int a, int b, int v) {\n        if (a == b) return;\n        normPair(a, b);\n        edgeCnt[a][b] += v;\n    }\n\n    void init(const vector<vector<int>> &src) {\n        g = src;\n        memset(cnt, 0, sizeof(cnt));\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                cnt[g[i][j]]++;\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = g[i][j];\n\n                if (i == 0) addEdgeCount(c, 0, 1);\n                if (i == n - 1) addEdgeCount(c, 0, 1);\n                if (j == 0) addEdgeCount(c, 0, 1);\n                if (j == n - 1) addEdgeCount(c, 0, 1);\n\n                if (i + 1 < n) addEdgeCount(c, g[i + 1][j], 1);\n                if (j + 1 < n) addEdgeCount(c, g[i][j + 1], 1);\n            }\n        }\n    }\n\n    bool adjacentZeroOrOutside(int r, int c) const {\n        if (r == 0 || r == n - 1 || c == 0 || c == n - 1) return true;\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == 0) return true;\n        }\n        return false;\n    }\n\n    bool oldColorConnectedAfterRemoval(int r, int c, int col) {\n        vector<pair<int, int>> starts;\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) {\n                starts.push_back({nr, nc});\n            }\n        }\n\n        if (starts.size() <= 1) return true;\n\n        curStamp++;\n        if (curStamp == INT_MAX) {\n            memset(stamp, 0, sizeof(stamp));\n            curStamp = 1;\n        }\n\n        queue<pair<int, int>> q;\n        q.push(starts[0]);\n        stamp[starts[0].first][starts[0].second] = curStamp;\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dr[k], ny = y + dc[k];\n                if (!inside(nx, ny)) continue;\n                if (nx == r && ny == c) continue;\n                if (stamp[nx][ny] == curStamp) continue;\n                if (g[nx][ny] != col) continue;\n\n                stamp[nx][ny] = curStamp;\n                q.push({nx, ny});\n            }\n        }\n\n        for (auto [x, y] : starts) {\n            if (stamp[x][y] != curStamp) return false;\n        }\n        return true;\n    }\n\n    bool zeroConnectedAfterRemoval(int r, int c) const {\n        if (cnt[0] <= 1) return true;\n\n        bool vis[MAXN][MAXN]{};\n        queue<pair<int, int>> q;\n\n        auto push = [&](int x, int y) {\n            if (!inside(x, y)) return;\n            if (x == r && y == c) return;\n            if (g[x][y] != 0) return;\n            if (vis[x][y]) return;\n            vis[x][y] = true;\n            q.push({x, y});\n        };\n\n        for (int i = 0; i < n; i++) {\n            push(i, 0);\n            push(i, n - 1);\n            push(0, i);\n            push(n - 1, i);\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n\n            for (int k = 0; k < 4; k++) {\n                push(x + dr[k], y + dc[k]);\n            }\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (i == r && j == c) continue;\n                if (g[i][j] == 0 && !vis[i][j]) return false;\n            }\n        }\n        return true;\n    }\n\n    struct Delta {\n        int a, b, d;\n    };\n\n    void addDelta(vector<Delta> &ds, int a, int b, int d) const {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n\n        for (auto &x : ds) {\n            if (x.a == a && x.b == b) {\n                x.d += d;\n                return;\n            }\n        }\n        ds.push_back({a, b, d});\n    }\n\n    vector<Delta> makeDelta(int r, int c, int to) const {\n        vector<Delta> ds;\n        int from = g[r][c];\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n\n            int nb = 0;\n            if (inside(nr, nc)) nb = g[nr][nc];\n\n            addDelta(ds, from, nb, -1);\n            addDelta(ds, to, nb, +1);\n        }\n\n        return ds;\n    }\n\n    bool touchesColor(int r, int c, int col) const {\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (inside(nr, nc) && g[nr][nc] == col) return true;\n        }\n        return false;\n    }\n\n    bool validChange(int r, int c, int to) {\n        int from = g[r][c];\n        if (from == to) return false;\n\n        if (from != 0 && cnt[from] <= 1) return false;\n\n        if (to == 0) {\n            if (from == 0) return false;\n            if (!adjacentZeroOrOutside(r, c)) return false;\n        } else {\n            if (!touchesColor(r, c, to)) return false;\n        }\n\n        if (from == 0) {\n            if (!zeroConnectedAfterRemoval(r, c)) return false;\n        } else {\n            if (!oldColorConnectedAfterRemoval(r, c, from)) return false;\n        }\n\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            int now = edgeCnt[x.a][x.b] + x.d;\n\n            if (allowedAdj[x.a][x.b]) {\n                if (now <= 0) return false;\n            } else {\n                if (now != 0) return false;\n            }\n        }\n\n        return true;\n    }\n\n    void applyChange(int r, int c, int to) {\n        int from = g[r][c];\n        auto ds = makeDelta(r, c, to);\n\n        for (auto &x : ds) {\n            edgeCnt[x.a][x.b] += x.d;\n        }\n\n        cnt[from]--;\n        cnt[to]++;\n        g[r][c] = to;\n    }\n\n    vector<int> computeDistanceToZero() const {\n        vector<int> dist(n * n, INF);\n        queue<int> q;\n\n        auto id = [&](int r, int c) {\n            return r * n + c;\n        };\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int v = id(i, j);\n\n                if (g[i][j] == 0) {\n                    dist[v] = 0;\n                    q.push(v);\n                } else if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    dist[v] = 1;\n                    q.push(v);\n                }\n            }\n        }\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            int r = v / n, c = v % n;\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!inside(nr, nc)) continue;\n\n                int nv = id(nr, nc);\n                if (dist[nv] > dist[v] + 1) {\n                    dist[nv] = dist[v] + 1;\n                    q.push(nv);\n                }\n            }\n        }\n\n        return dist;\n    }\n};\n\nint zeroCountGrid(const vector<vector<int>> &g) {\n    int z = 0;\n    for (auto &row : g) {\n        for (int x : row) {\n            if (x == 0) z++;\n        }\n    }\n    return z;\n}\n\nbool globalValid(const vector<vector<int>> &g) {\n    int cnt[MAXC]{};\n    bool adj[MAXC][MAXC]{};\n\n    auto addAdj = [&](int a, int b) {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n        adj[a][b] = true;\n    };\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cnt[g[i][j]]++;\n        }\n    }\n\n    for (int c = 1; c <= m; c++) {\n        if (cnt[c] == 0) return false;\n    }\n\n    for (int i = 0; i < n; i++) {\n        addAdj(g[i][0], 0);\n        addAdj(g[i][n - 1], 0);\n        addAdj(g[0][i], 0);\n        addAdj(g[n - 1][i], 0);\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (i + 1 < n) addAdj(g[i][j], g[i + 1][j]);\n            if (j + 1 < n) addAdj(g[i][j], g[i][j + 1]);\n        }\n    }\n\n    for (int a = 0; a <= m; a++) {\n        for (int b = a + 1; b <= m; b++) {\n            if (adj[a][b] != allowedAdj[a][b]) return false;\n        }\n    }\n\n    static int dr[4] = {-1, 1, 0, 0};\n    static int dc[4] = {0, 0, -1, 1};\n\n    for (int col = 1; col <= m; col++) {\n        bool vis[MAXN][MAXN]{};\n        queue<pair<int, int>> q;\n        bool found = false;\n\n        for (int i = 0; i < n && !found; i++) {\n            for (int j = 0; j < n && !found; j++) {\n                if (g[i][j] == col) {\n                    vis[i][j] = true;\n                    q.push({i, j});\n                    found = true;\n                }\n            }\n        }\n\n        int seen = 0;\n\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            seen++;\n\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]) continue;\n                if (g[nr][nc] != col) continue;\n\n                vis[nr][nc] = true;\n                q.push({nr, nc});\n            }\n        }\n\n        if (seen != cnt[col]) return false;\n    }\n\n    if (cnt[0] > 0) {\n        bool vis[MAXN][MAXN]{};\n        queue<pair<int, int>> q;\n\n        auto push = [&](int r, int c) {\n            if (r < 0 || r >= n || c < 0 || c >= n) return;\n            if (vis[r][c]) return;\n            if (g[r][c] != 0) return;\n\n            vis[r][c] = true;\n            q.push({r, c});\n        };\n\n        for (int i = 0; i < n; i++) {\n            push(i, 0);\n            push(i, n - 1);\n            push(0, i);\n            push(n - 1, i);\n        }\n\n        int seen = 0;\n\n        while (!q.empty()) {\n            auto [r, c] = q.front();\n            q.pop();\n            seen++;\n\n            for (int k = 0; k < 4; k++) {\n                push(r + dr[k], c + dc[k]);\n            }\n        }\n\n        if (seen != cnt[0]) return false;\n    }\n\n    return true;\n}\n\nstruct LineOp {\n    int gain;\n    int type;\n    int idx;\n};\n\nvector<vector<int>> applyLineOp(const vector<vector<int>> &g, const LineOp &op) {\n    vector<vector<int>> ng = g;\n\n    if (op.type == 0) {\n        int row = op.idx;\n        for (int i = row; i + 1 < n; i++) ng[i] = ng[i + 1];\n        ng[n - 1].assign(n, 0);\n    } else if (op.type == 1) {\n        int row = op.idx;\n        for (int i = row; i - 1 >= 0; i--) ng[i] = ng[i - 1];\n        ng[0].assign(n, 0);\n    } else if (op.type == 2) {\n        int col = op.idx;\n        for (int i = 0; i < n; i++) {\n            for (int j = col; j + 1 < n; j++) ng[i][j] = ng[i][j + 1];\n            ng[i][n - 1] = 0;\n        }\n    } else {\n        int col = op.idx;\n        for (int i = 0; i < n; i++) {\n            for (int j = col; j - 1 >= 0; j--) ng[i][j] = ng[i][j - 1];\n            ng[i][0] = 0;\n        }\n    }\n\n    return ng;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    vector<vector<int>> original(n, vector<int>(n));\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> original[i][j];\n        }\n    }\n\n    memset(allowedAdj, 0, sizeof(allowedAdj));\n\n    auto addAllowed = [&](int a, int b) {\n        if (a == b) return;\n        if (a > b) swap(a, b);\n        allowedAdj[a][b] = true;\n    };\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = original[i][j];\n\n            if (i == 0) addAllowed(c, 0);\n            if (i == n - 1) addAllowed(c, 0);\n            if (j == 0) addAllowed(c, 0);\n            if (j == n - 1) addAllowed(c, 0);\n\n            if (i + 1 < n) addAllowed(c, original[i + 1][j]);\n            if (j + 1 < n) addAllowed(c, original[i][j + 1]);\n        }\n    }\n\n    State st;\n    st.init(original);\n\n    vector<vector<int>> best = st.g;\n    int bestZero = st.cnt[0];\n\n    mt19937 rng(123456789);\n\n    auto startTime = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    const double TL_LOCAL = 1.88;\n    const double TL_TOTAL = 1.98;\n\n    vector<int> cells(n * n);\n    iota(cells.begin(), cells.end(), 0);\n\n    auto updateBest = [&]() {\n        if (st.cnt[0] > bestZero) {\n            bestZero = st.cnt[0];\n            best = st.g;\n        }\n    };\n\n    auto peelPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 255) == 0 && elapsed() > TL_LOCAL) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            if (st.g[r][c] == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n            }\n        }\n\n        updateBest();\n        return changed;\n    };\n\n    auto boundaryRecolorPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > TL_LOCAL) break;\n            if (applied >= 700) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n            if (!st.adjacentZeroOrOutside(r, c)) continue;\n\n            if (st.validChange(r, c, 0)) {\n                st.applyChange(r, c, 0);\n                changed = true;\n                applied++;\n                continue;\n            }\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n                used[to] = true;\n\n                int sameAround = 0;\n                for (int t = 0; t < 4; t++) {\n                    int ar = r + dr[t], ac = c + dc[t];\n                    if (st.inside(ar, ac) && st.g[ar][ac] == to) sameAround++;\n                }\n\n                cand.push_back({-sameAround, to});\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto inwardRecolorPass = [&]() {\n        bool changed = false;\n\n        auto dist = st.computeDistanceToZero();\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        stable_sort(cells.begin(), cells.end(), [&](int a, int b) {\n            return dist[a] < dist[b];\n        });\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > TL_LOCAL) break;\n            if (applied >= 700) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<pair<int, int>> cand;\n            bool used[MAXC]{};\n\n            int cd = dist[v];\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                int nd = dist[nr * n + nc];\n\n                if (nd <= cd) {\n                    used[to] = true;\n                    cand.push_back({nd, to});\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n\n            for (auto [_, to] : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    auto randomRecolorPass = [&]() {\n        bool changed = false;\n\n        shuffle(cells.begin(), cells.end(), rng);\n\n        static int dr[4] = {-1, 1, 0, 0};\n        static int dc[4] = {0, 0, -1, 1};\n\n        int applied = 0;\n\n        for (int idx = 0; idx < (int)cells.size(); idx++) {\n            if ((idx & 127) == 0 && elapsed() > TL_LOCAL) break;\n            if (applied >= 350) break;\n\n            int v = cells[idx];\n            int r = v / n, c = v % n;\n\n            int from = st.g[r][c];\n            if (from == 0) continue;\n\n            vector<int> cand;\n            bool used[MAXC]{};\n\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!st.inside(nr, nc)) continue;\n\n                int to = st.g[nr][nc];\n                if (to == 0 || to == from) continue;\n                if (used[to]) continue;\n\n                used[to] = true;\n                cand.push_back(to);\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            for (int to : cand) {\n                if (st.validChange(r, c, to)) {\n                    st.applyChange(r, c, to);\n                    changed = true;\n                    applied++;\n                    break;\n                }\n            }\n        }\n\n        return changed;\n    };\n\n    int stagnant = 0;\n\n    while (elapsed() < TL_LOCAL) {\n        int beforeBest = bestZero;\n\n        bool any = false;\n\n        any |= peelPass();\n        if (elapsed() > TL_LOCAL) break;\n\n        any |= boundaryRecolorPass();\n        if (elapsed() > TL_LOCAL) break;\n\n        any |= peelPass();\n        if (elapsed() > TL_LOCAL) break;\n\n        any |= inwardRecolorPass();\n        if (elapsed() > TL_LOCAL) break;\n\n        any |= peelPass();\n        if (elapsed() > TL_LOCAL) break;\n\n        updateBest();\n\n        if (bestZero == beforeBest) stagnant++;\n        else stagnant = 0;\n\n        if (stagnant >= 2) {\n            randomRecolorPass();\n            peelPass();\n            stagnant = 0;\n        }\n\n        if (!any && elapsed() < TL_LOCAL) {\n            bool r = randomRecolorPass();\n            if (!r) break;\n        }\n    }\n\n    auto tryLineCompression = [&]() -> bool {\n        vector<LineOp> cands;\n\n        for (int i = 0; i < n; i++) {\n            int zr = 0;\n            for (int j = 0; j < n; j++) {\n                if (best[i][j] == 0) zr++;\n            }\n\n            int rowGain = n - zr;\n            if (rowGain > 0) {\n                cands.push_back({rowGain, 0, i});\n                cands.push_back({rowGain, 1, i});\n            }\n\n            int zc = 0;\n            for (int j = 0; j < n; j++) {\n                if (best[j][i] == 0) zc++;\n            }\n\n            int colGain = n - zc;\n            if (colGain > 0) {\n                cands.push_back({colGain, 2, i});\n                cands.push_back({colGain, 3, i});\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const LineOp &a, const LineOp &b) {\n            return a.gain > b.gain;\n        });\n\n        for (auto op : cands) {\n            if (elapsed() > TL_TOTAL) return false;\n\n            vector<vector<int>> ng = applyLineOp(best, op);\n            int nz = zeroCountGrid(ng);\n            if (nz <= bestZero) continue;\n\n            if (globalValid(ng)) {\n                best = ng;\n                bestZero = nz;\n                return true;\n            }\n        }\n\n        int L = min<int>(8, cands.size());\n\n        for (int a = 0; a < L; a++) {\n            for (int b = 0; b < L; b++) {\n                if (elapsed() > TL_TOTAL) return false;\n\n                vector<vector<int>> ng = applyLineOp(best, cands[a]);\n                ng = applyLineOp(ng, cands[b]);\n\n                int nz = zeroCountGrid(ng);\n                if (nz <= bestZero) continue;\n\n                if (globalValid(ng)) {\n                    best = ng;\n                    bestZero = nz;\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    };\n\n    auto finalDirectPeel = [&]() -> bool {\n        State fs;\n        fs.init(best);\n\n        vector<int> ids(n * n);\n        iota(ids.begin(), ids.end(), 0);\n\n        bool improved = false;\n\n        for (int pass = 0; pass < 4 && elapsed() < TL_TOTAL; pass++) {\n            bool changed = false;\n            shuffle(ids.begin(), ids.end(), rng);\n\n            for (int idx = 0; idx < (int)ids.size(); idx++) {\n                if ((idx & 127) == 0 && elapsed() > TL_TOTAL) break;\n\n                int v = ids[idx];\n                int r = v / n, c = v % n;\n\n                if (fs.g[r][c] == 0) continue;\n                if (!fs.adjacentZeroOrOutside(r, c)) continue;\n\n                if (fs.validChange(r, c, 0)) {\n                    fs.applyChange(r, c, 0);\n                    changed = true;\n                    improved = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        if (improved && fs.cnt[0] > bestZero) {\n            bestZero = fs.cnt[0];\n            best = fs.g;\n            return true;\n        }\n\n        return false;\n    };\n\n    while (elapsed() < TL_TOTAL) {\n        bool changed = false;\n\n        if (tryLineCompression()) {\n            changed = true;\n            continue;\n        }\n\n        if (finalDirectPeel()) {\n            changed = true;\n            continue;\n        }\n\n        if (!changed) 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 << best[i][j];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 105;\n\nstruct QueryManager {\n    int N, D, Q;\n    int used = 0;\n\n    // direct_cmp[a][b]:\n    // 0 unknown, 1 means a>b, -1 means a<b, 2 means equality observed.\n    vector<vector<int>> direct_cmp;\n\n    // reach[a][b] means inferred/known a >= b in our comparison graph.\n    vector<bitset<MAXN>> reach;\n\n    QueryManager(int N_, int D_, int Q_) : N(N_), D(D_), Q(Q_) {\n        direct_cmp.assign(N, vector<int>(N, 0));\n        reach.assign(N, bitset<MAXN>());\n        for (int i = 0; i < N; i++) direct_cmp[i][i] = 2;\n    }\n\n    void add_greater_edge(int a, int b) {\n        if (a == b) return;\n        if (reach[a][b]) return;\n\n        bitset<MAXN> succ;\n        succ.set(b);\n        succ |= reach[b];\n\n        vector<int> preds;\n        preds.push_back(a);\n        for (int u = 0; u < N; u++) {\n            if (reach[u][a]) preds.push_back(u);\n        }\n\n        for (int u : preds) {\n            reach[u] |= succ;\n            reach[u].reset(u);\n        }\n    }\n\n    void store_single_cmp(int a, int b, char c) {\n        if (c == '>') {\n            direct_cmp[a][b] = 1;\n            direct_cmp[b][a] = -1;\n            add_greater_edge(a, b);\n        } else if (c == '<') {\n            direct_cmp[a][b] = -1;\n            direct_cmp[b][a] = 1;\n            add_greater_edge(b, a);\n        } else {\n            direct_cmp[a][b] = direct_cmp[b][a] = 2;\n        }\n    }\n\n    void add_exact_total_order(const vector<int>& order) {\n        int n = (int)order.size();\n        for (int i = 0; i < n; i++) {\n            for (int j = i + 1; j < n; j++) {\n                add_greater_edge(order[i], order[j]);\n            }\n        }\n    }\n\n    int known_single(int a, int b) const {\n        if (a == b) return 2;\n\n        if (direct_cmp[a][b] == 2) return 2;\n        if (direct_cmp[a][b] == 1) return 1;\n        if (direct_cmp[a][b] == -1) return -1;\n\n        if (reach[a][b]) return 1;\n        if (reach[b][a]) return -1;\n\n        return 0;\n    }\n\n    char query(const vector<int>& L, const vector<int>& R) {\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        string s;\n        if (!(cin >> s)) exit(0);\n\n        used++;\n\n        if (L.size() == 1 && R.size() == 1) {\n            store_single_cmp(L[0], R[0], s[0]);\n        }\n\n        return s[0];\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query(L, R);\n    }\n};\n\nint ceil_log2_int(int x) {\n    int r = 0, p = 1;\n    while (p < x) {\n        p <<= 1;\n        r++;\n    }\n    return r;\n}\n\nstruct Solver {\n    int N, D, Q;\n    QueryManager qm;\n\n    vector<double> estWeight;\n    vector<int> order;\n\n    vector<vector<int>> bins;\n    vector<double> estSum;\n    vector<int> answer;\n\n    mt19937 rng;\n\n    Solver(int N_, int D_, int Q_)\n        : N(N_), D(D_), Q(Q_), qm(N_, D_, Q_),\n          rng(1234567u + 1009u * N_ + 917u * D_ + 37u * Q_) {}\n\n    char compare_single_cached(int a, int b, bool allowQuery = true) {\n        int rel = qm.known_single(a, b);\n        if (rel == 1) return '>';\n        if (rel == -1) return '<';\n        if (rel == 2) return '=';\n        if (!allowQuery || qm.used >= Q) return '?';\n        return qm.query_single(a, b);\n    }\n\n    vector<int> merge_sort_rec(const vector<int>& v) {\n        int n = (int)v.size();\n        if (n <= 1) return v;\n\n        int mid = n / 2;\n        vector<int> L(v.begin(), v.begin() + mid);\n        vector<int> R(v.begin() + mid, v.end());\n\n        L = merge_sort_rec(L);\n        R = merge_sort_rec(R);\n\n        vector<int> res;\n        res.reserve(n);\n\n        int i = 0, j = 0;\n        while (i < (int)L.size() && j < (int)R.size()) {\n            char c = compare_single_cached(L[i], R[j], true);\n            if (c == '>') res.push_back(L[i++]);\n            else res.push_back(R[j++]);\n        }\n\n        while (i < (int)L.size()) res.push_back(L[i++]);\n        while (j < (int)R.size()) res.push_back(R[j++]);\n\n        return res;\n    }\n\n    void exact_sort_items() {\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        order = merge_sort_rec(order);\n\n        // Exact merge sort gives a full non-increasing order.\n        qm.add_exact_total_order(order);\n    }\n\n    void refine_order_by_known_relations() {\n        vector<int> pos(N);\n        for (int i = 0; i < N; i++) pos[order[i]] = i;\n\n        vector<int> indeg(N, 0);\n        for (int u = 0; u < N; u++) {\n            for (int v = 0; v < N; v++) {\n                if (qm.reach[u][v]) indeg[v]++;\n            }\n        }\n\n        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;\n        for (int i = 0; i < N; i++) {\n            if (indeg[i] == 0) pq.push({pos[i], i});\n        }\n\n        vector<int> refined;\n        refined.reserve(N);\n\n        while (!pq.empty()) {\n            auto [p, u] = pq.top();\n            pq.pop();\n\n            refined.push_back(u);\n\n            for (int v = 0; v < N; v++) {\n                if (qm.reach[u][v]) {\n                    indeg[v]--;\n                    if (indeg[v] == 0) pq.push({pos[v], v});\n                }\n            }\n        }\n\n        // If no contradiction exists, use the refined topological order.\n        if ((int)refined.size() == N) {\n            order = refined;\n        }\n    }\n\n    void approximate_sort_items(int targetQueries) {\n        targetQueries = min(targetQueries, Q);\n\n        order.resize(N);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n\n        vector<int> gaps;\n        for (int g = N / 2; g >= 1; g /= 2) {\n            gaps.push_back(g);\n            if (g == 1) break;\n        }\n\n        int stagnantRounds = 0;\n\n        while (qm.used < targetQueries && stagnantRounds < 3) {\n            int beforeUsed = qm.used;\n            bool anySwap = false;\n\n            for (int gap : gaps) {\n                for (int i = gap; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - gap];\n                    int b = order[i];\n\n                    char c = compare_single_cached(a, b, qm.used < targetQueries);\n                    if (c == '<') {\n                        swap(order[i - gap], order[i]);\n                        anySwap = true;\n                    }\n                }\n                if (qm.used >= targetQueries) break;\n            }\n\n            if (!anySwap) {\n                for (int i = 1; i < N && qm.used < targetQueries; i++) {\n                    int a = order[i - 1];\n                    int b = order[i];\n\n                    char c = compare_single_cached(a, b, qm.used < targetQueries);\n                    if (c == '<') {\n                        swap(order[i - 1], order[i]);\n                        anySwap = true;\n                    }\n                }\n            }\n\n            // If this whole pass consumed no queries because everything was cached,\n            // enrich the known graph with random unknown singleton comparisons.\n            if (qm.used == beforeUsed && qm.used < targetQueries) {\n                int added = 0;\n                vector<int> pos(N);\n                for (int i = 0; i < N; i++) pos[order[i]] = i;\n\n                for (int attempt = 0; attempt < 4 * N && qm.used < targetQueries; attempt++) {\n                    int a = uniform_int_distribution<int>(0, N - 1)(rng);\n                    int b = uniform_int_distribution<int>(0, N - 1)(rng);\n                    if (a == b) continue;\n                    if (qm.known_single(a, b) != 0) continue;\n\n                    char c = qm.query_single(a, b);\n                    added++;\n\n                    int pa = pos[a];\n                    int pb = pos[b];\n\n                    if (c == '>' && pa > pb) {\n                        swap(order[pa], order[pb]);\n                        pos[a] = pb;\n                        pos[b] = pa;\n                    }\n                    if (c == '<' && pa < pb) {\n                        swap(order[pa], order[pb]);\n                        pos[a] = pb;\n                        pos[b] = pa;\n                    }\n                }\n\n                if (added == 0) stagnantRounds++;\n                else stagnantRounds = 0;\n            } else {\n                stagnantRounds = 0;\n            }\n        }\n\n        // Query-free repair: enforce all known singleton relations.\n        refine_order_by_known_relations();\n    }\n\n    void normalize_est() {\n        double s = 0.0;\n        for (double x : estWeight) s += x;\n        if (s <= 0.0) return;\n\n        double mul = (double)N / s;\n        for (double& x : estWeight) x *= mul;\n    }\n\n    void make_estimated_weights() {\n        estWeight.assign(N, 0.0);\n\n        vector<double> H(N + 1, 0.0);\n        for (int i = 1; i <= N; i++) H[i] = H[i - 1] + 1.0 / i;\n\n        double T = (double)N / (double)D;\n        double A = 1.0 - exp(-T);\n\n        for (int k = 0; k < N; k++) {\n            int item = order[k];\n\n            double untr = H[N] - H[k];\n\n            double p = ((double)N - (double)k - 0.5) / (double)N;\n            p = min(1.0 - 1e-12, max(1e-12, p));\n\n            double u = p * A;\n            u = min(1.0 - 1e-12, max(1e-12, u));\n\n            double trunc = -log(1.0 - u);\n\n            double alpha = 0.25;\n            if (D * 5 >= N) alpha = 0.40;\n\n            estWeight[item] = (1.0 - alpha) * untr + alpha * trunc;\n        }\n\n        normalize_est();\n    }\n\n    int compare_bins_by_est(int a, int b) const {\n        const double eps = 1e-12;\n        if (estSum[a] + eps < estSum[b]) return -1;\n        if (estSum[a] > estSum[b] + eps) return 1;\n        return 0;\n    }\n\n    int compare_bins(int a, int b, bool allowQuery = true) {\n        if (a == b) return 0;\n\n        if (allowQuery && qm.used < Q) {\n            char c = qm.query(bins[a], bins[b]);\n            if (c == '<') return -1;\n            if (c == '>') return 1;\n            return 0;\n        }\n\n        return compare_bins_by_est(a, b);\n    }\n\n    vector<int> sort_bins_est(vector<int> v) {\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            if (fabs(estSum[a] - estSum[b]) > 1e-12) return estSum[a] < estSum[b];\n            return a < b;\n        });\n        return v;\n    }\n\n    vector<int> sort_bins_with_queries_if_possible(vector<int> v) {\n        int lg = max(1, ceil_log2_int((int)v.size()));\n        int estimatedCost = (int)v.size() * lg;\n\n        if (qm.used + estimatedCost > Q) return sort_bins_est(v);\n\n        vector<int> res;\n        res.reserve(v.size());\n\n        for (int b : v) {\n            int lo = 0, hi = (int)res.size();\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int cmp = compare_bins(b, res[mid], true);\n                if (cmp <= 0) hi = mid;\n                else lo = mid + 1;\n            }\n            res.insert(res.begin() + lo, b);\n        }\n\n        return res;\n    }\n\n    void build_partition() {\n        bins.assign(D, {});\n        estSum.assign(D, 0.0);\n        answer.assign(N, 0);\n\n        for (int i = 0; i < D; i++) {\n            int item = order[i];\n            bins[i].push_back(item);\n            estSum[i] += estWeight[item];\n            answer[item] = i;\n        }\n\n        vector<int> binOrder(D);\n        iota(binOrder.begin(), binOrder.end(), 0);\n\n        if (qm.used < Q && Q - qm.used > D)\n            binOrder = sort_bins_with_queries_if_possible(binOrder);\n        else\n            binOrder = sort_bins_est(binOrder);\n\n        for (int idx = D; idx < N; idx++) {\n            int item = order[idx];\n\n            int b = binOrder.front();\n            binOrder.erase(binOrder.begin());\n\n            bins[b].push_back(item);\n            estSum[b] += estWeight[item];\n            answer[item] = b;\n\n            int lo = 0, hi = (int)binOrder.size();\n            while (lo < hi) {\n                int mid = (lo + hi) / 2;\n                int cmp = compare_bins(b, binOrder[mid], true);\n                if (cmp <= 0) hi = mid;\n                else lo = mid + 1;\n            }\n            binOrder.insert(binOrder.begin() + lo, b);\n        }\n    }\n\n    int minmax_query_need() const {\n        if (D <= 1) return 0;\n        int need = 1;\n        int rem = D - 2;\n        need += (rem / 2) * 3;\n        if (rem % 2) need += 2;\n        return need;\n    }\n\n    bool find_min_max_bins(int& mn, int& mx) {\n        if (D == 1) {\n            mn = mx = 0;\n            return true;\n        }\n\n        if (qm.used + minmax_query_need() > Q) return false;\n\n        char c = qm.query(bins[0], bins[1]);\n        if (c == '<') {\n            mn = 0;\n            mx = 1;\n        } else if (c == '>') {\n            mn = 1;\n            mx = 0;\n        } else {\n            mn = 0;\n            mx = 0;\n        }\n\n        int i = 2;\n        for (; i + 1 < D; i += 2) {\n            int a = i, b = i + 1;\n            char p = qm.query(bins[a], bins[b]);\n\n            int small, large;\n            if (p == '<') {\n                small = a;\n                large = b;\n            } else if (p == '>') {\n                small = b;\n                large = a;\n            } else {\n                small = a;\n                large = a;\n            }\n\n            int c1 = compare_bins(small, mn, true);\n            if (c1 < 0) mn = small;\n\n            int c2 = compare_bins(large, mx, true);\n            if (c2 > 0) mx = large;\n        }\n\n        if (i < D) {\n            int b = i;\n\n            int c1 = compare_bins(b, mn, true);\n            if (c1 < 0) mn = b;\n\n            int c2 = compare_bins(b, mx, true);\n            if (c2 > 0) mx = b;\n        }\n\n        return true;\n    }\n\n    void do_move(int from, int to, int x) {\n        auto it = find(bins[from].begin(), bins[from].end(), x);\n        if (it != bins[from].end()) bins[from].erase(it);\n\n        bins[to].push_back(x);\n        estSum[from] -= estWeight[x];\n        estSum[to] += estWeight[x];\n        answer[x] = to;\n    }\n\n    void do_swap(int a, int b, int x, int y) {\n        auto itx = find(bins[a].begin(), bins[a].end(), x);\n        auto ity = find(bins[b].begin(), bins[b].end(), y);\n\n        if (itx != bins[a].end()) *itx = y;\n        if (ity != bins[b].end()) *ity = x;\n\n        estSum[a] += estWeight[y] - estWeight[x];\n        estSum[b] += estWeight[x] - estWeight[y];\n\n        answer[x] = b;\n        answer[y] = a;\n    }\n\n    bool try_safe_move(int lo, int hi) {\n        if ((int)bins[hi].size() <= 1) return false;\n\n        double diff = max(0.0, estSum[hi] - estSum[lo]);\n        double ideal = diff / 2.0;\n\n        vector<int> cand = bins[hi];\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            double da = fabs(estWeight[a] - ideal);\n            double db = fabs(estWeight[b] - ideal);\n            if (fabs(da - db) > 1e-12) return da < db;\n            return estWeight[a] > estWeight[b];\n        });\n\n        for (int x : cand) {\n            if (qm.used >= Q) break;\n            if ((int)bins[hi].size() <= 1) break;\n\n            vector<int> leftSet;\n            leftSet.reserve(bins[hi].size() - 1);\n            for (int y : bins[hi]) {\n                if (y != x) leftSet.push_back(y);\n            }\n\n            if (leftSet.empty()) continue;\n\n            char c = qm.query(leftSet, bins[lo]);\n\n            if (c == '>') {\n                do_move(hi, lo, x);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    bool is_single_greater_for_swap(int x, int y) {\n        int rel = qm.known_single(x, y);\n        if (rel == 1) return true;\n        if (rel == -1 || rel == 2) return false;\n\n        if (qm.used >= Q) return false;\n\n        char c = qm.query_single(x, y);\n        return c == '>';\n    }\n\n    bool try_safe_swap(int lo, int hi) {\n        if (qm.used + 1 > Q) return false;\n        if ((int)bins[hi].size() <= 1) return false;\n        if ((int)bins[lo].size() <= 1) return false;\n\n        vector<int> heavy = bins[hi];\n        vector<int> light = bins[lo];\n\n        sort(heavy.begin(), heavy.end(), [&](int a, int b) {\n            return estWeight[a] > estWeight[b];\n        });\n        sort(light.begin(), light.end(), [&](int a, int b) {\n            return estWeight[a] < estWeight[b];\n        });\n\n        int rem = Q - qm.used;\n        int lim = (rem >= 50 ? 12 : (rem >= 30 ? 10 : (rem >= 18 ? 8 : 6)));\n\n        int limitH = min<int>(lim, heavy.size());\n        int limitL = min<int>(lim, light.size());\n\n        struct Cand {\n            double score;\n            int x, y;\n        };\n        vector<Cand> cands;\n\n        double diff = max(0.0, estSum[hi] - estSum[lo]);\n        double ideal = diff / 2.0;\n\n        for (int i = 0; i < limitH; i++) {\n            for (int j = 0; j < limitL; j++) {\n                int x = heavy[i];\n                int y = light[j];\n\n                double delta = estWeight[x] - estWeight[y];\n                if (delta <= 1e-12) continue;\n\n                double score = fabs(delta - ideal);\n                cands.push_back({score, x, y});\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            return a.score < b.score;\n        });\n\n        for (auto [score, x, y] : cands) {\n            if (qm.used >= Q) break;\n\n            int known = qm.known_single(x, y);\n            int need = (known == 0 ? 2 : 1);\n            if (qm.used + need > Q) break;\n\n            if (!is_single_greater_for_swap(x, y)) continue;\n            if (qm.used >= Q) break;\n\n            vector<int> Lset, Rset;\n\n            for (int v : bins[hi]) {\n                if (v != x) Lset.push_back(v);\n            }\n            for (int v : bins[lo]) {\n                if (v != y) Rset.push_back(v);\n            }\n\n            if (Lset.empty() || Rset.empty()) continue;\n\n            char c = qm.query(Lset, Rset);\n\n            if (c == '>') {\n                do_swap(hi, lo, x, y);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    void local_improve() {\n        int iteration = 0;\n\n        while (qm.used < Q && iteration < 10000) {\n            iteration++;\n\n            int lo, hi;\n            if (!find_min_max_bins(lo, hi)) break;\n            if (lo == hi) break;\n\n            bool changed = false;\n\n            if (!changed && (int)bins[hi].size() > 1) {\n                changed = try_safe_move(lo, hi);\n            }\n\n            if (!changed && qm.used + 1 <= Q) {\n                changed = try_safe_swap(lo, hi);\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    bool opportunistic_move_once() {\n        vector<int> desc(D), asc(D);\n        iota(desc.begin(), desc.end(), 0);\n        iota(asc.begin(), asc.end(), 0);\n\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            return estSum[a] > estSum[b];\n        });\n        sort(asc.begin(), asc.end(), [&](int a, int b) {\n            return estSum[a] < estSum[b];\n        });\n\n        int limH = min(D, 6);\n        int limL = min(D, 6);\n\n        struct MCand {\n            double score;\n            int hi, lo, x;\n        };\n        vector<MCand> cands;\n\n        for (int ih = 0; ih < limH; ih++) {\n            int hi = desc[ih];\n            if ((int)bins[hi].size() <= 1) continue;\n\n            for (int il = 0; il < limL; il++) {\n                int lo = asc[il];\n                if (hi == lo) continue;\n\n                double diff = estSum[hi] - estSum[lo];\n                if (diff <= 0.0) continue;\n\n                double ideal = diff / 2.0;\n\n                vector<int> items = bins[hi];\n                sort(items.begin(), items.end(), [&](int a, int b) {\n                    double da = fabs(estWeight[a] - ideal);\n                    double db = fabs(estWeight[b] - ideal);\n                    if (fabs(da - db) > 1e-12) return da < db;\n                    return estWeight[a] > estWeight[b];\n                });\n\n                int limI = min<int>(8, items.size());\n                for (int i = 0; i < limI; i++) {\n                    int x = items[i];\n                    double score = fabs(estWeight[x] - ideal);\n                    cands.push_back({score, hi, lo, x});\n                }\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const MCand& a, const MCand& b) {\n            return a.score < b.score;\n        });\n\n        for (auto [score, hi, lo, x] : cands) {\n            if (qm.used >= Q) break;\n            if (hi == lo) continue;\n            if ((int)bins[hi].size() <= 1) continue;\n\n            bool exists = false;\n            for (int v : bins[hi]) {\n                if (v == x) {\n                    exists = true;\n                    break;\n                }\n            }\n            if (!exists) continue;\n\n            vector<int> Lset;\n            Lset.reserve(bins[hi].size() - 1);\n            for (int v : bins[hi]) {\n                if (v != x) Lset.push_back(v);\n            }\n            if (Lset.empty()) continue;\n\n            char c = qm.query(Lset, bins[lo]);\n\n            if (c == '>') {\n                do_move(hi, lo, x);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    bool opportunistic_swap_once() {\n        if (qm.used + 1 > Q) return false;\n\n        vector<int> desc(D), asc(D);\n        iota(desc.begin(), desc.end(), 0);\n        iota(asc.begin(), asc.end(), 0);\n\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            return estSum[a] > estSum[b];\n        });\n        sort(asc.begin(), asc.end(), [&](int a, int b) {\n            return estSum[a] < estSum[b];\n        });\n\n        int rem = Q - qm.used;\n        int limBins = (rem >= 50 ? 7 : (rem >= 30 ? 6 : 5));\n        int limItems = (rem >= 50 ? 9 : (rem >= 30 ? 7 : 5));\n\n        int limH = min(D, limBins);\n        int limL = min(D, limBins);\n\n        struct SCand {\n            double score;\n            int hi, lo, x, y;\n        };\n        vector<SCand> cands;\n\n        for (int ih = 0; ih < limH; ih++) {\n            int hi = desc[ih];\n            if ((int)bins[hi].size() <= 1) continue;\n\n            vector<int> heavy = bins[hi];\n            sort(heavy.begin(), heavy.end(), [&](int a, int b) {\n                return estWeight[a] > estWeight[b];\n            });\n            int hItems = min<int>(limItems, heavy.size());\n\n            for (int il = 0; il < limL; il++) {\n                int lo = asc[il];\n                if (hi == lo) continue;\n                if ((int)bins[lo].size() <= 1) continue;\n\n                vector<int> light = bins[lo];\n                sort(light.begin(), light.end(), [&](int a, int b) {\n                    return estWeight[a] < estWeight[b];\n                });\n                int lItems = min<int>(limItems, light.size());\n\n                double diff = estSum[hi] - estSum[lo];\n                if (diff <= 0.0) continue;\n                double ideal = diff / 2.0;\n\n                for (int i = 0; i < hItems; i++) {\n                    for (int j = 0; j < lItems; j++) {\n                        int x = heavy[i];\n                        int y = light[j];\n\n                        double delta = estWeight[x] - estWeight[y];\n                        if (delta <= 1e-12) continue;\n\n                        double score = fabs(delta - ideal);\n                        cands.push_back({score, hi, lo, x, y});\n                    }\n                }\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const SCand& a, const SCand& b) {\n            return a.score < b.score;\n        });\n\n        for (auto [score, hi, lo, x, y] : cands) {\n            if (qm.used >= Q) break;\n            if (hi == lo) continue;\n            if ((int)bins[hi].size() <= 1 || (int)bins[lo].size() <= 1) continue;\n\n            bool ex = false, ey = false;\n            for (int v : bins[hi]) if (v == x) ex = true;\n            for (int v : bins[lo]) if (v == y) ey = true;\n            if (!ex || !ey) continue;\n\n            int known = qm.known_single(x, y);\n            int need = (known == 0 ? 2 : 1);\n            if (qm.used + need > Q) break;\n\n            if (!is_single_greater_for_swap(x, y)) continue;\n            if (qm.used >= Q) break;\n\n            vector<int> Lset, Rset;\n            for (int v : bins[hi]) {\n                if (v != x) Lset.push_back(v);\n            }\n            for (int v : bins[lo]) {\n                if (v != y) Rset.push_back(v);\n            }\n\n            if (Lset.empty() || Rset.empty()) continue;\n\n            char c = qm.query(Lset, Rset);\n\n            if (c == '>') {\n                do_swap(hi, lo, x, y);\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    void opportunistic_improve() {\n        int noChangeRounds = 0;\n\n        while (qm.used < Q && noChangeRounds < 6) {\n            bool changed = false;\n\n            if (!changed) changed = opportunistic_move_once();\n            if (!changed && qm.used + 1 <= Q) changed = opportunistic_swap_once();\n\n            if (changed) noChangeRounds = 0;\n            else noChangeRounds++;\n        }\n    }\n\n    void spend_remaining_queries() {\n        while (qm.used < Q) {\n            qm.query_single(0, 1);\n        }\n    }\n\n    void output_answer() {\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << answer[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n\n    void solve() {\n        int lgN = ceil_log2_int(N);\n        int mergeWorst = N * lgN - (1 << lgN) + 1;\n        mergeWorst = max(0, mergeWorst);\n\n        int lgD = max(1, ceil_log2_int(D));\n        int constructionCostApprox = max(0, N - D) * lgD + D * lgD;\n\n        bool useExactSort = false;\n        int neededAfterSort = max(D, constructionCostApprox / 3);\n        if (Q >= mergeWorst + neededAfterSort) useExactSort = true;\n\n        if (useExactSort) {\n            exact_sort_items();\n        } else {\n            int reserve = min(constructionCostApprox, (int)(Q * 0.40));\n            int target = max(0, Q - reserve);\n            approximate_sort_items(target);\n        }\n\n        make_estimated_weights();\n\n        build_partition();\n\n        if (qm.used < Q) {\n            local_improve();\n        }\n\n        if (qm.used < Q) {\n            opportunistic_improve();\n        }\n\n        spend_remaining_queries();\n\n        output_answer();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    cin >> N >> D >> Q;\n\n    Solver solver(N, D, Q);\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int v, to;\n};\n\nstruct Result {\n    vector<Op> ops;\n    int energy = INT_MAX;\n    bool valid = false;\n};\n\nstatic const int N = 200;\nstatic const int M = 10;\nstatic const int EMPTY_VAL = 1000;\n\nint seg_max(const vector<int>& a) {\n    int mx = 0;\n    for (int x : a) mx = max(mx, x);\n    return mx;\n}\n\nint suffix_max_value(const vector<int>& a, int l) {\n    int mx = 0;\n    for (int i = l; i < (int)a.size(); i++) mx = max(mx, a[i]);\n    return mx;\n}\n\nint stack_min_value(const vector<int>& st) {\n    if (st.empty()) return EMPTY_VAL;\n    int mn = EMPTY_VAL;\n    for (int x : st) mn = min(mn, x);\n    return mn;\n}\n\nint stack_badness(const vector<int>& st) {\n    int bad = 0;\n    for (int i = 1; i < (int)st.size(); i++) {\n        if (st[i - 1] < st[i]) bad += st[i] - st[i - 1];\n    }\n    return bad;\n}\n\nint segment_bad_pairs(const vector<int>& st, int l, int r) {\n    int bad = 0;\n    for (int i = l + 1; i < r; i++) {\n        if (st[i - 1] < st[i]) bad++;\n    }\n    return bad;\n}\n\nbool has_good_destination_mx(const vector<vector<int>>& stacks, int src, int mx) {\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n        if (stacks[d].empty() || stacks[d].back() > mx) return true;\n    }\n    return false;\n}\n\nint future_penalty_stack(const vector<int>& st, int cur, int W) {\n    int p = 0;\n    for (int x : st) {\n        if (x >= cur && x < cur + W) p += cur + W - x;\n    }\n    return p;\n}\n\nint future_min_stack(const vector<int>& st, int cur) {\n    int mn = EMPTY_VAL;\n    for (int x : st) {\n        if (x >= cur) mn = min(mn, x);\n    }\n    return mn;\n}\n\nint choose_destination(\n    const vector<vector<int>>& stacks,\n    int src,\n    const vector<int>& vals,\n    int policy,\n    int cur,\n    mt19937& rng,\n    double noise_amp\n) {\n    int p = policy % 40;\n    int mx = seg_max(vals);\n    int len = (int)vals.size();\n\n    uniform_real_distribution<double> dist(0.0, noise_amp);\n\n    int best = -1;\n    double best_score = 1e100;\n\n    for (int d = 0; d < M; d++) {\n        if (d == src) continue;\n\n        const auto& dst = stacks[d];\n\n        int h = (int)dst.size();\n        bool empty = dst.empty();\n        int top = empty ? EMPTY_VAL : dst.back();\n        bool good_top = empty || top > mx;\n\n        int cached_mn = -1;\n        int cached_bad = -1;\n\n        auto get_mn = [&]() -> int {\n            if (cached_mn == -1) cached_mn = stack_min_value(dst);\n            return cached_mn;\n        };\n\n        auto get_bad = [&]() -> int {\n            if (cached_bad == -1) cached_bad = stack_badness(dst);\n            return cached_bad;\n        };\n\n        auto good_all = [&]() -> bool {\n            return empty || get_mn() > mx;\n        };\n\n        double score = 0.0;\n\n        switch (p) {\n            case 0:\n                if (good_top) score = top * 100.0 + h;\n                else score = 1e6 - top * 100.0 + h;\n                break;\n\n            case 1:\n                score = (good_top ? 0.0 : 100000.0) + h * 100.0 + top;\n                break;\n\n            case 2: {\n                int mn = get_mn();\n                if (good_all()) score = mn * 100.0 + h;\n                else if (good_top) score = 200000.0 + top * 100.0 + h;\n                else score = 1e6 - mn * 50.0 - top * 10.0 + h;\n                break;\n            }\n\n            case 3:\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0;\n                else score = 1e6 + (mx - top) * 100.0 + h;\n                break;\n\n            case 4:\n                score = h * 100.0 + (good_top ? 0.0 : 50000.0) + top;\n                break;\n\n            case 5:\n                if (good_top) score = top * 100.0 - h * 20.0;\n                else score = 1e6 - top * 100.0 - h * 10.0;\n                break;\n\n            case 6:\n                score = (good_top ? 0.0 : 500000.0) - top * 100.0 + h * 10.0;\n                break;\n\n            case 7: {\n                int mn = get_mn();\n                score = (good_top ? 0.0 : 300000.0) - mn * 100.0 - top * 10.0 + h;\n                break;\n            }\n\n            case 8:\n                if (good_top) score = (top - mx) * 200.0 + h;\n                else score = 1e6 + (mx - top) * 200.0 + h;\n                break;\n\n            case 9: {\n                int bad = get_bad();\n                if (good_top) score = top * 100.0 + h * 20.0 + bad * 2.0;\n                else score = 1e6 - top * 100.0 + h * 20.0 + bad * 2.0;\n                break;\n            }\n\n            case 10:\n                if (empty) {\n                    score = 50000.0 + h;\n                } else {\n                    int violation = max(0, mx - top);\n                    score = violation * 10000.0 + (good_top ? top : -top) * 10.0 + h;\n                }\n                break;\n\n            case 11:\n                if (empty) {\n                    score = good_top ? 150000.0 : 1000000.0;\n                } else if (good_top) {\n                    score = (top - mx) * 100.0 + h * 3.0;\n                } else {\n                    score = 1e6 - top * 200.0 + h;\n                }\n                break;\n\n            case 12:\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0 - len * 20.0;\n                else score = 1e6 + (mx - top) * 100.0 + h - len * 20.0;\n                break;\n\n            case 13:\n                if (empty) score = 10000.0 + h;\n                else {\n                    int add = max(0, mx - top);\n                    score = add * 20000.0 + abs(top - mx) * 20.0 + h;\n                }\n                break;\n\n            case 14: {\n                int bad = get_bad();\n                if (good_top) score = (top - mx) * 150.0 + h * 12.0 + bad;\n                else score = 1e6 + (mx - top) * 300.0 - h * 5.0;\n                break;\n            }\n\n            case 15: {\n                int mn = get_mn();\n                if (good_top) score = (top - mx) * 80.0 - mn * 20.0 + h * 10.0;\n                else score = 1e6 - top * 120.0 - mn * 20.0 + h;\n                break;\n            }\n\n            case 16:\n                if (empty) score = 80000.0 - len * 500.0;\n                else if (good_top) score = (top - mx) * 120.0 + h;\n                else score = 1e6 - top * 100.0 + h;\n                break;\n\n            case 17:\n                if (empty) score = 20000.0 - mx * 50.0 - len * 200.0;\n                else if (good_top) score = (top - mx) * 100.0 + h * 8.0;\n                else score = 1e6 + (mx - top) * 100.0 + h;\n                break;\n\n            case 18: {\n                int bad = get_bad();\n                if (good_top) score = (top - mx) * 100.0 + h * 4.0 - bad * 3.0;\n                else score = 1e6 - top * 100.0 - bad * 5.0;\n                break;\n            }\n\n            case 19: {\n                int bad = get_bad();\n                if (good_top) score = (top - mx) * 120.0 + bad * 8.0 + h;\n                else score = 1e6 - top * 150.0 + h;\n                break;\n            }\n\n            case 20: {\n                int f20 = future_penalty_stack(dst, cur, 20);\n                if (good_top) score = (top - mx) * 100.0 + h * 5.0 + f20 * len * 35.0;\n                else score = 1e6 + (mx - top) * 150.0 + f20 * len * 25.0;\n                break;\n            }\n\n            case 21: {\n                int f40 = future_penalty_stack(dst, cur, 40);\n                if (empty) score = 20000.0 - len * 300.0;\n                else if (good_top) score = (top - mx) * 80.0 + f40 * len * 18.0 + h;\n                else score = 1e6 - top * 100.0 + f40 * len * 15.0;\n                break;\n            }\n\n            case 22: {\n                int f20 = future_penalty_stack(dst, cur, 20);\n                int fmin = future_min_stack(dst, cur);\n                if (good_top) score = (top - mx) * 90.0 - fmin * 8.0 + f20 * 120.0 + h;\n                else score = 1e6 + (mx - top) * 120.0 - fmin * 5.0 + f20 * 80.0;\n                break;\n            }\n\n            case 23: {\n                int f20 = future_penalty_stack(dst, cur, 20);\n                int f40 = future_penalty_stack(dst, cur, 40);\n                int mn = get_mn();\n                if (good_all()) score = (mn - mx) * 70.0 + h * 4.0;\n                else if (good_top) score = 50000.0 + (top - mx) * 70.0 + f40 * len * 20.0;\n                else score = 1e6 + (mx - top) * 200.0 + f20 * len * 30.0;\n                break;\n            }\n\n            case 24: {\n                int f20 = future_penalty_stack(dst, cur, 20);\n                if (empty) score = 15000.0 - len * 250.0;\n                else if (good_top) score = (top - mx) * 110.0 + f20 * len * 45.0 + h;\n                else score = 1e6 - top * 100.0 + f20 * len * 30.0;\n                break;\n            }\n\n            case 25: {\n                int f40 = future_penalty_stack(dst, cur, 40);\n                int mn = get_mn();\n                if (good_top) score = (top - mx) * 70.0 - mn * 12.0 + f40 * len * 12.0 + h;\n                else score = 1e6 - top * 100.0 - mn * 10.0 + f40 * len * 10.0;\n                break;\n            }\n\n            case 26: {\n                int fmin = future_min_stack(dst, cur);\n                int f20 = future_penalty_stack(dst, cur, 20);\n                if (good_top) {\n                    int urgent = max(0, cur + 15 - fmin);\n                    score = (top - mx) * 100.0 + urgent * len * 300.0 + h;\n                } else {\n                    score = 1e6 + (mx - top) * 200.0 + f20 * len * 40.0;\n                }\n                break;\n            }\n\n            case 27: {\n                int f20 = future_penalty_stack(dst, cur, 20);\n                if (empty) score = 30000.0 - len * 600.0;\n                else if (good_top) score = (top - mx) * 60.0 + f20 * len * 60.0 - h * 5.0;\n                else score = 1e6 + (mx - top) * 150.0 + f20 * len * 40.0;\n                break;\n            }\n\n            case 28: {\n                int f25 = future_penalty_stack(dst, cur, 25);\n                int bad = get_bad();\n                if (good_top) score = (top - mx) * 85.0 + f25 * len * 32.0 + bad * 4.0 + h;\n                else score = 1e6 + (mx - top) * 170.0 + f25 * len * 25.0 - bad * 2.0;\n                break;\n            }\n\n            case 29: {\n                int fmin = future_min_stack(dst, cur);\n                int urgent = max(0, cur + 25 - fmin);\n                if (empty) score = 25000.0 - len * 350.0;\n                else if (good_top) score = (top - mx) * 75.0 + urgent * len * 180.0 + h * 3.0;\n                else score = 1e6 + (mx - top) * 180.0 + urgent * len * 120.0;\n                break;\n            }\n\n            case 30: {\n                int f35 = future_penalty_stack(dst, cur, 35);\n                int mn = get_mn();\n                if (good_all()) score = (mn - mx) * 45.0 + f35 * len * 8.0 + h;\n                else if (good_top) score = 40000.0 + (top - mx) * 65.0 + f35 * len * 16.0;\n                else score = 1e6 - top * 100.0 + f35 * len * 14.0;\n                break;\n            }\n\n            case 31: {\n                int f20 = future_penalty_stack(dst, cur, 20);\n                int bad = get_bad();\n                if (empty) score = 18000.0 - len * 450.0;\n                else if (good_top) score = (top - mx) * 55.0 + f20 * len * 70.0 - bad * 4.0 - h * 3.0;\n                else score = 1e6 + (mx - top) * 130.0 + f20 * len * 40.0 - bad * 5.0;\n                break;\n            }\n\n            case 32: {\n                int f15 = future_penalty_stack(dst, cur, 15);\n                int fmin = future_min_stack(dst, cur);\n                int urgent = max(0, cur + 18 - fmin);\n                if (empty) score = 22000.0 - len * 420.0;\n                else if (good_top) score = (top - mx) * 70.0 + f15 * len * 95.0 + urgent * len * 120.0 + h;\n                else score = 1e6 + (mx - top) * 170.0 + f15 * len * 55.0;\n                break;\n            }\n\n            case 33: {\n                int f30 = future_penalty_stack(dst, cur, 30);\n                int bad = get_bad();\n                if (good_top) score = (top - mx) * 65.0 + f30 * len * 22.0 - bad * 6.0 + h * 2.0;\n                else score = 1e6 + (mx - top) * 140.0 + f30 * len * 18.0 - bad * 8.0;\n                break;\n            }\n\n            case 34: {\n                int f20 = future_penalty_stack(dst, cur, 20);\n                int mn = get_mn();\n                if (good_all()) score = (mn - mx) * 35.0 + f20 * len * 20.0 - len * 80.0 + h;\n                else if (good_top) score = 35000.0 + (top - mx) * 50.0 + f20 * len * 45.0 + h;\n                else score = 1e6 + (mx - top) * 160.0 + f20 * len * 35.0;\n                break;\n            }\n\n            case 35: {\n                int f45 = future_penalty_stack(dst, cur, 45);\n                if (empty) score = 12000.0 - len * 500.0;\n                else if (good_top) score = (top - mx) * 45.0 + f45 * len * 10.0 - h * 8.0;\n                else score = 1e6 - top * 120.0 + f45 * len * 8.0;\n                break;\n            }\n\n            case 36: {\n                int f12 = future_penalty_stack(dst, cur, 12);\n                int urgent = max(0, cur + 14 - future_min_stack(dst, cur));\n                if (empty) score = 16000.0 - len * 520.0;\n                else if (good_top) score = (top - mx) * 50.0 + f12 * len * 120.0 + urgent * len * 140.0;\n                else score = 1e6 + (mx - top) * 180.0 + f12 * len * 70.0;\n                break;\n            }\n\n            case 37: {\n                int bad = get_bad();\n                int f30 = future_penalty_stack(dst, cur, 30);\n                int mn = get_mn();\n                if (good_all()) score = (mn - mx) * 28.0 + f30 * len * 10.0 - bad * 2.0;\n                else if (good_top) score = 28000.0 + (top - mx) * 48.0 + f30 * len * 24.0 + bad;\n                else score = 1e6 + (mx - top) * 130.0 + f30 * len * 20.0 - bad * 4.0;\n                break;\n            }\n\n            case 38: {\n                int f20 = future_penalty_stack(dst, cur, 20);\n                int bad = get_bad();\n                if (empty) score = 20000.0 - len * 300.0;\n                else if (good_top) score = (top - mx) * 35.0 + f20 * len * 55.0 - bad * 10.0 - h * 4.0;\n                else score = 1e6 + (mx - top) * 110.0 + f20 * len * 38.0 - bad * 12.0;\n                break;\n            }\n\n            case 39: {\n                int f50 = future_penalty_stack(dst, cur, 50);\n                if (empty) score = 10000.0 - len * 650.0;\n                else if (good_top) score = (top - mx) * 38.0 + f50 * len * 7.0 - h * 10.0;\n                else score = 1e6 - top * 130.0 + f50 * len * 6.0;\n                break;\n            }\n        }\n\n        if (noise_amp > 0.0) score += dist(rng);\n\n        if (score < best_score) {\n            best_score = score;\n            best = d;\n        }\n    }\n\n    return best;\n}\n\nint choose_left_index(\n    const vector<vector<int>>& stacks,\n    int s,\n    int pos,\n    int split_mode\n) {\n    const auto& st = stacks[s];\n    int h = (int)st.size();\n\n    if (split_mode == 0) return pos + 1;\n    if (split_mode == 2) return h - 1;\n\n    int run_start = h - 1;\n    while (run_start - 1 > pos && st[run_start - 1] > st[run_start]) {\n        run_start--;\n    }\n\n    if (split_mode == 1) return run_start;\n\n    auto good_l = [&](int l) {\n        return has_good_destination_mx(stacks, s, suffix_max_value(st, l));\n    };\n\n    if (split_mode == 3) {\n        for (int l = run_start; l <= h - 1; l++) {\n            if (good_l(l)) return l;\n        }\n        return run_start;\n    }\n\n    if (split_mode == 4) {\n        for (int l = run_start; l <= h - 1; l++) {\n            if (good_l(l)) return l;\n        }\n        return pos + 1;\n    }\n\n    if (split_mode == 5) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = run_start; l <= h - 1; l++) {\n            int len = h - l;\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n            double score = (good ? 0.0 : 100000.0 + mx * 10.0) - len * 120.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 6) {\n        if (good_l(run_start)) return run_start;\n        if (good_l(h - 1)) return h - 1;\n        return run_start;\n    }\n\n    if (split_mode == 7) {\n        int best_l = pos + 1;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n            double score = bad * 550.0 + (good ? 0.0 : 5000.0) - len * 80.0 + mx * 0.03;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 8) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            bool good = good_l(l);\n            double score = (good ? 0.0 : 8000.0) + bad * 1000.0 - len * 45.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 9) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            bool good = good_l(l);\n            double score = (good ? 0.0 : 3000.0) + bad * 700.0 - len * 100.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 10) {\n        for (int l = h - 1; l >= run_start; l--) {\n            if (good_l(l)) return l;\n        }\n        return h - 1;\n    }\n\n    if (split_mode == 11) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = run_start; l < h; l++) {\n            int len = h - l;\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n            double score = (good ? 0.0 : 20000.0) + mx * 2.0 + len * 18.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 12) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = run_start; l < h; l++) {\n            int len = h - l;\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n            double score = (good ? 0.0 : 15000.0) + abs(len - 4) * 90.0 + mx * 0.5;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 13) {\n        if (good_l(run_start)) return run_start;\n\n        for (int l = run_start + 1; l < h; l++) {\n            if (good_l(l)) return l;\n        }\n\n        return h - 1;\n    }\n\n    if (split_mode == 14) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n            double score = bad * 850.0 + (good ? 0.0 : 12000.0)\n                         + abs(len - 3) * 70.0 + mx * 0.8;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 15) {\n        int best_l = h - 1;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            bool good = good_l(l);\n            double score = (good ? -200.0 : 5000.0) + bad * 1200.0 - len * 30.0;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 16) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n            double score = bad * 950.0 + (good ? 0.0 : 7000.0) - len * 135.0 + mx * 0.25;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 17) {\n        int best_l = h - 1;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n            double score = (good ? -1200.0 : 9000.0) + bad * 1500.0\n                         + abs(len - 2) * 80.0 + mx * 0.4;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 18) {\n        int best_l = run_start;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n\n            double score = bad * 1100.0 + (good ? -len * 160.0 : 6500.0 - len * 70.0)\n                         + mx * 0.18;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    if (split_mode == 19) {\n        int best_l = h - 1;\n        double best_score = 1e100;\n\n        for (int l = pos + 1; l < h; l++) {\n            int len = h - l;\n            int bad = segment_bad_pairs(st, l, h);\n            int mx = suffix_max_value(st, l);\n            bool good = has_good_destination_mx(stacks, s, mx);\n\n            double score = (good ? -800.0 : 10000.0) + bad * 1700.0\n                         + abs(len - 5) * 75.0 + mx * 0.3;\n\n            if (score < best_score) {\n                best_score = score;\n                best_l = l;\n            }\n        }\n\n        return best_l;\n    }\n\n    return run_start;\n}\n\nResult simulate(\n    const vector<vector<int>>& initial,\n    int split_mode,\n    int policy,\n    uint32_t seed,\n    double noise_amp\n) {\n    mt19937 rng(seed);\n\n    vector<vector<int>> stacks = initial;\n    vector<Op> ops;\n    int energy = 0;\n\n    for (int cur = 1; cur <= N; cur++) {\n        int s = -1, pos = -1;\n\n        for (int i = 0; i < M; i++) {\n            for (int j = 0; j < (int)stacks[i].size(); j++) {\n                if (stacks[i][j] == cur) {\n                    s = i;\n                    pos = j;\n                }\n            }\n        }\n\n        if (s == -1) return Result{};\n\n        while (pos != (int)stacks[s].size() - 1) {\n            if ((int)ops.size() >= 5000) return Result{};\n\n            int h = (int)stacks[s].size();\n\n            int l;\n            if ((int)ops.size() > 4600) {\n                l = pos + 1;\n            } else {\n                l = choose_left_index(stacks, s, pos, split_mode);\n            }\n\n            if (l <= pos || l >= h) return Result{};\n\n            vector<int> vals(stacks[s].begin() + l, stacks[s].end());\n\n            int d = choose_destination(stacks, s, vals, policy, cur, rng, noise_amp);\n            if (d < 0 || d == s) return Result{};\n\n            ops.push_back({vals.front(), d + 1});\n            energy += (int)vals.size() + 1;\n\n            stacks[s].erase(stacks[s].begin() + l, stacks[s].end());\n            stacks[d].insert(stacks[d].end(), vals.begin(), vals.end());\n\n            if ((int)ops.size() > 5000) return Result{};\n        }\n\n        if (stacks[s].empty() || stacks[s].back() != cur) {\n            return Result{};\n        }\n\n        ops.push_back({cur, 0});\n        stacks[s].pop_back();\n\n        if ((int)ops.size() > 5000) return Result{};\n    }\n\n    Result res;\n    res.ops = move(ops);\n    res.energy = energy;\n    res.valid = true;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> initial(M);\n\n    for (int i = 0; i < M; i++) {\n        initial[i].resize(N / M);\n        for (int j = 0; j < N / M; j++) {\n            cin >> initial[i][j];\n        }\n    }\n\n    uint32_t base_seed = 123456789u;\n    for (int i = 0; i < M; i++) {\n        for (int x : initial[i]) {\n            base_seed = base_seed * 1000003u + (uint32_t)x;\n        }\n    }\n\n    Result best;\n\n    auto try_result = [&](const Result& r) {\n        if (!r.valid) return;\n        if ((int)r.ops.size() > 5000) return;\n\n        if (!best.valid ||\n            r.energy < best.energy ||\n            (r.energy == best.energy && r.ops.size() < best.ops.size())) {\n            best = r;\n        }\n    };\n\n    auto start_time = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    for (int split = 0; split <= 6; split++) {\n        for (int policy = 0; policy < 14; policy++) {\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + split * 1009u + policy * 9176u,\n                0.0\n            );\n            try_result(r);\n        }\n    }\n\n    mt19937 rng(base_seed ^ 0x9e3779b9u);\n\n    int iter = 0;\n\n    while (elapsed() <= 1.80) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 10) split = 0;\n        else if (sr < 35) split = 1;\n        else if (sr < 45) split = 2;\n        else if (sr < 70) split = 3;\n        else if (sr < 82) split = 4;\n        else if (sr < 94) split = 5;\n        else split = 6;\n\n        int policy = rng() % 14;\n\n        double noise;\n        int nr = rng() % 7;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 3.0;\n        else if (nr == 2) noise = 10.0;\n        else if (nr == 3) noise = 30.0;\n        else if (nr == 4) noise = 100.0;\n        else if (nr == 5) noise = 400.0;\n        else noise = 1500.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 1000003u + (uint32_t)iter * 17777u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    bool stop_det = false;\n    for (int split = 7; split <= 9 && !stop_det; split++) {\n        for (int policy = 0; policy < 20; policy++) {\n            if (elapsed() > 1.86) {\n                stop_det = true;\n                break;\n            }\n\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + 777777u + split * 2003u + policy * 10007u,\n                0.0\n            );\n            try_result(r);\n        }\n    }\n\n    while (elapsed() <= 1.88) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 8) split = 0;\n        else if (sr < 22) split = 1;\n        else if (sr < 30) split = 2;\n        else if (sr < 45) split = 3;\n        else if (sr < 55) split = 4;\n        else if (sr < 65) split = 5;\n        else if (sr < 72) split = 6;\n        else if (sr < 84) split = 7;\n        else if (sr < 94) split = 8;\n        else split = 9;\n\n        int policy = rng() % 20;\n\n        double noise;\n        int nr = rng() % 8;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 2.0;\n        else if (nr == 2) noise = 8.0;\n        else if (nr == 3) noise = 25.0;\n        else if (nr == 4) noise = 80.0;\n        else if (nr == 5) noise = 250.0;\n        else if (nr == 6) noise = 800.0;\n        else noise = 2000.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 3000001u + (uint32_t)iter * 31417u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    bool stop_future_det = false;\n    for (int split = 0; split <= 13 && !stop_future_det; split++) {\n        for (int policy = 20; policy < 28; policy++) {\n            if (elapsed() > 1.905) {\n                stop_future_det = true;\n                break;\n            }\n\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + 9876543u + split * 1237u + policy * 7919u,\n                0.0\n            );\n            try_result(r);\n        }\n    }\n\n    while (elapsed() <= 1.92) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 7) split = 0;\n        else if (sr < 18) split = 1;\n        else if (sr < 25) split = 2;\n        else if (sr < 38) split = 3;\n        else if (sr < 48) split = 4;\n        else if (sr < 58) split = 5;\n        else if (sr < 65) split = 6;\n        else if (sr < 73) split = 7;\n        else if (sr < 80) split = 8;\n        else if (sr < 86) split = 9;\n        else if (sr < 91) split = 10;\n        else if (sr < 95) split = 11;\n        else if (sr < 98) split = 12;\n        else split = 13;\n\n        int policy = 20 + (rng() % 8);\n\n        double noise;\n        int nr = rng() % 6;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 5.0;\n        else if (nr == 2) noise = 20.0;\n        else if (nr == 3) noise = 80.0;\n        else if (nr == 4) noise = 300.0;\n        else noise = 1000.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 5555555u + (uint32_t)iter * 27183u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    while (elapsed() <= 1.94) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 8) split = 3;\n        else if (sr < 18) split = 5;\n        else if (sr < 28) split = 7;\n        else if (sr < 40) split = 8;\n        else if (sr < 52) split = 9;\n        else if (sr < 62) split = 10;\n        else if (sr < 72) split = 11;\n        else if (sr < 82) split = 12;\n        else if (sr < 90) split = 13;\n        else if (sr < 96) split = 14;\n        else split = 15;\n\n        int policy = 20 + (rng() % 12);\n\n        double noise;\n        int nr = rng() % 7;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 3.0;\n        else if (nr == 2) noise = 12.0;\n        else if (nr == 3) noise = 40.0;\n        else if (nr == 4) noise = 120.0;\n        else if (nr == 5) noise = 400.0;\n        else noise = 1200.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 24681357u + (uint32_t)iter * 19249u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    while (elapsed() <= 1.955) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 10) split = 8;\n        else if (sr < 22) split = 9;\n        else if (sr < 34) split = 10;\n        else if (sr < 46) split = 11;\n        else if (sr < 58) split = 12;\n        else if (sr < 70) split = 13;\n        else if (sr < 82) split = 14;\n        else if (sr < 92) split = 15;\n        else if (sr < 97) split = 16;\n        else split = 17;\n\n        int policy = 28 + (rng() % 8);\n\n        double noise;\n        int nr = rng() % 6;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 4.0;\n        else if (nr == 2) noise = 16.0;\n        else if (nr == 3) noise = 60.0;\n        else if (nr == 4) noise = 220.0;\n        else noise = 900.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 135792468u + (uint32_t)iter * 25117u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    while (elapsed() <= 1.965) {\n        int split;\n        int sr = (int)(rng() % 100);\n        if (sr < 8) split = 10;\n        else if (sr < 18) split = 11;\n        else if (sr < 30) split = 12;\n        else if (sr < 42) split = 13;\n        else if (sr < 56) split = 14;\n        else if (sr < 70) split = 15;\n        else if (sr < 82) split = 16;\n        else if (sr < 92) split = 17;\n        else if (sr < 97) split = 18;\n        else split = 19;\n\n        int policy = 32 + (rng() % 8);\n\n        double noise;\n        int nr = rng() % 6;\n        if (nr == 0) noise = 0.0;\n        else if (nr == 1) noise = 2.0;\n        else if (nr == 2) noise = 10.0;\n        else if (nr == 3) noise = 35.0;\n        else if (nr == 4) noise = 140.0;\n        else noise = 600.0;\n\n        Result r = simulate(\n            initial,\n            split,\n            policy,\n            base_seed + 42424242u + (uint32_t)iter * 34567u,\n            noise\n        );\n\n        try_result(r);\n        iter++;\n    }\n\n    bool stop_last = false;\n    for (int split = 14; split <= 19 && !stop_last; split++) {\n        for (int policy = 32; policy < 40; policy++) {\n            if (elapsed() > 1.972) {\n                stop_last = true;\n                break;\n            }\n\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + 31415926u + split * 4441u + policy * 15511u,\n                0.0\n            );\n\n            try_result(r);\n        }\n    }\n\n    // Tiny deterministic coverage phase for combinations not covered above.\n    bool stop_cover = false;\n    for (int split = 10; split <= 13 && !stop_cover; split++) {\n        for (int policy = 28; policy < 40; policy++) {\n            if (elapsed() > 1.982) {\n                stop_cover = true;\n                break;\n            }\n\n            Result r = simulate(\n                initial,\n                split,\n                policy,\n                base_seed + 27182818u + split * 3331u + policy * 17239u,\n                0.0\n            );\n\n            try_result(r);\n        }\n    }\n\n    if (!best.valid) {\n        best = simulate(initial, 0, 0, base_seed, 0.0);\n    }\n\n    for (const auto& op : best.ops) {\n        cout << op.v << ' ' << op.to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const uint16_t INF16 = 65535;\n\nstruct Edge {\n    int to;\n    char c;\n};\n\nstruct XorShift {\n    uint32_t x = 2463534242u;\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    double real01() {\n        return (next() >> 8) * (1.0 / 16777216.0);\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto time_start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n    };\n\n    int N;\n    cin >> N;\n\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    int V = N * N;\n    vector<int> dirt(V);\n    long long sumD = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> dirt[i * N + j];\n            sumD += dirt[i * N + j];\n        }\n    }\n\n    double avgD = (double)sumD / V;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    vector<vector<Edge>> g(V);\n\n    auto add_edge = [&](int a, int b, char c1, char c2) {\n        g[a].push_back({b, c1});\n        g[b].push_back({a, c2});\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (i + 1 < N && h[i][j] == '0') {\n                add_edge(id(i, j), id(i + 1, j), 'D', 'U');\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                add_edge(id(i, j), id(i, j + 1), 'R', 'L');\n            }\n        }\n    }\n\n    auto rev_dir = [&](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    auto make_fallback_dfs = [&]() {\n        vector<char> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n            for (const auto &e : g[cur]) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n                    route.push_back(rev_dir(e.c));\n                }\n            }\n        };\n\n        dfs(0);\n        return route;\n    };\n\n    string fallbackRoute = make_fallback_dfs();\n\n    auto legal_route = [&](const string &route) -> bool {\n        if (route.empty() || route.size() > 100000) return false;\n\n        vector<char> vis(V, 0);\n        int cur = 0;\n        vis[0] = 1;\n\n        for (char c : route) {\n            bool ok = false;\n            for (const auto &e : g[cur]) {\n                if (e.c == c) {\n                    cur = e.to;\n                    ok = true;\n                    break;\n                }\n            }\n            if (!ok) return false;\n            vis[cur] = 1;\n        }\n\n        if (cur != 0) return false;\n\n        for (int i = 0; i < V; i++) {\n            if (!vis[i]) return false;\n        }\n\n        return true;\n    };\n\n    vector<uint16_t> dist((size_t)V * V, INF16);\n    vector<int> que(V);\n\n    for (int s = 0; s < V; s++) {\n        uint16_t *ds = &dist[(size_t)s * V];\n        int head = 0, tail = 0;\n        ds[s] = 0;\n        que[tail++] = s;\n\n        while (head < tail) {\n            int cur = que[head++];\n            uint16_t nd = ds[cur] + 1;\n\n            for (const auto &e : g[cur]) {\n                if (ds[e.to] == INF16) {\n                    ds[e.to] = nd;\n                    que[tail++] = e.to;\n                }\n            }\n        }\n    }\n\n    int maxDist = 0;\n    for (int i = 0; i < V; i++) {\n        for (int j = 0; j < V; j++) {\n            maxDist = max(maxDist, (int)dist[(size_t)i * V + j]);\n        }\n    }\n\n    vector<double> alphas = {1.0, 1.35, 1.7, 2.1, 2.7, 3.5};\n    vector<vector<double>> denom(alphas.size(), vector<double>(maxDist + 3));\n\n    for (int a = 0; a < (int)alphas.size(); a++) {\n        for (int d = 0; d <= maxDist + 2; d++) {\n            denom[a][d] = pow((double)max(1, d), alphas[a]);\n        }\n    }\n\n    auto score_route = [&](const string &route) -> long double {\n        int L = (int)route.size();\n        if (L <= 0 || L > 100000) return 1e100L;\n\n        vector<int> first(V, -1), prev(V, -1);\n        vector<long long> gapSum(V, 0);\n\n        auto visit = [&](int x, int t) {\n            if (first[x] == -1) {\n                first[x] = prev[x] = t;\n            } else {\n                long long gap = t - prev[x];\n                gapSum[x] += gap * (gap - 1);\n                prev[x] = t;\n            }\n        };\n\n        int cur = 0;\n        visit(0, 0);\n\n        for (int t = 1; t <= L; t++) {\n            char c = route[t - 1];\n            bool ok = false;\n\n            for (const auto &e : g[cur]) {\n                if (e.c == c) {\n                    cur = e.to;\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return 1e100L;\n\n            if (t < L) {\n                visit(cur, t);\n            }\n        }\n\n        if (cur != 0) return 1e100L;\n\n        long double total = 0.0L;\n\n        for (int x = 0; x < V; x++) {\n            if (first[x] == -1) return 1e100L;\n\n            long long gap = L - prev[x] + first[x];\n            long long s = gapSum[x] + gap * (gap - 1);\n\n            total += (long double)dirt[x] * (long double)s / (2.0L * L);\n        }\n\n        return total;\n    };\n\n    string bestRoute = fallbackRoute;\n    long double bestScore = score_route(bestRoute);\n\n    auto consider = [&](const string &route) {\n        if (route.empty() || route.size() > 100000) return;\n        if (!legal_route(route)) return;\n\n        long double sc = score_route(route);\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n        }\n    };\n\n    XorShift rng;\n\n    auto make_dfs_route = [&](int mode, double rndWeight) {\n        vector<char> used(V, 0);\n        string route;\n\n        function<void(int)> dfs = [&](int cur) {\n            used[cur] = 1;\n\n            vector<Edge> es = g[cur];\n\n            if (mode == 1) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] > dirt[b.to];\n                });\n            } else if (mode == 2) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return dirt[a.to] < dirt[b.to];\n                });\n            } else if (mode == 3) {\n                sort(es.begin(), es.end(), [&](const Edge &a, const Edge &b) {\n                    return a.c < b.c;\n                });\n            } else if (mode == 4) {\n                vector<pair<double, Edge>> keyed;\n                keyed.reserve(es.size());\n\n                for (const auto &e : es) {\n                    double key = log(1.0 + dirt[e.to]) + rndWeight * rng.real01();\n                    keyed.push_back({-key, e});\n                }\n\n                sort(keyed.begin(), keyed.end(), [](const auto &a, const auto &b) {\n                    return a.first < b.first;\n                });\n\n                es.clear();\n                for (const auto &p : keyed) es.push_back(p.second);\n            }\n\n            for (const auto &e : es) {\n                if (!used[e.to]) {\n                    route.push_back(e.c);\n                    dfs(e.to);\n                    route.push_back(rev_dir(e.c));\n                }\n            }\n        };\n\n        dfs(0);\n        return route;\n    };\n\n    for (int mode = 0; mode < 4; mode++) {\n        consider(make_dfs_route(mode, 0.0));\n    }\n\n    for (int rep = 0; rep < 60 && elapsed() < 0.35; rep++) {\n        consider(make_dfs_route(4, 0.5 + 4.0 * rng.real01()));\n    }\n\n    auto append_path = [&](string &route,\n                           int &cur,\n                           int target,\n                           int &t,\n                           vector<int> &last,\n                           vector<char> &visited,\n                           int &visitedCnt) {\n        while (cur != target) {\n            uint16_t dc = dist[(size_t)cur * V + target];\n\n            int bestNext = -1;\n            char bestChar = '?';\n            double bestVal = -1e100;\n\n            for (const auto &e : g[cur]) {\n                if (dist[(size_t)e.to * V + target] + 1 == dc) {\n                    double val = 0.0;\n\n                    if (!visited[e.to]) {\n                        val += avgD * 1000000.0;\n                    }\n\n                    val += (double)dirt[e.to] * (double)(t - last[e.to] + 1);\n                    val += 0.001 * rng.real01();\n\n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestNext = e.to;\n                        bestChar = e.c;\n                    }\n                }\n            }\n\n            if (bestNext == -1) return;\n\n            route.push_back(bestChar);\n            cur = bestNext;\n            t++;\n\n            last[cur] = t;\n\n            if (!visited[cur]) {\n                visited[cur] = 1;\n                visitedCnt++;\n            }\n\n            if ((int)route.size() > 100000) return;\n        }\n    };\n\n    auto generate_cover_then_patrol = [&](int cap,\n                                          int covAlphaIdx,\n                                          int patAlphaIdx,\n                                          double coverBiasMul,\n                                          bool noise) {\n        string route;\n        route.reserve(min(100000, max(cap, 2 * V)));\n\n        vector<int> last(V, 0);\n        vector<char> visited(V, 0);\n\n        int visitedCnt = 1;\n        int cur = 0;\n        int t = 0;\n\n        visited[0] = 1;\n\n        double coverBias = avgD * coverBiasMul;\n\n        while (visitedCnt < V && (int)route.size() <= 100000) {\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                if (visited[x]) continue;\n\n                int ds = dist[(size_t)cur * V + x];\n                double val = (coverBias + dirt[x]) / denom[covAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n\n            if ((int)route.size() > 100000) break;\n        }\n\n        int limit = cap;\n        if (limit <= 0) limit = (int)route.size();\n        limit = min(limit, 100000);\n\n        int loop = 0;\n\n        while ((int)route.size() + dist[(size_t)cur * V + 0] < limit &&\n               (int)route.size() < 100000) {\n            if ((++loop & 255) == 0 && elapsed() > 1.82) break;\n\n            int target = -1;\n            double bestVal = -1.0;\n\n            for (int x = 0; x < V; x++) {\n                int ds = dist[(size_t)cur * V + x];\n                if (ds == 0) continue;\n\n                int ret = dist[(size_t)x * V + 0];\n\n                if ((int)route.size() + ds + ret > limit) continue;\n\n                int age = t - last[x];\n\n                double val = (double)dirt[x] * (age + 1) / denom[patAlphaIdx][ds + 1];\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) break;\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n        }\n\n        append_path(route, cur, 0, t, last, visited, visitedCnt);\n\n        return route;\n    };\n\n    auto generate_mixed = [&](int cap,\n                              int alphaIdx,\n                              double unvisitedWeight,\n                              int betaMode,\n                              double forceRatio,\n                              int minPatrolDist,\n                              bool noise) {\n        string route;\n        route.reserve(min(100000, max(cap, 2 * V)));\n\n        vector<int> last(V, 0);\n        vector<char> visited(V, 0);\n\n        int visitedCnt = 1;\n        int cur = 0;\n        int t = 0;\n\n        visited[0] = 1;\n\n        int hardLimit = min(100000, cap);\n        if (hardLimit <= 0) hardLimit = 100000;\n\n        int loop = 0;\n\n        while ((int)route.size() < hardLimit) {\n            if ((++loop & 127) == 0 && elapsed() > 1.84) break;\n\n            int retNow = dist[(size_t)cur * V + 0];\n            if ((int)route.size() + retNow >= hardLimit) break;\n\n            bool forceCover = false;\n            if (visitedCnt < V && (int)route.size() > (int)(hardLimit * forceRatio)) {\n                forceCover = true;\n            }\n\n            int target = -1;\n            double bestVal = -1e100;\n\n            for (int x = 0; x < V; x++) {\n                if (x == cur) continue;\n\n                if (forceCover && visited[x]) continue;\n\n                int ds = dist[(size_t)cur * V + x];\n                int ret = dist[(size_t)x * V + 0];\n\n                if ((int)route.size() + ds + ret > hardLimit) continue;\n\n                if (visitedCnt == V && ds < minPatrolDist) continue;\n\n                int age = t - last[x];\n                double a = age + ds + 1.0;\n\n                double val;\n\n                if (betaMode == 2) {\n                    val = (double)dirt[x] * a * a / denom[alphaIdx][ds + 1];\n                } else {\n                    val = (double)dirt[x] * a / denom[alphaIdx][ds + 1];\n                }\n\n                if (!visited[x]) {\n                    double remainRatio = (double)V / max(1, V - visitedCnt);\n                    val += unvisitedWeight * avgD * remainRatio * (t + 50.0) / denom[alphaIdx][ds + 1];\n                }\n\n                if (noise) val *= 0.85 + 0.30 * rng.real01();\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    target = x;\n                }\n            }\n\n            if (target == -1) {\n                if (visitedCnt == V && minPatrolDist > 1) {\n                    minPatrolDist = 1;\n                    continue;\n                }\n                break;\n            }\n\n            append_path(route, cur, target, t, last, visited, visitedCnt);\n\n            if ((int)route.size() > 100000) break;\n        }\n\n        append_path(route, cur, 0, t, last, visited, visitedCnt);\n\n        return route;\n    };\n\n    vector<int> caps = {\n        2 * V,\n        3 * V,\n        4 * V,\n        5 * V,\n        7 * V,\n        10 * V,\n        14 * V,\n        20000,\n        30000,\n        45000,\n        65000,\n        100000\n    };\n\n    for (int &x : caps) {\n        x = min(100000, max(1, x));\n    }\n\n    sort(caps.begin(), caps.end());\n    caps.erase(unique(caps.begin(), caps.end()), caps.end());\n\n    struct CP {\n        int cap;\n        int ca;\n        int pa;\n        double bias;\n        bool noise;\n    };\n\n    vector<CP> cps;\n\n    cps.push_back({0, 4, 1, 20.0, false});\n    cps.push_back({0, 3, 1, 20.0, false});\n    cps.push_back({0, 3, 1, 5.0, false});\n    cps.push_back({0, 2, 1, 0.0, false});\n\n    for (int cap : caps) {\n        cps.push_back({cap, 3, 1, 10.0, false});\n        cps.push_back({cap, 2, 1, 5.0, false});\n    }\n\n    cps.push_back({30000, 3, 0, 10.0, false});\n    cps.push_back({60000, 3, 0, 10.0, false});\n    cps.push_back({100000, 3, 0, 10.0, false});\n    cps.push_back({60000, 3, 1, 10.0, true});\n    cps.push_back({100000, 3, 1, 10.0, true});\n\n    for (const auto &p : cps) {\n        if (elapsed() > 1.70) break;\n        consider(generate_cover_then_patrol(p.cap, p.ca, p.pa, p.bias, p.noise));\n    }\n\n    struct MP {\n        int cap;\n        int alpha;\n        double uw;\n        int beta;\n        double forceRatio;\n        int minDist;\n        bool noise;\n    };\n\n    vector<MP> mps;\n\n    for (int cap : caps) {\n        mps.push_back({cap, 2, 25.0, 1, 0.55, 3, false});\n        mps.push_back({cap, 2, 40.0, 1, 0.65, 4, false});\n    }\n\n    mps.push_back({30000, 1, 20.0, 2, 0.60, 3, false});\n    mps.push_back({45000, 1, 20.0, 2, 0.60, 4, false});\n    mps.push_back({65000, 1, 20.0, 2, 0.65, 5, false});\n    mps.push_back({100000, 1, 15.0, 2, 0.70, 6, false});\n\n    mps.push_back({30000, 2, 30.0, 1, 0.60, 3, true});\n    mps.push_back({65000, 2, 30.0, 1, 0.65, 4, true});\n    mps.push_back({100000, 2, 25.0, 1, 0.70, 5, true});\n\n    for (const auto &p : mps) {\n        if (elapsed() > 1.86) break;\n        consider(generate_mixed(p.cap, p.alpha, p.uw, p.beta, p.forceRatio, p.minDist, p.noise));\n    }\n\n    // Slightly extended successful late-random phase.\n    int extra = 0;\n    while (elapsed() < 1.94 && extra < 30) {\n        int cap = caps[rng.randint((int)caps.size())];\n        int ca = 2 + rng.randint(3);\n        int pa = rng.randint(3);\n        double bias = 2.0 + 25.0 * rng.real01();\n\n        consider(generate_cover_then_patrol(cap, ca, pa, bias, true));\n        extra++;\n    }\n\n    // Focused high-budget variants. No additional tail afterwards.\n    vector<CP> focused = {\n        {45000, 2, 0, 12.0, true},\n        {65000, 2, 0, 12.0, true},\n        {100000, 2, 0, 12.0, true},\n        {100000, 4, 0, 5.0, true},\n        {80000, 3, 0, 8.0, true}\n    };\n\n    for (const auto &p : focused) {\n        if (elapsed() > 1.965) break;\n        consider(generate_cover_then_patrol(p.cap, p.ca, p.pa, p.bias, p.noise));\n    }\n\n    if (!legal_route(bestRoute)) {\n        bestRoute = fallbackRoute;\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\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 nextInt(int n) {\n        return (int)(next() % n);\n    }\n    double nextDouble() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nint N, M;\nint si, sj;\nvector<string> Agrid;\nvector<string> t;\nvector<pair<int,int>> occ[26];\nint mindist_ch[26][26];\n\nconst int POW5 = 26 * 26 * 26 * 26 * 26;\nvector<int> codeId;\n\nchrono::steady_clock::time_point timeStart;\n\ndouble elapsedTime() {\n    return chrono::duration<double>(chrono::steady_clock::now() - timeStart).count();\n}\n\nint manhattan(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nint wordCode(const string& s) {\n    int c = 0;\n    for (char ch : s) c = c * 26 + (ch - 'A');\n    return c;\n}\n\nint overlap_word(const string& a, const string& b) {\n    for (int k = 4; k >= 1; --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) return k;\n    }\n    return 0;\n}\n\nint overlap_suffix_string(const string& s, const string& w) {\n    int lim = min<int>(4, s.size());\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (s[(int)s.size() - k + i] != w[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nint typingCostOnly(const string& s) {\n    const int INF = 1e9;\n    vector<int> dp_prev, dp_cur;\n\n    for (int pos = 0; pos < (int)s.size(); ++pos) {\n        int c = s[pos] - 'A';\n        int C = (int)occ[c].size();\n\n        dp_cur.assign(C, INF);\n\n        if (pos == 0) {\n            pair<int,int> start = {si, sj};\n            for (int i = 0; i < C; ++i) {\n                dp_cur[i] = manhattan(start, occ[c][i]) + 1;\n            }\n        } else {\n            int pc = s[pos - 1] - 'A';\n            int P = (int)occ[pc].size();\n\n            for (int i = 0; i < C; ++i) {\n                int best = INF;\n                for (int j = 0; j < P; ++j) {\n                    int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                    if (val < best) best = val;\n                }\n                dp_cur[i] = best;\n            }\n        }\n\n        dp_prev.swap(dp_cur);\n    }\n\n    return *min_element(dp_prev.begin(), dp_prev.end());\n}\n\nint segmentCostFromChar(int prevChar, const string& w, int from) {\n    const int INF = 1e9;\n\n    vector<int> dp_prev((int)occ[prevChar].size(), 0), dp_cur;\n    int pc = prevChar;\n\n    for (int k = from; k < 5; ++k) {\n        int c = w[k] - 'A';\n        int C = (int)occ[c].size();\n        int P = (int)occ[pc].size();\n\n        dp_cur.assign(C, INF);\n\n        for (int i = 0; i < C; ++i) {\n            int best = INF;\n            for (int j = 0; j < P; ++j) {\n                int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                if (val < best) best = val;\n            }\n            dp_cur[i] = best;\n        }\n\n        dp_prev.swap(dp_cur);\n        pc = c;\n    }\n\n    return *min_element(dp_prev.begin(), dp_prev.end());\n}\n\nint suffixCostFromPos(pair<int,int> pos, const string& w, int from) {\n    const int INF = 1e9;\n    if (from >= 5) return 0;\n\n    vector<int> dp_prev, dp_cur;\n\n    int c0 = w[from] - 'A';\n    int C0 = (int)occ[c0].size();\n    dp_prev.assign(C0, INF);\n\n    for (int i = 0; i < C0; ++i) {\n        dp_prev[i] = manhattan(pos, occ[c0][i]) + 1;\n    }\n\n    int pc = c0;\n\n    for (int k = from + 1; k < 5; ++k) {\n        int c = w[k] - 'A';\n        int C = (int)occ[c].size();\n        int P = (int)occ[pc].size();\n\n        dp_cur.assign(C, INF);\n\n        for (int i = 0; i < C; ++i) {\n            int best = INF;\n            for (int j = 0; j < P; ++j) {\n                int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                if (val < best) best = val;\n            }\n            dp_cur[i] = best;\n        }\n\n        dp_prev.swap(dp_cur);\n        pc = c;\n    }\n\n    return *min_element(dp_prev.begin(), dp_prev.end());\n}\n\npair<int,int> representativeEndPos(const string& w) {\n    const int INF = 1e9;\n\n    int c0 = w[0] - 'A';\n    vector<int> dp_prev((int)occ[c0].size(), 0), dp_cur;\n    int pc = c0;\n\n    for (int k = 1; k < 5; ++k) {\n        int c = w[k] - 'A';\n        int C = (int)occ[c].size();\n        int P = (int)occ[pc].size();\n\n        dp_cur.assign(C, INF);\n\n        for (int i = 0; i < C; ++i) {\n            int best = INF;\n            for (int j = 0; j < P; ++j) {\n                int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                if (val < best) best = val;\n            }\n            dp_cur[i] = best;\n        }\n\n        dp_prev.swap(dp_cur);\n        pc = c;\n    }\n\n    int bestIdx = min_element(dp_prev.begin(), dp_prev.end()) - dp_prev.begin();\n    return occ[w[4] - 'A'][bestIdx];\n}\n\npair<int,int> representativeEndPosFromStart(const string& w) {\n    const int INF = 1e9;\n\n    int c0 = w[0] - 'A';\n    vector<int> dp_prev((int)occ[c0].size(), INF), dp_cur;\n\n    pair<int,int> start = {si, sj};\n    for (int i = 0; i < (int)occ[c0].size(); ++i) {\n        dp_prev[i] = manhattan(start, occ[c0][i]) + 1;\n    }\n\n    int pc = c0;\n\n    for (int k = 1; k < 5; ++k) {\n        int c = w[k] - 'A';\n        int C = (int)occ[c].size();\n        int P = (int)occ[pc].size();\n\n        dp_cur.assign(C, INF);\n\n        for (int i = 0; i < C; ++i) {\n            int best = INF;\n            for (int j = 0; j < P; ++j) {\n                int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                if (val < best) best = val;\n            }\n            dp_cur[i] = best;\n        }\n\n        dp_prev.swap(dp_cur);\n        pc = c;\n    }\n\n    int bestIdx = min_element(dp_prev.begin(), dp_prev.end()) - dp_prev.begin();\n    return occ[w[4] - 'A'][bestIdx];\n}\n\nlong long pathCost(const vector<int>& p, const vector<vector<int>>& W, const vector<int>& startCost) {\n    long long c = startCost[p[0]];\n    for (int i = 0; i + 1 < (int)p.size(); ++i) c += W[p[i]][p[i + 1]];\n    return c;\n}\n\nlong long edgeContrib(const vector<int>& p, int idx, const vector<vector<int>>& W, const vector<int>& startCost) {\n    int n = (int)p.size();\n    if (idx == -1) return startCost[p[0]];\n    if (0 <= idx && idx + 1 < n) return W[p[idx]][p[idx + 1]];\n    return 0;\n}\n\nlong long deltaSwapFast(const vector<int>& p, int a, int b, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (a == b) return 0;\n    if (a > b) swap(a, b);\n\n    int n = (int)p.size();\n    int ids[5] = {-1, a - 1, a, b - 1, b};\n    sort(ids, ids + 5);\n\n    auto nodeAfter = [&](int idx) -> int {\n        if (idx == a) return p[b];\n        if (idx == b) return p[a];\n        return p[idx];\n    };\n\n    auto newContrib = [&](int idx) -> long long {\n        if (idx == -1) return startCost[nodeAfter(0)];\n        if (0 <= idx && idx + 1 < n) return W[nodeAfter(idx)][nodeAfter(idx + 1)];\n        return 0LL;\n    };\n\n    long long oldv = 0, newv = 0;\n    int last = -100;\n\n    for (int z = 0; z < 5; ++z) {\n        int id = ids[z];\n        if (id == last) continue;\n        last = id;\n\n        oldv += edgeContrib(p, id, W, startCost);\n        newv += newContrib(id);\n    }\n\n    return newv - oldv;\n}\n\ninline long long linkCostNode(int leftNode, int rightNode, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (rightNode == -1) return 0;\n    if (leftNode == -1) return startCost[rightNode];\n    return W[leftNode][rightNode];\n}\n\nlong long deltaMoveCorrect(const vector<int>& p, int a, int b, const vector<vector<int>>& W, const vector<int>& startCost) {\n    if (a == b) return 0;\n\n    int n = (int)p.size();\n    int x = p[a];\n\n    long long oldv = 0, newv = 0;\n\n    if (a < b) {\n        int Aprev = (a > 0 ? p[a - 1] : -1);\n        int Anext = p[a + 1];\n        int B = p[b];\n        int Bnext = (b + 1 < n ? p[b + 1] : -1);\n\n        oldv += linkCostNode(Aprev, x, W, startCost);\n        oldv += linkCostNode(x, Anext, W, startCost);\n        oldv += linkCostNode(B, Bnext, W, startCost);\n\n        newv += linkCostNode(Aprev, Anext, W, startCost);\n        newv += linkCostNode(B, x, W, startCost);\n        newv += linkCostNode(x, Bnext, W, startCost);\n    } else {\n        int Bprev = (b > 0 ? p[b - 1] : -1);\n        int B = p[b];\n        int Aprev = p[a - 1];\n        int Anext = (a + 1 < n ? p[a + 1] : -1);\n\n        oldv += linkCostNode(Bprev, B, W, startCost);\n        oldv += linkCostNode(Aprev, x, W, startCost);\n        oldv += linkCostNode(x, Anext, W, startCost);\n\n        newv += linkCostNode(Bprev, x, W, startCost);\n        newv += linkCostNode(x, B, W, startCost);\n        newv += linkCostNode(Aprev, Anext, W, startCost);\n    }\n\n    return newv - oldv;\n}\n\nvoid applyMove(vector<int>& p, int a, int b) {\n    if (a == b) return;\n\n    if (a < b) {\n        rotate(p.begin() + a, p.begin() + a + 1, p.begin() + b + 1);\n    } else {\n        rotate(p.begin() + b, p.begin() + a, p.begin() + a + 1);\n    }\n}\n\nvector<int> greedyOrder(const vector<vector<int>>& W, const vector<int>& startCost, const vector<vector<int>>& ov) {\n    vector<int> best;\n    long long bestCost = (1LL << 60);\n\n    for (int st = 0; st < M; ++st) {\n        vector<int> p;\n        vector<char> used(M, 0);\n        p.reserve(M);\n\n        p.push_back(st);\n        used[st] = 1;\n\n        for (int step = 1; step < M; ++step) {\n            int last = p.back();\n            int bj = -1;\n            pair<int,int> bestKey = {INT_MAX, INT_MAX};\n\n            for (int j = 0; j < M; ++j) if (!used[j]) {\n                pair<int,int> key = {W[last][j], -ov[last][j]};\n                if (key < bestKey) {\n                    bestKey = key;\n                    bj = j;\n                }\n            }\n\n            used[bj] = 1;\n            p.push_back(bj);\n        }\n\n        long long c = pathCost(p, W, startCost);\n        if (c < bestCost) {\n            bestCost = c;\n            best = p;\n        }\n    }\n\n    return best;\n}\n\nvoid annealOrder(\n    vector<int>& perm,\n    long long& curCost,\n    vector<int>& bestPerm,\n    long long& bestCost,\n    const vector<vector<int>>& W,\n    const vector<int>& startCost,\n    double endTime,\n    double tempStart,\n    double tempEnd,\n    XorShift& rng\n) {\n    double beginTime = elapsedTime();\n    double temp = tempStart;\n    int iter = 0;\n\n    while (true) {\n        if ((iter & 255) == 0) {\n            double now = elapsedTime();\n            if (now > endTime) break;\n\n            double progress = (now - beginTime) / max(1e-9, endTime - beginTime);\n            progress = min(1.0, max(0.0, progress));\n            temp = tempStart * pow(tempEnd / tempStart, progress);\n        }\n        ++iter;\n\n        if (rng.nextInt(100) < 55) {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            long long d = deltaSwapFast(perm, a, b, W, startCost);\n\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                swap(perm[a], perm[b]);\n                curCost += d;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        } else {\n            int a = rng.nextInt(M);\n            int b = rng.nextInt(M);\n            if (a == b) continue;\n\n            long long d = deltaMoveCorrect(perm, a, b, W, startCost);\n\n            if (d <= 0 || rng.nextDouble() < exp(-(double)d / temp)) {\n                applyMove(perm, a, b);\n                curCost += d;\n\n                if (curCost < bestCost) {\n                    bestCost = curCost;\n                    bestPerm = perm;\n                }\n            }\n        }\n    }\n}\n\nstring buildStringFromOrder(const vector<int>& ord) {\n    string s;\n    s.reserve(1200);\n\n    vector<char> covered(M, 0);\n    int code = 0;\n    int seen = 0;\n\n    auto appendChar = [&](char ch) {\n        s.push_back(ch);\n        code = (code * 26 + (ch - 'A')) % POW5;\n        ++seen;\n\n        if (seen >= 5) {\n            int id = codeId[code];\n            if (id != -1) covered[id] = 1;\n        }\n    };\n\n    auto appendWord = [&](int id) {\n        if (covered[id]) return;\n        int o = overlap_suffix_string(s, t[id]);\n        for (int k = o; k < 5; ++k) appendChar(t[id][k]);\n    };\n\n    for (int id : ord) appendWord(id);\n\n    for (int i = 0; i < M; ++i) {\n        if (!covered[i]) appendWord(i);\n    }\n\n    return s;\n}\n\nbool coversAllAfterDeleting(const string& s, int delPos) {\n    vector<char> covered(M, 0);\n    int cnt = 0;\n    int code = 0;\n    int seen = 0;\n\n    for (int i = 0; i < (int)s.size(); ++i) {\n        if (i == delPos) continue;\n\n        code = (code * 26 + (s[i] - 'A')) % POW5;\n        ++seen;\n\n        if (seen >= 5) {\n            int id = codeId[code];\n            if (id != -1 && !covered[id]) {\n                covered[id] = 1;\n                ++cnt;\n                if (cnt == M) return true;\n            }\n        }\n    }\n\n    return cnt == M;\n}\n\nstring pruneStringByDeletion(string s, int& curCost) {\n    if (elapsedTime() > 1.90) return s;\n\n    bool improved = true;\n\n    while (improved && elapsedTime() < 1.93) {\n        improved = false;\n\n        for (int pos = 0; pos < (int)s.size(); ++pos) {\n            if ((pos & 15) == 0 && elapsedTime() > 1.93) break;\n\n            if (!coversAllAfterDeleting(s, pos)) continue;\n\n            string ns;\n            ns.reserve(s.size() - 1);\n            ns.append(s.begin(), s.begin() + pos);\n            ns.append(s.begin() + pos + 1, s.end());\n\n            int nc = typingCostOnly(ns);\n            if (nc < curCost) {\n                s.swap(ns);\n                curCost = nc;\n                improved = true;\n                break;\n            }\n        }\n    }\n\n    return s;\n}\n\npair<int, vector<pair<int,int>>> solveTypingDP(const string& s) {\n    const int INF = 1e9;\n    int L = (int)s.size();\n\n    vector<vector<int>> par(L);\n    vector<int> dp_prev, dp_cur;\n\n    for (int pos = 0; pos < L; ++pos) {\n        int c = s[pos] - 'A';\n        int C = (int)occ[c].size();\n\n        dp_cur.assign(C, INF);\n        par[pos].assign(C, -1);\n\n        if (pos == 0) {\n            pair<int,int> start = {si, sj};\n            for (int i = 0; i < C; ++i) {\n                dp_cur[i] = manhattan(start, occ[c][i]) + 1;\n            }\n        } else {\n            int pc = s[pos - 1] - 'A';\n            int P = (int)occ[pc].size();\n\n            for (int i = 0; i < C; ++i) {\n                for (int j = 0; j < P; ++j) {\n                    int val = dp_prev[j] + manhattan(occ[pc][j], occ[c][i]) + 1;\n                    if (val < dp_cur[i]) {\n                        dp_cur[i] = val;\n                        par[pos][i] = j;\n                    }\n                }\n            }\n        }\n\n        dp_prev.swap(dp_cur);\n    }\n\n    int bestIdx = 0;\n    int bestCost = INF;\n\n    for (int i = 0; i < (int)dp_prev.size(); ++i) {\n        if (dp_prev[i] < bestCost) {\n            bestCost = dp_prev[i];\n            bestIdx = i;\n        }\n    }\n\n    vector<pair<int,int>> path(L);\n    int idx = bestIdx;\n\n    for (int pos = L - 1; pos >= 0; --pos) {\n        int c = s[pos] - 'A';\n        path[pos] = occ[c][idx];\n        idx = par[pos][idx];\n    }\n\n    return {bestCost, path};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    timeStart = chrono::steady_clock::now();\n\n    cin >> N >> M;\n    cin >> si >> sj;\n\n    Agrid.resize(N);\n    for (int i = 0; i < N; ++i) cin >> Agrid[i];\n\n    t.resize(M);\n    for (int i = 0; i < M; ++i) cin >> t[i];\n\n    codeId.assign(POW5, -1);\n    for (int i = 0; i < M; ++i) {\n        codeId[wordCode(t[i])] = i;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            occ[Agrid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) {\n            int best = 1e9;\n            for (auto pa : occ[a]) {\n                for (auto pb : occ[b]) {\n                    best = min(best, manhattan(pa, pb));\n                }\n            }\n            mindist_ch[a][b] = best;\n        }\n    }\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) {\n            if (i != j) ov[i][j] = overlap_word(t[i], t[j]);\n        }\n    }\n\n    vector<vector<int>> Wapprox(M, vector<int>(M, 100000000));\n    vector<vector<int>> Wexact(M, vector<int>(M, 100000000));\n    vector<vector<int>> Wrep(M, vector<int>(M, 100000000));\n    vector<vector<int>> WrepStart(M, vector<int>(M, 100000000));\n\n    vector<pair<int,int>> repEnd(M), repEndStart(M);\n    for (int i = 0; i < M; ++i) {\n        repEnd[i] = representativeEndPos(t[i]);\n        repEndStart[i] = representativeEndPosFromStart(t[i]);\n    }\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            int o = ov[i][j];\n\n            int prev = t[i][4] - 'A';\n            int cost = 0;\n\n            for (int k = o; k < 5; ++k) {\n                int c = t[j][k] - 'A';\n                cost += mindist_ch[prev][c] + 1;\n                prev = c;\n            }\n\n            Wapprox[i][j] = cost;\n            Wexact[i][j] = segmentCostFromChar(t[i][4] - 'A', t[j], o);\n            Wrep[i][j] = suffixCostFromPos(repEnd[i], t[j], o);\n            WrepStart[i][j] = suffixCostFromPos(repEndStart[i], t[j], o);\n        }\n    }\n\n    vector<int> startApprox(M, 0);\n    vector<int> startExact(M, 0);\n    pair<int,int> startPos = {si, sj};\n\n    for (int i = 0; i < M; ++i) {\n        int cost = 1e9;\n        int c0 = t[i][0] - 'A';\n\n        for (auto p : occ[c0]) {\n            cost = min(cost, manhattan(startPos, p) + 1);\n        }\n\n        for (int k = 1; k < 5; ++k) {\n            int a = t[i][k - 1] - 'A';\n            int b = t[i][k] - 'A';\n            cost += mindist_ch[a][b] + 1;\n        }\n\n        startApprox[i] = cost;\n        startExact[i] = typingCostOnly(t[i]);\n    }\n\n    vector<string> candidates;\n    XorShift rng;\n\n    vector<int> perm = greedyOrder(Wapprox, startApprox, ov);\n    long long curCost = pathCost(perm, Wapprox, startApprox);\n    vector<int> bestPerm = perm;\n    long long bestCost = curCost;\n\n    annealOrder(\n        perm,\n        curCost,\n        bestPerm,\n        bestCost,\n        Wapprox,\n        startApprox,\n        1.78,\n        18.0,\n        0.03,\n        rng\n    );\n\n    candidates.push_back(buildStringFromOrder(bestPerm));\n    candidates.push_back(buildStringFromOrder(perm));\n\n    vector<vector<int>> Wover(M, vector<int>(M, 1000000));\n    vector<int> zeroStart(M, 0);\n\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < M; ++j) if (i != j) {\n            Wover[i][j] = 5 - ov[i][j];\n        }\n    }\n\n    candidates.push_back(buildStringFromOrder(greedyOrder(Wover, zeroStart, ov)));\n\n    if (elapsedTime() < 1.84) {\n        vector<int> eperm = greedyOrder(Wexact, startExact, ov);\n        long long ecur = pathCost(eperm, Wexact, startExact);\n        vector<int> ebestPerm = eperm;\n        long long ebest = ecur;\n\n        annealOrder(\n            eperm,\n            ecur,\n            ebestPerm,\n            ebest,\n            Wexact,\n            startExact,\n            1.88,\n            12.0,\n            0.05,\n            rng\n        );\n\n        candidates.push_back(buildStringFromOrder(ebestPerm));\n        candidates.push_back(buildStringFromOrder(eperm));\n    }\n\n    vector<int> lexPerm(M);\n    iota(lexPerm.begin(), lexPerm.end(), 0);\n    candidates.push_back(buildStringFromOrder(lexPerm));\n\n    reverse(lexPerm.begin(), lexPerm.end());\n    candidates.push_back(buildStringFromOrder(lexPerm));\n\n    if (elapsedTime() < 1.90) {\n        for (int bonus : {2, 4}) {\n            vector<vector<int>> Wb = Wapprox;\n\n            for (int i = 0; i < M; ++i) {\n                for (int j = 0; j < M; ++j) if (i != j) {\n                    Wb[i][j] = Wapprox[i][j] - bonus * ov[i][j];\n                }\n            }\n\n            candidates.push_back(buildStringFromOrder(greedyOrder(Wb, startApprox, ov)));\n        }\n    }\n\n    if (elapsedTime() < 1.91) {\n        candidates.push_back(buildStringFromOrder(greedyOrder(Wrep, startExact, ov)));\n\n        vector<vector<int>> Wmix(M, vector<int>(M, 100000000));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) if (i != j) {\n                Wmix[i][j] = (Wapprox[i][j] + Wrep[i][j]) / 2;\n            }\n        }\n        candidates.push_back(buildStringFromOrder(greedyOrder(Wmix, startApprox, ov)));\n    }\n\n    // Additional start-conditioned representative-end candidates.\n    if (elapsedTime() < 1.92) {\n        candidates.push_back(buildStringFromOrder(greedyOrder(WrepStart, startExact, ov)));\n\n        vector<vector<int>> WmixStart(M, vector<int>(M, 100000000));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) if (i != j) {\n                WmixStart[i][j] = (Wapprox[i][j] + WrepStart[i][j]) / 2;\n            }\n        }\n        candidates.push_back(buildStringFromOrder(greedyOrder(WmixStart, startApprox, ov)));\n    }\n\n    sort(candidates.begin(), candidates.end());\n    candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n    int bestStringCost = INT_MAX;\n    string bestString;\n\n    for (const string& s : candidates) {\n        int c = typingCostOnly(s);\n        if (c < bestStringCost) {\n            bestStringCost = c;\n            bestString = s;\n        }\n    }\n\n    if (elapsedTime() < 1.90) {\n        bestString = pruneStringByDeletion(bestString, bestStringCost);\n    }\n\n    auto answer = solveTypingDP(bestString);\n    vector<pair<int,int>> answerPath = move(answer.second);\n\n    if ((int)answerPath.size() > 5000) {\n        answerPath.resize(5000);\n    }\n\n    for (auto [i, j] : answerPath) {\n        cout << i << ' ' << j << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXC = 400;\n\nint N, M, C;\ndouble EPSV;\nint MAX_OPS;\nint op_cnt = 0;\n\nstruct Placement {\n    vector<int> cells;\n    bitset<MAXC> mask;\n};\n\nstruct Obs {\n    bitset<MAXC> mask;\n    int k;\n    double target;\n    double weight;\n    bool drill;\n    int cell;\n    int value;\n};\n\nstruct State {\n    vector<int> pos;\n    double score;\n    bitset<MAXC> uni;\n};\n\nvector<vector<pair<int,int>>> shapes;\nvector<vector<Placement>> placements;\nvector<Obs> observations;\nvector<int> drilled;\n\nbitset<MAXC> zeroMask;\nbitset<MAXC> positiveMask;\n\nvector<vector<int>> seed_positions;\nunordered_set<string> failed_masks;\n\nmt19937 rng(1234567);\nauto time_start = chrono::steady_clock::now();\n\ndouble elapsed_ms() {\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double, milli>(now - time_start).count();\n}\n\nint id_of(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> coord_of(int id) {\n    return {id / N, id % N};\n}\n\nint unknown_count() {\n    int ret = 0;\n    for (int x : drilled) {\n        if (x == -1) ret++;\n    }\n    return ret;\n}\n\nstring mask_key(const bitset<MAXC>& mask) {\n    string s;\n    s.reserve(C);\n    for (int id = 0; id < C; id++) {\n        s.push_back(mask.test(id) ? '1' : '0');\n    }\n    return s;\n}\n\nint ask_query(const vector<int>& cells) {\n    cout << \"q \" << cells.size();\n    for (int id : cells) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n    return res;\n}\n\nbool ask_answer(bitset<MAXC> mask, const string& key = \"\") {\n    for (int id = 0; id < C; id++) {\n        if (positiveMask.test(id)) mask.set(id);\n    }\n\n    vector<int> ans;\n    for (int id = 0; id < C; id++) {\n        if (mask.test(id)) ans.push_back(id);\n    }\n\n    cout << \"a \" << ans.size();\n    for (int id : ans) {\n        auto [i, j] = coord_of(id);\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    if (!(cin >> res)) exit(0);\n    op_cnt++;\n\n    if (res == 1) exit(0);\n    if (!key.empty()) failed_masks.insert(key);\n    return false;\n}\n\nvoid add_divination_observation(const vector<int>& cells, int y) {\n    Obs obs;\n    obs.mask.reset();\n    for (int id : cells) obs.mask.set(id);\n\n    obs.k = (int)cells.size();\n    obs.drill = false;\n    obs.cell = -1;\n    obs.value = -1;\n\n    double a = 1.0 - 2.0 * EPSV;\n    double target = (y - obs.k * EPSV) / max(1e-9, a);\n    target = max(0.0, min(target, (double)M * obs.k));\n\n    double var = obs.k * EPSV * (1.0 - EPSV) + 0.35;\n    double weight = a * a / max(1e-9, var);\n\n    obs.target = target;\n    obs.weight = weight;\n    observations.push_back(obs);\n}\n\nvoid add_drill_observation(int cell, int val) {\n    Obs obs;\n    obs.mask.reset();\n    obs.mask.set(cell);\n\n    obs.k = 1;\n    obs.target = val;\n    obs.weight = 20000.0;\n    obs.drill = true;\n    obs.cell = cell;\n    obs.value = val;\n\n    observations.push_back(obs);\n}\n\nvoid do_divination(const vector<int>& cells) {\n    if ((int)cells.size() < 2) return;\n    int y = ask_query(cells);\n    add_divination_observation(cells, y);\n}\n\nint do_drill(int cell) {\n    vector<int> q = {cell};\n    int v = ask_query(q);\n\n    drilled[cell] = v;\n    if (v == 0) zeroMask.set(cell);\n    if (v > 0) positiveMask.set(cell);\n\n    add_drill_observation(cell, v);\n    return v;\n}\n\nvoid build_placements() {\n    placements.assign(M, {});\n\n    for (int m = 0; m < M; m++) {\n        int imax = 0, jmax = 0;\n        for (auto [i, j] : shapes[m]) {\n            imax = max(imax, i);\n            jmax = max(jmax, j);\n        }\n\n        for (int di = 0; di + imax < N; di++) {\n            for (int dj = 0; dj + jmax < N; dj++) {\n                Placement p;\n                p.mask.reset();\n\n                for (auto [i, j] : shapes[m]) {\n                    int id = id_of(di + i, dj + j);\n                    p.cells.push_back(id);\n                    p.mask.set(id);\n                }\n\n                placements[m].push_back(p);\n            }\n        }\n    }\n}\n\nvoid initial_queries() {\n    // Whole-grid query is skipped because total reserve is known from shape areas.\n\n    for (int i = 0; i < N; i++) {\n        vector<int> cells;\n        for (int j = 0; j < N; j++) {\n            cells.push_back(id_of(i, j));\n        }\n        do_divination(cells);\n    }\n\n    for (int j = 0; j < N; j++) {\n        vector<int> cells;\n        for (int i = 0; i < N; i++) {\n            cells.push_back(id_of(i, j));\n        }\n        do_divination(cells);\n    }\n\n    int B = 4;\n    for (int si = 0; si < N; si += B) {\n        for (int sj = 0; sj < N; sj += B) {\n            vector<int> cells;\n            for (int i = si; i < min(N, si + B); i++) {\n                for (int j = sj; j < min(N, sj + B); j++) {\n                    cells.push_back(id_of(i, j));\n                }\n            }\n            if ((int)cells.size() >= 2) do_divination(cells);\n        }\n    }\n\n    int R = (N <= 10 ? 18 : 30);\n    vector<int> ids(C);\n    iota(ids.begin(), ids.end(), 0);\n\n    for (int r = 0; r < R; r++) {\n        shuffle(ids.begin(), ids.end(), rng);\n\n        vector<int> cells;\n        int sz = max(2, C / 2);\n        for (int t = 0; t < sz; t++) {\n            cells.push_back(ids[t]);\n        }\n\n        do_divination(cells);\n    }\n}\n\nbitset<MAXC> union_of_state(const vector<int>& pos) {\n    bitset<MAXC> res;\n    res.reset();\n\n    for (int m = 0; m < M; m++) {\n        res |= placements[m][pos[m]].mask;\n    }\n\n    return res;\n}\n\nbool union_consistent_with_drills(const bitset<MAXC>& mask) {\n    if ((mask & zeroMask).any()) return false;\n\n    for (int id = 0; id < C; id++) {\n        if (positiveMask.test(id) && !mask.test(id)) return false;\n    }\n\n    return true;\n}\n\nbool placement_valid_by_zero(int m, int p) {\n    return !((placements[m][p].mask & zeroMask).any());\n}\n\nbool position_vector_valid_by_zero(const vector<int>& pos) {\n    if ((int)pos.size() != M) return false;\n\n    for (int m = 0; m < M; m++) {\n        if (pos[m] < 0 || pos[m] >= (int)placements[m].size()) return false;\n        if (!placement_valid_by_zero(m, pos[m])) return false;\n    }\n\n    return true;\n}\n\nvector<State> finalize_candidates(vector<State>& result, int want) {\n    sort(result.begin(), result.end(), [](const State& a, const State& b) {\n        return a.score < b.score;\n    });\n\n    vector<State> uniq;\n    unordered_set<string> seen;\n\n    for (auto &st : result) {\n        string key = mask_key(st.uni);\n        if (seen.insert(key).second) {\n            uniq.push_back(st);\n            if ((int)uniq.size() >= want) break;\n        }\n    }\n\n    seed_positions.clear();\n    for (int i = 0; i < (int)uniq.size() && i < 20; i++) {\n        if (position_vector_valid_by_zero(uniq[i].pos)) {\n            seed_positions.push_back(uniq[i].pos);\n        }\n    }\n\n    return uniq;\n}\n\nvector<State> find_candidates(int want, int time_ms) {\n    int O = observations.size();\n\n    vector<vector<int>> active(M);\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p < (int)placements[m].size(); p++) {\n            if (placement_valid_by_zero(m, p)) {\n                active[m].push_back(p);\n            }\n        }\n\n        // Robust fallback. Should not occur for valid exact drilling info.\n        if (active[m].empty()) {\n            for (int p = 0; p < (int)placements[m].size(); p++) {\n                active[m].push_back(p);\n            }\n        }\n    }\n\n    vector<vector<vector<unsigned char>>> contrib(M);\n    for (int m = 0; m < M; m++) {\n        int P = placements[m].size();\n        contrib[m].assign(P, vector<unsigned char>(O, 0));\n\n        for (int p : active[m]) {\n            for (int o = 0; o < O; o++) {\n                contrib[m][p][o] =\n                    (unsigned char)((placements[m][p].mask & observations[o].mask).count());\n            }\n        }\n    }\n\n    auto score_of_sums = [&](const vector<int>& sums) {\n        double sc = 0.0;\n        for (int o = 0; o < O; o++) {\n            double e = sums[o] - observations[o].target;\n            sc += observations[o].weight * e * e;\n        }\n        return sc;\n    };\n\n    vector<State> result;\n    auto deadline = chrono::steady_clock::now() + chrono::milliseconds(max(3, time_ms));\n\n    int restarts = 0;\n    int min_restarts = (time_ms <= 5 ? 1 : 3);\n\n    while (restarts < min_restarts || chrono::steady_clock::now() < deadline) {\n        restarts++;\n\n        vector<int> pos(M, -1);\n\n        if (!seed_positions.empty() && restarts % 3 == 0) {\n            pos = seed_positions[rng() % seed_positions.size()];\n\n            for (int m = 0; m < M; m++) {\n                if (pos[m] < 0 || pos[m] >= (int)placements[m].size() ||\n                    !placement_valid_by_zero(m, pos[m])) {\n                    pos[m] = active[m][rng() % active[m].size()];\n                }\n            }\n\n            int changes = max(1, M / 5);\n            for (int t = 0; t < changes; t++) {\n                int m = rng() % M;\n                pos[m] = active[m][rng() % active[m].size()];\n            }\n        } else {\n            for (int m = 0; m < M; m++) {\n                pos[m] = active[m][rng() % active[m].size()];\n            }\n        }\n\n        vector<int> sums(O, 0);\n        for (int m = 0; m < M; m++) {\n            for (int o = 0; o < O; o++) {\n                sums[o] += contrib[m][pos[m]][o];\n            }\n        }\n\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n\n        int sweeps = (time_ms <= 5 ? 3 : 7);\n        for (int sweep = 0; sweep < sweeps; sweep++) {\n            shuffle(order.begin(), order.end(), rng);\n            bool changed = false;\n\n            for (int mm = 0; mm < M; mm++) {\n                int m = order[mm];\n                int oldp = pos[m];\n\n                for (int o = 0; o < O; o++) {\n                    sums[o] -= contrib[m][oldp][o];\n                }\n\n                int bestp = oldp;\n                double bestsc = numeric_limits<double>::infinity();\n\n                for (int p : active[m]) {\n                    double sc = 0.0;\n\n                    for (int o = 0; o < O; o++) {\n                        double v = sums[o] + contrib[m][p][o];\n                        double e = v - observations[o].target;\n                        sc += observations[o].weight * e * e;\n\n                        if (sc >= bestsc) break;\n                    }\n\n                    if (sc < bestsc) {\n                        bestsc = sc;\n                        bestp = p;\n                    }\n                }\n\n                pos[m] = bestp;\n\n                for (int o = 0; o < O; o++) {\n                    sums[o] += contrib[m][bestp][o];\n                }\n\n                if (bestp != oldp) changed = true;\n            }\n\n            if (!changed) break;\n        }\n\n        State st;\n        st.pos = pos;\n        st.score = score_of_sums(sums);\n        st.uni = union_of_state(pos);\n        result.push_back(st);\n\n        if (elapsed_ms() > 2800.0) break;\n    }\n\n    return finalize_candidates(result, want);\n}\n\nint choose_drill_cell(const vector<State>& cand, int wrong_same_count) {\n    int K = (int)cand.size();\n    vector<int> freq(C, 0);\n\n    for (auto &st : cand) {\n        for (int id = 0; id < C; id++) {\n            if (st.uni.test(id)) freq[id]++;\n        }\n    }\n\n    int best = -1;\n    int bestScore = -1;\n\n    // Prefer cells where candidate unions disagree.\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] != -1) continue;\n\n        int f = freq[id];\n        if (f == 0 || f == K) continue;\n\n        int score = min(f, K - f);\n        if (score > bestScore) {\n            bestScore = score;\n            best = id;\n        }\n    }\n\n    if (best != -1) return best;\n\n    // If candidates agree, verify the predicted union.\n    if (!cand.empty()) {\n        const bitset<MAXC>& mask = cand[0].uni;\n\n        // First verify predicted positive cells.\n        if (wrong_same_count % 2 == 0) {\n            for (int id = 0; id < C; id++) {\n                if (drilled[id] == -1 && mask.test(id)) {\n                    return id;\n                }\n            }\n        }\n\n        // Then inspect boundary negatives.\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] != -1 || mask.test(id)) continue;\n\n            int i = id / N, j = id % N;\n            bool near = false;\n\n            const int di[4] = {-1, 1, 0, 0};\n            const int dj[4] = {0, 0, -1, 1};\n\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d];\n                int nj = j + dj[d];\n\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    if (mask.test(id_of(ni, nj))) {\n                        near = true;\n                    }\n                }\n            }\n\n            if (near) return id;\n        }\n\n        for (int id = 0; id < C; id++) {\n            if (drilled[id] == -1 && !mask.test(id)) {\n                return id;\n            }\n        }\n    }\n\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) return id;\n    }\n\n    return -1;\n}\n\nvoid fallback_drill_all_and_answer() {\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] == -1) {\n            do_drill(id);\n        }\n    }\n\n    bitset<MAXC> ans;\n    ans.reset();\n\n    for (int id = 0; id < C; id++) {\n        if (drilled[id] > 0) ans.set(id);\n    }\n\n    ask_answer(ans);\n    exit(0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> EPSV;\n\n    C = N * N;\n    MAX_OPS = 2 * C;\n\n    shapes.resize(M);\n    for (int m = 0; m < M; m++) {\n        int d;\n        cin >> d;\n\n        shapes[m].resize(d);\n        for (int k = 0; k < d; k++) {\n            cin >> shapes[m][k].first >> shapes[m][k].second;\n        }\n    }\n\n    drilled.assign(C, -1);\n    zeroMask.reset();\n    positiveMask.reset();\n\n    build_placements();\n    initial_queries();\n\n    unordered_set<string> guessed;\n    int heuristic_drills = 0;\n    int guesses = 0;\n    int wrong_same_count = 0;\n\n    while (true) {\n        int unknown = unknown_count();\n\n        // Always reserve enough operations to drill all unknown cells and submit.\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        if (elapsed_ms() > 2850.0) {\n            fallback_drill_all_and_answer();\n        }\n\n        // Longer than previous best. Drills are not wasted if fallback happens.\n        if (heuristic_drills >= min(C, 160)) {\n            fallback_drill_all_and_answer();\n        }\n\n        int tlim;\n        if (heuristic_drills == 0) {\n            tlim = 350;\n        } else if (heuristic_drills < 25) {\n            tlim = 80;\n        } else if (heuristic_drills < 60) {\n            tlim = 30;\n        } else if (heuristic_drills < 100) {\n            tlim = 5;\n        } else {\n            tlim = 3;\n        }\n\n        if (elapsed_ms() > 2300.0) {\n            tlim = min(tlim, 3);\n        }\n\n        vector<State> cand = find_candidates(12, tlim);\n        if (cand.empty()) {\n            fallback_drill_all_and_answer();\n        }\n\n        // Guess best unfailed candidate when consistent with exact drilling info.\n        bitset<MAXC> bestMask = cand[0].uni;\n        string key = mask_key(bestMask);\n\n        bool can_try_answer =\n            guesses < 25 &&\n            op_cnt + unknown + 2 <= MAX_OPS &&\n            guessed.find(key) == guessed.end() &&\n            failed_masks.find(key) == failed_masks.end() &&\n            union_consistent_with_drills(bestMask);\n\n        if (can_try_answer) {\n            guessed.insert(key);\n            guesses++;\n\n            bool ok = ask_answer(bestMask, key);\n            if (ok) return 0;\n\n            wrong_same_count++;\n        }\n\n        unknown = unknown_count();\n\n        if (op_cnt + unknown + 1 >= MAX_OPS) {\n            fallback_drill_all_and_answer();\n        }\n\n        int cell = choose_drill_cell(cand, wrong_same_count);\n        if (cell == -1) {\n            fallback_drill_all_and_answer();\n        }\n\n        do_drill(cell);\n        heuristic_drills++;\n    }\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int W = 1000;\nusing ll = long long;\nusing ull = unsigned long long;\n\nstruct Rect { int i0, j0, i1, j1; };\nstruct Option { int l, r, h; ll cost; bool stat; };\n\nint D, N;\nvector<vector<int>> A;\nvector<int> maxA;\n\ninline int ceil_div(int x, int y) { return (x + y - 1) / y; }\n\nstruct Timer {\n    chrono::steady_clock::time_point st = chrono::steady_clock::now();\n    double ms() const {\n        return chrono::duration<double, milli>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nvector<vector<Rect>> empty_sol() {\n    return vector<vector<Rect>>(D, vector<Rect>(N));\n}\n\nbool valid_solution(const vector<vector<Rect>>& sol) {\n    if ((int)sol.size() != D) return false;\n    for (int d = 0; d < D; d++) {\n        if ((int)sol[d].size() != N) return false;\n        for (int k = 0; k < N; k++) {\n            const auto& r = sol[d][k];\n            if (!(0 <= r.i0 && r.i0 < r.i1 && r.i1 <= W)) return false;\n            if (!(0 <= r.j0 && r.j0 < r.j1 && r.j1 <= W)) return false;\n        }\n    }\n    return true;\n}\n\nstruct Scorer {\n    int HW = (999000 + 63) >> 6;\n    int VW = (999000 + 63) >> 6;\n\n    inline void setbit(vector<ull>& b, int idx) const {\n        b[idx >> 6] |= 1ULL << (idx & 63);\n    }\n\n    ll score(const vector<vector<Rect>>& sol, ll lim = (1LL << 62)) const {\n        vector<ull> ph(HW), pv(VW), ch(HW), cv(VW);\n        ll total = 0;\n\n        for (int d = 0; d < D; d++) {\n            fill(ch.begin(), ch.end(), 0);\n            fill(cv.begin(), cv.end(), 0);\n\n            for (int k = 0; k < N; k++) {\n                const auto& r = sol[d][k];\n                ll area = 1LL * (r.i1 - r.i0) * (r.j1 - r.j0);\n                if (area < A[d][k]) total += 100LL * (A[d][k] - area);\n\n                if (r.i0 > 0) {\n                    int row = r.i0 - 1;\n                    for (int x = r.j0; x < r.j1; x++) setbit(ch, row * 1000 + x);\n                }\n                if (r.i1 < W) {\n                    int row = r.i1 - 1;\n                    for (int x = r.j0; x < r.j1; x++) setbit(ch, row * 1000 + x);\n                }\n                if (r.j0 > 0) {\n                    int col = r.j0 - 1;\n                    for (int y = r.i0; y < r.i1; y++) setbit(cv, y * 999 + col);\n                }\n                if (r.j1 < W) {\n                    int col = r.j1 - 1;\n                    for (int y = r.i0; y < r.i1; y++) setbit(cv, y * 999 + col);\n                }\n            }\n\n            if (d > 0) {\n                for (int i = 0; i < HW; i++) total += __builtin_popcountll(ph[i] ^ ch[i]);\n                for (int i = 0; i < VW; i++) total += __builtin_popcountll(pv[i] ^ cv[i]);\n            }\n\n            if (total >= lim) return total;\n            ph.swap(ch);\n            pv.swap(cv);\n        }\n\n        return total;\n    }\n};\n\nvector<int> average_area_vector() {\n    vector<int> v(N);\n    for (int k = 0; k < N; k++) {\n        ll s = 0;\n        for (int d = 0; d < D; d++) s += A[d][k];\n        v[k] = max(1, (int)((s + D - 1) / D));\n    }\n    return v;\n}\n\nvector<int> percentile_area_vector(double p) {\n    vector<int> res(N);\n    for (int k = 0; k < N; k++) {\n        vector<int> v;\n        for (int d = 0; d < D; d++) v.push_back(A[d][k]);\n        sort(v.begin(), v.end());\n        int idx = min(D - 1, max(0, (int)floor(p * (D - 1) + 1e-9)));\n        res[k] = v[idx];\n    }\n    return res;\n}\n\nvector<int> aggregate_block(int l, int r, int type) {\n    vector<int> wt(N, 1);\n    for (int k = 0; k < N; k++) {\n        if (type == 0) {\n            ll s = 0;\n            for (int d = l; d < r; d++) s += A[d][k];\n            wt[k] = max(1, (int)((s + r - l - 1) / (r - l)));\n        } else if (type == 1) {\n            int mx = 0;\n            for (int d = l; d < r; d++) mx = max(mx, A[d][k]);\n            wt[k] = max(1, mx);\n        } else {\n            vector<int> v;\n            for (int d = l; d < r; d++) v.push_back(A[d][k]);\n            sort(v.begin(), v.end());\n            int idx = min((int)v.size() - 1, (int)floor(0.75 * ((int)v.size() - 1) + 1e-9));\n            wt[k] = max(1, v[idx]);\n        }\n    }\n    return wt;\n}\n\nstruct TreemapPacker {\n    vector<int> w;\n    vector<Rect> out;\n    int mode = 0;\n\n    ll sum_ids(const vector<int>& ids) const {\n        ll s = 0;\n        for (int id : ids) s += w[id];\n        return s;\n    }\n\n    void rec(const vector<int>& ids, int x, int y, int ww, int hh) {\n        int m = ids.size();\n        if (m == 1) {\n            int id = ids[0];\n            out[id] = {y, x, y + hh, x + ww};\n            return;\n        }\n\n        ll total = max(1LL, sum_ids(ids));\n        ll area = 1LL * ww * hh;\n\n        vector<vector<int>> orders;\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (w[a] != w[b]) return w[a] < w[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (w[a] != w[b]) return w[a] > w[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end());\n            orders.push_back(v);\n        }\n\n        struct Cand {\n            ll score;\n            bool vert;\n            int cut;\n            vector<int> a, b;\n        };\n\n        vector<Cand> cand;\n\n        auto add = [&](vector<int> left) {\n            sort(left.begin(), left.end());\n            left.erase(unique(left.begin(), left.end()), left.end());\n            if (left.empty() || (int)left.size() == m) return;\n\n            vector<int> mark(N);\n            for (int id : left) mark[id] = 1;\n\n            vector<int> right;\n            for (int id : ids) if (!mark[id]) right.push_back(id);\n            if (right.empty()) return;\n\n            ll s1 = 0, s2 = 0;\n            for (int id : left) s1 += w[id];\n            for (int id : right) s2 += w[id];\n\n            int n1 = left.size();\n            int n2 = right.size();\n\n            {\n                int lo = ceil_div(n1, hh);\n                int hi = ww - ceil_div(n2, hh);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)ww * s1 / total);\n                    vector<int> cuts = {\n                        lo, hi,\n                        max(lo, min(hi, ideal)),\n                        max(lo, min(hi, ideal - 1)),\n                        max(lo, min(hi, ideal + 1))\n                    };\n\n                    for (int cut : cuts) {\n                        if (cut < lo || cut > hi) continue;\n                        ll cap1 = 1LL * cut * hh;\n                        ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - 1LL * (ww - cut) * hh);\n                        ll dev = llabs(cap1 * total - s1 * area) / total;\n                        ll aspect = 1000LL * max(cut, hh) / max(1, min(cut, hh))\n                                  + 1000LL * max(ww - cut, hh) / max(1, min(ww - cut, hh));\n                        ll extra = (mode == 0 ? hh : abs(n1 - n2) * 10LL);\n                        cand.push_back({shortage * 1000000000LL + dev * 1000LL + aspect + extra,\n                                        true, cut, left, right});\n                    }\n                }\n            }\n\n            {\n                int lo = ceil_div(n1, ww);\n                int hi = hh - ceil_div(n2, ww);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)hh * s1 / total);\n                    vector<int> cuts = {\n                        lo, hi,\n                        max(lo, min(hi, ideal)),\n                        max(lo, min(hi, ideal - 1)),\n                        max(lo, min(hi, ideal + 1))\n                    };\n\n                    for (int cut : cuts) {\n                        if (cut < lo || cut > hi) continue;\n                        ll cap1 = 1LL * ww * cut;\n                        ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - 1LL * ww * (hh - cut));\n                        ll dev = llabs(cap1 * total - s1 * area) / total;\n                        ll aspect = 1000LL * max(ww, cut) / max(1, min(ww, cut))\n                                  + 1000LL * max(ww, hh - cut) / max(1, min(ww, hh - cut));\n                        ll extra = (mode == 0 ? ww : abs(n1 - n2) * 10LL);\n                        cand.push_back({shortage * 1000000000LL + dev * 1000LL + aspect + extra,\n                                        false, cut, left, right});\n                    }\n                }\n            }\n        };\n\n        for (auto ord : orders) {\n            vector<int> pref;\n            for (int i = 0; i + 1 < (int)ord.size(); i++) {\n                pref.push_back(ord[i]);\n                add(pref);\n            }\n        }\n\n        vector<double> targets = {0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80};\n        auto desc = ids;\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            if (w[a] != w[b]) return w[a] > w[b];\n            return a < b;\n        });\n\n        for (double t : targets) {\n            ll target = (ll)(total * t);\n            vector<int> group;\n            ll s = 0;\n            for (int id : desc) {\n                if (group.empty() || s + w[id] <= target) {\n                    group.push_back(id);\n                    s += w[id];\n                }\n            }\n            add(group);\n        }\n\n        if (cand.empty()) {\n            vector<int> a, b;\n            for (int i = 0; i < m; i++) {\n                if (i < m / 2) a.push_back(ids[i]);\n                else b.push_back(ids[i]);\n            }\n\n            if (ww >= hh && ww >= 2) {\n                int cut = max(1, min(ww - 1, ww / 2));\n                rec(a, x, y, cut, hh);\n                rec(b, x + cut, y, ww - cut, hh);\n            } else {\n                int cut = max(1, min(hh - 1, hh / 2));\n                rec(a, x, y, ww, cut);\n                rec(b, x, y + cut, ww, hh - cut);\n            }\n            return;\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            return a.score < b.score;\n        });\n\n        const auto& best = cand[0];\n        if (best.vert) {\n            rec(best.a, x, y, best.cut, hh);\n            rec(best.b, x + best.cut, y, ww - best.cut, hh);\n        } else {\n            rec(best.a, x, y, ww, best.cut);\n            rec(best.b, x, y + best.cut, ww, hh - best.cut);\n        }\n    }\n\n    vector<Rect> pack(const vector<int>& weight, int m = 0) {\n        w = weight;\n        mode = m;\n        out.assign(N, {-1, -1, -1, -1});\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        rec(ids, 0, 0, W, W);\n        return out;\n    }\n};\n\nvector<vector<Rect>> treemap_dynamic_solution(int mode) {\n    auto sol = empty_sol();\n    for (int d = 0; d < D; d++) {\n        TreemapPacker tp;\n        auto r = tp.pack(A[d], mode);\n        for (int k = 0; k < N; k++) sol[d][k] = r[k];\n    }\n    return sol;\n}\n\nvector<vector<Rect>> treemap_static_solution(const vector<int>& base, int mode) {\n    auto sol = empty_sol();\n    TreemapPacker tp;\n    auto r = tp.pack(base, mode);\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) sol[d][k] = r[k];\n    }\n    return sol;\n}\n\nvector<vector<Rect>> treemap_block_solution(int bs, int mode, int typ, int off) {\n    auto sol = empty_sol();\n\n    auto apply = [&](int l, int r) {\n        if (l >= r) return;\n        auto wt = aggregate_block(l, r, typ);\n        TreemapPacker tp;\n        auto rects = tp.pack(wt, mode);\n        for (int d = l; d < r; d++) {\n            for (int k = 0; k < N; k++) sol[d][k] = rects[k];\n        }\n    };\n\n    int cur = 0;\n    if (off > 0 && off < D) {\n        apply(0, off);\n        cur = off;\n    }\n\n    while (cur < D) {\n        int nxt = min(D, cur + bs);\n        apply(cur, nxt);\n        cur = nxt;\n    }\n\n    return sol;\n}\n\nbool pack_bfd(const vector<int>& widths, int h, vector<vector<int>>& rows) {\n    rows.clear();\n    if (h <= 0 || h > 1000) return false;\n\n    int maxRows = 1000 / h;\n    if (maxRows <= 0) return false;\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 (widths[x] != widths[y]) return widths[x] > widths[y];\n        return x < y;\n    });\n\n    vector<int> rem;\n\n    for (int id : ids) {\n        int w = widths[id];\n        if (w <= 0 || w > 1000) return false;\n\n        int best = -1;\n        int bestRem = 1000000;\n\n        for (int r = 0; r < (int)rows.size(); r++) {\n            if (rem[r] >= w && rem[r] - w < bestRem) {\n                bestRem = rem[r] - w;\n                best = r;\n            }\n        }\n\n        if (best == -1) {\n            if ((int)rows.size() >= maxRows) return false;\n            rows.push_back(vector<int>{id});\n            rem.push_back(1000 - w);\n        } else {\n            rows[best].push_back(id);\n            rem[best] -= w;\n        }\n    }\n\n    for (auto& row : rows) sort(row.begin(), row.end());\n    sort(rows.begin(), rows.end(), [](const vector<int>& a, const vector<int>& b) {\n        return a.front() < b.front();\n    });\n\n    return true;\n}\n\nvector<Rect> static_bfd_rects_from_weights(const vector<int>& wt) {\n    ll bestEst = (1LL << 60);\n    int bestH = -1;\n    vector<vector<int>> bestRows;\n\n    for (int h = 1; h <= 1000; h++) {\n        vector<int> widths(N);\n        bool ok = true;\n        for (int k = 0; k < N; k++) {\n            widths[k] = ceil_div(wt[k], h);\n            if (widths[k] > 1000) ok = false;\n        }\n        if (!ok) continue;\n\n        vector<vector<int>> rows;\n        if (!pack_bfd(widths, h, rows)) continue;\n\n        ll est = 1LL * rows.size() * h;\n        if (est < bestEst) {\n            bestEst = est;\n            bestH = h;\n            bestRows = rows;\n        }\n    }\n\n    if (bestH == -1) return {};\n\n    vector<Rect> rects(N);\n    int y = 0;\n\n    for (const auto& row : bestRows) {\n        int x = 0;\n        for (int t = 0; t < (int)row.size(); t++) {\n            int k = row[t];\n            int ww = (t + 1 == (int)row.size()) ? W - x : ceil_div(wt[k], bestH);\n            if (ww <= 0) return {};\n            rects[k] = {y, x, y + bestH, x + ww};\n            x += ww;\n        }\n        y += bestH;\n    }\n\n    return rects;\n}\n\nvector<vector<Rect>> static_bfd_solution() {\n    auto rects = static_bfd_rects_from_weights(maxA);\n    if (rects.empty()) return {};\n    auto sol = empty_sol();\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) sol[d][k] = rects[k];\n    }\n    return sol;\n}\n\nvector<vector<Rect>> build_from_rows_dynamic_height(const vector<vector<vector<int>>>& rows, const vector<int>& hs) {\n    auto sol = empty_sol();\n\n    for (int d = 0; d < D; d++) {\n        int h = hs[d];\n        int y = 0;\n\n        for (const auto& row : rows[d]) {\n            int x = 0;\n            for (int t = 0; t < (int)row.size(); t++) {\n                int k = row[t];\n                int ww = (t + 1 == (int)row.size()) ? W - x : ceil_div(A[d][k], h);\n                if (ww <= 0) ww = 1;\n                sol[d][k] = {y, x, y + h, x + ww};\n                x += ww;\n            }\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> per_day_bfd_solution() {\n    vector<vector<vector<int>>> allRows(D);\n    vector<int> hs(D, -1);\n\n    for (int d = 0; d < D; d++) {\n        ll bestEst = (1LL << 60);\n        int bestH = -1;\n        vector<vector<int>> bestRows;\n\n        for (int h = 1; h <= 1000; h++) {\n            vector<int> widths(N);\n            bool ok = true;\n            for (int k = 0; k < N; k++) {\n                widths[k] = ceil_div(A[d][k], h);\n                if (widths[k] > 1000) ok = false;\n            }\n            if (!ok) continue;\n\n            vector<vector<int>> rows;\n            if (!pack_bfd(widths, h, rows)) continue;\n\n            int R = rows.size();\n            ll est = 1000LL * max(0, R - 1) + 1LL * h * max(0, N - R);\n            est += abs(h - 50);\n\n            if (est < bestEst) {\n                bestEst = est;\n                bestH = h;\n                bestRows = rows;\n            }\n        }\n\n        if (bestH == -1) return {};\n        hs[d] = bestH;\n        allRows[d] = bestRows;\n    }\n\n    return build_from_rows_dynamic_height(allRows, hs);\n}\n\nvector<vector<Rect>> fixed_h_bfd_solution(int h) {\n    vector<vector<vector<int>>> allRows(D);\n    vector<int> hs(D, h);\n\n    for (int d = 0; d < D; d++) {\n        vector<int> widths(N);\n        bool ok = true;\n        for (int k = 0; k < N; k++) {\n            widths[k] = ceil_div(A[d][k], h);\n            if (widths[k] > 1000) ok = false;\n        }\n        if (!ok) return {};\n\n        vector<vector<int>> rows;\n        if (!pack_bfd(widths, h, rows)) return {};\n        allRows[d] = rows;\n    }\n\n    return build_from_rows_dynamic_height(allRows, hs);\n}\n\nvector<int> promising_fixed_heights() {\n    vector<pair<ll, int>> cand;\n\n    for (int h = 1; h <= 1000; h++) {\n        bool allok = true;\n        ll est = 0;\n\n        for (int d = 0; d < D; d++) {\n            vector<int> widths(N);\n            bool ok = true;\n            for (int k = 0; k < N; k++) {\n                widths[k] = ceil_div(A[d][k], h);\n                if (widths[k] > 1000) ok = false;\n            }\n            if (!ok) {\n                allok = false;\n                break;\n            }\n\n            vector<vector<int>> rows;\n            if (!pack_bfd(widths, h, rows)) {\n                allok = false;\n                break;\n            }\n\n            int R = rows.size();\n            est += 1000LL * max(0, R - 1);\n            est += 1LL * h * max(0, N - R);\n        }\n\n        if (allok) {\n            est += 1000 % h;\n            cand.push_back({est, h});\n        }\n    }\n\n    sort(cand.begin(), cand.end());\n\n    vector<int> res;\n    for (auto [e, h] : cand) {\n        bool close = false;\n        for (int x : res) {\n            if (abs(x - h) <= 2) close = true;\n        }\n        if (!close) res.push_back(h);\n        if ((int)res.size() >= 8) break;\n    }\n\n    return res;\n}\n\nvector<vector<Rect>> stable_shelf_dp_order(const vector<int>& ord) {\n    vector<vector<int>> B(D, vector<int>(N));\n    vector<int> maxB(N);\n\n    for (int d = 0; d < D; d++) {\n        for (int p = 0; p < N; p++) {\n            B[d][p] = A[d][ord[p]];\n            maxB[p] = max(maxB[p], B[d][p]);\n        }\n    }\n\n    int K = N + 1;\n    vector<int> pref(1001 * D * K);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) P(h, d, k + 1) = P(h, d, k) + ceil_div(B[d][k], h);\n        }\n    }\n\n    vector<int> prefMax(1001 * K);\n    auto PM = [&](int h, int k) -> int& {\n        return prefMax[h * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        PM(h, 0) = 0;\n        for (int k = 0; k < N; k++) PM(h, k + 1) = PM(h, k) + ceil_div(maxB[k], h);\n    }\n\n    auto dyn_feasible = [&](int l, int r, int h) {\n        for (int d = 0; d < D; d++) {\n            if (P(h, d, r + 1) - P(h, d, l) > W) return false;\n        }\n        return true;\n    };\n\n    auto stat_feasible = [&](int l, int r, int h) {\n        return PM(h, r + 1) - PM(h, l) <= W;\n    };\n\n    auto dyn_cost = [&](int l, int r, int h) -> ll {\n        int m = r - l + 1;\n        if (m <= 1) return 0;\n\n        ll res = 0;\n        vector<int> a, b;\n        a.reserve(m - 1);\n        b.reserve(m - 1);\n\n        for (int d = 1; d < D; d++) {\n            a.clear();\n            b.clear();\n\n            for (int t = l; t < r; t++) {\n                a.push_back(P(h, d - 1, t + 1) - P(h, d - 1, l));\n                b.push_back(P(h, d, t + 1) - P(h, d, l));\n            }\n\n            int i = 0, j = 0, common = 0;\n            while (i < (int)a.size() && j < (int)b.size()) {\n                if (a[i] == b[j]) {\n                    common++;\n                    i++;\n                    j++;\n                } else if (a[i] < b[j]) {\n                    i++;\n                } else {\n                    j++;\n                }\n            }\n\n            int sym = 2 * (m - 1) - 2 * common;\n            res += 1LL * sym * h;\n        }\n\n        return res;\n    };\n\n    vector<Option> opts;\n    vector<vector<int>> byStart(N);\n\n    for (int l = 0; l < N; l++) {\n        for (int r = l; r < N; r++) {\n            int hmin = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (dyn_feasible(l, r, h)) {\n                    hmin = h;\n                    break;\n                }\n            }\n            if (hmin == -1) continue;\n\n            vector<Option> tmp;\n\n            auto add_dyn = [&](int h) {\n                if (h < hmin || h > 1000) return;\n                if (!dyn_feasible(l, r, h)) return;\n                tmp.push_back({l, r, h, dyn_cost(l, r, h), false});\n            };\n\n            add_dyn(hmin);\n            for (int x = 1; x <= 8; x++) add_dyn(hmin + x);\n\n            vector<pair<int, int>> fs = {\n                {11,10}, {6,5}, {5,4}, {4,3}, {3,2},\n                {2,1}, {5,2}, {3,1}, {4,1}, {5,1},\n                {6,1}, {8,1}, {10,1}\n            };\n\n            for (auto [num, den] : fs) {\n                int h = (hmin * num + den - 1) / den;\n                add_dyn(h);\n            }\n\n            int hs = -1;\n            for (int h = 1; h <= 1000; h++) {\n                if (stat_feasible(l, r, h)) {\n                    hs = h;\n                    break;\n                }\n            }\n            if (hs != -1) tmp.push_back({l, r, hs, 0, true});\n\n            sort(tmp.begin(), tmp.end(), [](const Option& a, const Option& b) {\n                if (a.h != b.h) return a.h < b.h;\n                if (a.cost != b.cost) return a.cost < b.cost;\n                return a.stat > b.stat;\n            });\n\n            vector<Option> uniq;\n            for (auto& op : tmp) {\n                if (uniq.empty() || uniq.back().h != op.h) uniq.push_back(op);\n                else if (op.cost < uniq.back().cost) uniq.back() = op;\n            }\n\n            ll best = (1LL << 60);\n            for (auto& op : uniq) {\n                if (op.cost < best) {\n                    best = op.cost;\n                    int id = opts.size();\n                    opts.push_back(op);\n                    byStart[l].push_back(id);\n                }\n            }\n        }\n    }\n\n    const ll INF = (1LL << 60);\n    vector<vector<ll>> dp(N + 1, vector<ll>(1001, INF));\n    vector<vector<int>> parH(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parK(N + 1, vector<int>(1001, -1));\n    vector<vector<int>> parO(N + 1, vector<int>(1001, -1));\n\n    dp[0][0] = 0;\n    for (int i = 0; i < N; i++) {\n        for (int used = 0; used <= 1000; used++) {\n            if (dp[i][used] == INF) continue;\n            for (int id : byStart[i]) {\n                const auto& op = opts[id];\n                int nu = used + op.h;\n                if (nu > 1000) continue;\n\n                int ni = op.r + 1;\n                ll nv = dp[i][used] + op.cost;\n                if (nv < dp[ni][nu]) {\n                    dp[ni][nu] = nv;\n                    parH[ni][nu] = used;\n                    parK[ni][nu] = i;\n                    parO[ni][nu] = id;\n                }\n            }\n        }\n    }\n\n    int bestH = -1;\n    ll bestV = INF;\n    for (int h = 0; h <= 1000; h++) {\n        if (dp[N][h] < bestV) {\n            bestV = dp[N][h];\n            bestH = h;\n        }\n    }\n\n    if (bestH == -1 || bestV == INF) return {};\n\n    vector<Option> rows;\n    int curK = N, curH = bestH;\n\n    while (curK > 0) {\n        int id = parO[curK][curH];\n        if (id < 0) return {};\n\n        rows.push_back(opts[id]);\n        int pk = parK[curK][curH];\n        int ph = parH[curK][curH];\n        curK = pk;\n        curH = ph;\n    }\n\n    reverse(rows.begin(), rows.end());\n\n    auto sol = empty_sol();\n    int y = 0;\n\n    for (auto& op : rows) {\n        int l = op.l, r = op.r, h = op.h;\n\n        if (op.stat) {\n            vector<int> widths(r - l + 1);\n            int sum = 0;\n            for (int p = l; p < r; p++) {\n                widths[p - l] = ceil_div(maxB[p], h);\n                sum += widths[p - l];\n            }\n            widths[r - l] = W - sum;\n\n            for (int d = 0; d < D; d++) {\n                int x = 0;\n                for (int p = l; p <= r; p++) {\n                    int ww = widths[p - l];\n                    int k = ord[p];\n                    sol[d][k] = {y, x, y + h, x + ww};\n                    x += ww;\n                }\n            }\n        } else {\n            for (int d = 0; d < D; d++) {\n                vector<int> widths(r - l + 1);\n                int sum = 0;\n                for (int p = l; p < r; p++) {\n                    widths[p - l] = ceil_div(B[d][p], h);\n                    sum += widths[p - l];\n                }\n                widths[r - l] = W - sum;\n\n                int x = 0;\n                for (int p = l; p <= r; p++) {\n                    int ww = widths[p - l];\n                    int k = ord[p];\n                    sol[d][k] = {y, x, y + h, x + ww};\n                    x += ww;\n                }\n            }\n        }\n\n        y += h;\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> day_shelf_solution_order(const vector<int>& ord) {\n    vector<vector<int>> B(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int p = 0; p < N; p++) B[d][p] = A[d][ord[p]];\n    }\n\n    int K = N + 1;\n    vector<int> pref(1001 * D * K);\n    auto P = [&](int h, int d, int k) -> int& {\n        return pref[(h * D + d) * K + k];\n    };\n\n    for (int h = 1; h <= 1000; h++) {\n        for (int d = 0; d < D; d++) {\n            P(h, d, 0) = 0;\n            for (int k = 0; k < N; k++) P(h, d, k + 1) = P(h, d, k) + ceil_div(B[d][k], h);\n        }\n    }\n\n    auto sol = empty_sol();\n\n    for (int d = 0; d < D; d++) {\n        vector<vector<int>> hmin(N, vector<int>(N, -1));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l; r < N; r++) {\n                for (int h = 1; h <= 1000; h++) {\n                    if (P(h, d, r + 1) - P(h, d, l) <= W) {\n                        hmin[l][r] = h;\n                        break;\n                    }\n                }\n            }\n        }\n\n        const int INF = 1e9;\n        vector<int> dp(N + 1, INF), par(N + 1, -1);\n        dp[0] = 0;\n\n        for (int i = 0; i < N; i++) {\n            if (dp[i] == INF) continue;\n            for (int r = i; r < N; r++) {\n                int h = hmin[i][r];\n                if (h < 0) continue;\n                if (dp[i] + h < dp[r + 1]) {\n                    dp[r + 1] = dp[i] + h;\n                    par[r + 1] = i;\n                }\n            }\n        }\n\n        if (dp[N] > 1000) return {};\n\n        vector<pair<int, int>> rows;\n        int cur = N;\n        while (cur > 0) {\n            int p = par[cur];\n            if (p < 0) return {};\n            rows.push_back({p, cur - 1});\n            cur = p;\n        }\n\n        reverse(rows.begin(), rows.end());\n\n        int y = 0;\n        for (auto [l, r] : rows) {\n            int h = hmin[l][r];\n            int x = 0;\n\n            for (int p = l; p < r; p++) {\n                int ww = ceil_div(B[d][p], h);\n                int k = ord[p];\n                sol[d][k] = {y, x, y + h, x + ww};\n                x += ww;\n            }\n\n            int k = ord[r];\n            sol[d][k] = {y, x, y + h, W};\n            y += h;\n        }\n    }\n\n    return sol;\n}\n\nstruct FixedGuillotine {\n    struct Node {\n        bool leaf = false;\n        int id = -1;\n        bool vert = false;\n        int left = -1, right = -1;\n        int cnt = 0;\n    };\n\n    vector<int> base;\n    vector<Node> nodes;\n\n    int new_node() {\n        nodes.push_back(Node());\n        return (int)nodes.size() - 1;\n    }\n\n    ll sum_base(const vector<int>& ids) const {\n        ll s = 0;\n        for (int id : ids) s += base[id];\n        return s;\n    }\n\n    int build_rec(const vector<int>& ids, int ww, int hh) {\n        int idx = new_node();\n        nodes[idx].cnt = ids.size();\n\n        if ((int)ids.size() == 1) {\n            nodes[idx].leaf = true;\n            nodes[idx].id = ids[0];\n            return idx;\n        }\n\n        int m = ids.size();\n        ll total = max(1LL, sum_base(ids));\n        ll area = 1LL * ww * hh;\n\n        struct Cand {\n            ll score;\n            bool vert;\n            vector<int> a, b;\n        };\n\n        vector<Cand> cand;\n\n        auto add = [&](vector<int> left) {\n            sort(left.begin(), left.end());\n            left.erase(unique(left.begin(), left.end()), left.end());\n            if (left.empty() || (int)left.size() == m) return;\n\n            vector<int> mark(N);\n            for (int id : left) mark[id] = 1;\n\n            vector<int> right;\n            for (int id : ids) if (!mark[id]) right.push_back(id);\n            if (right.empty()) return;\n\n            ll s1 = 0, s2 = 0;\n            for (int id : left) s1 += base[id];\n            for (int id : right) s2 += base[id];\n\n            int n1 = left.size();\n            int n2 = right.size();\n\n            {\n                int lo = ceil_div(n1, hh);\n                int hi = ww - ceil_div(n2, hh);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)ww * s1 / total);\n                    int cut = max(lo, min(hi, ideal));\n                    ll cap1 = 1LL * cut * hh;\n                    ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - 1LL * (ww - cut) * hh);\n                    ll dev = llabs(cap1 * total - s1 * area) / total;\n                    ll aspect = 1000LL * max(cut, hh) / max(1, min(cut, hh))\n                              + 1000LL * max(ww - cut, hh) / max(1, min(ww - cut, hh));\n                    cand.push_back({shortage * 1000000000LL + dev * 1000LL + aspect + hh,\n                                    true, left, right});\n                }\n            }\n\n            {\n                int lo = ceil_div(n1, ww);\n                int hi = hh - ceil_div(n2, ww);\n                if (lo <= hi) {\n                    int ideal = (int)llround((long double)hh * s1 / total);\n                    int cut = max(lo, min(hi, ideal));\n                    ll cap1 = 1LL * ww * cut;\n                    ll shortage = max(0LL, s1 - cap1) + max(0LL, s2 - 1LL * ww * (hh - cut));\n                    ll dev = llabs(cap1 * total - s1 * area) / total;\n                    ll aspect = 1000LL * max(ww, cut) / max(1, min(ww, cut))\n                              + 1000LL * max(ww, hh - cut) / max(1, min(ww, hh - cut));\n                    cand.push_back({shortage * 1000000000LL + dev * 1000LL + aspect + ww,\n                                    false, left, right});\n                }\n            }\n        };\n\n        vector<vector<int>> orders;\n        {\n            auto v = ids;\n            sort(v.begin(), v.end());\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (base[a] != base[b]) return base[a] > base[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n        {\n            auto v = ids;\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                if (base[a] != base[b]) return base[a] < base[b];\n                return a < b;\n            });\n            orders.push_back(v);\n        }\n\n        for (auto ord : orders) {\n            vector<int> pref;\n            for (int i = 0; i + 1 < (int)ord.size(); i++) {\n                pref.push_back(ord[i]);\n                add(pref);\n            }\n        }\n\n        vector<double> targets = {0.25, 0.33, 0.40, 0.50, 0.60, 0.67, 0.75};\n        auto desc = ids;\n        sort(desc.begin(), desc.end(), [&](int a, int b) {\n            if (base[a] != base[b]) return base[a] > base[b];\n            return a < b;\n        });\n\n        for (double t : targets) {\n            ll target = (ll)(total * t);\n            vector<int> group;\n            ll s = 0;\n            for (int id : desc) {\n                if (group.empty() || s + base[id] <= target) {\n                    group.push_back(id);\n                    s += base[id];\n                }\n            }\n            add(group);\n        }\n\n        if (cand.empty()) {\n            vector<int> a, b;\n            for (int i = 0; i < m; i++) {\n                if (i < m / 2) a.push_back(ids[i]);\n                else b.push_back(ids[i]);\n            }\n\n            bool vert = (ww >= hh);\n            nodes[idx].vert = vert;\n\n            if (vert) {\n                int cut = max(1, min(ww - 1, ww / 2));\n                nodes[idx].left = build_rec(a, cut, hh);\n                nodes[idx].right = build_rec(b, ww - cut, hh);\n            } else {\n                int cut = max(1, min(hh - 1, hh / 2));\n                nodes[idx].left = build_rec(a, ww, cut);\n                nodes[idx].right = build_rec(b, ww, hh - cut);\n            }\n            return idx;\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            return a.score < b.score;\n        });\n\n        auto best = cand[0];\n        nodes[idx].vert = best.vert;\n\n        ll s1 = 0;\n        for (int id : best.a) s1 += base[id];\n\n        if (best.vert) {\n            int lo = ceil_div((int)best.a.size(), hh);\n            int hi = ww - ceil_div((int)best.b.size(), hh);\n            int cut = max(lo, min(hi, (int)llround((long double)ww * s1 / total)));\n            nodes[idx].left = build_rec(best.a, cut, hh);\n            nodes[idx].right = build_rec(best.b, ww - cut, hh);\n        } else {\n            int lo = ceil_div((int)best.a.size(), ww);\n            int hi = hh - ceil_div((int)best.b.size(), ww);\n            int cut = max(lo, min(hi, (int)llround((long double)hh * s1 / total)));\n            nodes[idx].left = build_rec(best.a, ww, cut);\n            nodes[idx].right = build_rec(best.b, ww, hh - cut);\n        }\n\n        return idx;\n    }\n\n    ll sum_weight(int idx, const vector<int>& weight) const {\n        const auto& nd = nodes[idx];\n        if (nd.leaf) return weight[nd.id];\n        return sum_weight(nd.left, weight) + sum_weight(nd.right, weight);\n    }\n\n    void layout_rec(int idx, int x, int y, int ww, int hh,\n                    const vector<int>& weight, vector<Rect>& out) const {\n        const auto& nd = nodes[idx];\n\n        if (nd.leaf) {\n            out[nd.id] = {y, x, y + hh, x + ww};\n            return;\n        }\n\n        const auto& L = nodes[nd.left];\n        const auto& R = nodes[nd.right];\n\n        ll sl = sum_weight(nd.left, weight);\n        ll sr = sum_weight(nd.right, weight);\n        ll total = max(1LL, sl + sr);\n\n        if (nd.vert) {\n            int lo = ceil_div(L.cnt, hh);\n            int hi = ww - ceil_div(R.cnt, hh);\n            int cut;\n\n            if (lo <= hi) {\n                int ideal = (int)llround((long double)ww * sl / total);\n                cut = max(lo, min(hi, ideal));\n            } else {\n                cut = max(1, min(ww - 1, ww / 2));\n            }\n\n            layout_rec(nd.left, x, y, cut, hh, weight, out);\n            layout_rec(nd.right, x + cut, y, ww - cut, hh, weight, out);\n        } else {\n            int lo = ceil_div(L.cnt, ww);\n            int hi = hh - ceil_div(R.cnt, ww);\n            int cut;\n\n            if (lo <= hi) {\n                int ideal = (int)llround((long double)hh * sl / total);\n                cut = max(lo, min(hi, ideal));\n            } else {\n                cut = max(1, min(hh - 1, hh / 2));\n            }\n\n            layout_rec(nd.left, x, y, ww, cut, weight, out);\n            layout_rec(nd.right, x, y + cut, ww, hh - cut, weight, out);\n        }\n    }\n\n    vector<vector<Rect>> solve(const vector<int>& baseWeight, int alphaNum, int alphaDen) {\n        base = baseWeight;\n        nodes.clear();\n\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        int root = build_rec(ids, W, W);\n\n        auto sol = empty_sol();\n\n        for (int d = 0; d < D; d++) {\n            vector<int> mixed(N);\n            for (int k = 0; k < N; k++) {\n                ll v = 1LL * (alphaDen - alphaNum) * base[k] + 1LL * alphaNum * A[d][k];\n                mixed[k] = max(1, (int)((v + alphaDen / 2) / alphaDen));\n            }\n\n            vector<Rect> out(N);\n            layout_rec(root, 0, 0, W, W, mixed, out);\n\n            for (int k = 0; k < N; k++) sol[d][k] = out[k];\n        }\n\n        return sol;\n    }\n};\n\nvector<vector<Rect>> fixed_guillotine_solution(const vector<int>& base, int alphaNum, int alphaDen) {\n    FixedGuillotine fg;\n    return fg.solve(base, alphaNum, alphaDen);\n}\n\nvector<vector<Rect>> block_fixed_guillotine_solution(int bs, int typ, int alphaNum, int alphaDen, int off) {\n    auto sol = empty_sol();\n\n    auto apply = [&](int l, int r) {\n        if (l >= r) return;\n\n        vector<int> base = aggregate_block(l, r, typ);\n\n        FixedGuillotine fg;\n        fg.base = base;\n        fg.nodes.clear();\n\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        int root = fg.build_rec(ids, W, W);\n\n        for (int d = l; d < r; d++) {\n            vector<int> mixed(N);\n            for (int k = 0; k < N; k++) {\n                ll v = 1LL * (alphaDen - alphaNum) * base[k] + 1LL * alphaNum * A[d][k];\n                mixed[k] = max(1, (int)((v + alphaDen / 2) / alphaDen));\n            }\n\n            vector<Rect> out(N);\n            fg.layout_rec(root, 0, 0, W, W, mixed, out);\n\n            for (int k = 0; k < N; k++) sol[d][k] = out[k];\n        }\n    };\n\n    int cur = 0;\n    if (off > 0 && off < D) {\n        apply(0, off);\n        cur = off;\n    }\n\n    while (cur < D) {\n        int nxt = min(D, cur + bs);\n        apply(cur, nxt);\n        cur = nxt;\n    }\n\n    return sol;\n}\n\nvector<int> allocate_single_day_heights(int d) {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) {\n        int rem = A[d][k] - h[k] * W;\n        if (rem <= 0) return 0;\n        return min(W, rem);\n    };\n\n    priority_queue<pair<int, int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n\n        if (b <= 0) break;\n\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<int> allocate_static_heights() {\n    vector<int> h(N, 1);\n    int used = N;\n\n    auto benefit = [&](int k) {\n        int res = 0;\n        for (int d = 0; d < D; d++) {\n            int rem = A[d][k] - h[k] * W;\n            if (rem > 0) res += min(W, rem);\n        }\n        return res;\n    };\n\n    priority_queue<pair<int, int>> pq;\n    for (int k = 0; k < N; k++) pq.push({benefit(k), k});\n\n    while (used < 1000 && !pq.empty()) {\n        auto [b, k] = pq.top();\n        pq.pop();\n\n        if (b != benefit(k)) {\n            pq.push({benefit(k), k});\n            continue;\n        }\n\n        if (b <= 0) break;\n\n        h[k]++;\n        used++;\n        pq.push({benefit(k), k});\n    }\n\n    return h;\n}\n\nvector<vector<Rect>> singleton_dynamic_solution() {\n    auto sol = empty_sol();\n\n    for (int d = 0; d < D; d++) {\n        auto h = allocate_single_day_heights(d);\n        int y = 0;\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<Rect>> singleton_static_solution() {\n    auto sol = empty_sol();\n    auto h = allocate_static_heights();\n\n    for (int d = 0; d < D; d++) {\n        int y = 0;\n        for (int k = 0; k < N; k++) {\n            sol[d][k] = {y, 0, y + h[k], W};\n            y += h[k];\n        }\n    }\n\n    return sol;\n}\n\nvector<vector<int>> make_orders() {\n    vector<vector<int>> orders;\n    vector<int> id(N);\n    iota(id.begin(), id.end(), 0);\n    orders.push_back(id);\n\n    auto rev = id;\n    reverse(rev.begin(), rev.end());\n    orders.push_back(rev);\n\n    vector<int> zig;\n    for (int l = 0, r = N - 1; l <= r; l++, r--) {\n        zig.push_back(l);\n        if (l != r) zig.push_back(r);\n    }\n    orders.push_back(zig);\n\n    vector<int> zag;\n    for (int l = 0, r = N - 1; l <= r; l++, r--) {\n        zag.push_back(r);\n        if (l != r) zag.push_back(l);\n    }\n    orders.push_back(zag);\n\n    vector<int> evenOdd;\n    for (int i = 0; i < N; i += 2) evenOdd.push_back(i);\n    for (int i = 1; i < N; i += 2) evenOdd.push_back(i);\n    orders.push_back(evenOdd);\n\n    vector<int> oddEven;\n    for (int i = 1; i < N; i += 2) oddEven.push_back(i);\n    for (int i = 0; i < N; i += 2) oddEven.push_back(i);\n    orders.push_back(oddEven);\n\n    vector<int> center;\n    int c = N / 2;\n    center.push_back(c);\n    for (int t = 1; (int)center.size() < N; t++) {\n        if (c - t >= 0) center.push_back(c - t);\n        if (c + t < N) center.push_back(c + t);\n    }\n    orders.push_back(center);\n\n    vector<int> stride;\n    int step = max(1, N / 2 - 1);\n    while (std::gcd(step, N) != 1 && step > 1) step--;\n    int cur = 0;\n    for (int i = 0; i < N; i++) {\n        stride.push_back(cur);\n        cur = (cur + step) % N;\n    }\n    orders.push_back(stride);\n\n    return orders;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n    const double TIME_LIMIT_MS = 2820.0;\n\n    int inputW;\n    cin >> inputW >> D >> N;\n\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    maxA.assign(N, 0);\n    for (int k = 0; k < N; k++) {\n        for (int d = 0; d < D; d++) maxA[k] = max(maxA[k], A[d][k]);\n    }\n\n    Scorer scorer;\n    vector<vector<Rect>> bestSol;\n    ll bestScore = (1LL << 62);\n\n    auto time_ok = [&]() {\n        return timer.ms() < TIME_LIMIT_MS;\n    };\n\n    auto consider = [&](vector<vector<Rect>> s) {\n        if (!time_ok()) return;\n        if (!valid_solution(s)) return;\n        ll sc = scorer.score(s, bestScore);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestSol = move(s);\n        }\n    };\n\n    vector<int> avg = average_area_vector();\n    vector<int> p25 = percentile_area_vector(0.25);\n    vector<int> p50 = percentile_area_vector(0.50);\n    vector<int> p75 = percentile_area_vector(0.75);\n    vector<int> p90 = percentile_area_vector(0.90);\n\n    auto orders = make_orders();\n\n    consider(singleton_static_solution());\n    consider(static_bfd_solution());\n\n    for (auto& ord : orders) {\n        if (!time_ok()) break;\n        consider(stable_shelf_dp_order(ord));\n    }\n\n    if (time_ok()) consider(day_shelf_solution_order(orders[0]));\n    if (time_ok()) consider(day_shelf_solution_order(orders[1]));\n\n    if (time_ok()) consider(per_day_bfd_solution());\n\n    if (time_ok()) {\n        for (int h : promising_fixed_heights()) {\n            if (!time_ok()) break;\n            consider(fixed_h_bfd_solution(h));\n        }\n    }\n\n    for (int mode = 0; mode <= 1 && time_ok(); mode++) {\n        consider(treemap_dynamic_solution(mode));\n        consider(treemap_static_solution(maxA, mode));\n        consider(treemap_static_solution(avg, mode));\n        consider(treemap_static_solution(p75, mode));\n        consider(treemap_static_solution(p90, mode));\n    }\n\n    vector<int> blockSizes = {2, 3, 4, 5, 7, 10, 15};\n    for (int mode = 0; mode <= 1 && time_ok(); mode++) {\n        for (int bs : blockSizes) {\n            if (!time_ok()) break;\n            vector<int> offsets = {0};\n            if (bs >= 3) offsets.push_back(bs / 2);\n\n            for (int off : offsets) {\n                if (!time_ok()) break;\n                consider(treemap_block_solution(bs, mode, 0, off));\n                if (!time_ok()) break;\n                consider(treemap_block_solution(bs, mode, 1, off));\n                if (!time_ok()) break;\n                if (bs >= 4) consider(treemap_block_solution(bs, mode, 2, off));\n            }\n        }\n    }\n\n    if (time_ok()) consider(fixed_guillotine_solution(avg, 0, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(avg, 1, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(avg, 2, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(avg, 3, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(avg, 4, 4));\n\n    if (time_ok()) consider(fixed_guillotine_solution(maxA, 0, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(maxA, 1, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(maxA, 2, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(maxA, 4, 4));\n\n    if (time_ok()) consider(fixed_guillotine_solution(p25, 2, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(p25, 4, 4));\n\n    if (time_ok()) consider(fixed_guillotine_solution(p50, 1, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(p50, 2, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(p50, 3, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(p50, 4, 4));\n\n    if (time_ok()) consider(fixed_guillotine_solution(p75, 1, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(p75, 2, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(p75, 4, 4));\n\n    if (time_ok()) consider(fixed_guillotine_solution(p90, 1, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(p90, 2, 4));\n    if (time_ok()) consider(fixed_guillotine_solution(p90, 4, 4));\n\n    // Extra optional candidates: block fixed-topology guillotine.\n    if (time_ok() && timer.ms() < 2580.0) {\n        for (int bs : {3, 5, 7, 10}) {\n            if (!time_ok()) break;\n            vector<int> offsets = {0};\n            if (bs >= 5) offsets.push_back(bs / 2);\n\n            for (int off : offsets) {\n                if (!time_ok()) break;\n                for (int typ : {0, 1, 2}) {\n                    if (!time_ok()) break;\n                    consider(block_fixed_guillotine_solution(bs, typ, 1, 4, off));\n                    if (!time_ok()) break;\n                    consider(block_fixed_guillotine_solution(bs, typ, 2, 4, off));\n                    if (!time_ok()) break;\n                    consider(block_fixed_guillotine_solution(bs, typ, 4, 4, off));\n                }\n            }\n        }\n    }\n\n    if (time_ok()) consider(singleton_dynamic_solution());\n\n    if (!valid_solution(bestSol)) bestSol = singleton_static_solution();\n\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            const auto& r = bestSol[d][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 K = 81;\nstatic constexpr int MOD = 998244353;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int nextInt(int n) {\n        return int(next() % n);\n    }\n};\n\nstruct Action {\n    int m, p, q;\n    int cell[9];\n    int val[9];\n    long long sum;\n    int noise;\n    uint64_t lo, hi;\n};\n\nstruct State {\n    array<int, 81> board;\n    array<int, 81> seq;\n    long long score;\n};\n\nclass Solver {\nprivate:\n    int inN, M, inK;\n    int stamp[20][3][3];\n\n    vector<Action> actions;\n    vector<int> rawTopIds;\n\n    int DUMMY;\n\n    array<int, 81> initBoard;\n    long long initScore = 0;\n\n    chrono::steady_clock::time_point startTime;\n\n    static constexpr double DIVERSIFY_TIME = 1.89;\n    static constexpr double HARD_TIME = 1.94;\n\n    XorShift rng;\n\n    inline double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    }\n\n    inline bool timeOver() const {\n        return elapsed() >= HARD_TIME;\n    }\n\n    inline bool diversifyOver() const {\n        return elapsed() >= DIVERSIFY_TIME;\n    }\n\n    inline bool overlapAction(int a, int b) const {\n        if (a == DUMMY || b == DUMMY) return false;\n        return ((actions[a].lo & actions[b].lo) | (actions[a].hi & actions[b].hi)) != 0;\n    }\n\n    inline long long rawKey(int id) const {\n        return actions[id].sum * 2048LL + actions[id].noise;\n    }\n\n    inline long long gainAdd(const array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long g = a.sum;\n\n        for (int k = 0; k < 9; k++) {\n            if (board[a.cell[k]] + a.val[k] >= MOD) {\n                g -= MOD;\n            }\n        }\n\n        return g;\n    }\n\n    inline long long gainRemove(const array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long g = -a.sum;\n\n        for (int k = 0; k < 9; k++) {\n            if (board[a.cell[k]] < a.val[k]) {\n                g += MOD;\n            }\n        }\n\n        return g;\n    }\n\n    inline long long applyAdd(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = a.sum;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int nv = board[c] + a.val[k];\n\n            if (nv >= MOD) {\n                nv -= MOD;\n                diff -= MOD;\n            }\n\n            board[c] = nv;\n        }\n\n        return diff;\n    }\n\n    inline long long applyRemove(array<int, 81>& board, int id) const {\n        if (id == DUMMY) return 0;\n\n        const Action& a = actions[id];\n        long long diff = -a.sum;\n\n        for (int k = 0; k < 9; k++) {\n            int c = a.cell[k];\n            int nv = board[c] - a.val[k];\n\n            if (nv < 0) {\n                nv += MOD;\n                diff += MOD;\n            }\n\n            board[c] = nv;\n        }\n\n        return diff;\n    }\n\n    State emptyState() const {\n        State st;\n        st.board = initBoard;\n        st.seq.fill(DUMMY);\n        st.score = initScore;\n        return st;\n    }\n\n    template<int C>\n    inline void insertTop(array<int, C>& ids, array<long long, C>& gs, int id, long long g) {\n        if (g <= gs[C - 1]) return;\n\n        int pos = C - 1;\n\n        while (pos > 0 && g > gs[pos - 1]) {\n            ids[pos] = ids[pos - 1];\n            gs[pos] = gs[pos - 1];\n            pos--;\n        }\n\n        ids[pos] = id;\n        gs[pos] = g;\n    }\n\n    inline void addUnique(vector<int>& v, array<unsigned char, 1000>& used, int id) {\n        if (id < 0) return;\n\n        if (!used[id]) {\n            used[id] = 1;\n            v.push_back(id);\n        }\n    }\n\n    int bestAction(const array<int, 81>& board) const {\n        long long bestG = 0;\n        int bestId = DUMMY;\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(board, id);\n\n            if (g > bestG) {\n                bestG = g;\n                bestId = id;\n            }\n        }\n\n        return bestId;\n    }\n\n    State greedyState() {\n        State st = emptyState();\n\n        for (int t = 0; t < K; t++) {\n            int id = bestAction(st.board);\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    State randomizedGreedyState(int topC) {\n        State st = emptyState();\n        topC = min(topC, 32);\n\n        for (int t = 0; t < K; t++) {\n            array<int, 32> ids;\n            array<long long, 32> gs;\n\n            ids.fill(DUMMY);\n            gs.fill(LLONG_MIN / 4);\n\n            auto ins = [&](int id, long long g) {\n                if (g <= gs[topC - 1]) return;\n\n                int pos = topC - 1;\n\n                while (pos > 0 && g > gs[pos - 1]) {\n                    ids[pos] = ids[pos - 1];\n                    gs[pos] = gs[pos - 1];\n                    pos--;\n                }\n\n                ids[pos] = id;\n                gs[pos] = g;\n            };\n\n            ins(DUMMY, 0);\n\n            for (int id = 0; id < DUMMY; id++) {\n                ins(id, gainAdd(st.board, id));\n            }\n\n            int r;\n            int x = rng.nextInt(100);\n\n            if (x < 55) r = 0;\n            else if (x < 75) r = min(1, topC - 1);\n            else if (x < 88) r = min(2, topC - 1);\n            else r = rng.nextInt(topC);\n\n            int id = ids[r];\n            if (gs[r] < 0) id = DUMMY;\n\n            st.seq[t] = id;\n            st.score += applyAdd(st.board, id);\n        }\n\n        return st;\n    }\n\n    void shuffleOrder(array<int, 81>& ord) {\n        for (int i = K - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    void coordinateDescent(State& st, int maxPass) {\n        array<int, 81> ord;\n        for (int i = 0; i < K; i++) ord[i] = i;\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            if (timeOver()) return;\n\n            shuffleOrder(ord);\n            bool changed = false;\n\n            for (int oi = 0; oi < K; oi++) {\n                if ((oi & 7) == 0 && timeOver()) return;\n\n                int idx = ord[oi];\n                int oldId = st.seq[idx];\n\n                st.score += applyRemove(st.board, oldId);\n\n                long long bestG = 0;\n                int bestId = DUMMY;\n\n                for (int id = 0; id < DUMMY; id++) {\n                    long long g = gainAdd(st.board, id);\n\n                    if (g > bestG) {\n                        bestG = g;\n                        bestId = id;\n                    }\n                }\n\n                st.seq[idx] = bestId;\n                st.score += applyAdd(st.board, bestId);\n\n                if (bestId != oldId) changed = true;\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    int weakSlot(const State& st, int samples = 18) {\n        int bestIdx = rng.nextInt(K);\n        long long bestRemoveGain = gainRemove(st.board, st.seq[bestIdx]);\n\n        for (int t = 1; t < samples; t++) {\n            int idx = rng.nextInt(K);\n            long long g = gainRemove(st.board, st.seq[idx]);\n\n            if (g > bestRemoveGain) {\n                bestRemoveGain = g;\n                bestIdx = idx;\n            }\n        }\n\n        return bestIdx;\n    }\n\n    int weakSlotExcept(const State& st, int except, int refAction, int samples = 24) {\n        int bestIdx = -1;\n        long long bestValue = LLONG_MIN / 4;\n\n        for (int t = 0; t < samples; t++) {\n            int idx = rng.nextInt(K);\n            if (idx == except) continue;\n\n            long long v = gainRemove(st.board, st.seq[idx]);\n\n            if (overlapAction(refAction, st.seq[idx])) {\n                v += MOD / 2;\n            }\n\n            if (v > bestValue) {\n                bestValue = v;\n                bestIdx = idx;\n            }\n        }\n\n        if (bestIdx == -1) {\n            bestIdx = rng.nextInt(K - 1);\n            if (bestIdx >= except) bestIdx++;\n        }\n\n        return bestIdx;\n    }\n\n    void choosePairSlots(const State& st, int& x, int& y) {\n        int mode = rng.nextInt(100);\n\n        if (mode < 82) {\n            x = weakSlot(st, 16);\n            y = weakSlotExcept(st, x, st.seq[x], 26);\n        } else if (mode < 92) {\n            x = weakSlot(st, 12);\n            y = rng.nextInt(K - 1);\n            if (y >= x) y++;\n        } else {\n            x = rng.nextInt(K);\n            y = rng.nextInt(K - 1);\n            if (y >= x) y++;\n        }\n    }\n\n    void randomPerturb(State& st, int strength) {\n        for (int r = 0; r < strength; r++) {\n            int idx = rng.nextInt(K);\n            int oldId = st.seq[idx];\n\n            st.score += applyRemove(st.board, oldId);\n\n            int newId = rng.nextInt(DUMMY);\n            st.seq[idx] = newId;\n            st.score += applyAdd(st.board, newId);\n        }\n    }\n\n    void ruinRecreate(State& st, int strength, bool weak) {\n        bool used[81] = {};\n        vector<int> slots;\n        slots.reserve(strength);\n\n        while ((int)slots.size() < strength) {\n            int idx;\n\n            if (weak) {\n                idx = -1;\n                long long best = LLONG_MIN / 4;\n\n                for (int t = 0; t < 25; t++) {\n                    int cand = rng.nextInt(K);\n                    if (used[cand]) continue;\n\n                    long long g = gainRemove(st.board, st.seq[cand]);\n\n                    if (g > best) {\n                        best = g;\n                        idx = cand;\n                    }\n                }\n\n                if (idx == -1) idx = rng.nextInt(K);\n            } else {\n                idx = rng.nextInt(K);\n            }\n\n            if (!used[idx]) {\n                used[idx] = true;\n                slots.push_back(idx);\n\n                st.score += applyRemove(st.board, st.seq[idx]);\n                st.seq[idx] = DUMMY;\n            }\n        }\n\n        for (int i = (int)slots.size() - 1; i >= 1; i--) {\n            int j = rng.nextInt(i + 1);\n            swap(slots[i], slots[j]);\n        }\n\n        for (int idx : slots) {\n            int id = bestAction(st.board);\n            st.seq[idx] = id;\n            st.score += applyAdd(st.board, id);\n        }\n    }\n\n    vector<int> collectPairFirstCandidates(const array<int, 81>& board, int oldA, int oldB) {\n        static constexpr int CG = 26;\n\n        array<int, CG> gainIds;\n        array<long long, CG> gainKeys;\n\n        gainIds.fill(DUMMY);\n        gainKeys.fill(LLONG_MIN / 4);\n\n        insertTop<CG>(gainIds, gainKeys, DUMMY, 0);\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(board, id);\n            insertTop<CG>(gainIds, gainKeys, id, g);\n        }\n\n        vector<int> cand;\n        cand.reserve(48);\n        array<unsigned char, 1000> used{};\n\n        addUnique(cand, used, DUMMY);\n\n        for (int i = 0; i < CG; i++) {\n            addUnique(cand, used, gainIds[i]);\n        }\n\n        for (int i = 0; i < min<int>(8, rawTopIds.size()); i++) {\n            addUnique(cand, used, rawTopIds[i]);\n        }\n\n        addUnique(cand, used, oldA);\n        addUnique(cand, used, oldB);\n\n        for (int i = 0; i < 6; i++) {\n            addUnique(cand, used, rng.nextInt(DUMMY));\n        }\n\n        return cand;\n    }\n\n    bool pairAttempt(State& st) {\n        int x, y;\n        choosePairSlots(st, x, y);\n\n        int oldX = st.seq[x];\n        int oldY = st.seq[y];\n\n        long long originalScore = st.score;\n\n        st.score += applyRemove(st.board, oldX);\n        st.score += applyRemove(st.board, oldY);\n\n        long long baseScore = st.score;\n\n        vector<int> firstCand = collectPairFirstCandidates(st.board, oldX, oldY);\n\n        long long bestTotal = 0;\n        int bestA = DUMMY;\n        int bestB = DUMMY;\n\n        auto evalFirst = [&](int a) {\n            long long g1 = gainAdd(st.board, a);\n            applyAdd(st.board, a);\n\n            long long bestG2 = 0;\n            int b = DUMMY;\n\n            for (int id = 0; id < DUMMY; id++) {\n                long long g2 = gainAdd(st.board, id);\n\n                if (g2 > bestG2) {\n                    bestG2 = g2;\n                    b = id;\n                }\n            }\n\n            long long total = g1 + bestG2;\n\n            if (total > bestTotal) {\n                bestTotal = total;\n                bestA = a;\n                bestB = b;\n            }\n\n            applyRemove(st.board, a);\n        };\n\n        for (int a : firstCand) {\n            evalFirst(a);\n        }\n\n        if (baseScore + bestTotal > originalScore) {\n            st.seq[x] = bestA;\n            st.seq[y] = bestB;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, bestA);\n            st.score += applyAdd(st.board, bestB);\n\n            return true;\n        } else {\n            st.seq[x] = oldX;\n            st.seq[y] = oldY;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, oldX);\n            st.score += applyAdd(st.board, oldY);\n\n            return false;\n        }\n    }\n\n    vector<int> collectTripleFirstCandidates(const array<int, 81>& board, int oldA, int oldB, int oldC) {\n        static constexpr int CG = 10;\n\n        array<int, CG> gainIds;\n        array<long long, CG> gainKeys;\n\n        gainIds.fill(DUMMY);\n        gainKeys.fill(LLONG_MIN / 4);\n\n        insertTop<CG>(gainIds, gainKeys, DUMMY, 0);\n\n        for (int id = 0; id < DUMMY; id++) {\n            long long g = gainAdd(board, id);\n            insertTop<CG>(gainIds, gainKeys, id, g);\n        }\n\n        vector<int> cand;\n        cand.reserve(24);\n        array<unsigned char, 1000> used{};\n\n        addUnique(cand, used, DUMMY);\n\n        for (int i = 0; i < CG; i++) {\n            addUnique(cand, used, gainIds[i]);\n        }\n\n        for (int i = 0; i < min<int>(4, rawTopIds.size()); i++) {\n            addUnique(cand, used, rawTopIds[i]);\n        }\n\n        addUnique(cand, used, oldA);\n        addUnique(cand, used, oldB);\n        addUnique(cand, used, oldC);\n\n        for (int i = 0; i < 3; i++) {\n            addUnique(cand, used, rng.nextInt(DUMMY));\n        }\n\n        return cand;\n    }\n\n    bool tripleAttempt(State& st) {\n        int x = weakSlot(st, 14);\n        int y = weakSlotExcept(st, x, st.seq[x], 20);\n\n        int z = -1;\n\n        for (int t = 0; t < 30; t++) {\n            int cand = rng.nextInt(K);\n\n            if (cand == x || cand == y) continue;\n\n            if (z == -1) {\n                z = cand;\n            } else {\n                long long vc = gainRemove(st.board, st.seq[cand]);\n                long long vz = gainRemove(st.board, st.seq[z]);\n\n                if (vc > vz) z = cand;\n            }\n        }\n\n        if (z == -1) {\n            z = rng.nextInt(K);\n            while (z == x || z == y) z = rng.nextInt(K);\n        }\n\n        int oldX = st.seq[x];\n        int oldY = st.seq[y];\n        int oldZ = st.seq[z];\n\n        long long originalScore = st.score;\n\n        st.score += applyRemove(st.board, oldX);\n        st.score += applyRemove(st.board, oldY);\n        st.score += applyRemove(st.board, oldZ);\n\n        long long baseScore = st.score;\n\n        static constexpr int C2 = 7;\n\n        vector<int> firstCand = collectTripleFirstCandidates(st.board, oldX, oldY, oldZ);\n\n        long long bestTotal = 0;\n        int bestA = DUMMY;\n        int bestB = DUMMY;\n        int bestC = DUMMY;\n\n        auto evalFirst = [&](int a) {\n            long long g1 = gainAdd(st.board, a);\n            applyAdd(st.board, a);\n\n            array<int, C2> secondIds;\n            array<long long, C2> secondGs;\n\n            secondIds.fill(DUMMY);\n            secondGs.fill(LLONG_MIN / 4);\n\n            insertTop<C2>(secondIds, secondGs, DUMMY, 0);\n\n            for (int id = 0; id < DUMMY; id++) {\n                insertTop<C2>(secondIds, secondGs, id, gainAdd(st.board, id));\n            }\n\n            for (int bi = 0; bi < C2; bi++) {\n                int b = secondIds[bi];\n\n                long long g2 = gainAdd(st.board, b);\n                applyAdd(st.board, b);\n\n                long long bestG3 = 0;\n                int c = DUMMY;\n\n                for (int id = 0; id < DUMMY; id++) {\n                    long long g3 = gainAdd(st.board, id);\n\n                    if (g3 > bestG3) {\n                        bestG3 = g3;\n                        c = id;\n                    }\n                }\n\n                long long total = g1 + g2 + bestG3;\n\n                if (total > bestTotal) {\n                    bestTotal = total;\n                    bestA = a;\n                    bestB = b;\n                    bestC = c;\n                }\n\n                applyRemove(st.board, b);\n            }\n\n            applyRemove(st.board, a);\n        };\n\n        for (int a : firstCand) {\n            evalFirst(a);\n        }\n\n        if (baseScore + bestTotal > originalScore) {\n            st.seq[x] = bestA;\n            st.seq[y] = bestB;\n            st.seq[z] = bestC;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, bestA);\n            st.score += applyAdd(st.board, bestB);\n            st.score += applyAdd(st.board, bestC);\n\n            return true;\n        } else {\n            st.seq[x] = oldX;\n            st.seq[y] = oldY;\n            st.seq[z] = oldZ;\n\n            st.score = baseScore;\n            st.score += applyAdd(st.board, oldX);\n            st.score += applyAdd(st.board, oldY);\n            st.score += applyAdd(st.board, oldZ);\n\n            return false;\n        }\n    }\n\n    void pairLocalSearch(State& st, int attempts) {\n        int improved = 0;\n\n        for (int t = 0; t < attempts; t++) {\n            if ((t & 3) == 0 && timeOver()) return;\n\n            if (pairAttempt(st)) {\n                improved++;\n\n                if ((improved & 7) == 0) {\n                    coordinateDescent(st, 2);\n                }\n            }\n        }\n\n        if (improved > 0) coordinateDescent(st, 4);\n    }\n\n    void tripleLocalSearch(State& st, int attempts) {\n        int improved = 0;\n\n        for (int t = 0; t < attempts; t++) {\n            if (timeOver()) return;\n\n            if (tripleAttempt(st)) {\n                improved++;\n\n                if ((improved & 3) == 0) {\n                    coordinateDescent(st, 2);\n                }\n            }\n        }\n\n        if (improved > 0) coordinateDescent(st, 4);\n    }\n\npublic:\n    void readInput() {\n        cin >> inN >> M >> inK;\n\n        uint64_t seed = 123456789123ULL;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int x;\n                cin >> x;\n\n                initBoard[i * N + j] = x;\n                initScore += x;\n\n                seed ^= uint64_t(x + 1) * 1000003ULL;\n                seed = seed * 11995408973635179863ULL + 101;\n            }\n        }\n\n        for (int m = 0; m < M; m++) {\n            for (int i = 0; i < 3; i++) {\n                for (int j = 0; j < 3; j++) {\n                    cin >> stamp[m][i][j];\n\n                    seed ^= uint64_t(stamp[m][i][j] + 7) * 1000000007ULL;\n                    seed = seed * 1000003ULL + 97;\n                }\n            }\n        }\n\n        rng = XorShift(seed);\n    }\n\n    void buildActions() {\n        actions.clear();\n\n        for (int p = 0; p <= N - 3; p++) {\n            for (int q = 0; q <= N - 3; q++) {\n                for (int m = 0; m < M; m++) {\n                    Action a;\n                    a.m = m;\n                    a.p = p;\n                    a.q = q;\n                    a.sum = 0;\n                    a.lo = 0;\n                    a.hi = 0;\n\n                    uint64_t h = uint64_t(m + 1) * 1000003ULL\n                               ^ uint64_t(p + 11) * 10007ULL\n                               ^ uint64_t(q + 37) * 1009ULL;\n                    h ^= h >> 23;\n                    h *= 0x2127599bf4325c37ULL;\n                    h ^= h >> 47;\n                    a.noise = int(h & 2047);\n\n                    int idx = 0;\n\n                    for (int di = 0; di < 3; di++) {\n                        for (int dj = 0; dj < 3; dj++) {\n                            int c = (p + di) * N + (q + dj);\n\n                            a.cell[idx] = c;\n                            a.val[idx] = stamp[m][di][dj];\n                            a.sum += stamp[m][di][dj];\n\n                            if (c < 64) {\n                                a.lo |= 1ULL << c;\n                            } else {\n                                a.hi |= 1ULL << (c - 64);\n                            }\n\n                            idx++;\n                        }\n                    }\n\n                    actions.push_back(a);\n                }\n            }\n        }\n\n        DUMMY = (int)actions.size();\n\n        vector<pair<long long, int>> raw;\n        raw.reserve(DUMMY);\n\n        for (int id = 0; id < DUMMY; id++) {\n            raw.emplace_back(rawKey(id), id);\n        }\n\n        sort(raw.rbegin(), raw.rend());\n\n        rawTopIds.clear();\n        for (int i = 0; i < min<int>(80, raw.size()); i++) {\n            rawTopIds.push_back(raw[i].second);\n        }\n    }\n\n    void solve() {\n        startTime = chrono::steady_clock::now();\n\n        buildActions();\n\n        State best = greedyState();\n        coordinateDescent(best, 1000);\n\n        pairLocalSearch(best, 90);\n        tripleLocalSearch(best, 8);\n\n        int iter = 0;\n\n        while (!timeOver() && !diversifyOver()) {\n            State cand;\n\n            int mode = iter % 10;\n\n            if (mode <= 3) {\n                cand = best;\n\n                int strength = 3 + rng.nextInt(10);\n                bool weak = (mode <= 1);\n\n                ruinRecreate(cand, strength, weak);\n                coordinateDescent(cand, 22);\n                pairLocalSearch(cand, 16);\n\n                if ((iter & 3) == 0) {\n                    tripleLocalSearch(cand, 2);\n                }\n            } else if (mode <= 6) {\n                cand = best;\n\n                int strength = 3 + rng.nextInt(12);\n\n                randomPerturb(cand, strength);\n                coordinateDescent(cand, 26);\n                pairLocalSearch(cand, 14);\n\n                if ((iter & 7) == 0) {\n                    tripleLocalSearch(cand, 2);\n                }\n            } else {\n                int topC = 6 + rng.nextInt(14);\n\n                cand = randomizedGreedyState(topC);\n                coordinateDescent(cand, 36);\n                pairLocalSearch(cand, 14);\n\n                if ((iter & 7) == 1) {\n                    tripleLocalSearch(cand, 2);\n                }\n            }\n\n            if (cand.score > best.score) {\n                best = cand;\n                coordinateDescent(best, 6);\n                pairLocalSearch(best, 8);\n            }\n\n            iter++;\n        }\n\n        int fin = 0;\n\n        while (!timeOver()) {\n            pairLocalSearch(best, 6);\n\n            if (timeOver()) break;\n\n            if ((fin & 1) == 0) {\n                tripleLocalSearch(best, 1);\n            } else {\n                coordinateDescent(best, 2);\n            }\n\n            fin++;\n        }\n\n        vector<tuple<int, int, int>> ans;\n\n        for (int i = 0; i < K; i++) {\n            int id = best.seq[i];\n            if (id == DUMMY) continue;\n\n            const Action& a = actions[id];\n            ans.emplace_back(a.m, a.p, a.q);\n        }\n\n        cout << ans.size() << '\\n';\n\n        for (auto [m, p, q] : ans) {\n            cout << m << ' ' << p << ' ' << q << '\\n';\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\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int V = 25;\nstatic constexpr long long INF_SCORE = (1LL << 60);\n\nstruct Param {\n    int deliverMode, digMode, storeMode;\n};\n\nint outputLength(const vector<string>& s) {\n    int t = 0;\n    for (auto &x : s) t = max(t, (int)x.size());\n    return t;\n}\n\nint mdist(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nlong long evaluateOutput(vector<string> S, const vector<vector<int>>& A) {\n    int T = outputLength(S);\n    if (T <= 0 || T > 10000) return INF_SCORE;\n\n    for (auto &s : S) {\n        if (s.empty() || (int)s.size() > 10000) return INF_SCORE;\n        while ((int)s.size() < T) s.push_back('.');\n    }\n\n    int grid[N][N], idx[N];\n    memset(grid, -1, sizeof(grid));\n    memset(idx, 0, sizeof(idx));\n\n    struct Crane {\n        int r, c, hold;\n        bool alive;\n    };\n\n    Crane cr[N];\n    for (int i = 0; i < N; i++) cr[i] = {i, 0, -1, true};\n\n    vector<int> dispatchedByGate[N];\n    vector<int> allDispatched;\n\n    auto inside = [&](int r, int c) {\n        return 0 <= r && r < N && 0 <= c && c < N;\n    };\n\n    for (int t = 0; t < T; t++) {\n        // 1. arrivals\n        for (int r = 0; r < N; r++) {\n            bool blocked = false;\n            for (int k = 0; k < N; k++) {\n                if (cr[k].alive && cr[k].hold != -1 && cr[k].r == r && cr[k].c == 0) {\n                    blocked = true;\n                }\n            }\n            if (idx[r] < N && grid[r][0] == -1 && !blocked) {\n                grid[r][0] = A[r][idx[r]++];\n            }\n        }\n\n        vector<pair<int,int>> oldPos(N), newPos(N);\n        vector<bool> aliveAfter(N);\n        vector<char> act(N);\n\n        for (int i = 0; i < N; i++) {\n            act[i] = S[i][t];\n            if (string(\"PQUDLR.B\").find(act[i]) == string::npos) return INF_SCORE;\n\n            oldPos[i] = {cr[i].r, cr[i].c};\n            newPos[i] = oldPos[i];\n            aliveAfter[i] = cr[i].alive;\n\n            if (!cr[i].alive) {\n                if (act[i] != '.') return INF_SCORE;\n                continue;\n            }\n\n            char a = act[i];\n\n            if (a == 'P') {\n                if (cr[i].hold != -1 || grid[cr[i].r][cr[i].c] == -1) return INF_SCORE;\n            } else if (a == 'Q') {\n                if (cr[i].hold == -1 || grid[cr[i].r][cr[i].c] != -1) return INF_SCORE;\n            } else if (a == 'B') {\n                if (cr[i].hold != -1) return INF_SCORE;\n                aliveAfter[i] = false;\n            } else if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                int nr = cr[i].r, nc = cr[i].c;\n                if (a == 'U') nr--;\n                if (a == 'D') nr++;\n                if (a == 'L') nc--;\n                if (a == 'R') nc++;\n                if (!inside(nr, nc)) return INF_SCORE;\n                if (i != 0 && cr[i].hold != -1 && grid[nr][nc] != -1) return INF_SCORE;\n                newPos[i] = {nr, nc};\n            }\n        }\n\n        // collision\n        for (int i = 0; i < N; i++) if (aliveAfter[i]) {\n            for (int j = i + 1; j < N; j++) if (aliveAfter[j]) {\n                if (newPos[i] == newPos[j]) return INF_SCORE;\n            }\n        }\n\n        // swap\n        for (int i = 0; i < N; i++) if (cr[i].alive && aliveAfter[i]) {\n            for (int j = i + 1; j < N; j++) if (cr[j].alive && aliveAfter[j]) {\n                if (newPos[i] == oldPos[j] && newPos[j] == oldPos[i]) return INF_SCORE;\n            }\n        }\n\n        // apply P/Q\n        for (int i = 0; i < N; i++) {\n            if (!cr[i].alive) continue;\n\n            if (act[i] == 'P') {\n                cr[i].hold = grid[cr[i].r][cr[i].c];\n                grid[cr[i].r][cr[i].c] = -1;\n            } else if (act[i] == 'Q') {\n                grid[cr[i].r][cr[i].c] = cr[i].hold;\n                cr[i].hold = -1;\n            }\n        }\n\n        // apply movement / bomb\n        for (int i = 0; i < N; i++) {\n            if (!cr[i].alive) continue;\n\n            if (act[i] == 'B') cr[i].alive = false;\n            else {\n                cr[i].r = newPos[i].first;\n                cr[i].c = newPos[i].second;\n            }\n        }\n\n        // 3. dispatch\n        for (int r = 0; r < N; r++) {\n            if (grid[r][N - 1] != -1) {\n                int id = grid[r][N - 1];\n                dispatchedByGate[r].push_back(id);\n                allDispatched.push_back(id);\n                grid[r][N - 1] = -1;\n            }\n        }\n    }\n\n    long long M0 = T, M1 = 0, M2 = 0;\n    vector<int> seen(V, 0);\n\n    for (int g = 0; g < N; g++) {\n        vector<int> correct;\n        for (int id : dispatchedByGate[g]) {\n            if (0 <= id && id < V) seen[id]++;\n            if (g * N <= id && id < (g + 1) * N) {\n                correct.push_back(id);\n            } else {\n                M2++;\n            }\n        }\n\n        for (int i = 0; i < (int)correct.size(); i++) {\n            for (int j = i + 1; j < (int)correct.size(); j++) {\n                if (correct[i] > correct[j]) M1++;\n            }\n        }\n    }\n\n    long long dispatchedCnt = 0;\n    for (int id = 0; id < V; id++) {\n        if (seen[id] > 0) dispatchedCnt++;\n        if (seen[id] > 1) {\n            // Should not happen for legal physics, but penalize heavily if it does.\n            return INF_SCORE;\n        }\n    }\n\n    long long M3 = V - dispatchedCnt;\n    return M0 + 100LL * M1 + 10000LL * M2 + 1000000LL * M3;\n}\n\nint scoreDispatchMode(int mode, int curToSrc, int srcToDst, int srcCol, int rowGap, int nextEst = 0) {\n    int base = curToSrc + srcToDst;\n    if (mode == 0) return base * 10;\n    if (mode == 1) return curToSrc * 15 + srcToDst * 5;\n    if (mode == 2) return base * 10 + nextEst * 3;\n    if (mode == 3) return base * 10 - srcCol * 2;\n    if (mode == 4) return curToSrc * 8 + srcToDst * 12 + nextEst * 2;\n    if (mode == 5) return base * 10 + rowGap * 4 - srcCol * 4;\n    if (mode == 6) return curToSrc * 20 + srcToDst * 2;\n    if (mode == 7) return curToSrc * 2 + srcToDst * 20;\n    return base * 10;\n}\n\nint scoreDigMode(int mode, int dep, int dcur, int future, int row) {\n    if (mode == 0) return dep * 100 + dcur * 5;\n    if (mode == 1) return dep * 35 + dcur * 8 + future * 2;\n    if (mode == 2) return dep * 25 + dcur * 15;\n    if (mode == 3) return dep * 50 + dcur * 3 + future * 5;\n    if (mode == 4) return dep * 20 + dcur * 20 + row;\n    if (mode == 5) return dep * 60 + dcur * 10 + future;\n    if (mode == 6) return dep * 15 + dcur * 25 + future * 2;\n    if (mode == 7) return dep * 80 + dcur * 2 + future * 8;\n    if (mode == 8) return dep * 40 + dcur * 12 + future * 4;\n    return dep * 30 + dcur * 18 + future * 3 + row;\n}\n\nint scoreStorageMode(int mode, int a, int b, int rowGap, int col) {\n    if (mode == 0) return a * 10 + b * 10;\n    if (mode == 1) return a * 18 + b * 7;\n    if (mode == 2) return a * 7 + b * 18;\n    if (mode == 3) return a * 10 + b * 10 - col * 3;\n    if (mode == 4) return a * 10 + b * 10 + rowGap * 5 - col;\n    if (mode == 5) return a * 5 + b * 25;\n    if (mode == 6) return a * 25 + b * 5;\n    if (mode == 7) return a * 10 + b * 10 - col * 8 + rowGap * 2;\n    if (mode == 8) return a * 12 + b * 8 + (col == 1 ? -5 : 0);\n    return a * 8 + b * 12 + rowGap * 10 - col * 2;\n}\n\nstruct GreedySolver {\n    vector<vector<int>> A;\n    Param param;\n\n    int grid[N][N], idx[N];\n    int cr = 0, cc = 0, hold = -1;\n    vector<string> S;\n    bool firstStep = true;\n\n    vector<int> nextNeed, delivered;\n    int deliveredCnt = 0;\n\n    GreedySolver(const vector<vector<int>>& A_, Param p) : A(A_), param(p) {\n        memset(grid, -1, sizeof(grid));\n        memset(idx, 0, sizeof(idx));\n        S.assign(N, \"\");\n        nextNeed.resize(N);\n        delivered.assign(V, 0);\n        for (int g = 0; g < N; g++) nextNeed[g] = g * N;\n    }\n\n    void step(char act) {\n        for (int r = 0; r < N; r++) {\n            bool blocked = (hold != -1 && cr == r && cc == 0);\n            if (idx[r] < N && grid[r][0] == -1 && !blocked) {\n                grid[r][0] = A[r][idx[r]++];\n            }\n        }\n\n        S[0].push_back(act);\n        for (int i = 1; i < N; i++) S[i].push_back(firstStep ? 'B' : '.');\n        firstStep = false;\n\n        if (act == 'P') hold = grid[cr][cc], grid[cr][cc] = -1;\n        else if (act == 'Q') grid[cr][cc] = hold, hold = -1;\n        else if (act == 'U') cr--;\n        else if (act == 'D') cr++;\n        else if (act == 'L') cc--;\n        else if (act == 'R') cc++;\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][N - 1] != -1) grid[r][N - 1] = -1;\n        }\n    }\n\n    void moveTo(int r, int c) {\n        while (cr < r) step('D');\n        while (cr > r) step('U');\n        while (cc < c) step('R');\n        while (cc > c) step('L');\n    }\n\n    void pickAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('P');\n    }\n\n    void releaseAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('Q');\n    }\n\n    void markDelivered(int id) {\n        if (!delivered[id]) delivered[id] = 1, deliveredCnt++;\n        int g = id / N;\n        while (nextNeed[g] < (g + 1) * N && delivered[nextNeed[g]]) nextNeed[g]++;\n    }\n\n    optional<pair<int,int>> findAccessible(int id) {\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (grid[r][c] == id) return pair<int,int>{r, c};\n            }\n        }\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == id) {\n                return pair<int,int>{r, 0};\n            }\n        }\n        return nullopt;\n    }\n\n    int frontId(int r) const {\n        if (grid[r][0] != -1) return grid[r][0];\n        if (idx[r] < N) return A[r][idx[r]];\n        return -1;\n    }\n\n    vector<pair<int,int>> freeStorageCells() const {\n        vector<pair<int,int>> res;\n        for (int r = 0; r < N; r++) {\n            for (int c = 1; c <= 3; c++) {\n                if (grid[r][c] == -1) res.push_back({r, c});\n            }\n        }\n        for (int r = 0; r < N; r++) {\n            if (idx[r] >= N && grid[r][0] == -1) res.push_back({r, 0});\n        }\n        return res;\n    }\n\n    int estimateNextAfterDeliver(int deliveredId) {\n        int g0 = deliveredId / N;\n        int best = 20;\n\n        for (int g = 0; g < N; g++) {\n            int target = nextNeed[g];\n            if (g == g0) target++;\n            if (target >= (g + 1) * N) continue;\n\n            optional<pair<int,int>> pos;\n\n            for (int r = 0; r < N; r++) {\n                for (int c = 0; c < N; c++) {\n                    if (grid[r][c] == target && target != deliveredId) pos = {r, c};\n                }\n            }\n\n            for (int r = 0; r < N; r++) {\n                if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == target) {\n                    pos = {r, 0};\n                }\n            }\n\n            if (pos) best = min(best, mdist({g0, N - 1}, *pos) + mdist(*pos, {g, N - 1}));\n        }\n\n        return best;\n    }\n\n    int dispatchScore(int id, pair<int,int> src) {\n        int g = id / N;\n        int curToSrc = mdist({cr, cc}, src);\n        int srcToDst = mdist(src, {g, N - 1});\n        int nextEst = (param.deliverMode == 2 || param.deliverMode == 4) ? estimateNextAfterDeliver(id) : 0;\n        return scoreDispatchMode(param.deliverMode, curToSrc, srcToDst, src.second, abs(src.first - g), nextEst);\n    }\n\n    int depthToNeeded(int r) {\n        bool need[V] = {};\n        for (int g = 0; g < N; g++) {\n            if (nextNeed[g] < (g + 1) * N) need[nextNeed[g]] = true;\n        }\n\n        int d = 0;\n        if (grid[r][0] != -1) {\n            if (need[grid[r][0]]) return 0;\n            d = 1;\n        }\n\n        for (int k = idx[r]; k < N; k++, d++) {\n            if (need[A[r][k]]) return d;\n        }\n\n        return 100;\n    }\n\n    int digScore(int r) {\n        int f = frontId(r);\n        int dep = depthToNeeded(r);\n        int dcur = abs(cr - r) + cc;\n        int future = 0;\n\n        if (f != -1) {\n            int g = f / N;\n            future = abs(r - g) + 4;\n        }\n\n        return scoreDigMode(param.digMode, dep, dcur, future, r);\n    }\n\n    int chooseRowToDig() {\n        int bestRow = -1, bestScore = 1e9;\n\n        for (int r = 0; r < N; r++) {\n            int f = frontId(r);\n            if (f == -1) continue;\n            if (idx[r] >= N && grid[r][0] != -1) continue;\n\n            int sc = digScore(r);\n            if (sc < bestScore) bestScore = sc, bestRow = r;\n        }\n\n        if (bestRow != -1) return bestRow;\n\n        for (int r = 0; r < N; r++) {\n            if (frontId(r) != -1) return r;\n        }\n\n        return -1;\n    }\n\n    int storageScore(pair<int,int> from, pair<int,int> p, int id) {\n        int g = id / N;\n        int a = mdist(from, p);\n        int b = mdist(p, {g, N - 1});\n        return scoreStorageMode(param.storeMode, a, b, abs(p.first - g), p.second);\n    }\n\n    pair<int,int> chooseStorageCell(pair<int,int> from, int id) {\n        auto cells = freeStorageCells();\n        pair<int,int> best = cells[0];\n        int bestCost = 1e9;\n\n        for (auto p : cells) {\n            int cost = storageScore(from, p, id);\n            if (cost < bestCost) bestCost = cost, best = p;\n        }\n\n        return best;\n    }\n\n    void dispatchContainer(int id) {\n        auto srcOpt = findAccessible(id);\n        if (!srcOpt) return;\n\n        auto src = *srcOpt;\n        pickAt(src);\n\n        int g = id / N;\n        releaseAt({g, N - 1});\n        markDelivered(id);\n    }\n\n    void storeFrontContainer(int r) {\n        int id = frontId(r);\n        if (id == -1) return;\n\n        pair<int,int> src = {r, 0};\n        auto dst = chooseStorageCell(src, id);\n\n        pickAt(src);\n        releaseAt(dst);\n    }\n\n    void solve() {\n        while (deliveredCnt < V && (int)S[0].size() < 9500) {\n            int bestId = -1, bestScore = 1e9;\n\n            for (int g = 0; g < N; g++) {\n                if (nextNeed[g] >= (g + 1) * N) continue;\n\n                int id = nextNeed[g];\n                auto srcOpt = findAccessible(id);\n                if (!srcOpt) continue;\n\n                int sc = dispatchScore(id, *srcOpt);\n                if (sc < bestScore) bestScore = sc, bestId = id;\n            }\n\n            if (bestId != -1) {\n                dispatchContainer(bestId);\n                continue;\n            }\n\n            auto cells = freeStorageCells();\n            if (!cells.empty()) {\n                int r = chooseRowToDig();\n                if (r != -1) {\n                    storeFrontContainer(r);\n                    continue;\n                }\n            }\n\n            step('.');\n        }\n\n        if (S[0].empty()) step('.');\n    }\n\n    vector<string> outputStrings() {\n        int T = outputLength(S);\n        for (auto &s : S) while ((int)s.size() < T) s.push_back('.');\n        return S;\n    }\n};\n\nstruct SmallAssistSolver {\n    vector<vector<int>> A;\n    Param param;\n    int mask, stageCol, setupWait, routeSafeCol;\n    bool selfPickup;\n\n    int grid[N][N], idx[N];\n    int lr = 0, lc = 0, lhold = -1;\n    int scol[N], shold[N];\n    bool salive[N];\n\n    vector<string> S;\n    vector<int> nextNeed, delivered;\n    int deliveredCnt = 0;\n    bool valid = true;\n\n    SmallAssistSolver(\n        const vector<vector<int>>& A_,\n        Param p,\n        int mask_,\n        int stageCol_,\n        int setupWait_,\n        int routeSafeCol_ = -1,\n        bool selfPickup_ = false\n    ) : A(A_), param(p), mask(mask_), stageCol(stageCol_), setupWait(setupWait_), selfPickup(selfPickup_) {\n        if (routeSafeCol_ < 0) routeSafeCol = stageCol - 1;\n        else routeSafeCol = routeSafeCol_;\n        routeSafeCol = max(0, min(4, routeSafeCol));\n\n        memset(grid, -1, sizeof(grid));\n        memset(idx, 0, sizeof(idx));\n        S.assign(N, \"\");\n\n        for (int i = 0; i < N; i++) {\n            scol[i] = 0;\n            shold[i] = -1;\n            salive[i] = (i >= 1 && assisted(i));\n        }\n\n        nextNeed.resize(N);\n        delivered.assign(V, 0);\n        for (int g = 0; g < N; g++) nextNeed[g] = g * N;\n    }\n\n    bool assisted(int r) const {\n        return r >= 1 && ((mask >> (r - 1)) & 1);\n    }\n\n    pair<int,int> deliveryTarget(int id) const {\n        int g = id / N;\n        if (assisted(g)) return {g, stageCol};\n        return {g, 4};\n    }\n\n    bool shuttlePathEmpty(int r) const {\n        if (!assisted(r)) return true;\n        for (int c = stageCol + 1; c <= 3; c++) {\n            if (grid[r][c] != -1) return false;\n        }\n        return true;\n    }\n\n    bool selfPathEmpty(int r) const {\n        for (int c = 1; c <= 3; c++) {\n            if (grid[r][c] != -1) return false;\n        }\n        return true;\n    }\n\n    void markDelivered(int id) {\n        if (id < 0 || id >= V) return;\n        if (!delivered[id]) delivered[id] = 1, deliveredCnt++;\n        int g = id / N;\n        while (nextNeed[g] < (g + 1) * N && delivered[nextNeed[g]]) nextNeed[g]++;\n    }\n\n    void step(char largeAct) {\n        if (!valid) return;\n\n        for (int r = 0; r < N; r++) {\n            bool blockLarge = (lhold != -1 && lr == r && lc == 0);\n            bool blockSmall = (r >= 1 && salive[r] && shold[r] != -1 && scol[r] == 0);\n\n            if (idx[r] < N && grid[r][0] == -1 && !blockLarge && !blockSmall) {\n                grid[r][0] = A[r][idx[r]++];\n            }\n        }\n\n        char acts[N];\n        acts[0] = largeAct;\n        int turn = (int)S[0].size();\n\n        for (int r = 1; r < N; r++) {\n            acts[r] = '.';\n\n            if (!assisted(r)) {\n                if (turn == 0) acts[r] = 'B';\n                continue;\n            }\n\n            if (!salive[r]) continue;\n\n            if (shold[r] != -1) {\n                if (scol[r] < 4) acts[r] = 'R';\n                else acts[r] = 'Q';\n            } else {\n                if (turn < 4 && scol[r] < 4) {\n                    acts[r] = 'R';\n                } else if (grid[r][stageCol] != -1) {\n                    if (scol[r] > stageCol) acts[r] = 'L';\n                    else if (scol[r] < stageCol) acts[r] = 'R';\n                    else acts[r] = 'P';\n                } else if (selfPickup && grid[r][0] == nextNeed[r] && selfPathEmpty(r)) {\n                    if (scol[r] > 0) acts[r] = 'L';\n                    else acts[r] = 'P';\n                } else {\n                    if (scol[r] < 4) acts[r] = 'R';\n                }\n            }\n        }\n\n        for (int i = 0; i < N; i++) S[i].push_back(acts[i]);\n\n        if (largeAct == 'P') {\n            if (lhold != -1 || grid[lr][lc] == -1) valid = false;\n            else lhold = grid[lr][lc], grid[lr][lc] = -1;\n        } else if (largeAct == 'Q') {\n            if (lhold == -1 || grid[lr][lc] != -1) valid = false;\n            else grid[lr][lc] = lhold, lhold = -1;\n        } else if (largeAct == 'U') {\n            if (lr == 0) valid = false;\n            else lr--;\n        } else if (largeAct == 'D') {\n            if (lr == N - 1) valid = false;\n            else lr++;\n        } else if (largeAct == 'L') {\n            if (lc == 0) valid = false;\n            else lc--;\n        } else if (largeAct == 'R') {\n            if (lc == N - 1) valid = false;\n            else lc++;\n        }\n\n        for (int r = 1; r < N; r++) {\n            char a = acts[r];\n\n            if (a == 'B') {\n                salive[r] = false;\n            } else if (!salive[r]) {\n            } else if (a == 'L') {\n                if (scol[r] == 0) valid = false;\n                else scol[r]--;\n            } else if (a == 'R') {\n                if (scol[r] == 4) valid = false;\n                else {\n                    if (shold[r] != -1 && grid[r][scol[r] + 1] != -1) valid = false;\n                    scol[r]++;\n                }\n            } else if (a == 'P') {\n                if (shold[r] != -1 || grid[r][scol[r]] == -1) valid = false;\n                else shold[r] = grid[r][scol[r]], grid[r][scol[r]] = -1;\n            } else if (a == 'Q') {\n                if (shold[r] == -1 || grid[r][scol[r]] != -1) valid = false;\n                else {\n                    int id = shold[r];\n                    grid[r][scol[r]] = id;\n                    shold[r] = -1;\n                    if (scol[r] == 4 && id / N == r) markDelivered(id);\n                }\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][4] != -1) grid[r][4] = -1;\n        }\n    }\n\n    void waitSmallReadyForStage(int r) {\n        if (!assisted(r)) return;\n\n        int guard = 0;\n        while (valid &&\n               (grid[r][stageCol] != -1 || !shuttlePathEmpty(r) ||\n                shold[r] != -1 || scol[r] != 4) &&\n               guard++ < 120) {\n            step('.');\n        }\n    }\n\n    void moveTo(int r, int c) {\n        if (!valid) return;\n\n        if (assisted(r) && c == stageCol) {\n            moveTo(r, stageCol - 1);\n            waitSmallReadyForStage(r);\n            if (lc < stageCol) step('R');\n            return;\n        }\n\n        if (lr != r && lc > routeSafeCol) {\n            while (valid && lc > routeSafeCol) step('L');\n        }\n\n        while (valid && lr < r) step('D');\n        while (valid && lr > r) step('U');\n        while (valid && lc < c) step('R');\n        while (valid && lc > c) step('L');\n    }\n\n    void pickAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('P');\n    }\n\n    void releaseAt(pair<int,int> p) {\n        moveTo(p.first, p.second);\n        step('Q');\n    }\n\n    optional<pair<int,int>> findAccessible(int id) {\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (grid[r][c] == id) return pair<int,int>{r, c};\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1 && idx[r] < N && A[r][idx[r]] == id) {\n                return pair<int,int>{r, 0};\n            }\n        }\n\n        return nullopt;\n    }\n\n    int frontId(int r) const {\n        if (grid[r][0] != -1) return grid[r][0];\n        if (idx[r] < N) return A[r][idx[r]];\n        return -1;\n    }\n\n    vector<pair<int,int>> freeStorageCells() const {\n        vector<pair<int,int>> res;\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 1; c <= 3; c++) {\n                if (grid[r][c] != -1) continue;\n                if (assisted(r) && c >= stageCol) continue;\n                res.push_back({r, c});\n            }\n        }\n\n        for (int r = 0; r < N; r++) {\n            if (idx[r] >= N && grid[r][0] == -1) res.push_back({r, 0});\n        }\n\n        return res;\n    }\n\n    int dispatchScore(int id, pair<int,int> src) {\n        auto dst = deliveryTarget(id);\n        int curToSrc = mdist({lr, lc}, src);\n        int srcToDst = mdist(src, dst);\n        return scoreDispatchMode(\n            param.deliverMode, curToSrc, srcToDst, src.second,\n            abs(src.first - dst.first), 0\n        );\n    }\n\n    int depthToNeeded(int r) {\n        bool need[V] = {};\n        for (int g = 0; g < N; g++) {\n            if (nextNeed[g] < (g + 1) * N) need[nextNeed[g]] = true;\n        }\n\n        int d = 0;\n        if (grid[r][0] != -1) {\n            if (need[grid[r][0]]) return 0;\n            d = 1;\n        }\n\n        for (int k = idx[r]; k < N; k++, d++) {\n            if (need[A[r][k]]) return d;\n        }\n\n        return 100;\n    }\n\n    int digScore(int r) {\n        int f = frontId(r);\n        int dep = depthToNeeded(r);\n        int dcur = abs(lr - r) + lc;\n        int future = 0;\n\n        if (f != -1) {\n            auto dst = deliveryTarget(f);\n            future = abs(r - dst.first) + dst.second;\n        }\n\n        return scoreDigMode(param.digMode, dep, dcur, future, r);\n    }\n\n    int chooseRowToDig() {\n        int bestRow = -1, bestScore = 1e9;\n\n        for (int r = 0; r < N; r++) {\n            int f = frontId(r);\n            if (f == -1) continue;\n            if (idx[r] >= N && grid[r][0] != -1) continue;\n\n            int sc = digScore(r);\n            if (sc < bestScore) bestScore = sc, bestRow = r;\n        }\n\n        if (bestRow != -1) return bestRow;\n\n        for (int r = 0; r < N; r++) {\n            if (frontId(r) != -1) return r;\n        }\n\n        return -1;\n    }\n\n    int storageScore(pair<int,int> from, pair<int,int> p, int id) {\n        auto dst = deliveryTarget(id);\n        int a = mdist(from, p);\n        int b = mdist(p, dst);\n        return scoreStorageMode(param.storeMode, a, b, abs(p.first - dst.first), p.second);\n    }\n\n    pair<int,int> chooseStorageCell(pair<int,int> from, int id) {\n        auto cells = freeStorageCells();\n        pair<int,int> best = cells[0];\n        int bestCost = 1e9;\n\n        for (auto p : cells) {\n            int cost = storageScore(from, p, id);\n            if (cost < bestCost) bestCost = cost, best = p;\n        }\n\n        return best;\n    }\n\n    void dispatchContainer(int id) {\n        auto srcOpt = findAccessible(id);\n        if (!srcOpt) return;\n\n        auto src = *srcOpt;\n        pickAt(src);\n\n        auto dst = deliveryTarget(id);\n        releaseAt(dst);\n\n        markDelivered(id);\n    }\n\n    void storeFrontContainer(int r) {\n        int id = frontId(r);\n        if (id == -1) return;\n\n        auto cells = freeStorageCells();\n        if (cells.empty()) return;\n\n        pair<int,int> src = {r, 0};\n        auto dst = chooseStorageCell(src, id);\n\n        pickAt(src);\n        releaseAt(dst);\n    }\n\n    void solve() {\n        for (int t = 0; t < setupWait; t++) step('.');\n\n        while (valid && deliveredCnt < V && (int)S[0].size() < 9500) {\n            int bestId = -1, bestScore = 1e9;\n\n            for (int g = 0; g < N; g++) {\n                if (nextNeed[g] >= (g + 1) * N) continue;\n\n                int id = nextNeed[g];\n                auto srcOpt = findAccessible(id);\n                if (!srcOpt) continue;\n\n                int sc = dispatchScore(id, *srcOpt);\n                if (sc < bestScore) bestScore = sc, bestId = id;\n            }\n\n            if (bestId != -1) {\n                dispatchContainer(bestId);\n                continue;\n            }\n\n            auto cells = freeStorageCells();\n            if (!cells.empty()) {\n                int r = chooseRowToDig();\n                if (r != -1) {\n                    storeFrontContainer(r);\n                    continue;\n                }\n            }\n\n            step('.');\n        }\n\n        for (int t = 0; t < 150; t++) {\n            bool busy = false;\n\n            for (int r = 1; r < N; r++) {\n                if (!assisted(r)) continue;\n\n                if (grid[r][stageCol] != -1 || !shuttlePathEmpty(r) ||\n                    shold[r] != -1 || scol[r] != 4) {\n                    busy = true;\n                }\n            }\n\n            if (!busy) break;\n            step('.');\n        }\n\n        if (S[0].empty()) step('.');\n    }\n\n    vector<string> outputStrings() {\n        int T = outputLength(S);\n        for (auto &s : S) while ((int)s.size() < T) s.push_back('.');\n        return S;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n\n    auto elapsedMs = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(\n            chrono::steady_clock::now() - startTime\n        ).count();\n    };\n\n    int inputN;\n    cin >> inputN;\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<Param> allParams;\n    for (int dm = 0; dm < 4; dm++) {\n        for (int dig = 0; dig < 5; dig++) {\n            for (int sm = 0; sm < 5; sm++) {\n                allParams.push_back({dm, dig, sm});\n            }\n        }\n    }\n\n    vector<Param> coreParams = {\n        {0,0,0}, {0,0,4}, {2,1,4},\n        {0,1,4}, {0,2,4}, {0,3,4}, {0,4,4},\n        {1,0,4}, {1,1,4}, {1,2,4},\n        {2,0,4}, {2,2,4}, {2,3,4},\n        {3,0,4}, {3,1,4}, {3,2,4},\n        {0,0,0}, {1,0,0}, {2,0,0}, {3,0,0},\n        {0,1,0}, {0,2,0}, {0,3,0}, {0,4,0},\n        {0,0,1}, {0,0,2}, {0,0,3}\n    };\n\n    vector<Param> smallCore = {\n        {0,0,0}, {0,0,4}, {2,1,4},\n        {0,1,4}, {1,0,4}, {2,0,4}, {3,0,4},\n        {0,0,1}, {0,0,2}, {0,0,3}\n    };\n\n    vector<Param> extraCore = {\n        {4,5,5}, {4,5,7}, {4,6,5}, {4,7,7},\n        {5,5,5}, {5,6,7}, {5,8,8},\n        {6,5,6}, {6,6,6}, {6,8,9},\n        {7,5,5}, {7,7,5}, {7,8,7},\n        {4,0,5}, {4,1,7}, {5,0,8},\n        {6,1,6}, {7,2,5},\n        {0,5,5}, {0,6,6}, {1,5,7}, {2,6,8}, {3,7,9}\n    };\n\n    allParams.insert(allParams.begin(), {0,0,0});\n    allParams.insert(allParams.begin(), {0,0,4});\n    allParams.insert(allParams.begin(), {2,1,4});\n\n    vector<string> best;\n    long long bestScore = INF_SCORE;\n\n    auto tryCandidate = [&](const vector<string>& cand) {\n        long long sc = evaluateOutput(cand, A);\n        if (sc < bestScore) {\n            bestScore = sc;\n            best = cand;\n        }\n    };\n\n    for (auto p : allParams) {\n        GreedySolver solver(A, p);\n        solver.solve();\n\n        if (solver.deliveredCnt != V) continue;\n        tryCandidate(solver.outputStrings());\n    }\n\n    for (auto p : allParams) {\n        if (elapsedMs() > 2200) break;\n\n        SmallAssistSolver solver(A, p, 15, 3, 4);\n        solver.solve();\n\n        if (!solver.valid || solver.deliveredCnt != V) continue;\n        tryCandidate(solver.outputStrings());\n    }\n\n    for (int wait : {0, 1, 2, 3}) {\n        for (auto p : coreParams) {\n            if (elapsedMs() > 2300) break;\n\n            SmallAssistSolver solver(A, p, 15, 3, wait);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n            tryCandidate(solver.outputStrings());\n        }\n    }\n\n    for (int wait : {0, 1, 2, 3, 4}) {\n        for (auto p : coreParams) {\n            if (elapsedMs() > 2400) break;\n\n            SmallAssistSolver solver(A, p, 15, 2, wait);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n            tryCandidate(solver.outputStrings());\n        }\n    }\n\n    for (int routeSafe : {2, 3}) {\n        for (int wait : {0, 1, 2, 3, 4}) {\n            for (auto p : smallCore) {\n                if (elapsedMs() > 2470) break;\n\n                SmallAssistSolver solver(A, p, 15, 2, wait, routeSafe);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    for (int wait : {0, 1, 2, 3, 4}) {\n        for (auto p : extraCore) {\n            if (elapsedMs() > 2530) break;\n\n            SmallAssistSolver solver(A, p, 15, 2, wait);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n            tryCandidate(solver.outputStrings());\n        }\n    }\n\n    for (int wait : {0, 1, 2, 3, 4}) {\n        for (auto p : smallCore) {\n            if (elapsedMs() > 2580) break;\n\n            SmallAssistSolver solver(A, p, 15, 1, wait);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n            tryCandidate(solver.outputStrings());\n        }\n    }\n\n    for (int routeSafe : {1, 2}) {\n        for (int wait : {0, 1, 2, 3, 4}) {\n            for (auto p : smallCore) {\n                if (elapsedMs() > 2630) break;\n\n                SmallAssistSolver solver(A, p, 15, 1, wait, routeSafe);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    for (int wait : {0, 2, 4}) {\n        for (auto p : extraCore) {\n            if (elapsedMs() > 2660) break;\n\n            SmallAssistSolver solver(A, p, 15, 1, wait);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n            tryCandidate(solver.outputStrings());\n        }\n    }\n\n    // Risky self-pickup candidates are now scored exactly, not selected by length only.\n    for (int stage : {2, 1, 3}) {\n        for (int wait : {0, 2, 4}) {\n            for (auto p : smallCore) {\n                if (elapsedMs() > 2720) break;\n\n                SmallAssistSolver solver(A, p, 15, stage, wait, -1, true);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    for (int mask = 1; mask < 16; mask++) {\n        if (mask == 15) continue;\n\n        for (auto p : coreParams) {\n            if (elapsedMs() > 2760) break;\n\n            SmallAssistSolver solver(A, p, mask, 3, 4);\n            solver.solve();\n\n            if (!solver.valid || solver.deliveredCnt != V) continue;\n            tryCandidate(solver.outputStrings());\n        }\n    }\n\n    for (int mask = 1; mask < 16; mask++) {\n        if (mask == 15) continue;\n\n        for (int wait : {0, 2}) {\n            for (auto p : coreParams) {\n                if (elapsedMs() > 2800) break;\n\n                SmallAssistSolver solver(A, p, mask, 3, wait);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    for (int mask = 1; mask < 16; mask++) {\n        if (mask == 15) continue;\n\n        for (int wait : {0, 2, 4}) {\n            for (auto p : smallCore) {\n                if (elapsedMs() > 2830) break;\n\n                SmallAssistSolver solver(A, p, mask, 2, wait);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    for (int mask = 1; mask < 16; mask++) {\n        if (mask == 15) continue;\n\n        for (int wait : {0, 2}) {\n            for (auto p : smallCore) {\n                if (elapsedMs() > 2850) break;\n\n                SmallAssistSolver solver(A, p, mask, 2, wait, 2);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    for (int mask = 1; mask < 16; mask++) {\n        for (int wait : {0, 3}) {\n            for (auto p : smallCore) {\n                if (elapsedMs() > 2870) break;\n\n                SmallAssistSolver solver(A, p, mask, 1, wait);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    for (int mask = 1; mask < 16; mask++) {\n        for (int wait : {0, 2}) {\n            for (auto p : extraCore) {\n                if (elapsedMs() > 2890) break;\n\n                SmallAssistSolver solver(A, p, mask, 2, wait);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    for (int mask = 1; mask < 16; mask++) {\n        for (int wait : {0, 2}) {\n            for (auto p : smallCore) {\n                if (elapsedMs() > 2910) break;\n\n                SmallAssistSolver solver(A, p, mask, 2, wait, -1, true);\n                solver.solve();\n\n                if (!solver.valid || solver.deliveredCnt != V) continue;\n                tryCandidate(solver.outputStrings());\n            }\n        }\n    }\n\n    if (best.empty()) {\n        GreedySolver solver(A, {0,0,0});\n        solver.solve();\n        best = solver.outputStrings();\n    }\n\n    int T = outputLength(best);\n    for (auto &s : best) while ((int)s.size() < T) s.push_back('.');\n\n    for (int i = 0; i < N; i++) {\n        cout << best[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int B = 10;\nstatic const int V = 400;\nstatic const int BV = 100;\nstatic const long long INF = (1LL << 60);\n\nstatic const double T_INIT_TREE = 0.84;\nstatic const double T_TREE_LOCAL = 1.73;\nstatic const double T_TREE_END = 1.73;\nstatic const double T_FINAL1 = 1.805;\nstatic const double T_FINAL2 = 1.855;\nstatic const double T_FINAL3 = 1.890;\nstatic const double T_RAND = 1.915;\n\nint hval[V];\nint mdist[V][V];\nlong long base_cost = 0;\n\nint dr[4] = {-1, 0, 1, 0};\nint dc[4] = {0, 1, 0, -1};\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 a, b;\n};\n\nstruct EvalResult {\n    long long cost = INF;\n    vector<int> order;\n};\n\nstruct DSU {\n    int p[BV], sz[BV];\n\n    DSU() { init(); }\n\n    void init() {\n        for (int i = 0; i < BV; i++) {\n            p[i] = i;\n            sz[i] = 1;\n        }\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nvector<Edge> all_edges;\nvector<pair<int, int>> block_adj[BV];\nint edge_id[BV][BV];\n\nint id20(int r, int c) {\n    return r * N + c;\n}\n\nint dir_between(int a, int b) {\n    int ar = a / N;\n    int ac = a % N;\n    int br = b / N;\n    int bc = b % N;\n\n    for (int d = 0; d < 4; d++) {\n        if (ar + dr[d] == br && ac + dc[d] == bc) return d;\n    }\n\n    return -1;\n}\n\nvoid add_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n    if (d < 0 || e < 0) return;\n    mask[a] |= (1u << d);\n    mask[b] |= (1u << e);\n}\n\nvoid remove_edge_cell(array<unsigned char, V>& mask, int a, int b) {\n    int d = dir_between(a, b);\n    int e = dir_between(b, a);\n    if (d < 0 || e < 0) return;\n    mask[a] &= ~(1u << d);\n    mask[b] &= ~(1u << e);\n}\n\nvoid eval_order_direction_fast(const vector<int>& seq, EvalResult& res, bool store_order) {\n    int M = (int)seq.size();\n\n    if (M == 0) {\n        if (0 < res.cost) {\n            res.cost = 0;\n            if (store_order) res.order.clear();\n        }\n        return;\n    }\n\n    static long long pref[2 * V + 5];\n    static long long sumD[2 * V + 5];\n    static long long sumPD[2 * V + 5];\n\n    pref[0] = 0;\n\n    for (int i = 0; i < 2 * M; i++) {\n        pref[i + 1] = pref[i] + hval[seq[i % M]];\n    }\n\n    if (pref[M] != 0) return;\n\n    long long mn = pref[0];\n\n    for (int i = 0; i < M; i++) {\n        mn = min(mn, pref[i]);\n    }\n\n    sumD[0] = 0;\n    sumPD[0] = 0;\n\n    for (int i = 0; i < 2 * M; i++) {\n        int a = seq[i % M];\n        int b = seq[(i + 1) % M];\n        long long d = mdist[a][b];\n\n        sumD[i + 1] = sumD[i] + d;\n        sumPD[i + 1] = sumPD[i] + pref[i + 1] * d;\n    }\n\n    for (int k = 0; k < M; k++) {\n        if (pref[k] != mn) continue;\n\n        long long dist_sum = 0;\n        long long load_dist_sum = 0;\n\n        if (M >= 2) {\n            int l = k;\n            int r = k + M - 1;\n\n            dist_sum = sumD[r] - sumD[l];\n            long long pd = sumPD[r] - sumPD[l];\n\n            load_dist_sum = pd - pref[k] * dist_sum;\n        }\n\n        int start = seq[k];\n\n        long long cost = base_cost;\n        cost += 100LL * (start / N + start % N);\n        cost += 100LL * dist_sum;\n        cost += load_dist_sum;\n\n        if (cost < res.cost) {\n            res.cost = cost;\n\n            if (store_order) {\n                res.order.clear();\n                res.order.reserve(M);\n\n                for (int t = 0; t < M; t++) {\n                    res.order.push_back(seq[(k + t) % M]);\n                }\n            }\n        }\n    }\n}\n\nEvalResult evaluate_order_cycle(const vector<int>& seq, bool store_order) {\n    EvalResult res;\n\n    eval_order_direction_fast(seq, res, store_order);\n\n    vector<int> rev = seq;\n    reverse(rev.begin(), rev.end());\n\n    eval_order_direction_fast(rev, res, store_order);\n\n    return res;\n}\n\nEvalResult evaluate_hamiltonian_cycle_skip_zero(const vector<int>& cyc, bool store_order) {\n    vector<int> seq;\n    seq.reserve(V);\n\n    for (int x : cyc) {\n        if (hval[x] != 0) seq.push_back(x);\n    }\n\n    return evaluate_order_cycle(seq, store_order);\n}\n\nbool build_cycle_from_tree_edges(const vector<Edge>& tree_edges, vector<int>& cyc) {\n    array<unsigned char, V> mask;\n    mask.fill(0);\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int a = id20(2 * r, 2 * c);\n            int b = id20(2 * r, 2 * c + 1);\n            int e = id20(2 * r + 1, 2 * c + 1);\n            int d = id20(2 * r + 1, 2 * c);\n\n            add_edge_cell(mask, a, b);\n            add_edge_cell(mask, b, e);\n            add_edge_cell(mask, e, d);\n            add_edge_cell(mask, d, a);\n        }\n    }\n\n    for (auto ed : tree_edges) {\n        int ar = ed.a / B;\n        int ac = ed.a % B;\n        int br = ed.b / B;\n        int bc = ed.b % B;\n\n        if (ar == br) {\n            int r = ar;\n            int c = min(ac, bc);\n\n            int a1 = id20(2 * r, 2 * c + 1);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r, 2 * c + 2);\n            int b2 = id20(2 * r + 1, 2 * c + 2);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        } else {\n            int r = min(ar, br);\n            int c = ac;\n\n            int a1 = id20(2 * r + 1, 2 * c);\n            int a2 = id20(2 * r + 1, 2 * c + 1);\n            int b1 = id20(2 * r + 2, 2 * c);\n            int b2 = id20(2 * r + 2, 2 * c + 1);\n\n            remove_edge_cell(mask, a1, a2);\n            remove_edge_cell(mask, b1, b2);\n            add_edge_cell(mask, a1, b1);\n            add_edge_cell(mask, a2, b2);\n        }\n    }\n\n    for (int i = 0; i < V; i++) {\n        if (__builtin_popcount((int)mask[i]) != 2) return false;\n    }\n\n    cyc.clear();\n\n    int start = 0;\n    int cur = start;\n    int prev = -1;\n\n    while (true) {\n        cyc.push_back(cur);\n\n        int nxt = -1;\n\n        for (int d = 0; d < 4; d++) {\n            if (!(mask[cur] & (1u << d))) continue;\n\n            int r = cur / N + dr[d];\n            int c = cur % N + dc[d];\n            int nb = id20(r, c);\n\n            if (nb != prev) {\n                nxt = nb;\n                break;\n            }\n        }\n\n        if (nxt < 0) return false;\n\n        prev = cur;\n        cur = nxt;\n\n        if (cur == start) break;\n        if ((int)cyc.size() > V) return false;\n    }\n\n    return (int)cyc.size() == V;\n}\n\nvector<char> tree_to_mask(const vector<Edge>& tr) {\n    vector<char> in(all_edges.size(), 0);\n\n    for (auto e : tr) {\n        int id = edge_id[e.a][e.b];\n\n        if (id >= 0) {\n            in[id] = 1;\n        }\n    }\n\n    return in;\n}\n\nvector<Edge> mask_to_tree_edges(const vector<char>& in) {\n    vector<Edge> tr;\n    tr.reserve(BV - 1);\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        if (in[i]) tr.push_back(all_edges[i]);\n    }\n\n    return tr;\n}\n\nEvalResult evaluate_tree_mask(const vector<char>& in, bool store_order) {\n    vector<Edge> tr = mask_to_tree_edges(in);\n    vector<int> cyc;\n\n    if ((int)tr.size() != BV - 1) return EvalResult();\n\n    if (!build_cycle_from_tree_edges(tr, cyc)) return EvalResult();\n\n    return evaluate_hamiltonian_cycle_skip_zero(cyc, store_order);\n}\n\nvector<Edge> make_row_tree(int col) {\n    vector<Edge> res;\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c + 1 < B; c++) {\n            res.push_back({r * B + c, r * B + c + 1});\n        }\n    }\n\n    for (int r = 0; r + 1 < B; r++) {\n        res.push_back({r * B + col, (r + 1) * B + col});\n    }\n\n    return res;\n}\n\nvector<Edge> make_col_tree(int row) {\n    vector<Edge> res;\n\n    for (int c = 0; c < B; c++) {\n        for (int r = 0; r + 1 < B; r++) {\n            res.push_back({r * B + c, (r + 1) * B + c});\n        }\n    }\n\n    for (int c = 0; c + 1 < B; c++) {\n        res.push_back({row * B + c, row * B + c + 1});\n    }\n\n    return res;\n}\n\nvector<char> random_kruskal_tree(mt19937& rng) {\n    static vector<int> perm;\n\n    if (perm.empty()) {\n        perm.resize(all_edges.size());\n        iota(perm.begin(), perm.end(), 0);\n    }\n\n    shuffle(perm.begin(), perm.end(), rng);\n\n    DSU dsu;\n    vector<char> in(all_edges.size(), 0);\n\n    int cnt = 0;\n\n    for (int id : perm) {\n        auto e = all_edges[id];\n\n        if (dsu.unite(e.a, e.b)) {\n            in[id] = 1;\n            cnt++;\n\n            if (cnt == BV - 1) break;\n        }\n    }\n\n    return in;\n}\n\nvector<char> random_prim_tree(mt19937& rng) {\n    vector<char> used(BV, 0);\n    vector<char> in(all_edges.size(), 0);\n\n    int st = uniform_int_distribution<int>(0, BV - 1)(rng);\n\n    used[st] = 1;\n\n    vector<pair<int, int>> frontier;\n\n    for (auto p : block_adj[st]) {\n        frontier.push_back(p);\n    }\n\n    int cnt = 0;\n\n    while (cnt < BV - 1 && !frontier.empty()) {\n        int k = uniform_int_distribution<int>(0, (int)frontier.size() - 1)(rng);\n\n        auto [to, eid] = frontier[k];\n\n        frontier[k] = frontier.back();\n        frontier.pop_back();\n\n        auto e = all_edges[eid];\n\n        int a = e.a;\n        int b = e.b;\n        int nxt = -1;\n\n        if (used[a] && !used[b]) {\n            nxt = b;\n        } else if (used[b] && !used[a]) {\n            nxt = a;\n        } else {\n            continue;\n        }\n\n        used[nxt] = 1;\n        in[eid] = 1;\n        cnt++;\n\n        for (auto p : block_adj[nxt]) {\n            if (!used[p.first]) {\n                frontier.push_back(p);\n            }\n        }\n    }\n\n    return in;\n}\n\nvector<int> get_path_edges_from_adj(const vector<pair<int, int>> adj[BV], int s, int t) {\n    int par[BV];\n    int pedge[BV];\n\n    fill(par, par + BV, -1);\n    fill(pedge, pedge + BV, -1);\n\n    int q[BV];\n    int head = 0;\n    int tail = 0;\n\n    par[s] = s;\n    q[tail++] = s;\n\n    while (head < tail) {\n        int v = q[head++];\n\n        if (v == t) break;\n\n        for (auto [to, eid] : adj[v]) {\n            if (par[to] != -1) continue;\n\n            par[to] = v;\n            pedge[to] = eid;\n            q[tail++] = to;\n        }\n    }\n\n    vector<int> path;\n\n    if (par[t] == -1) return path;\n\n    int cur = t;\n\n    while (cur != s) {\n        path.push_back(pedge[cur]);\n        cur = par[cur];\n    }\n\n    return path;\n}\n\nvoid add_to_pool(vector<EvalResult>& pool, const EvalResult& ev) {\n    if (ev.cost >= INF || ev.order.empty()) return;\n\n    for (auto& x : pool) {\n        if (x.order == ev.order) return;\n    }\n\n    pool.push_back(ev);\n\n    sort(pool.begin(), pool.end(), [](const EvalResult& a, const EvalResult& b) {\n        return a.cost < b.cost;\n    });\n\n    if ((int)pool.size() > 10) pool.resize(10);\n}\n\nvoid local_search(vector<char>& cur_tree, EvalResult& global_best, vector<EvalResult>& pool, const Timer& timer) {\n    EvalResult cur_eval = evaluate_tree_mask(cur_tree, false);\n    long long cur_cost = cur_eval.cost;\n\n    if (cur_cost >= INF) return;\n\n    bool improved = true;\n\n    while (timer.elapsed() < T_TREE_LOCAL && improved) {\n        improved = false;\n\n        vector<pair<int, int>> tree_adj[BV];\n\n        for (int i = 0; i < (int)all_edges.size(); i++) {\n            if (!cur_tree[i]) continue;\n\n            auto e = all_edges[i];\n\n            tree_adj[e.a].push_back({e.b, i});\n            tree_adj[e.b].push_back({e.a, i});\n        }\n\n        long long best_cost = cur_cost;\n        int best_add = -1;\n        int best_rem = -1;\n\n        for (int eid = 0; eid < (int)all_edges.size(); eid++) {\n            if (cur_tree[eid]) continue;\n            if (timer.elapsed() > T_TREE_LOCAL) break;\n\n            auto e = all_edges[eid];\n            vector<int> path = get_path_edges_from_adj(tree_adj, e.a, e.b);\n\n            for (int rem : path) {\n                cur_tree[eid] = 1;\n                cur_tree[rem] = 0;\n\n                EvalResult ev = evaluate_tree_mask(cur_tree, false);\n\n                cur_tree[eid] = 0;\n                cur_tree[rem] = 1;\n\n                if (ev.cost < best_cost) {\n                    best_cost = ev.cost;\n                    best_add = eid;\n                    best_rem = rem;\n                }\n            }\n        }\n\n        if (best_add != -1) {\n            cur_tree[best_add] = 1;\n            cur_tree[best_rem] = 0;\n\n            cur_cost = best_cost;\n            improved = true;\n\n            EvalResult stored = evaluate_tree_mask(cur_tree, true);\n\n            add_to_pool(pool, stored);\n\n            if (stored.cost < global_best.cost) {\n                global_best = stored;\n            }\n        }\n    }\n}\n\nvoid try_order_candidate(EvalResult& best, vector<EvalResult>& pool, const vector<int>& seq) {\n    if (seq.empty()) return;\n\n    EvalResult ev = evaluate_order_cycle(seq, true);\n\n    add_to_pool(pool, ev);\n\n    if (ev.cost < best.cost) {\n        best = ev;\n    }\n}\n\nvector<int> make_row_snake_order() {\n    vector<int> seq;\n\n    for (int r = 0; r < N; r++) {\n        if (r % 2 == 0) {\n            for (int c = 0; c < N; c++) {\n                int id = id20(r, c);\n                if (hval[id] != 0) seq.push_back(id);\n            }\n        } else {\n            for (int c = N - 1; c >= 0; c--) {\n                int id = id20(r, c);\n                if (hval[id] != 0) seq.push_back(id);\n            }\n        }\n    }\n\n    return seq;\n}\n\nvector<int> make_col_snake_order() {\n    vector<int> seq;\n\n    for (int c = 0; c < N; c++) {\n        if (c % 2 == 0) {\n            for (int r = 0; r < N; r++) {\n                int id = id20(r, c);\n                if (hval[id] != 0) seq.push_back(id);\n            }\n        } else {\n            for (int r = N - 1; r >= 0; r--) {\n                int id = id20(r, c);\n                if (hval[id] != 0) seq.push_back(id);\n            }\n        }\n    }\n\n    return seq;\n}\n\nvector<int> make_nearest_neighbor_order(int start_cell) {\n    vector<int> cells;\n\n    for (int i = 0; i < V; i++) {\n        if (hval[i] != 0) cells.push_back(i);\n    }\n\n    int M = (int)cells.size();\n\n    if (M == 0) return {};\n\n    vector<char> used(V, 0);\n    vector<int> seq;\n    seq.reserve(M);\n\n    int cur = cells[0];\n    int bestd = 1e9;\n\n    for (int x : cells) {\n        int d = mdist[start_cell][x];\n\n        if (d < bestd) {\n            bestd = d;\n            cur = x;\n        }\n    }\n\n    for (int step = 0; step < M; step++) {\n        seq.push_back(cur);\n        used[cur] = 1;\n\n        int nxt = -1;\n        int nd = 1e9;\n\n        for (int x : cells) {\n            if (used[x]) continue;\n\n            int d = mdist[cur][x];\n\n            if (d < nd) {\n                nd = d;\n                nxt = x;\n            }\n        }\n\n        if (nxt == -1) break;\n\n        cur = nxt;\n    }\n\n    return seq;\n}\n\nvector<int> make_sign_greedy_order(int start_cell, int mode, mt19937& rng) {\n    vector<int> cells;\n\n    for (int i = 0; i < V; i++) {\n        if (hval[i] != 0) cells.push_back(i);\n    }\n\n    int M = (int)cells.size();\n\n    vector<char> used(V, 0);\n    vector<int> seq;\n    seq.reserve(M);\n\n    int cur = start_cell;\n    long long load = 0;\n\n    for (int step = 0; step < M; step++) {\n        vector<pair<long long, int>> cand;\n\n        for (int x : cells) {\n            if (used[x]) continue;\n\n            int v = hval[x];\n\n            if (v < 0 && load < -v) continue;\n            if (load == 0 && v < 0) continue;\n\n            int dist = mdist[cur][x];\n\n            long long score = 1000LL * dist;\n\n            if (mode == 0) {\n                if (v < 0) score -= 300LL * (-v);\n                else score += 80LL * v;\n            } else if (mode == 1) {\n                if (v < 0) score -= 600LL * (-v);\n                else score += 160LL * v;\n            } else if (mode == 2) {\n                if (v > 0) score -= 120LL * v;\n                else score -= 200LL * (-v);\n            } else {\n                if (v < 0) score -= 400LL * (-v);\n            }\n\n            cand.push_back({score, x});\n        }\n\n        if (cand.empty()) {\n            for (int x : cells) {\n                if (!used[x] && hval[x] > 0) {\n                    cand.push_back({1000LL * mdist[cur][x], x});\n                }\n            }\n        }\n\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end());\n\n        int pick = 0;\n\n        if (mode == 3) {\n            int lim = min<int>(5, cand.size());\n            pick = uniform_int_distribution<int>(0, lim - 1)(rng);\n        }\n\n        int nxt = cand[pick].second;\n\n        seq.push_back(nxt);\n        used[nxt] = 1;\n        load += hval[nxt];\n        cur = nxt;\n    }\n\n    return seq;\n}\n\nvoid optimize_sequence(vector<int> seq, EvalResult& global_best, vector<EvalResult>& pool, const Timer& timer, double limit) {\n    if (seq.empty()) return;\n\n    EvalResult cur_eval = evaluate_order_cycle(seq, true);\n    if (cur_eval.cost >= INF) return;\n\n    add_to_pool(pool, cur_eval);\n\n    if (cur_eval.cost < global_best.cost) {\n        global_best = cur_eval;\n    }\n\n    seq = cur_eval.order;\n    long long cur_cost = cur_eval.cost;\n    int M = (int)seq.size();\n\n    auto accept_current = [&]() {\n        EvalResult stored = evaluate_order_cycle(seq, true);\n\n        cur_cost = stored.cost;\n        seq = stored.order;\n        M = (int)seq.size();\n\n        add_to_pool(pool, stored);\n\n        if (stored.cost < global_best.cost) {\n            global_best = stored;\n        }\n    };\n\n    while (timer.elapsed() < limit) {\n        bool found = false;\n\n        for (int i = 0; i < M && !found; i++) {\n            if ((i & 7) == 0 && timer.elapsed() > limit) break;\n\n            for (int j = i + 2; j < M; j++) {\n                if ((j & 31) == 0 && timer.elapsed() > limit) break;\n                if (i == 0 && j == M - 1) continue;\n\n                reverse(seq.begin() + i + 1, seq.begin() + j + 1);\n\n                EvalResult ev = evaluate_order_cycle(seq, false);\n\n                if (ev.cost < cur_cost) {\n                    accept_current();\n                    found = true;\n                    break;\n                }\n\n                reverse(seq.begin() + i + 1, seq.begin() + j + 1);\n            }\n        }\n\n        if (found) continue;\n\n        for (int i = 0; i < M && !found; i++) {\n            if ((i & 7) == 0 && timer.elapsed() > limit) break;\n\n            int x = seq[i];\n            seq.erase(seq.begin() + i);\n\n            for (int j = 0; j <= M - 1; j++) {\n                if ((j & 31) == 0 && timer.elapsed() > limit) break;\n                if (j == i) continue;\n\n                seq.insert(seq.begin() + j, x);\n\n                EvalResult ev = evaluate_order_cycle(seq, false);\n\n                if (ev.cost < cur_cost) {\n                    accept_current();\n                    found = true;\n                    break;\n                }\n\n                seq.erase(seq.begin() + j);\n            }\n\n            if (!found) {\n                seq.insert(seq.begin() + i, x);\n            }\n        }\n\n        if (found) continue;\n\n        for (int i = 0; i < M && !found; i++) {\n            if ((i & 7) == 0 && timer.elapsed() > limit) break;\n\n            for (int j = i + 1; j < M; j++) {\n                if ((j & 31) == 0 && timer.elapsed() > limit) break;\n\n                swap(seq[i], seq[j]);\n\n                EvalResult ev = evaluate_order_cycle(seq, false);\n\n                if (ev.cost < cur_cost) {\n                    accept_current();\n                    found = true;\n                    break;\n                }\n\n                swap(seq[i], seq[j]);\n            }\n        }\n\n        if (!found) break;\n    }\n}\n\nvoid random_improve(EvalResult& global_best, const Timer& timer, mt19937& rng) {\n    if (global_best.order.empty()) return;\n\n    vector<int> seq = global_best.order;\n    long long cur_cost = global_best.cost;\n    int M = (int)seq.size();\n\n    auto accept_current = [&]() {\n        EvalResult stored = evaluate_order_cycle(seq, true);\n\n        cur_cost = stored.cost;\n        seq = stored.order;\n        M = (int)seq.size();\n\n        if (stored.cost < global_best.cost) {\n            global_best = stored;\n        }\n    };\n\n    while (timer.elapsed() < T_RAND) {\n        if (M <= 2) break;\n\n        int type = uniform_int_distribution<int>(0, 2)(rng);\n\n        if (type == 0) {\n            int i = uniform_int_distribution<int>(0, M - 2)(rng);\n            int j = uniform_int_distribution<int>(i + 1, M - 1)(rng);\n\n            if (i == 0 && j == M - 1) continue;\n\n            reverse(seq.begin() + i, seq.begin() + j + 1);\n\n            EvalResult ev = evaluate_order_cycle(seq, false);\n\n            if (ev.cost < cur_cost) {\n                accept_current();\n            } else {\n                reverse(seq.begin() + i, seq.begin() + j + 1);\n            }\n        } else if (type == 1) {\n            int i = uniform_int_distribution<int>(0, M - 1)(rng);\n            int j = uniform_int_distribution<int>(0, M - 1)(rng);\n\n            if (i == j) continue;\n\n            swap(seq[i], seq[j]);\n\n            EvalResult ev = evaluate_order_cycle(seq, false);\n\n            if (ev.cost < cur_cost) {\n                accept_current();\n            } else {\n                swap(seq[i], seq[j]);\n            }\n        } else {\n            int i = uniform_int_distribution<int>(0, M - 1)(rng);\n\n            int x = seq[i];\n\n            seq.erase(seq.begin() + i);\n\n            int pos = uniform_int_distribution<int>(0, M - 1)(rng);\n\n            seq.insert(seq.begin() + pos, x);\n\n            EvalResult ev = evaluate_order_cycle(seq, false);\n\n            if (ev.cost < cur_cost) {\n                accept_current();\n            } else {\n                seq.erase(seq.begin() + pos);\n                seq.insert(seq.begin() + i, x);\n            }\n        }\n    }\n}\n\nvoid append_manhattan_moves(vector<string>& ans, int from, int to) {\n    int r = from / N;\n    int c = from % N;\n    int tr = to / N;\n    int tc = to % N;\n\n    while (r < tr) {\n        ans.push_back(\"D\");\n        r++;\n    }\n\n    while (r > tr) {\n        ans.push_back(\"U\");\n        r--;\n    }\n\n    while (c < tc) {\n        ans.push_back(\"R\");\n        c++;\n    }\n\n    while (c > tc) {\n        ans.push_back(\"L\");\n        c--;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int n;\n    cin >> n;\n\n    for (int a = 0; a < V; a++) {\n        for (int b = 0; b < V; b++) {\n            mdist[a][b] = abs(a / N - b / N) + abs(a % N - b % N);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x;\n            cin >> x;\n\n            hval[id20(i, j)] = x;\n            base_cost += abs(x);\n        }\n    }\n\n    if (base_cost == 0) {\n        return 0;\n    }\n\n    memset(edge_id, -1, sizeof(edge_id));\n\n    for (int r = 0; r < B; r++) {\n        for (int c = 0; c < B; c++) {\n            int v = r * B + c;\n\n            if (r + 1 < B) {\n                int u = (r + 1) * B + c;\n                int id = all_edges.size();\n\n                all_edges.push_back({v, u});\n\n                edge_id[v][u] = edge_id[u][v] = id;\n            }\n\n            if (c + 1 < B) {\n                int u = r * B + c + 1;\n                int id = all_edges.size();\n\n                all_edges.push_back({v, u});\n\n                edge_id[v][u] = edge_id[u][v] = id;\n            }\n        }\n    }\n\n    for (int i = 0; i < (int)all_edges.size(); i++) {\n        auto e = all_edges[i];\n\n        block_adj[e.a].push_back({e.b, i});\n        block_adj[e.b].push_back({e.a, i});\n    }\n\n    mt19937 rng(123456789);\n\n    EvalResult best;\n    vector<EvalResult> pool;\n\n    vector<char> best_tree_candidate;\n    long long best_tree_candidate_cost = INF;\n\n    try_order_candidate(best, pool, make_row_snake_order());\n    try_order_candidate(best, pool, make_col_snake_order());\n\n    {\n        vector<int> rev = make_row_snake_order();\n        reverse(rev.begin(), rev.end());\n        try_order_candidate(best, pool, rev);\n    }\n\n    {\n        vector<int> rev = make_col_snake_order();\n        reverse(rev.begin(), rev.end());\n        try_order_candidate(best, pool, rev);\n    }\n\n    vector<int> starts = {\n        id20(0, 0),\n        id20(0, N - 1),\n        id20(N - 1, 0),\n        id20(N - 1, N - 1),\n        id20(N / 2, N / 2)\n    };\n\n    for (int st : starts) {\n        try_order_candidate(best, pool, make_nearest_neighbor_order(st));\n    }\n\n    for (int st : starts) {\n        for (int mode = 0; mode < 4; mode++) {\n            try_order_candidate(best, pool, make_sign_greedy_order(st, mode, rng));\n        }\n    }\n\n    auto try_tree = [&](const vector<char>& in) {\n        EvalResult ev = evaluate_tree_mask(in, true);\n\n        add_to_pool(pool, ev);\n\n        if (ev.cost < best.cost) {\n            best = ev;\n        }\n\n        if (ev.cost < best_tree_candidate_cost) {\n            best_tree_candidate_cost = ev.cost;\n            best_tree_candidate = in;\n        }\n    };\n\n    for (int c = 0; c < B; c++) {\n        try_tree(tree_to_mask(make_row_tree(c)));\n    }\n\n    for (int r = 0; r < B; r++) {\n        try_tree(tree_to_mask(make_col_tree(r)));\n    }\n\n    int iter = 0;\n\n    while (timer.elapsed() < T_INIT_TREE) {\n        vector<char> tr;\n\n        if (iter & 1) {\n            tr = random_kruskal_tree(rng);\n        } else {\n            tr = random_prim_tree(rng);\n        }\n\n        try_tree(tr);\n\n        iter++;\n    }\n\n    if (!best_tree_candidate.empty()) {\n        vector<char> cur = best_tree_candidate;\n        local_search(cur, best, pool, timer);\n    }\n\n    while (timer.elapsed() < T_TREE_END) {\n        vector<char> tr;\n\n        if (iter & 1) {\n            tr = random_kruskal_tree(rng);\n        } else {\n            tr = random_prim_tree(rng);\n        }\n\n        EvalResult ev = evaluate_tree_mask(tr, true);\n\n        add_to_pool(pool, ev);\n\n        bool promising_tree = false;\n\n        if (ev.cost < best.cost) {\n            best = ev;\n            promising_tree = true;\n        }\n\n        if (ev.cost < best_tree_candidate_cost) {\n            best_tree_candidate_cost = ev.cost;\n            promising_tree = true;\n        }\n\n        if (promising_tree) {\n            vector<char> cur = tr;\n            local_search(cur, best, pool, timer);\n        }\n\n        iter++;\n    }\n\n    sort(pool.begin(), pool.end(), [](const EvalResult& a, const EvalResult& b) {\n        return a.cost < b.cost;\n    });\n\n    if (!best.order.empty()) {\n        EvalResult e = evaluate_order_cycle(best.order, true);\n        add_to_pool(pool, e);\n    }\n\n    if (!pool.empty()) optimize_sequence(pool[0].order, best, pool, timer, T_FINAL1);\n    if ((int)pool.size() >= 2) optimize_sequence(pool[1].order, best, pool, timer, T_FINAL2);\n    if ((int)pool.size() >= 3) optimize_sequence(pool[2].order, best, pool, timer, T_FINAL3);\n\n    if (!best.order.empty()) {\n        optimize_sequence(best.order, best, pool, timer, T_FINAL3);\n    }\n\n    random_improve(best, timer, rng);\n\n    if (best.order.empty()) {\n        return 0;\n    }\n\n    vector<string> ans;\n    ans.reserve(20000);\n\n    int cur = 0;\n\n    append_manhattan_moves(ans, cur, best.order[0]);\n    cur = best.order[0];\n\n    long long load = 0;\n\n    for (int idx = 0; idx < (int)best.order.size(); idx++) {\n        int id = best.order[idx];\n        int v = hval[id];\n\n        if (v > 0) {\n            ans.push_back(\"+\" + to_string(v));\n            load += v;\n        } else if (v < 0) {\n            ans.push_back(\"-\" + to_string(-v));\n            load += v;\n        }\n\n        if (idx + 1 < (int)best.order.size()) {\n            int nxt = best.order[idx + 1];\n\n            append_manhattan_moves(ans, id, nxt);\n\n            cur = nxt;\n        }\n    }\n\n    for (const string& s : ans) {\n        cout << s << '\\n';\n    }\n\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n\n    int randint(int n) {\n        return (int)(next_u32() % n);\n    }\n\n    double uniform01() {\n        return (next_u32() >> 8) * (1.0 / 16777216.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int G = N * N;\n    const int K = 2 * N * (N - 1);\n    const int MAXS = 1500;\n    const int TOTAL = 1 << 15;\n\n    vector<vector<int>> X(K, vector<int>(M));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    XorShift rng;\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) {\n            rng.x ^= (uint64_t)(X[i][j] + 1009) * 11995408973635179863ULL;\n            rng.x ^= rng.x << 7;\n            rng.x ^= rng.x >> 9;\n        }\n    }\n\n    vector<int> initialMax(M, 0);\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < M; j++) {\n            initialMax[j] = max(initialMax[j], X[i][j]);\n        }\n    }\n\n    vector<pair<int, int>> edges;\n    vector<vector<int>> incident(G);\n    vector<vector<int>> neigh(G);\n\n    auto gid = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j + 1 < N; j++) {\n            int a = gid(i, j);\n            int b = gid(i, j + 1);\n            int e = edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n            neigh[a].push_back(b);\n            neigh[b].push_back(a);\n        }\n    }\n\n    for (int i = 0; i + 1 < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = gid(i, j);\n            int b = gid(i + 1, j);\n            int e = edges.size();\n            edges.push_back({a, b});\n            incident[a].push_back(e);\n            incident[b].push_back(e);\n            neigh[a].push_back(b);\n            neigh[b].push_back(a);\n        }\n    }\n\n    vector<int> posOrder(G);\n    iota(posOrder.begin(), posOrder.end(), 0);\n\n    sort(posOrder.begin(), posOrder.end(), [&](int a, int b) {\n        int da = incident[a].size();\n        int db = incident[b].size();\n        if (da != db) return da > db;\n\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n        double ca = abs(ai - (N - 1) / 2.0) + abs(aj - (N - 1) / 2.0);\n        double cb = abs(bi - (N - 1) / 2.0) + abs(bj - (N - 1) / 2.0);\n        return ca < cb;\n    });\n\n    vector<double> logVal(TOTAL + 1, -1e100);\n    for (int i = 1; i <= TOTAL; i++) {\n        logVal[i] = log((double)i / TOTAL);\n    }\n\n    auto calc_delta_pair_score = [&](const vector<int>& slots,\n                                     const vector<vector<double>>& W,\n                                     int a,\n                                     int b) -> double {\n        if (a == b) return 0.0;\n        if (a >= G && b >= G) return 0.0;\n\n        double delta = 0.0;\n\n        for (auto [u, v] : edges) {\n            if (u != a && u != b && v != a && v != b) continue;\n\n            int su = slots[u];\n            int sv = slots[v];\n\n            int nsu = su;\n            int nsv = sv;\n\n            if (u == a) nsu = slots[b];\n            else if (u == b) nsu = slots[a];\n\n            if (v == a) nsv = slots[b];\n            else if (v == b) nsv = slots[a];\n\n            delta += W[nsu][nsv] - W[su][sv];\n        }\n\n        return delta;\n    };\n\n    auto total_pair_score = [&](const vector<int>& slots,\n                                const vector<vector<double>>& W) -> double {\n        double s = 0.0;\n        for (auto [u, v] : edges) {\n            s += W[slots[u]][slots[v]];\n        }\n        return s;\n    };\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> sumValue(K, 0);\n        for (int i = 0; i < K; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) s += X[i][j];\n            sumValue[i] = s;\n        }\n\n        double progress = (T == 1 ? 1.0 : (double)turn / (T - 1));\n\n        bool useExactQuantile = (turn >= 4);\n        bool finalTurn = (turn == T - 1);\n\n        vector<vector<int>> q950(K, vector<int>(K, 0));\n        vector<vector<int>> q985(K, vector<int>(K, 0));\n        vector<vector<int>> q995(K, vector<int>(K, 0));\n\n        vector<unsigned short> cdf;\n        if (finalTurn) {\n            cdf.assign(K * K * (MAXS + 1), 0);\n        }\n\n        if (useExactQuantile || finalTurn) {\n            vector<int> cnt(MAXS + 1, 0), nxt(MAXS + 1, 0);\n            vector<int> active, nactive;\n\n            int target950 = (950 * TOTAL + 999) / 1000;\n            int target985 = (985 * TOTAL + 999) / 1000;\n            int target995 = (995 * TOTAL + 999) / 1000;\n\n            for (int i = 0; i < K; i++) {\n                for (int j = i + 1; j < K; j++) {\n                    fill(cnt.begin(), cnt.end(), 0);\n                    fill(nxt.begin(), nxt.end(), 0);\n\n                    active.clear();\n                    active.push_back(0);\n                    cnt[0] = 1;\n\n                    for (int l = 0; l < M; l++) {\n                        nactive.clear();\n\n                        int a = X[i][l];\n                        int b = X[j][l];\n\n                        for (int s : active) {\n                            int c = cnt[s];\n\n                            int s1 = s + a;\n                            if (nxt[s1] == 0) nactive.push_back(s1);\n                            nxt[s1] += c;\n\n                            int s2 = s + b;\n                            if (nxt[s2] == 0) nactive.push_back(s2);\n                            nxt[s2] += c;\n                        }\n\n                        for (int s : active) cnt[s] = 0;\n\n                        for (int s : nactive) {\n                            cnt[s] = nxt[s];\n                            nxt[s] = 0;\n                        }\n\n                        active.swap(nactive);\n                    }\n\n                    int cum = 0;\n                    int qq950 = MAXS;\n                    int qq985 = MAXS;\n                    int qq995 = MAXS;\n                    bool f950 = false, f985 = false, f995 = false;\n\n                    int base1 = (i * K + j) * (MAXS + 1);\n                    int base2 = (j * K + i) * (MAXS + 1);\n\n                    for (int s = 0; s <= MAXS; s++) {\n                        cum += cnt[s];\n\n                        if (!f950 && cum >= target950) {\n                            qq950 = s;\n                            f950 = true;\n                        }\n\n                        if (!f985 && cum >= target985) {\n                            qq985 = s;\n                            f985 = true;\n                        }\n\n                        if (!f995 && cum >= target995) {\n                            qq995 = s;\n                            f995 = true;\n                        }\n\n                        if (finalTurn) {\n                            cdf[base1 + s] = (unsigned short)cum;\n                            cdf[base2 + s] = (unsigned short)cum;\n                        }\n                    }\n\n                    q950[i][j] = q950[j][i] = qq950;\n                    q985[i][j] = q985[j][i] = qq985;\n                    q995[i][j] = q995[j][i] = qq995;\n                }\n            }\n        }\n\n        double alpha = 0.45 * (1.0 - progress) + 0.08 * progress;\n        double tailCoef = 0.55 * (1.0 - progress) + 1.30 * progress;\n        double geneCoef = 0.08 * (1.0 - progress) + 0.02 * progress;\n\n        vector<vector<double>> W(K, vector<double>(K, 0.0));\n\n        for (int i = 0; i < K; i++) {\n            for (int j = i + 1; j < K; j++) {\n                double mu = 0.5 * (sumValue[i] + sumValue[j]);\n\n                double cmax = 0.0;\n                double diff2 = 0.0;\n                double gene = 0.0;\n\n                for (int l = 0; l < M; l++) {\n                    int a = X[i][l];\n                    int b = X[j][l];\n                    int mx = max(a, b);\n                    int d = a - b;\n\n                    cmax += mx;\n                    diff2 += (double)d * d;\n\n                    int den = max(1, initialMax[l]);\n                    gene += (double)mx * mx / den;\n                }\n\n                double sigma = 0.5 * sqrt(diff2);\n\n                double baseScore = mu;\n                baseScore += alpha * (cmax - mu);\n                baseScore += tailCoef * sigma;\n                baseScore += geneCoef * gene;\n\n                double score = baseScore;\n\n                if (useExactQuantile) {\n                    double exactScore =\n                        0.20 * q950[i][j] +\n                        0.55 * q985[i][j] +\n                        0.18 * q995[i][j] +\n                        0.07 * cmax;\n\n                    double blend = min(1.0, progress * progress * 1.15);\n                    score = (1.0 - blend) * baseScore + blend * exactScore;\n                }\n\n                W[i][j] = W[j][i] = score;\n            }\n        }\n\n        vector<double> potBySeed(K, 0.0);\n        vector<pair<double, int>> potential;\n        potential.reserve(K);\n\n        for (int i = 0; i < K; i++) {\n            vector<double> v;\n            v.reserve(K - 1);\n\n            for (int j = 0; j < K; j++) {\n                if (i != j) v.push_back(W[i][j]);\n            }\n\n            nth_element(v.begin(), v.begin() + 8, v.end(), greater<double>());\n\n            double p = 0.0;\n            for (int k = 0; k < 8; k++) p += v[k];\n\n            p += 0.16 * sumValue[i];\n\n            double soloGene = 0.0;\n            for (int l = 0; l < M; l++) {\n                int den = max(1, initialMax[l]);\n                double r = (double)X[i][l] / den;\n                soloGene += X[i][l] * r * r;\n            }\n\n            p += (0.85 * (1.0 - progress) + 0.25 * progress) * soloGene;\n\n            potBySeed[i] = p;\n            potential.push_back({p, i});\n        }\n\n        sort(potential.begin(), potential.end(), greater<pair<double, int>>());\n\n        vector<int> slots(K, -1);\n        vector<int> usedSeed(K, 0);\n        vector<int> selected;\n        selected.reserve(G);\n\n        for (int k = 0; k < G; k++) {\n            selected.push_back(potential[k].second);\n            usedSeed[potential[k].second] = 1;\n        }\n\n        // Greedy constructive initial layout.\n        vector<int> placedSeed(K, 0);\n        vector<int> filledPos(G, 0);\n\n        int firstPos = posOrder[0];\n        int firstSeed = selected[0];\n\n        slots[firstPos] = firstSeed;\n        filledPos[firstPos] = 1;\n        placedSeed[firstSeed] = 1;\n\n        for (int step = 1; step < G; step++) {\n            int bestPos = -1;\n            tuple<int, int, double> bestPosKey(-1, -1, 1e100);\n\n            for (int p = 0; p < G; p++) {\n                if (filledPos[p]) continue;\n\n                int cnt = 0;\n                for (int nb : neigh[p]) {\n                    if (filledPos[nb]) cnt++;\n                }\n\n                int deg = incident[p].size();\n                int pi = p / N, pj = p % N;\n                double centerDist = abs(pi - (N - 1) / 2.0) + abs(pj - (N - 1) / 2.0);\n\n                auto key = make_tuple(cnt, deg, -centerDist);\n                if (key > bestPosKey) {\n                    bestPosKey = key;\n                    bestPos = p;\n                }\n            }\n\n            int bestSeed = -1;\n            double bestScore = -1e100;\n\n            for (int s : selected) {\n                if (placedSeed[s]) continue;\n\n                double sc = 0.025 * potBySeed[s];\n\n                for (int nb : neigh[bestPos]) {\n                    if (filledPos[nb]) {\n                        sc += W[s][slots[nb]];\n                    }\n                }\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestSeed = s;\n                }\n            }\n\n            slots[bestPos] = bestSeed;\n            filledPos[bestPos] = 1;\n            placedSeed[bestSeed] = 1;\n        }\n\n        int ptr = G;\n        for (int i = 0; i < K; i++) {\n            if (!usedSeed[i]) {\n                slots[ptr++] = i;\n            }\n        }\n\n        double curScore = total_pair_score(slots, W);\n\n        int ITER = finalTurn ? 75000 : 92000;\n        double T0 = finalTurn ? 60.0 : 82.0;\n        double T1 = 0.05;\n\n        for (int it = 0; it < ITER; it++) {\n            int a, b;\n\n            if (rng.randint(100) < 67) {\n                a = rng.randint(G);\n                b = rng.randint(K);\n            } else {\n                a = rng.randint(K);\n                b = rng.randint(K);\n            }\n\n            if (a == b) continue;\n            if (a >= G && b >= G) continue;\n\n            double delta = calc_delta_pair_score(slots, W, a, b);\n\n            double ratio = (double)it / ITER;\n            double temp = T0 * (1.0 - ratio) + T1 * ratio;\n\n            bool accept = false;\n            if (delta >= 0.0) {\n                accept = true;\n            } else {\n                double prob = exp(delta / temp);\n                if (rng.uniform01() < prob) accept = true;\n            }\n\n            if (accept) {\n                swap(slots[a], slots[b]);\n                curScore += delta;\n            }\n        }\n\n        for (int pass = 0; pass < 3; pass++) {\n            bool improved = false;\n\n            for (int a = 0; a < K; a++) {\n                for (int b = a + 1; b < K; b++) {\n                    if (a >= G && b >= G) continue;\n\n                    double delta = calc_delta_pair_score(slots, W, a, b);\n                    if (delta > 1e-9) {\n                        swap(slots[a], slots[b]);\n                        curScore += delta;\n                        improved = true;\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n\n        if (finalTurn) {\n            vector<double> sumLog(MAXS + 1, 0.0), tmpLog(MAXS + 1);\n            vector<int> zeroCnt(MAXS + 1, 0), tmpZero(MAXS + 1);\n\n            auto addPair = [&](vector<double>& sl,\n                               vector<int>& zc,\n                               int a,\n                               int b,\n                               int coef) {\n                int base = (a * K + b) * (MAXS + 1);\n                for (int s = 0; s <= MAXS; s++) {\n                    int c = cdf[base + s];\n                    if (c == 0) {\n                        zc[s] += coef;\n                    } else {\n                        sl[s] += coef * logVal[c];\n                    }\n                }\n            };\n\n            auto exactScoreFromState = [&](const vector<double>& sl,\n                                           const vector<int>& zc) {\n                double res = 0.0;\n                for (int s = 0; s < MAXS; s++) {\n                    double prod = (zc[s] > 0 ? 0.0 : exp(sl[s]));\n                    res += 1.0 - prod;\n                }\n                return res;\n            };\n\n            for (auto [u, v] : edges) {\n                addPair(sumLog, zeroCnt, slots[u], slots[v], +1);\n            }\n\n            double exactCur = exactScoreFromState(sumLog, zeroCnt);\n            double bestExact = exactCur;\n            vector<int> bestExactSlots = slots;\n            vector<double> bestLog = sumLog;\n            vector<int> bestZero = zeroCnt;\n\n            auto evalExactSwap = [&](int a, int b) -> double {\n                tmpLog = sumLog;\n                tmpZero = zeroCnt;\n\n                vector<int> aff;\n\n                if (a < G) {\n                    for (int e : incident[a]) aff.push_back(e);\n                }\n                if (b < G) {\n                    for (int e : incident[b]) aff.push_back(e);\n                }\n\n                sort(aff.begin(), aff.end());\n                aff.erase(unique(aff.begin(), aff.end()), aff.end());\n\n                for (int e : aff) {\n                    auto [u, v] = edges[e];\n\n                    int oldU = slots[u];\n                    int oldV = slots[v];\n\n                    int newU = oldU;\n                    int newV = oldV;\n\n                    if (u == a) newU = slots[b];\n                    else if (u == b) newU = slots[a];\n\n                    if (v == a) newV = slots[b];\n                    else if (v == b) newV = slots[a];\n\n                    addPair(tmpLog, tmpZero, oldU, oldV, -1);\n                    addPair(tmpLog, tmpZero, newU, newV, +1);\n                }\n\n                return exactScoreFromState(tmpLog, tmpZero);\n            };\n\n            const int EXACT_ITER = 16000;\n\n            for (int it = 0; it < EXACT_ITER; it++) {\n                int a, b;\n\n                if (rng.randint(100) < 72) {\n                    a = rng.randint(G);\n                    b = rng.randint(K);\n                } else {\n                    a = rng.randint(K);\n                    b = rng.randint(K);\n                }\n\n                if (a == b) continue;\n                if (a >= G && b >= G) continue;\n\n                double nxtScore = evalExactSwap(a, b);\n                double delta = nxtScore - exactCur;\n\n                double ratio = (double)it / EXACT_ITER;\n                double temp = 3.2 * (1.0 - ratio) + 0.01 * ratio;\n\n                bool accept = false;\n                if (delta >= 0.0) {\n                    accept = true;\n                } else {\n                    if (rng.uniform01() < exp(delta / temp)) accept = true;\n                }\n\n                if (accept) {\n                    swap(slots[a], slots[b]);\n                    sumLog.swap(tmpLog);\n                    zeroCnt.swap(tmpZero);\n                    exactCur = nxtScore;\n\n                    if (exactCur > bestExact) {\n                        bestExact = exactCur;\n                        bestExactSlots = slots;\n                        bestLog = sumLog;\n                        bestZero = zeroCnt;\n                    }\n                }\n            }\n\n            slots = bestExactSlots;\n            sumLog = bestLog;\n            zeroCnt = bestZero;\n            exactCur = bestExact;\n\n            for (int pass = 0; pass < 2; pass++) {\n                bool improved = false;\n\n                for (int a = 0; a < K; a++) {\n                    for (int b = a + 1; b < K; b++) {\n                        if (a >= G && b >= G) continue;\n\n                        double nxtScore = evalExactSwap(a, b);\n                        if (nxtScore > exactCur + 1e-9) {\n                            swap(slots[a], slots[b]);\n                            sumLog.swap(tmpLog);\n                            zeroCnt.swap(tmpZero);\n                            exactCur = nxtScore;\n                            improved = true;\n                        }\n                    }\n                }\n\n                if (!improved) break;\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << slots[gid(i, j)];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < M; j++) {\n                if (!(cin >> X[i][j])) return 0;\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing Clock = chrono::steady_clock;\nClock::time_point ST;\n\nbool time_ok(double lim = 2.72) {\n    return chrono::duration<double>(Clock::now() - ST).count() < lim;\n}\n\nstruct Pos {\n    int x, y;\n};\n\nconst int DX[4] = {0, 1, 0, -1};\nconst int DY[4] = {1, 0, -1, 0};\n\nint mdist(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nbool inside(int N, int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\nstruct Sol {\n    int Vp = 1;\n    vector<pair<int, int>> edges;\n    Pos init{0, 0};\n    vector<string> ops;\n};\n\nchar mv1(Pos& p, Pos q) {\n    if (p.x < q.x) return ++p.x, 'D';\n    if (p.x > q.x) return --p.x, 'U';\n    if (p.y < q.y) return ++p.y, 'R';\n    if (p.y > q.y) return --p.y, 'L';\n    return '.';\n}\n\nbool better(int mode, int k, int cost, int bk, int bc, long long score, long long bs) {\n    if (mode == 0) return k > bk || (k == bk && cost < bc);\n    if (mode == 1) return score > bs || (score == bs && (k > bk || (k == bk && cost < bc)));\n\n    if (bk < 0) return true;\n\n    long long lhs = 1LL * k * (bc + 8);\n    long long rhs = 1LL * bk * (cost + 8);\n\n    return lhs > rhs || (lhs == rhs && cost < bc);\n}\n\n/* ---------- single fingertip fallback ---------- */\n\nvoid append_single(vector<string>& ops, Pos& cur, Pos to, bool act) {\n    vector<char> m;\n\n    while (cur.x < to.x) {\n        m.push_back('D');\n        cur.x++;\n    }\n    while (cur.x > to.x) {\n        m.push_back('U');\n        cur.x--;\n    }\n    while (cur.y < to.y) {\n        m.push_back('R');\n        cur.y++;\n    }\n    while (cur.y > to.y) {\n        m.push_back('L');\n        cur.y--;\n    }\n\n    if (m.empty()) {\n        if (act) ops.push_back(\".P\");\n        return;\n    }\n\n    for (int i = 0; i < (int)m.size(); i++) {\n        string s = \"..\";\n        s[0] = m[i];\n        if (i + 1 == (int)m.size() && act) s[1] = 'P';\n        ops.push_back(s);\n    }\n}\n\nSol make_single(const vector<Pos>& src, const vector<Pos>& dst) {\n    int D = src.size();\n\n    Sol sol;\n    sol.Vp = 1;\n\n    if (D == 0) return sol;\n\n    vector<int> rs(D), rt(D);\n    iota(rs.begin(), rs.end(), 0);\n    iota(rt.begin(), rt.end(), 0);\n\n    vector<pair<int, int>> plan;\n    Pos cur{0, 0};\n    bool has = false;\n\n    while (!rs.empty()) {\n        int ba = -1;\n        int bb = -1;\n        int bv = INT_MAX;\n\n        for (int a = 0; a < (int)rs.size(); a++) {\n            int si = rs[a];\n            int dcur = has ? mdist(cur, src[si]) : 0;\n\n            for (int b = 0; b < (int)rt.size(); b++) {\n                int ti = rt[b];\n                int val = dcur + 2 * mdist(src[si], dst[ti]);\n\n                if (val < bv) {\n                    bv = val;\n                    ba = a;\n                    bb = b;\n                }\n            }\n        }\n\n        int si = rs[ba];\n        int ti = rt[bb];\n\n        plan.push_back({si, ti});\n        cur = dst[ti];\n        has = true;\n\n        rs[ba] = rs.back();\n        rs.pop_back();\n\n        rt[bb] = rt.back();\n        rt.pop_back();\n    }\n\n    sol.init = src[plan[0].first];\n    cur = sol.init;\n\n    sol.ops.push_back(\".P\");\n\n    for (int i = 0; i < D; i++) {\n        int si = plan[i].first;\n        int ti = plan[i].second;\n\n        if (i > 0) append_single(sol.ops, cur, src[si], true);\n        append_single(sol.ops, cur, dst[ti], true);\n    }\n\n    return sol;\n}\n\n/* ---------- star arm ---------- */\n\nstruct StarState {\n    int Vp;\n    Pos root;\n    vector<int> dir;\n    vector<int> hold;\n    vector<string> ops;\n};\n\nvoid star_go(StarState& st, Pos to, const vector<int>& des, const vector<int>& leaves) {\n    vector<int> act(st.Vp, 0);\n    for (int v : leaves) act[v] = 1;\n\n    auto ready = [&]() {\n        if (st.root.x != to.x || st.root.y != to.y) return false;\n\n        for (int i = 1; i < st.Vp; i++) {\n            if (des[i] != -1 && st.dir[i] != des[i]) return false;\n        }\n\n        return true;\n    };\n\n    while (true) {\n        if (ready()) {\n            string op(2 * st.Vp, '.');\n            bool any = false;\n\n            for (int i = 1; i < st.Vp; i++) {\n                if (act[i]) {\n                    op[st.Vp + i] = 'P';\n                    st.hold[i] ^= 1;\n                    any = true;\n                }\n            }\n\n            if (any) st.ops.push_back(op);\n            return;\n        }\n\n        string op(2 * st.Vp, '.');\n        op[0] = mv1(st.root, to);\n\n        for (int i = 1; i < st.Vp; i++) {\n            if (des[i] == -1 || st.dir[i] == des[i]) continue;\n\n            int diff = (des[i] - st.dir[i] + 4) % 4;\n\n            if (diff == 1 || diff == 2) {\n                op[i] = 'R';\n                st.dir[i] = (st.dir[i] + 1) % 4;\n            } else {\n                op[i] = 'L';\n                st.dir[i] = (st.dir[i] + 3) % 4;\n            }\n        }\n\n        if (ready()) {\n            for (int i = 1; i < st.Vp; i++) {\n                if (act[i]) {\n                    op[st.Vp + i] = 'P';\n                    st.hold[i] ^= 1;\n                }\n            }\n\n            st.ops.push_back(op);\n            return;\n        }\n\n        st.ops.push_back(op);\n    }\n}\n\nSol make_star(\n    int N,\n    int V,\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    const vector<int>& lens_in,\n    int mode\n) {\n    int D = src.size();\n\n    Sol sol;\n    sol.Vp = min(V, 1 + (int)lens_in.size());\n\n    int F = sol.Vp - 1;\n\n    if (F <= 0 || D == 0) {\n        sol.Vp = 1;\n        return sol;\n    }\n\n    vector<int> len(sol.Vp), uniq;\n\n    for (int i = 1; i < sol.Vp; i++) {\n        int L = max(1, min(lens_in[i - 1], N - 1));\n\n        len[i] = L;\n        uniq.push_back(L);\n        sol.edges.push_back({0, L});\n    }\n\n    sort(uniq.begin(), uniq.end());\n    uniq.erase(unique(uniq.begin(), uniq.end()), uniq.end());\n\n    int C = uniq.size();\n\n    unordered_map<int, int> idx;\n    for (int i = 0; i < C; i++) idx[uniq[i]] = i;\n\n    vector<vector<int>> leaves(C);\n\n    for (int i = 1; i < sol.Vp; i++) {\n        leaves[idx[len[i]]].push_back(i);\n    }\n\n    vector<vector<int>> sid(N, vector<int>(N, -1));\n    vector<vector<int>> tid(N, vector<int>(N, -1));\n\n    for (int i = 0; i < D; i++) {\n        sid[src[i].x][src[i].y] = i;\n        tid[dst[i].x][dst[i].y] = i;\n    }\n\n    vector<char> remS(D, 1), remT(D, 1);\n\n    auto count_center = [&](Pos c, const vector<vector<int>>& id, const vector<char>& alive) {\n        vector<int> cnt(C, 0);\n\n        for (int ci = 0; ci < C; ci++) {\n            int L = uniq[ci];\n\n            for (int d = 0; d < 4; d++) {\n                int x = c.x + DX[d] * L;\n                int y = c.y + DY[d] * L;\n\n                if (!inside(N, x, y)) continue;\n\n                int k = id[x][y];\n                if (k != -1 && alive[k]) cnt[ci]++;\n            }\n\n            cnt[ci] = min(cnt[ci], (int)leaves[ci].size());\n        }\n\n        return cnt;\n    };\n\n    auto dirs_center = [&](Pos c, int ci, const vector<vector<int>>& id, const vector<char>& alive) {\n        vector<int> ds;\n        int L = uniq[ci];\n\n        for (int d = 0; d < 4; d++) {\n            int x = c.x + DX[d] * L;\n            int y = c.y + DY[d] * L;\n\n            if (!inside(N, x, y)) continue;\n\n            int k = id[x][y];\n            if (k != -1 && alive[k]) ds.push_back(d);\n        }\n\n        return ds;\n    };\n\n    StarState st;\n    st.Vp = sol.Vp;\n    st.root = {0, 0};\n    st.dir.assign(sol.Vp, 0);\n    st.hold.assign(sol.Vp, 0);\n\n    bool init = false;\n    Pos cur{0, 0};\n    int rem = D;\n\n    while (rem > 0) {\n        if (!time_ok()) break;\n\n        vector<vector<int>> scnt(N * N), tcnt(N * N);\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                int id = x * N + y;\n                Pos c{x, y};\n\n                scnt[id] = count_center(c, sid, remS);\n                tcnt[id] = count_center(c, tid, remT);\n            }\n        }\n\n        int bk = -1;\n        int bc = 1e9;\n        long long bs = LLONG_MIN;\n        Pos bspos{0, 0};\n        Pos btpos{0, 0};\n\n        for (int si = 0; si < N * N; si++) {\n            int stotal = 0;\n\n            for (int v : scnt[si]) stotal += v;\n            if (stotal == 0) continue;\n\n            Pos sp{si / N, si % N};\n\n            for (int ti = 0; ti < N * N; ti++) {\n                int k = 0;\n\n                for (int c = 0; c < C; c++) {\n                    k += min(scnt[si][c], tcnt[ti][c]);\n                }\n\n                if (k <= 0) continue;\n\n                Pos tp{ti / N, ti % N};\n                int cost = (init ? mdist(cur, sp) : 0) + mdist(sp, tp);\n                long long score = 90LL * k - cost;\n\n                if (better(mode, k, cost, bk, bc, score, bs)) {\n                    bk = k;\n                    bc = cost;\n                    bs = score;\n                    bspos = sp;\n                    btpos = tp;\n                }\n            }\n        }\n\n        if (bk <= 0) break;\n\n        if (!init) {\n            sol.init = bspos;\n            st.root = bspos;\n            cur = bspos;\n            init = true;\n        }\n\n        vector<int> pdes(sol.Vp, -1), rdes(sol.Vp, -1), acts;\n\n        for (int c = 0; c < C; c++) {\n            auto sd = dirs_center(bspos, c, sid, remS);\n            auto td = dirs_center(btpos, c, tid, remT);\n\n            int q = min({(int)sd.size(), (int)td.size(), (int)leaves[c].size()});\n\n            for (int z = 0; z < q; z++) {\n                int leaf = leaves[c][z];\n                int sdir = sd[z];\n                int tdir = td[z];\n                int L = uniq[c];\n\n                pdes[leaf] = sdir;\n                rdes[leaf] = tdir;\n                acts.push_back(leaf);\n\n                int sx = bspos.x + DX[sdir] * L;\n                int sy = bspos.y + DY[sdir] * L;\n                int tx = btpos.x + DX[tdir] * L;\n                int ty = btpos.y + DY[tdir] * L;\n\n                int si = sid[sx][sy];\n                int ti = tid[tx][ty];\n\n                if (si != -1 && remS[si]) {\n                    remS[si] = 0;\n                    rem--;\n                }\n\n                if (ti != -1 && remT[ti]) {\n                    remT[ti] = 0;\n                }\n            }\n        }\n\n        if (acts.empty()) break;\n\n        star_go(st, bspos, pdes, acts);\n        star_go(st, btpos, rdes, acts);\n\n        cur = btpos;\n\n        if ((int)st.ops.size() > 100000) break;\n    }\n\n    if (rem != 0 || !init || (int)st.ops.size() > 100000) {\n        sol.Vp = 1;\n        sol.edges.clear();\n        sol.ops.clear();\n        sol.init = {0, 0};\n        return sol;\n    }\n\n    sol.ops = move(st.ops);\n    return sol;\n}\n\n/* ---------- two-link arm ---------- */\n\nstruct Opt {\n    int dx, dy, d1, d2;\n};\n\nstruct TwoState {\n    int Vp, F;\n    Pos root;\n    vector<int> d1, d2;\n    vector<string> ops;\n};\n\nvoid two_go(\n    TwoState& st,\n    Pos to,\n    const vector<int>& des1,\n    const vector<int>& des2,\n    const vector<int>& acts\n) {\n    auto ready = [&]() {\n        if (st.root.x != to.x || st.root.y != to.y) return false;\n\n        for (int f = 0; f < st.F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            if (des1[j] != -1 && st.d1[f] != des1[j]) return false;\n            if (des2[l] != -1 && st.d2[f] != des2[l]) return false;\n        }\n\n        return true;\n    };\n\n    while (true) {\n        if (ready()) {\n            string op(2 * st.Vp, '.');\n            bool any = false;\n\n            for (int v : acts) {\n                op[st.Vp + v] = 'P';\n                any = true;\n            }\n\n            if (any) st.ops.push_back(op);\n            return;\n        }\n\n        string op(2 * st.Vp, '.');\n\n        op[0] = mv1(st.root, to);\n\n        for (int f = 0; f < st.F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            if (des1[j] != -1 && st.d1[f] != des1[j]) {\n                int diff = (des1[j] - st.d1[f] + 4) % 4;\n\n                if (diff == 1 || diff == 2) {\n                    op[j] = 'R';\n                    st.d1[f] = (st.d1[f] + 1) % 4;\n                    st.d2[f] = (st.d2[f] + 1) % 4;\n                } else {\n                    op[j] = 'L';\n                    st.d1[f] = (st.d1[f] + 3) % 4;\n                    st.d2[f] = (st.d2[f] + 3) % 4;\n                }\n            }\n\n            if (des2[l] != -1 && st.d2[f] != des2[l]) {\n                int diff = (des2[l] - st.d2[f] + 4) % 4;\n\n                if (diff == 1 || diff == 2) {\n                    op[l] = 'R';\n                    st.d2[f] = (st.d2[f] + 1) % 4;\n                } else {\n                    op[l] = 'L';\n                    st.d2[f] = (st.d2[f] + 3) % 4;\n                }\n            }\n        }\n\n        if (ready()) {\n            for (int v : acts) op[st.Vp + v] = 'P';\n            st.ops.push_back(op);\n            return;\n        }\n\n        st.ops.push_back(op);\n    }\n}\n\nSol make_two(\n    int N,\n    int V,\n    const vector<Pos>& src,\n    const vector<Pos>& dst,\n    const vector<pair<int, int>>& types,\n    int mode\n) {\n    int D = src.size();\n\n    Sol sol;\n    int F = min((V - 1) / 2, (int)types.size());\n\n    if (F <= 0 || D == 0) {\n        sol.Vp = 1;\n        return sol;\n    }\n\n    sol.Vp = 1 + 2 * F;\n\n    vector<int> A(F), B(F);\n\n    for (int f = 0; f < F; f++) {\n        A[f] = max(1, min(types[f].first, N - 1));\n        B[f] = max(1, min(types[f].second, N - 1));\n\n        int j = 1 + 2 * f;\n\n        sol.edges.push_back({0, A[f]});\n        sol.edges.push_back({j, B[f]});\n    }\n\n    vector<vector<Opt>> opts(F);\n\n    for (int f = 0; f < F; f++) {\n        map<pair<int, int>, Opt> mp;\n\n        for (int d1 = 0; d1 < 4; d1++) {\n            for (int d2 = 0; d2 < 4; d2++) {\n                int ox = DX[d1] * A[f] + DX[d2] * B[f];\n                int oy = DY[d1] * A[f] + DY[d2] * B[f];\n\n                pair<int, int> key{ox, oy};\n\n                if (!mp.count(key)) {\n                    mp[key] = {ox, oy, d1, d2};\n                }\n            }\n        }\n\n        for (auto& kv : mp) opts[f].push_back(kv.second);\n    }\n\n    vector<vector<int>> sid(N, vector<int>(N, -1));\n    vector<vector<int>> tid(N, vector<int>(N, -1));\n\n    for (int i = 0; i < D; i++) {\n        sid[src[i].x][src[i].y] = i;\n        tid[dst[i].x][dst[i].y] = i;\n    }\n\n    vector<char> remS(D, 1), remT(D, 1);\n\n    TwoState st;\n    st.Vp = sol.Vp;\n    st.F = F;\n    st.root = {0, 0};\n    st.d1.assign(F, 0);\n    st.d2.assign(F, 0);\n\n    bool init = false;\n    Pos cur{0, 0};\n    int rem = D;\n\n    vector<int> stamp(N * N, 0);\n    int token = 1;\n\n    auto compute = [&](const vector<vector<int>>& id, const vector<char>& alive) {\n        vector<int> mask(N * N, 0), cnt(N * N, 0);\n\n        for (int cx = 0; cx < N; cx++) {\n            for (int cy = 0; cy < N; cy++) {\n                int cid = cx * N + cy;\n                ++token;\n\n                for (int f = 0; f < F; f++) {\n                    bool ok = false;\n\n                    for (const auto& o : opts[f]) {\n                        int x = cx + o.dx;\n                        int y = cy + o.dy;\n\n                        if (!inside(N, x, y)) continue;\n\n                        int k = id[x][y];\n                        if (k == -1 || !alive[k]) continue;\n\n                        ok = true;\n\n                        int cell = x * N + y;\n\n                        if (stamp[cell] != token) {\n                            stamp[cell] = token;\n                            cnt[cid]++;\n                        }\n                    }\n\n                    if (ok) mask[cid] |= (1 << f);\n                }\n            }\n        }\n\n        return pair<vector<int>, vector<int>>(move(mask), move(cnt));\n    };\n\n    auto collect = [&](Pos c, int f, const vector<vector<int>>& id, const vector<char>& alive) {\n        vector<pair<int, Opt>> res;\n\n        for (const auto& o : opts[f]) {\n            int x = c.x + o.dx;\n            int y = c.y + o.dy;\n\n            if (!inside(N, x, y)) continue;\n\n            int k = id[x][y];\n\n            if (k != -1 && alive[k]) {\n                res.push_back({k, o});\n            }\n        }\n\n        return res;\n    };\n\n    while (rem > 0) {\n        if (!time_ok()) break;\n\n        auto [smask, scnt] = compute(sid, remS);\n        auto [tmask, tcnt] = compute(tid, remT);\n\n        int bk = -1;\n        int bc = 1e9;\n        long long bs = LLONG_MIN;\n        Pos bsp{0, 0};\n        Pos btp{0, 0};\n\n        for (int si = 0; si < N * N; si++) {\n            if (scnt[si] == 0) continue;\n\n            Pos sp{si / N, si % N};\n\n            for (int ti = 0; ti < N * N; ti++) {\n                if (tcnt[ti] == 0) continue;\n\n                int common = __builtin_popcount((unsigned)(smask[si] & tmask[ti]));\n                int k = min({common, scnt[si], tcnt[ti]});\n\n                if (k <= 0) continue;\n\n                Pos tp{ti / N, ti % N};\n\n                int cost = (init ? mdist(cur, sp) : 0) + mdist(sp, tp);\n                long long score = 90LL * k - cost;\n\n                if (better(mode, k, cost, bk, bc, score, bs)) {\n                    bk = k;\n                    bc = cost;\n                    bs = score;\n                    bsp = sp;\n                    btp = tp;\n                }\n            }\n        }\n\n        if (bk <= 0) break;\n\n        if (!init) {\n            sol.init = bsp;\n            st.root = bsp;\n            cur = bsp;\n            init = true;\n        }\n\n        vector<int> p1(sol.Vp, -1), p2(sol.Vp, -1), r1(sol.Vp, -1), r2(sol.Vp, -1), acts;\n        vector<char> usedS(D, 0), usedT(D, 0);\n\n        for (int f = 0; f < F; f++) {\n            int j = 1 + 2 * f;\n            int l = j + 1;\n\n            auto so = collect(bsp, f, sid, remS);\n            auto to = collect(btp, f, tid, remT);\n\n            bool done = false;\n\n            for (auto [si, sop] : so) {\n                if (usedS[si]) continue;\n\n                for (auto [ti, top] : to) {\n                    if (usedT[ti]) continue;\n\n                    usedS[si] = 1;\n                    usedT[ti] = 1;\n\n                    p1[j] = sop.d1;\n                    p2[l] = sop.d2;\n                    r1[j] = top.d1;\n                    r2[l] = top.d2;\n                    acts.push_back(l);\n\n                    remS[si] = 0;\n                    remT[ti] = 0;\n                    rem--;\n\n                    done = true;\n                    break;\n                }\n\n                if (done) break;\n            }\n        }\n\n        if (acts.empty()) break;\n\n        two_go(st, bsp, p1, p2, acts);\n        two_go(st, btp, r1, r2, acts);\n\n        cur = btp;\n\n        if ((int)st.ops.size() > 100000) break;\n    }\n\n    if (rem != 0 || !init || (int)st.ops.size() > 100000) {\n        sol.Vp = 1;\n        sol.edges.clear();\n        sol.ops.clear();\n        sol.init = {0, 0};\n        return sol;\n    }\n\n    sol.ops = move(st.ops);\n    return sol;\n}\n\n/* ---------- main ---------- */\n\nint main() {\n    ST = Clock::now();\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n\n    for (int i = 0; i < N; i++) cin >> s[i];\n    for (int i = 0; i < N; i++) cin >> t[i];\n\n    vector<Pos> src, dst;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (s[i][j] == '1' && t[i][j] == '0') {\n                src.push_back({i, j});\n            } else if (s[i][j] == '0' && t[i][j] == '1') {\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    Sol best = make_single(src, dst);\n\n    auto consider = [&](Sol sol) {\n        if (!src.empty() && sol.ops.empty()) return;\n        if (sol.ops.size() < best.ops.size()) best = move(sol);\n    };\n\n    int Fs = max(0, V - 1);\n\n    vector<int> l1, l2, l3, l4, l5, l6;\n\n    for (int i = 0; i < Fs; i++) l1.push_back(1 + i / 4);\n    for (int i = 0; i < Fs; i++) l2.push_back(1 + i / 2);\n    for (int i = 0; i < Fs; i++) l3.push_back(1 + (i % 7));\n    for (int i = 0; i < Fs; i++) l4.push_back(2 + (i % 6));\n    for (int i = 0; i < Fs; i++) l5.push_back(1 + (i % 10));\n    for (int i = 0; i < Fs; i++) l6.push_back(3 + (i % 10));\n\n    if (time_ok(2.40)) consider(make_star(N, V, src, dst, l1, 0));\n    if (time_ok(2.40)) consider(make_star(N, V, src, dst, l2, 0));\n    if (time_ok(2.40)) consider(make_star(N, V, src, dst, l3, 0));\n    if (time_ok(2.25)) consider(make_star(N, V, src, dst, l1, 1));\n    if (time_ok(2.20)) consider(make_star(N, V, src, dst, l4, 0));\n    if (time_ok(2.10)) consider(make_star(N, V, src, dst, l5, 2));\n    if (time_ok(1.95)) consider(make_star(N, V, src, dst, l6, 0));\n\n    int F2 = max(0, (V - 1) / 2);\n\n    auto repeated = [&](pair<int, int> p) {\n        vector<pair<int, int>> v;\n        for (int i = 0; i < F2; i++) v.push_back(p);\n        return v;\n    };\n\n    auto cycle = [&](vector<pair<int, int>> c) {\n        vector<pair<int, int>> v;\n        for (int i = 0; i < F2; i++) v.push_back(c[i % c.size()]);\n        return v;\n    };\n\n    vector<pair<int, int>> ty1 = repeated({1, 2});\n    vector<pair<int, int>> ty2 = cycle({{1, 1}, {1, 2}, {2, 3}});\n    vector<pair<int, int>> ty3 = cycle({{1, 1}, {1, 2}, {1, 3}, {2, 2}, {2, 3}, {3, 3}, {1, 4}});\n    vector<pair<int, int>> ty4 = cycle({{1, 2}, {2, 1}, {1, 3}, {3, 1}, {2, 2}, {2, 4}, {4, 2}});\n    vector<pair<int, int>> ty5 = cycle({{1, 4}, {4, 1}, {2, 3}, {3, 2}, {2, 4}, {4, 2}, {3, 3}});\n    vector<pair<int, int>> ty6 = cycle({{1, 5}, {5, 1}, {2, 5}, {5, 2}, {3, 4}, {4, 3}, {4, 4}});\n    vector<pair<int, int>> ty7 = cycle({{1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {1, 6}, {2, 6}});\n    vector<pair<int, int>> ty8 = cycle({{1, 6}, {6, 1}, {2, 6}, {6, 2}, {3, 5}, {5, 3}, {4, 4}});\n    vector<pair<int, int>> ty9 = cycle({{1, 7}, {7, 1}, {2, 7}, {7, 2}, {3, 6}, {6, 3}, {4, 5}});\n    vector<pair<int, int>> ty10 = cycle({{1, 8}, {8, 1}, {2, 8}, {8, 2}, {3, 7}, {7, 3}, {4, 6}});\n    vector<pair<int, int>> ty11 = cycle({{2, 9}, {9, 2}, {3, 8}, {8, 3}, {4, 7}, {7, 4}, {5, 6}});\n    vector<pair<int, int>> ty12 = cycle({{1, 10}, {10, 1}, {2, 10}, {10, 2}, {4, 8}, {8, 4}, {5, 7}});\n    vector<pair<int, int>> ty13 = cycle({{1, 9}, {9, 1}, {3, 9}, {9, 3}, {5, 8}, {8, 5}, {6, 7}});\n    vector<pair<int, int>> ty14 = cycle({{1, 11}, {11, 1}, {2, 11}, {11, 2}, {5, 9}, {9, 5}, {7, 7}});\n    vector<pair<int, int>> ty15 = cycle({{2, 12}, {12, 2}, {4, 10}, {10, 4}, {6, 8}, {8, 6}, {7, 7}});\n    vector<pair<int, int>> ty16 = cycle({{1, 12}, {12, 1}, {3, 11}, {11, 3}, {5, 10}, {10, 5}, {8, 8}});\n\n    if (time_ok(2.35)) consider(make_two(N, V, src, dst, ty1, 0));\n    if (time_ok(2.35)) consider(make_two(N, V, src, dst, ty2, 0));\n\n    if (time_ok(2.18)) consider(make_two(N, V, src, dst, repeated({1, 1}), 0));\n    if (time_ok(2.18)) consider(make_two(N, V, src, dst, repeated({2, 2}), 0));\n    if (time_ok(2.18)) consider(make_two(N, V, src, dst, repeated({2, 3}), 0));\n    if (time_ok(2.18)) consider(make_two(N, V, src, dst, repeated({1, 3}), 0));\n\n    if (time_ok(2.08)) consider(make_two(N, V, src, dst, ty1, 1));\n    if (time_ok(2.08)) consider(make_two(N, V, src, dst, ty2, 1));\n    if (time_ok(2.08)) consider(make_two(N, V, src, dst, ty2, 2));\n\n    if (time_ok(2.00)) consider(make_two(N, V, src, dst, ty3, 0));\n    if (time_ok(1.94)) consider(make_two(N, V, src, dst, ty4, 0));\n    if (time_ok(1.88)) consider(make_two(N, V, src, dst, repeated({3, 3}), 0));\n    if (time_ok(1.82)) consider(make_two(N, V, src, dst, repeated({2, 4}), 0));\n    if (time_ok(1.76)) consider(make_two(N, V, src, dst, ty3, 1));\n\n    if (time_ok(1.70)) consider(make_two(N, V, src, dst, repeated({1, 4}), 0));\n    if (time_ok(1.64)) consider(make_two(N, V, src, dst, repeated({3, 4}), 0));\n    if (time_ok(1.58)) consider(make_two(N, V, src, dst, repeated({4, 4}), 0));\n    if (time_ok(1.52)) consider(make_two(N, V, src, dst, repeated({2, 5}), 0));\n    if (time_ok(1.46)) consider(make_two(N, V, src, dst, ty4, 1));\n    if (time_ok(1.40)) consider(make_two(N, V, src, dst, ty3, 2));\n    if (time_ok(1.34)) consider(make_two(N, V, src, dst, ty5, 0));\n    if (time_ok(1.28)) consider(make_two(N, V, src, dst, ty5, 1));\n    if (time_ok(1.22)) consider(make_two(N, V, src, dst, ty6, 0));\n\n    if (time_ok(1.16)) consider(make_two(N, V, src, dst, repeated({1, 5}), 0));\n    if (time_ok(1.10)) consider(make_two(N, V, src, dst, repeated({3, 5}), 0));\n    if (time_ok(1.04)) consider(make_two(N, V, src, dst, repeated({4, 5}), 0));\n    if (time_ok(0.98)) consider(make_two(N, V, src, dst, repeated({5, 5}), 0));\n    if (time_ok(0.92)) consider(make_two(N, V, src, dst, repeated({2, 6}), 0));\n    if (time_ok(0.86)) consider(make_two(N, V, src, dst, ty6, 1));\n    if (time_ok(0.80)) consider(make_two(N, V, src, dst, ty6, 2));\n    if (time_ok(0.74)) consider(make_two(N, V, src, dst, ty7, 0));\n    if (time_ok(0.68)) consider(make_two(N, V, src, dst, ty7, 1));\n    if (time_ok(0.62)) consider(make_two(N, V, src, dst, ty8, 0));\n\n    if (time_ok(0.58)) consider(make_two(N, V, src, dst, repeated({1, 6}), 0));\n    if (time_ok(0.54)) consider(make_two(N, V, src, dst, repeated({3, 6}), 0));\n    if (time_ok(0.50)) consider(make_two(N, V, src, dst, repeated({6, 6}), 0));\n    if (time_ok(0.46)) consider(make_two(N, V, src, dst, ty8, 1));\n    if (time_ok(0.42)) consider(make_two(N, V, src, dst, ty9, 0));\n    if (time_ok(0.38)) consider(make_two(N, V, src, dst, ty9, 1));\n    if (time_ok(0.34)) consider(make_two(N, V, src, dst, ty10, 0));\n    if (time_ok(0.30)) consider(make_two(N, V, src, dst, ty10, 1));\n    if (time_ok(0.26)) consider(make_two(N, V, src, dst, repeated({2, 7}), 0));\n    if (time_ok(0.22)) consider(make_two(N, V, src, dst, repeated({4, 7}), 0));\n    if (time_ok(0.18)) consider(make_two(N, V, src, dst, ty11, 0));\n    if (time_ok(0.14)) consider(make_two(N, V, src, dst, ty12, 0));\n\n    // Slightly less strict final guards than before.\n    if (time_ok(0.28)) consider(make_two(N, V, src, dst, repeated({5, 7}), 0));\n    if (time_ok(0.25)) consider(make_two(N, V, src, dst, ty13, 0));\n    if (time_ok(0.22)) consider(make_two(N, V, src, dst, ty13, 1));\n    if (time_ok(0.19)) consider(make_two(N, V, src, dst, ty14, 0));\n    if (time_ok(0.16)) consider(make_two(N, V, src, dst, repeated({8, 8}), 0));\n    if (time_ok(0.13)) consider(make_two(N, V, src, dst, ty15, 0));\n    if (time_ok(0.10)) consider(make_two(N, V, src, dst, ty16, 0));\n\n    cout << best.Vp << '\\n';\n\n    for (auto [p, L] : best.edges) {\n        cout << p << ' ' << L << '\\n';\n    }\n\n    cout << best.init.x << ' ' << best.init.y << '\\n';\n\n    for (const string& op : best.ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Fish { int x, y, w; };\n\nstruct PolyCand {\n    int diff = -1000000000;\n    vector<pair<int,int>> poly;\n};\n\nstruct EvalResult {\n    bool ok = false;\n    int diff = -1000000000;\n    vector<char> mask;\n    vector<pair<int,int>> poly;\n};\n\nstatic const int LIM = 100000;\nstatic const int MAX_PERIM = 400000;\nstatic const int MAX_VERT = 1000;\n\nint N;\nvector<Fish> fishes;\nPolyCand bestAns;\nTimer timer;\n\nstatic inline int id(int x, int y, int G) { return y * G + x; }\n\nint exactDiffRect(int x1, int y1, int x2, int y2) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) s += p.w;\n    }\n    return s;\n}\n\nvoid updateBest(const vector<pair<int,int>>& poly, int diff) {\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return;\n    if (diff > bestAns.diff) {\n        bestAns.diff = diff;\n        bestAns.poly = poly;\n    }\n}\n\nbool pointInsideMask(const vector<char>& mask, int G, int L, int px, int py) {\n    int xs[2], ys[2], nx = 0, ny = 0;\n\n    if (px == LIM) xs[nx++] = G - 1;\n    else xs[nx++] = px / L;\n    if (px > 0 && px % L == 0) xs[nx++] = px / L - 1;\n\n    if (py == LIM) ys[ny++] = G - 1;\n    else ys[ny++] = py / L;\n    if (py > 0 && py % L == 0) ys[ny++] = py / L - 1;\n\n    for (int i = 0; i < nx; i++) {\n        for (int j = 0; j < ny; j++) {\n            int x = xs[i], y = ys[j];\n            if (0 <= x && x < G && 0 <= y && y < G && mask[id(x,y,G)]) return true;\n        }\n    }\n    return false;\n}\n\nint exactDiffMask(const vector<char>& mask, int G, int L) {\n    int s = 0;\n    for (auto &p : fishes) {\n        if (pointInsideMask(mask, G, L, p.x, p.y)) s += p.w;\n    }\n    return s;\n}\n\nbool isConnected(const vector<char>& mask, int G) {\n    int st = -1, cnt = 0;\n    for (int i = 0; i < G * G; i++) {\n        if (mask[i]) {\n            cnt++;\n            if (st == -1) st = i;\n        }\n    }\n    if (cnt == 0) return false;\n\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n    q.push(st);\n    vis[st] = 1;\n    int got = 0;\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        got++;\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n            int ni = id(nx,ny,G);\n            if (!mask[ni] || vis[ni]) continue;\n            vis[ni] = 1;\n            q.push(ni);\n        }\n    }\n    return got == cnt;\n}\n\nvoid fillHoles(vector<char>& mask, int G) {\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n\n    auto push_empty = [&](int x, int y) {\n        if (x < 0 || x >= G || y < 0 || y >= G) return;\n        int v = id(x,y,G);\n        if (!mask[v] && !vis[v]) {\n            vis[v] = 1;\n            q.push(v);\n        }\n    };\n\n    for (int i = 0; i < G; i++) {\n        push_empty(i, 0);\n        push_empty(i, G - 1);\n        push_empty(0, i);\n        push_empty(G - 1, i);\n    }\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int x = v % G, y = v / G;\n        for (int d = 0; d < 4; d++) push_empty(x + dx[d], y + dy[d]);\n    }\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] && !vis[i]) mask[i] = 1;\n    }\n}\n\nvoid normalizeMask(vector<char>& mask, int G, const vector<int>& cellW) {\n    fillHoles(mask, G);\n\n    for (int iter = 0; iter < G * G; iter++) {\n        bool changed = false;\n\n        for (int y = 0; y + 1 < G; y++) {\n            for (int x = 0; x + 1 < G; x++) {\n                int a = id(x,y,G);\n                int b = id(x+1,y,G);\n                int c = id(x,y+1,G);\n                int d = id(x+1,y+1,G);\n\n                if (mask[a] && mask[d] && !mask[b] && !mask[c]) {\n                    if (cellW[b] >= cellW[c]) mask[b] = 1;\n                    else mask[c] = 1;\n                    changed = true;\n                }\n                if (mask[b] && mask[c] && !mask[a] && !mask[d]) {\n                    if (cellW[a] >= cellW[d]) mask[a] = 1;\n                    else mask[d] = 1;\n                    changed = true;\n                }\n            }\n        }\n\n        if (!changed) break;\n        fillHoles(mask, G);\n    }\n}\n\nint calcPerimCells(const vector<char>& mask, int G) {\n    int per = 0;\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n            if (x == 0 || !mask[id(x-1,y,G)]) per++;\n            if (x == G-1 || !mask[id(x+1,y,G)]) per++;\n            if (y == 0 || !mask[id(x,y-1,G)]) per++;\n            if (y == G-1 || !mask[id(x,y+1,G)]) per++;\n        }\n    }\n    return per;\n}\n\nvector<pair<int,int>> extractPolygon(const vector<char>& mask, int G, int L) {\n    int V = (G + 1) * (G + 1);\n    vector<int> nxt(V, -1), indeg(V, 0);\n    bool bad = false;\n    int edgeCnt = 0;\n\n    auto vid = [&](int x, int y) { return y * (G + 1) + x; };\n\n    auto addEdge = [&](int x1, int y1, int x2, int y2) {\n        int u = vid(x1,y1), v = vid(x2,y2);\n        if (nxt[u] != -1) bad = true;\n        nxt[u] = v;\n        indeg[v]++;\n        if (indeg[v] > 1) bad = true;\n        edgeCnt++;\n    };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            if (!mask[id(x,y,G)]) continue;\n            if (y == 0 || !mask[id(x,y-1,G)]) addEdge(x, y, x+1, y);\n            if (x == G-1 || !mask[id(x+1,y,G)]) addEdge(x+1, y, x+1, y+1);\n            if (y == G-1 || !mask[id(x,y+1,G)]) addEdge(x+1, y+1, x, y+1);\n            if (x == 0 || !mask[id(x-1,y,G)]) addEdge(x, y+1, x, y);\n        }\n    }\n\n    if (bad || edgeCnt == 0) return {};\n\n    int st = -1;\n    for (int i = 0; i < V; i++) {\n        if (nxt[i] != -1) {\n            st = i;\n            break;\n        }\n    }\n\n    vector<char> used(V, 0);\n    vector<pair<int,int>> poly;\n    int cur = st;\n\n    for (int step = 0; step <= edgeCnt; step++) {\n        if (cur == -1) return {};\n        if (cur == st && step > 0) break;\n        if (used[cur]) return {};\n        used[cur] = 1;\n\n        int gx = cur % (G + 1);\n        int gy = cur / (G + 1);\n        poly.push_back({gx * L, gy * L});\n        cur = nxt[cur];\n    }\n\n    if (cur != st) return {};\n    if ((int)poly.size() != edgeCnt) return {};\n\n    auto collinear = [](pair<int,int> a, pair<int,int> b, pair<int,int> c) {\n        return (a.first == b.first && b.first == c.first) ||\n               (a.second == b.second && b.second == c.second);\n    };\n\n    bool changed = true;\n    while (changed && poly.size() >= 4) {\n        changed = false;\n        vector<pair<int,int>> np;\n        int m = (int)poly.size();\n\n        for (int i = 0; i < m; i++) {\n            auto a = poly[(i - 1 + m) % m];\n            auto b = poly[i];\n            auto c = poly[(i + 1) % m];\n            if (collinear(a,b,c)) changed = true;\n            else np.push_back(b);\n        }\n\n        poly.swap(np);\n    }\n\n    if (poly.size() < 4 || poly.size() > MAX_VERT) return {};\n\n    set<pair<int,int>> ss(poly.begin(), poly.end());\n    if (ss.size() != poly.size()) return {};\n\n    return poly;\n}\n\nEvalResult evalMask(vector<char> mask, int G, int L, const vector<int>& cellW) {\n    EvalResult res;\n    normalizeMask(mask, G, cellW);\n\n    if (!isConnected(mask, G)) return res;\n\n    int perCells = calcPerimCells(mask, G);\n    if (perCells * L > MAX_PERIM) return res;\n\n    auto poly = extractPolygon(mask, G, L);\n    if (poly.empty()) return res;\n\n    int diff = exactDiffMask(mask, G, L);\n\n    res.ok = true;\n    res.diff = diff;\n    res.mask = std::move(mask);\n    res.poly = std::move(poly);\n    return res;\n}\n\nvector<int> buildGridWeight(int G, int L) {\n    vector<int> w(G * G, 0);\n    for (auto &p : fishes) {\n        int x = min(G - 1, p.x / L);\n        int y = min(G - 1, p.y / L);\n        w[id(x,y,G)] += p.w;\n    }\n    return w;\n}\n\nvoid tryTinyBaseline() {\n    for (int i = 0; i < N; i++) {\n        int x = fishes[i].x;\n        int y = fishes[i].y;\n\n        int x1, x2, y1, y2;\n        if (x < LIM) x1 = x, x2 = x + 1;\n        else x1 = x - 1, x2 = x;\n\n        if (y < LIM) y1 = y, y2 = y + 1;\n        else y1 = y - 1, y2 = y;\n\n        int diff = exactDiffRect(x1,y1,x2,y2);\n        vector<pair<int,int>> poly = {{x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}};\n        updateBest(poly, diff);\n    }\n}\n\nvoid tryBestRectangle(int G, int L, const vector<int>& cellW) {\n    int maxSideSum = MAX_PERIM / (2 * L);\n\n    int bestVal = -1000000000;\n    int bx1 = 0, by1 = 0, bx2 = 1, by2 = 1;\n\n    vector<int> arr(G), pref(G + 1);\n\n    for (int xl = 0; xl < G; xl++) {\n        fill(arr.begin(), arr.end(), 0);\n\n        for (int xr = xl; xr < G; xr++) {\n            for (int y = 0; y < G; y++) arr[y] += cellW[id(xr,y,G)];\n\n            int width = xr - xl + 1;\n            int maxH = maxSideSum - width;\n            if (maxH <= 0) continue;\n            maxH = min(maxH, G);\n\n            pref[0] = 0;\n            for (int y = 0; y < G; y++) pref[y+1] = pref[y] + arr[y];\n\n            deque<int> dq;\n            for (int e = 1; e <= G; e++) {\n                int sNew = e - 1;\n                while (!dq.empty() && pref[dq.back()] >= pref[sNew]) dq.pop_back();\n                dq.push_back(sNew);\n\n                while (!dq.empty() && dq.front() < e - maxH) dq.pop_front();\n\n                int s = dq.front();\n                int val = pref[e] - pref[s];\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    bx1 = xl;\n                    bx2 = xr + 1;\n                    by1 = s;\n                    by2 = e;\n                }\n            }\n        }\n    }\n\n    int x1 = bx1 * L;\n    int x2 = bx2 * L;\n    int y1 = by1 * L;\n    int y2 = by2 * L;\n\n    int diff = exactDiffRect(x1,y1,x2,y2);\n    vector<pair<int,int>> poly = {{x1,y1}, {x2,y1}, {x2,y2}, {x1,y2}};\n    updateBest(poly, diff);\n}\n\nstruct Comp {\n    int score = 0;\n    int size = 0;\n    long long sx = 0, sy = 0;\n    vector<int> cells;\n};\n\nvector<Comp> getComponents(const vector<char>& mask, int G, const vector<int>& cellW) {\n    vector<Comp> comps;\n    vector<char> vis(G * G, 0);\n    queue<int> q;\n\n    const int dx[4] = {1,-1,0,0};\n    const int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < G * G; i++) {\n        if (!mask[i] || vis[i]) continue;\n\n        Comp c;\n        vis[i] = 1;\n        q.push(i);\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            int x = v % G, y = v / G;\n\n            c.cells.push_back(v);\n            c.score += cellW[v];\n            c.size++;\n            c.sx += x;\n            c.sy += y;\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= G || ny < 0 || ny >= G) continue;\n                int ni = id(nx,ny,G);\n                if (!mask[ni] || vis[ni]) continue;\n                vis[ni] = 1;\n                q.push(ni);\n            }\n        }\n\n        if (c.size > 0) comps.push_back(std::move(c));\n    }\n\n    sort(comps.begin(), comps.end(), [](const Comp& a, const Comp& b) {\n        return a.score > b.score;\n    });\n\n    return comps;\n}\n\nvector<char> makeCompMask(const Comp& c, int G) {\n    vector<char> m(G * G, 0);\n    for (int v : c.cells) m[v] = 1;\n    return m;\n}\n\nvoid addPath(vector<char>& m, int G, int x1, int y1, int x2, int y2, bool hv) {\n    if (hv) {\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y1,G)] = 1;\n\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x2,y,G)] = 1;\n    } else {\n        int ya = min(y1,y2), yb = max(y1,y2);\n        for (int y = ya; y <= yb; y++) m[id(x1,y,G)] = 1;\n\n        int xa = min(x1,x2), xb = max(x1,x2);\n        for (int x = xa; x <= xb; x++) m[id(x,y2,G)] = 1;\n    }\n}\n\nvoid tryGreedyUnion(vector<Comp>& comps, int G, int L, const vector<int>& cellW) {\n    vector<Comp> pos;\n    for (auto &c : comps) {\n        if (c.score > 0) pos.push_back(c);\n        if ((int)pos.size() >= 20) break;\n    }\n    if (pos.empty()) return;\n\n    vector<char> cur = makeCompMask(pos[0], G);\n    auto er0 = evalMask(cur, G, L, cellW);\n    if (!er0.ok) return;\n\n    updateBest(er0.poly, er0.diff);\n    cur = er0.mask;\n    int curDiff = er0.diff;\n\n    for (int ci = 1; ci < (int)pos.size(); ci++) {\n        const Comp& c = pos[ci];\n\n        int cx = (int)(c.sx / max(1, c.size));\n        int cy = (int)(c.sy / max(1, c.size));\n\n        int ax = -1, ay = -1, bestD = INT_MAX;\n        for (int y = 0; y < G; y++) {\n            for (int x = 0; x < G; x++) {\n                if (!cur[id(x,y,G)]) continue;\n                int d = abs(x - cx) + abs(y - cy);\n                if (d < bestD) {\n                    bestD = d;\n                    ax = x;\n                    ay = y;\n                }\n            }\n        }\n\n        int bx = -1, by = -1;\n        bestD = INT_MAX;\n        for (int v : c.cells) {\n            int x = v % G, y = v / G;\n            int d = abs(x - ax) + abs(y - ay);\n            if (d < bestD) {\n                bestD = d;\n                bx = x;\n                by = y;\n            }\n        }\n\n        vector<char> base = cur;\n        for (int v : c.cells) base[v] = 1;\n\n        vector<char> m1 = base, m2 = base;\n        addPath(m1, G, ax, ay, bx, by, true);\n        addPath(m2, G, ax, ay, bx, by, false);\n\n        auto e1 = evalMask(m1, G, L, cellW);\n        auto e2 = evalMask(m2, G, L, cellW);\n\n        EvalResult bestE;\n        if (e1.ok) bestE = e1;\n        if (e2.ok && (!bestE.ok || e2.diff > bestE.diff)) bestE = e2;\n\n        if (bestE.ok) {\n            updateBest(bestE.poly, bestE.diff);\n            if (bestE.diff > curDiff) {\n                curDiff = bestE.diff;\n                cur = bestE.mask;\n            }\n        }\n    }\n}\n\nvector<int> boxSmooth(const vector<int>& w, int G, int r) {\n    vector<int> pref((G+1)*(G+1), 0);\n\n    auto pid = [&](int x, int y) {\n        return y * (G + 1) + x;\n    };\n\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            pref[pid(x+1,y+1)] =\n                pref[pid(x+1,y)] + pref[pid(x,y+1)] -\n                pref[pid(x,y)] + w[id(x,y,G)];\n        }\n    }\n\n    vector<int> sm(G * G, 0);\n    for (int y = 0; y < G; y++) {\n        for (int x = 0; x < G; x++) {\n            int x1 = max(0, x - r);\n            int y1 = max(0, y - r);\n            int x2 = min(G, x + r + 1);\n            int y2 = min(G, y + r + 1);\n\n            sm[id(x,y,G)] =\n                pref[pid(x2,y2)] - pref[pid(x1,y2)] -\n                pref[pid(x2,y1)] + pref[pid(x1,y1)];\n        }\n    }\n\n    return sm;\n}\n\nvoid processGrid(int L) {\n    int G = LIM / L;\n    vector<int> cellW = buildGridWeight(G, L);\n\n    tryBestRectangle(G, L, cellW);\n\n    vector<int> radii;\n    if (L == 500) radii = {0,1,2,3,5,8,12};\n    else if (L == 1000) radii = {0,1,2,3,5,8};\n    else if (L == 2000) radii = {0,1,2,3,4};\n    else radii = {0,1,2,3};\n\n    for (int r : radii) {\n        vector<int> sm = boxSmooth(cellW, G, r);\n\n        vector<int> thresholds;\n        if (r == 0) thresholds = {0};\n        else thresholds = {-1, 0, 1, 2, 4};\n\n        for (int th : thresholds) {\n            vector<char> mask(G * G, 0);\n            for (int i = 0; i < G * G; i++) {\n                if (sm[i] > th) mask[i] = 1;\n            }\n\n            auto comps = getComponents(mask, G, cellW);\n\n            int cnt = 0;\n            for (auto &c : comps) {\n                if (c.score <= 0) continue;\n\n                auto cm = makeCompMask(c, G);\n                auto er = evalMask(cm, G, L, cellW);\n                if (er.ok) updateBest(er.poly, er.diff);\n\n                cnt++;\n                if (cnt >= 30) break;\n            }\n\n            tryGreedyUnion(comps, G, L, cellW);\n        }\n    }\n}\n\nlong long twiceArea(const vector<pair<int,int>>& p) {\n    long long a = 0;\n    int m = (int)p.size();\n\n    for (int i = 0; i < m; i++) {\n        auto [x1,y1] = p[i];\n        auto [x2,y2] = p[(i+1)%m];\n        a += 1LL * x1 * y2 - 1LL * y1 * x2;\n    }\n\n    return a;\n}\n\nlong long polygonPerimeter(const vector<pair<int,int>>& p) {\n    long long per = 0;\n    int m = (int)p.size();\n\n    for (int i = 0; i < m; i++) {\n        auto [x1,y1] = p[i];\n        auto [x2,y2] = p[(i+1)%m];\n        per += abs(x1 - x2) + abs(y1 - y2);\n    }\n\n    return per;\n}\n\nbool betweenLL(long long a, long long b, long long c) {\n    return min(a,b) <= c && c <= max(a,b);\n}\n\nbool segIntersect(pair<int,int> a, pair<int,int> b, pair<int,int> c, pair<int,int> d) {\n    if (a.first == b.first && c.first == d.first) {\n        if (a.first != c.first) return false;\n        return max(min(a.second,b.second), min(c.second,d.second)) <=\n               min(max(a.second,b.second), max(c.second,d.second));\n    }\n\n    if (a.second == b.second && c.second == d.second) {\n        if (a.second != c.second) return false;\n        return max(min(a.first,b.first), min(c.first,d.first)) <=\n               min(max(a.first,b.first), max(c.first,d.first));\n    }\n\n    if (a.second == b.second) {\n        swap(a,c);\n        swap(b,d);\n    }\n\n    int vx = a.first;\n    int hy = c.second;\n\n    return betweenLL(a.second,b.second,hy) &&\n           betweenLL(c.first,d.first,vx);\n}\n\nbool validPolygon(const vector<pair<int,int>>& p) {\n    int m = (int)p.size();\n    if (m < 4 || m > MAX_VERT) return false;\n\n    set<pair<int,int>> st(p.begin(), p.end());\n    if ((int)st.size() != m) return false;\n\n    for (int i = 0; i < m; i++) {\n        auto a = p[i];\n        auto b = p[(i+1)%m];\n\n        if (a == b) return false;\n        if (!(a.first == b.first || a.second == b.second)) return false;\n        if (a.first < 0 || a.first > LIM || a.second < 0 || a.second > LIM) return false;\n    }\n\n    if (polygonPerimeter(p) > MAX_PERIM) return false;\n\n    for (int i = 0; i < m; i++) {\n        auto a = p[i], b = p[(i+1)%m];\n\n        for (int j = i + 1; j < m; j++) {\n            if ((i + 1) % m == j) continue;\n            if ((j + 1) % m == i) continue;\n\n            auto c = p[j], d = p[(j+1)%m];\n            if (segIntersect(a,b,c,d)) return false;\n        }\n    }\n\n    return true;\n}\n\nbool onSegmentPoint(pair<int,int> a, pair<int,int> b, int x, int y) {\n    if (a.first == b.first) {\n        return x == a.first &&\n               min(a.second,b.second) <= y &&\n               y <= max(a.second,b.second);\n    } else {\n        return y == a.second &&\n               min(a.first,b.first) <= x &&\n               x <= max(a.first,b.first);\n    }\n}\n\nbool pointInPolygon(const vector<pair<int,int>>& p, int x, int y) {\n    int m = (int)p.size();\n\n    for (int i = 0; i < m; i++) {\n        if (onSegmentPoint(p[i], p[(i+1)%m], x, y)) return true;\n    }\n\n    bool inside = false;\n    for (int i = 0; i < m; i++) {\n        auto [x1,y1] = p[i];\n        auto [x2,y2] = p[(i+1)%m];\n\n        if (x1 == x2) {\n            if ((y1 > y) != (y2 > y)) {\n                if (x < x1) inside = !inside;\n            }\n        }\n    }\n\n    return inside;\n}\n\nint exactDiffPolygon(const vector<pair<int,int>>& p) {\n    int s = 0;\n    for (auto &f : fishes) {\n        if (pointInPolygon(p, f.x, f.y)) s += f.w;\n    }\n    return s;\n}\n\nint rangeSumInclusive(const vector<pair<int,int>>& xs, const vector<int>& pref, int l, int r) {\n    if (l > r) return 0;\n\n    int L = lower_bound(xs.begin(), xs.end(), make_pair(l, -1000000000)) - xs.begin();\n    int R = upper_bound(xs.begin(), xs.end(), make_pair(r,  1000000000)) - xs.begin();\n\n    return pref[R] - pref[L];\n}\n\nvoid tryEdgeShiftRefine(int SHIFT, int passes) {\n    if (bestAns.poly.empty()) return;\n    if (timer.sec() > 1.90) return;\n\n    vector<pair<int,int>> p = bestAns.poly;\n    if (!validPolygon(p)) return;\n\n    int m = (int)p.size();\n    bool ccw = twiceArea(p) > 0;\n\n    for (int pass = 0; pass < passes; pass++) {\n        if (timer.sec() > 1.92) break;\n\n        for (int i = 0; i < m; i++) {\n            if (timer.sec() > 1.92) break;\n\n            int j = (i + 1) % m;\n            int im = (i - 1 + m) % m;\n            int j2 = (i + 2) % m;\n\n            auto a = p[i], b = p[j];\n\n            if (a.first == b.first) {\n                int x = a.first;\n                int y1 = min(a.second, b.second);\n                int y2 = max(a.second, b.second);\n\n                int lo = max(0, x - SHIFT);\n                int hi = min(LIM, x + SHIFT);\n\n                int xp = p[im].first;\n                int xn = p[j2].first;\n\n                if (x > xp) lo = max(lo, xp + 1);\n                else hi = min(hi, xp - 1);\n\n                if (x > xn) lo = max(lo, xn + 1);\n                else hi = min(hi, xn - 1);\n\n                if (lo > hi) continue;\n\n                vector<pair<int,int>> xs;\n                vector<int> cand;\n                cand.push_back(x);\n\n                for (auto &f : fishes) {\n                    if (y1 <= f.y && f.y <= y2 && lo <= f.x && f.x <= hi) {\n                        xs.push_back({f.x, f.w});\n                        cand.push_back(f.x);\n                        if (f.x + 1 <= hi) cand.push_back(f.x + 1);\n                        if (f.x - 1 >= lo) cand.push_back(f.x - 1);\n                    }\n                }\n\n                if (xs.empty()) continue;\n\n                sort(xs.begin(), xs.end());\n\n                vector<int> pref(xs.size() + 1, 0);\n                for (int k = 0; k < (int)xs.size(); k++) pref[k+1] = pref[k] + xs[k].second;\n\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n                int dy = b.second - a.second;\n                int leftSign = (dy > 0 ? -1 : +1);\n                int insideSign = ccw ? leftSign : -leftSign;\n\n                int bestX = x;\n                int bestDelta = 0;\n\n                for (int nx : cand) {\n                    if (nx == x || nx < lo || nx > hi) continue;\n\n                    int sum = rangeSumInclusive(xs, pref, min(x,nx), max(x,nx));\n                    int dx = nx - x;\n\n                    int delta;\n                    if (insideSign * dx < 0) delta = sum;\n                    else delta = -sum;\n\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestX = nx;\n                    }\n                }\n\n                if (bestDelta > 0 && bestX != x) {\n                    p[i].first = bestX;\n                    p[j].first = bestX;\n\n                    if (polygonPerimeter(p) > MAX_PERIM) {\n                        p[i].first = x;\n                        p[j].first = x;\n                    }\n                }\n            } else if (a.second == b.second) {\n                int y = a.second;\n                int x1 = min(a.first, b.first);\n                int x2 = max(a.first, b.first);\n\n                int lo = max(0, y - SHIFT);\n                int hi = min(LIM, y + SHIFT);\n\n                int yp = p[im].second;\n                int yn = p[j2].second;\n\n                if (y > yp) lo = max(lo, yp + 1);\n                else hi = min(hi, yp - 1);\n\n                if (y > yn) lo = max(lo, yn + 1);\n                else hi = min(hi, yn - 1);\n\n                if (lo > hi) continue;\n\n                vector<pair<int,int>> ys;\n                vector<int> cand;\n                cand.push_back(y);\n\n                for (auto &f : fishes) {\n                    if (x1 <= f.x && f.x <= x2 && lo <= f.y && f.y <= hi) {\n                        ys.push_back({f.y, f.w});\n                        cand.push_back(f.y);\n                        if (f.y + 1 <= hi) cand.push_back(f.y + 1);\n                        if (f.y - 1 >= lo) cand.push_back(f.y - 1);\n                    }\n                }\n\n                if (ys.empty()) continue;\n\n                sort(ys.begin(), ys.end());\n\n                vector<int> pref(ys.size() + 1, 0);\n                for (int k = 0; k < (int)ys.size(); k++) pref[k+1] = pref[k] + ys[k].second;\n\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n                int dx = b.first - a.first;\n                int leftSign = (dx > 0 ? +1 : -1);\n                int insideSign = ccw ? leftSign : -leftSign;\n\n                int bestY = y;\n                int bestDelta = 0;\n\n                for (int ny : cand) {\n                    if (ny == y || ny < lo || ny > hi) continue;\n\n                    int sum = rangeSumInclusive(ys, pref, min(y,ny), max(y,ny));\n                    int dy = ny - y;\n\n                    int delta;\n                    if (insideSign * dy < 0) delta = sum;\n                    else delta = -sum;\n\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestY = ny;\n                    }\n                }\n\n                if (bestDelta > 0 && bestY != y) {\n                    p[i].second = bestY;\n                    p[j].second = bestY;\n\n                    if (polygonPerimeter(p) > MAX_PERIM) {\n                        p[i].second = y;\n                        p[j].second = y;\n                    }\n                }\n            }\n        }\n\n        if (validPolygon(p)) {\n            int diff = exactDiffPolygon(p);\n            updateBest(p, diff);\n        }\n    }\n}\n\nstruct NotchCand {\n    int approx;\n    int edge;\n    int t1, t2;\n    int nx, ny;\n    int depth;\n};\n\nvector<pair<int,int>> applyNotch(const vector<pair<int,int>>& p, const NotchCand& c) {\n    int m = (int)p.size();\n    if (m + 4 > MAX_VERT) return {};\n\n    int i = c.edge;\n    auto A = p[i];\n    auto B = p[(i + 1) % m];\n\n    int vx = (B.first > A.first) ? 1 : (B.first < A.first ? -1 : 0);\n    int vy = (B.second > A.second) ? 1 : (B.second < A.second ? -1 : 0);\n\n    pair<int,int> P1 = {A.first + vx * c.t1, A.second + vy * c.t1};\n    pair<int,int> P2 = {A.first + vx * c.t2, A.second + vy * c.t2};\n    pair<int,int> Q1 = {P1.first + c.nx * c.depth, P1.second + c.ny * c.depth};\n    pair<int,int> Q2 = {P2.first + c.nx * c.depth, P2.second + c.ny * c.depth};\n\n    if (P1 == A || P2 == B || P1 == P2 || Q1 == Q2) return {};\n    if (Q1.first < 0 || Q1.first > LIM || Q1.second < 0 || Q1.second > LIM) return {};\n    if (Q2.first < 0 || Q2.first > LIM || Q2.second < 0 || Q2.second > LIM) return {};\n\n    vector<pair<int,int>> np;\n    np.reserve(m + 4);\n\n    for (int k = 0; k < m; k++) {\n        np.push_back(p[k]);\n\n        if (k == i) {\n            np.push_back(P1);\n            np.push_back(Q1);\n            np.push_back(Q2);\n            np.push_back(P2);\n        }\n    }\n\n    return np;\n}\n\nbool tryOneNotchIteration(int candLimit) {\n    if (bestAns.poly.empty()) return false;\n    if (timer.sec() > 1.83) return false;\n\n    vector<pair<int,int>> base = bestAns.poly;\n    if (!validPolygon(base)) return false;\n    if ((int)base.size() + 4 > MAX_VERT) return false;\n\n    bool ccw = twiceArea(base) > 0;\n    int m = (int)base.size();\n    long long basePer = polygonPerimeter(base);\n\n    const int MAX_D = 340;\n    vector<int> widths = {60, 110, 190, 320, 560, 950, 1550};\n    vector<NotchCand> cands;\n\n    for (int i = 0; i < m; i++) {\n        if (timer.sec() > 1.87) break;\n\n        auto A = base[i];\n        auto B = base[(i + 1) % m];\n\n        int vx = (B.first > A.first) ? 1 : (B.first < A.first ? -1 : 0);\n        int vy = (B.second > A.second) ? 1 : (B.second < A.second ? -1 : 0);\n        int len = abs(B.first - A.first) + abs(B.second - A.second);\n        if (len < 20) continue;\n\n        int leftNx = -vy;\n        int leftNy = vx;\n        int inNx = ccw ? leftNx : -leftNx;\n        int inNy = ccw ? leftNy : -leftNy;\n        int outNx = -inNx;\n        int outNy = -inNy;\n\n        struct Near {\n            int t;\n            int din;\n            int dout;\n            int w;\n        };\n\n        vector<Near> near;\n\n        for (auto &f : fishes) {\n            int t;\n            if (vx != 0) t = (f.x - A.first) * vx;\n            else t = (f.y - A.second) * vy;\n\n            if (t <= 0 || t >= len) continue;\n\n            int dx = f.x - A.first;\n            int dy = f.y - A.second;\n            int din = dx * inNx + dy * inNy;\n            int dout = dx * outNx + dy * outNy;\n\n            if ((din > 0 && din <= MAX_D) || (dout > 0 && dout <= MAX_D)) {\n                near.push_back({t, din, dout, f.w});\n            }\n        }\n\n        if (near.empty()) continue;\n\n        struct Anchor {\n            int t;\n            int dist;\n            int mode;\n        };\n\n        vector<Anchor> anchors;\n\n        for (auto &q : near) {\n            if (q.dout > 0 && q.w > 0) anchors.push_back({q.t, q.dout, 0});\n            if (q.din > 0 && q.w < 0) anchors.push_back({q.t, q.din, 1});\n        }\n\n        if (anchors.empty()) continue;\n\n        sort(anchors.begin(), anchors.end(), [](const Anchor& a, const Anchor& b) {\n            if (a.dist != b.dist) return a.dist < b.dist;\n            return a.t < b.t;\n        });\n\n        if ((int)anchors.size() > 120) anchors.resize(120);\n\n        for (auto &anchor : anchors) {\n            int mode = anchor.mode;\n\n            int nx = (mode == 0 ? outNx : inNx);\n            int ny = (mode == 0 ? outNy : inNy);\n            int depth = min(MAX_D, anchor.dist + 35);\n\n            if (basePer + 2LL * depth > MAX_PERIM) continue;\n\n            for (int W : widths) {\n                int t1 = max(1, anchor.t - W);\n                int t2 = min(len - 1, anchor.t + W);\n                if (t2 - t1 < 2) continue;\n\n                int approx = 0;\n\n                for (auto &q : near) {\n                    if (q.t < t1 || q.t > t2) continue;\n\n                    if (mode == 0) {\n                        if (q.dout > 0 && q.dout <= depth) approx += q.w;\n                    } else {\n                        if (q.din > 0 && q.din <= depth) approx -= q.w;\n                    }\n                }\n\n                if (approx > 0) cands.push_back({approx, i, t1, t2, nx, ny, depth});\n            }\n        }\n    }\n\n    if (cands.empty()) return false;\n\n    sort(cands.begin(), cands.end(), [](const NotchCand& a, const NotchCand& b) {\n        return a.approx > b.approx;\n    });\n\n    int limit = min<int>(candLimit, cands.size());\n    int bestDiff = bestAns.diff;\n    vector<pair<int,int>> bestPoly;\n\n    for (int idx = 0; idx < limit; idx++) {\n        if (timer.sec() > 1.92) break;\n\n        auto np = applyNotch(base, cands[idx]);\n        if (np.empty()) continue;\n        if (!validPolygon(np)) continue;\n\n        int diff = exactDiffPolygon(np);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly = std::move(np);\n        }\n    }\n\n    if (!bestPoly.empty()) {\n        updateBest(bestPoly, bestDiff);\n        return true;\n    }\n\n    return false;\n}\n\nvoid tryNotchRefineIterative() {\n    if (timer.sec() > 1.82) return;\n\n    for (int iter = 0; iter < 3; iter++) {\n        if (timer.sec() > 1.86) break;\n\n        int limit = (iter == 0 ? 95 : 50);\n        bool improved = tryOneNotchIteration(limit);\n\n        if (!improved) break;\n\n        if (timer.sec() < 1.88) tryEdgeShiftRefine(120, 1);\n    }\n}\n\nstruct CornerCand {\n    int approx;\n    int vertex;\n    int d1, d2;\n};\n\nvector<pair<int,int>> applyCornerCut(const vector<pair<int,int>>& p, const CornerCand& c) {\n    int m = (int)p.size();\n    if (m + 2 > MAX_VERT) return {};\n\n    int i = c.vertex;\n    int pi = (i - 1 + m) % m;\n    int ni = (i + 1) % m;\n\n    auto A = p[pi];\n    auto B = p[i];\n    auto C = p[ni];\n\n    int e1x = (B.first > A.first) ? 1 : (B.first < A.first ? -1 : 0);\n    int e1y = (B.second > A.second) ? 1 : (B.second < A.second ? -1 : 0);\n    int e2x = (C.first > B.first) ? 1 : (C.first < B.first ? -1 : 0);\n    int e2y = (C.second > B.second) ? 1 : (C.second < B.second ? -1 : 0);\n\n    int len1 = abs(B.first - A.first) + abs(B.second - A.second);\n    int len2 = abs(C.first - B.first) + abs(C.second - B.second);\n\n    if (c.d1 <= 0 || c.d2 <= 0 || c.d1 >= len1 || c.d2 >= len2) return {};\n\n    pair<int,int> R1 = {B.first - e1x * c.d1, B.second - e1y * c.d1};\n    pair<int,int> R2 = {B.first + e2x * c.d2, B.second + e2y * c.d2};\n    pair<int,int> Q  = {R1.first + e2x * c.d2, R1.second + e2y * c.d2};\n\n    if (Q.first < 0 || Q.first > LIM || Q.second < 0 || Q.second > LIM) return {};\n    if (R1 == Q || R2 == Q || R1 == R2) return {};\n\n    vector<pair<int,int>> np;\n    np.reserve(m + 2);\n\n    for (int k = 0; k < m; k++) {\n        if (k == i) {\n            np.push_back(R1);\n            np.push_back(Q);\n            np.push_back(R2);\n        } else {\n            np.push_back(p[k]);\n        }\n    }\n\n    return np;\n}\n\nbool tryOneCornerCutIteration(int candLimit) {\n    if (bestAns.poly.empty()) return false;\n    if (timer.sec() > 1.84) return false;\n\n    vector<pair<int,int>> base = bestAns.poly;\n    if (!validPolygon(base)) return false;\n    if ((int)base.size() + 2 > MAX_VERT) return false;\n\n    bool ccw = twiceArea(base) > 0;\n    int m = (int)base.size();\n\n    const int MAX_D = 540;\n    vector<CornerCand> cands;\n\n    for (int i = 0; i < m; i++) {\n        if (timer.sec() > 1.88) break;\n\n        int pi = (i - 1 + m) % m;\n        int ni = (i + 1) % m;\n\n        auto A = base[pi];\n        auto B = base[i];\n        auto C = base[ni];\n\n        int e1x = (B.first > A.first) ? 1 : (B.first < A.first ? -1 : 0);\n        int e1y = (B.second > A.second) ? 1 : (B.second < A.second ? -1 : 0);\n        int e2x = (C.first > B.first) ? 1 : (C.first < B.first ? -1 : 0);\n        int e2y = (C.second > B.second) ? 1 : (C.second < B.second ? -1 : 0);\n\n        if (e1x * e2x + e1y * e2y != 0) continue;\n\n        int len1 = abs(B.first - A.first) + abs(B.second - A.second);\n        int len2 = abs(C.first - B.first) + abs(C.second - B.second);\n\n        if (len1 < 40 || len2 < 40) continue;\n\n        int cross = e1x * e2y - e1y * e2x;\n        bool convex = ccw ? (cross > 0) : (cross < 0);\n\n        struct Near { int a, b, w; };\n        vector<Near> near;\n\n        vector<int> d1s = {35, 70, 120, 210, 340, 520};\n        vector<int> d2s = {35, 70, 120, 210, 340, 520};\n\n        for (auto &f : fishes) {\n            int dx = f.x - B.first;\n            int dy = f.y - B.second;\n\n            int a = dx * (-e1x) + dy * (-e1y);\n            int b = dx * e2x + dy * e2y;\n\n            if (a > 0 && b > 0 && a < len1 && b < len2 && a <= MAX_D && b <= MAX_D) {\n                near.push_back({a,b,f.w});\n\n                int aa1 = min(len1 - 1, a + 22);\n                int bb1 = min(len2 - 1, b + 22);\n                int aa2 = min(len1 - 1, a + 75);\n                int bb2 = min(len2 - 1, b + 75);\n\n                if (aa1 > 0) d1s.push_back(aa1);\n                if (aa2 > 0) d1s.push_back(aa2);\n                if (bb1 > 0) d2s.push_back(bb1);\n                if (bb2 > 0) d2s.push_back(bb2);\n            }\n        }\n\n        if (near.empty()) continue;\n\n        sort(d1s.begin(), d1s.end());\n        d1s.erase(unique(d1s.begin(), d1s.end()), d1s.end());\n        sort(d2s.begin(), d2s.end());\n        d2s.erase(unique(d2s.begin(), d2s.end()), d2s.end());\n\n        if ((int)d1s.size() > 24) d1s.resize(24);\n        if ((int)d2s.size() > 24) d2s.resize(24);\n\n        for (int d1 : d1s) {\n            if (d1 <= 0 || d1 >= len1) continue;\n\n            for (int d2 : d2s) {\n                if (d2 <= 0 || d2 >= len2) continue;\n\n                int sum = 0;\n                for (auto &q : near) {\n                    if (q.a <= d1 && q.b <= d2) sum += q.w;\n                }\n\n                int approx = convex ? -sum : sum;\n                if (approx > 0) cands.push_back({approx, i, d1, d2});\n            }\n        }\n    }\n\n    if (cands.empty()) return false;\n\n    sort(cands.begin(), cands.end(), [](const CornerCand& a, const CornerCand& b) {\n        return a.approx > b.approx;\n    });\n\n    int limit = min<int>(candLimit, cands.size());\n    int bestDiff = bestAns.diff;\n    vector<pair<int,int>> bestPoly;\n\n    for (int idx = 0; idx < limit; idx++) {\n        if (timer.sec() > 1.93) break;\n\n        auto np = applyCornerCut(base, cands[idx]);\n        if (np.empty()) continue;\n        if (!validPolygon(np)) continue;\n\n        int diff = exactDiffPolygon(np);\n        if (diff > bestDiff) {\n            bestDiff = diff;\n            bestPoly = std::move(np);\n        }\n    }\n\n    if (!bestPoly.empty()) {\n        updateBest(bestPoly, bestDiff);\n        return true;\n    }\n\n    return false;\n}\n\nvoid tryCornerCutRefine() {\n    if (timer.sec() > 1.84) return;\n\n    for (int iter = 0; iter < 2; iter++) {\n        if (timer.sec() > 1.88) break;\n\n        int limit = (iter == 0 ? 75 : 38);\n        bool improved = tryOneCornerCutIteration(limit);\n\n        if (!improved) break;\n\n        if (timer.sec() < 1.89) tryEdgeShiftRefine(120, 1);\n    }\n}\n\nvoid tryRemoveRectDetours() {\n    if (bestAns.poly.empty()) return;\n    if (timer.sec() > 1.88) return;\n\n    for (int iter = 0; iter < 3; iter++) {\n        if (timer.sec() > 1.93) break;\n\n        vector<pair<int,int>> base = bestAns.poly;\n        int m = (int)base.size();\n        if (m <= 8) break;\n        if (!validPolygon(base)) break;\n\n        bool improved = false;\n\n        for (int i = 0; i < m; i++) {\n            if (timer.sec() > 1.93) break;\n\n            int j = (i + 5) % m;\n            if (!(base[i].first == base[j].first || base[i].second == base[j].second)) continue;\n\n            vector<char> skip(m, 0);\n            for (int k = 1; k <= 4; k++) skip[(i + k) % m] = 1;\n\n            vector<pair<int,int>> np;\n            np.reserve(m - 4);\n            for (int k = 0; k < m; k++) {\n                if (!skip[k]) np.push_back(base[k]);\n            }\n\n            if ((int)np.size() < 4) continue;\n            if (!validPolygon(np)) continue;\n\n            int diff = exactDiffPolygon(np);\n            if (diff > bestAns.diff) {\n                updateBest(np, diff);\n                improved = true;\n                break;\n            }\n        }\n\n        if (!improved) break;\n    }\n}\n\nvoid tryRemoveCornerDetours() {\n    if (bestAns.poly.empty()) return;\n    if (timer.sec() > 1.90) return;\n\n    for (int iter = 0; iter < 2; iter++) {\n        if (timer.sec() > 1.93) break;\n\n        vector<pair<int,int>> base = bestAns.poly;\n        int m = (int)base.size();\n        if (m <= 6) break;\n        if (!validPolygon(base)) break;\n\n        bool improved = false;\n\n        for (int i = 1; i + 3 < m; i++) {\n            if (timer.sec() > 1.93) break;\n\n            auto P = base[i - 1];\n            auto R1 = base[i];\n            auto Q = base[i + 1];\n            auto R2 = base[i + 2];\n            auto Nxt = base[i + 3];\n\n            pair<int,int> B;\n            bool ok = false;\n\n            if (P.first == R1.first && R2.second == Nxt.second) {\n                B = {P.first, R2.second};\n                ok = true;\n            } else if (P.second == R1.second && R2.first == Nxt.first) {\n                B = {R2.first, P.second};\n                ok = true;\n            }\n\n            if (!ok) continue;\n            if (B == P || B == Nxt || B == R1 || B == Q || B == R2) continue;\n            if (B.first < 0 || B.first > LIM || B.second < 0 || B.second > LIM) continue;\n\n            vector<pair<int,int>> np;\n            np.reserve(m - 2);\n\n            for (int k = 0; k < m; k++) {\n                if (k == i) {\n                    np.push_back(B);\n                    k += 2;\n                } else {\n                    np.push_back(base[k]);\n                }\n            }\n\n            if ((int)np.size() < 4) continue;\n            if (!validPolygon(np)) continue;\n\n            int diff = exactDiffPolygon(np);\n            if (diff > bestAns.diff) {\n                updateBest(np, diff);\n                improved = true;\n                break;\n            }\n        }\n\n        if (!improved) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    fishes.reserve(2 * N);\n\n    for (int i = 0; i < 2 * N; i++) {\n        int x, y;\n        cin >> x >> y;\n        int w = (i < N ? 1 : -1);\n        fishes.push_back({x,y,w});\n    }\n\n    tryTinyBaseline();\n\n    vector<int> Ls = {500, 1000, 2000, 2500, 4000, 5000};\n    for (int L : Ls) processGrid(L);\n\n    tryEdgeShiftRefine(120, 2);\n    tryEdgeShiftRefine(240, 1);\n\n    tryNotchRefineIterative();\n    tryCornerCutRefine();\n\n    if (timer.sec() < 1.86) {\n        tryOneNotchIteration(35);\n    }\n\n    tryEdgeShiftRefine(120, 1);\n\n    if (timer.sec() < 1.88) tryEdgeShiftRefine(520, 1);\n    if (timer.sec() < 1.89) tryEdgeShiftRefine(1000, 1);\n    if (timer.sec() < 1.89) tryEdgeShiftRefine(2000, 1);\n\n    tryRemoveRectDetours();\n    tryRemoveCornerDetours();\n\n    if (timer.sec() < 1.90) tryEdgeShiftRefine(520, 1);\n    if (timer.sec() < 1.91) tryEdgeShiftRefine(120, 1);\n\n    // New extra-wide final polishing. Exact-score accepted only.\n    if (timer.sec() < 1.90) tryEdgeShiftRefine(4000, 1);\n    if (timer.sec() < 1.90) tryEdgeShiftRefine(8000, 1);\n    if (timer.sec() < 1.91) tryEdgeShiftRefine(120, 1);\n\n    if (bestAns.poly.empty()) {\n        cout << 4 << '\\n';\n        cout << \"0 0\\n1 0\\n1 1\\n0 1\\n\";\n        return 0;\n    }\n\n    cout << bestAns.poly.size() << '\\n';\n    for (auto [x,y] : bestAns.poly) {\n        x = max(0, min(LIM, x));\n        y = max(0, min(LIM, y));\n        cout << x << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF = (1LL << 60);\n\nstruct Op {\n    int p, r;\n    char d;\n    int b;\n};\n\nstruct Sol {\n    vector<Op> ops;\n    ll score;\n};\n\nstatic inline bool ov(ll l1, ll r1, ll l2, ll r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstruct Solver {\n    int N, T;\n    ll sigma;\n    vector<ll> w, h, rawW, rawH, obsW, obsH, adjW, adjH;\n    vector<Sol> sols;\n    unordered_set<string> seen;\n    mt19937 rng{1234567};\n    chrono::steady_clock::time_point st;\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    pair<ll,ll> simulateWith(const vector<Op>& ops, const vector<ll>& W0, const vector<ll>& H0) const {\n        vector<ll> X(N), Y(N), W(N), H(N);\n        vector<char> used(N, 0);\n        ll BW = 0, BH = 0;\n\n        for (auto &op : ops) {\n            int p = op.p;\n            ll rw = op.r ? H0[p] : W0[p];\n            ll rh = op.r ? W0[p] : H0[p];\n            ll x = 0, y = 0;\n\n            if (op.d == 'U') {\n                x = (op.b == -1 ? 0 : X[op.b] + W[op.b]);\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (ov(x, x + rw, X[j], X[j] + W[j])) {\n                        y = max(y, Y[j] + H[j]);\n                    }\n                }\n            } else {\n                y = (op.b == -1 ? 0 : Y[op.b] + H[op.b]);\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (ov(y, y + rh, Y[j], Y[j] + H[j])) {\n                        x = max(x, X[j] + W[j]);\n                    }\n                }\n            }\n\n            X[p] = x;\n            Y[p] = y;\n            W[p] = rw;\n            H[p] = rh;\n            used[p] = 1;\n            BW = max(BW, x + rw);\n            BH = max(BH, y + rh);\n        }\n\n        return {BW, BH};\n    }\n\n    pair<ll,ll> simulate(const vector<Op>& ops) const {\n        return simulateWith(ops, w, h);\n    }\n\n    pair<ll,ll> scoreParts(const vector<Op>& ops) const {\n        auto [a, b] = simulateWith(ops, obsW, obsH);\n        auto [c, d] = simulateWith(ops, rawW, rawH);\n        return {a + b, c + d};\n    }\n\n    ll mixedScore(const vector<Op>& ops) const {\n        auto [a, b] = scoreParts(ops);\n        return (3 * a + b) / 4;\n    }\n\n    string keyOf(const vector<Op>& ops) const {\n        string s;\n        s.reserve(ops.size() * 3);\n        for (auto &op : ops) {\n            s.push_back(char(op.r));\n            s.push_back(op.d);\n            s.push_back(char(op.b + 1));\n        }\n        return s;\n    }\n\n    void addSol(const vector<Op>& ops) {\n        if ((int)ops.size() != N) return;\n        string k = keyOf(ops);\n        if (seen.count(k)) return;\n        seen.insert(k);\n        auto [a, b] = simulate(ops);\n        sols.push_back({ops, a + b});\n    }\n\n    void addSolScored(const vector<Op>& ops, ll sc) {\n        if ((int)ops.size() != N) return;\n        string k = keyOf(ops);\n        if (seen.count(k)) return;\n        seen.insert(k);\n        sols.push_back({ops, sc});\n    }\n\n    void outputOps(const vector<Op>& ops) {\n        cout << ops.size() << '\\n';\n        for (auto &op : ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n    }\n\n    vector<Op> blockRow(int l, int r, int rot) {\n        vector<Op> ops;\n        for (int i = l; i < r; i++) ops.push_back({i, rot, 'L', -1});\n        return ops;\n    }\n\n    vector<Op> blockCol(int l, int r, int rot) {\n        vector<Op> ops;\n        for (int i = l; i < r; i++) ops.push_back({i, rot, 'U', -1});\n        return ops;\n    }\n\n    int calibrate() {\n        int reserveTurns = max(20, N / 2);\n        int budget = T - reserveTurns;\n        int maxPairs = budget / 2;\n        int G = max(0, min(8, maxPairs));\n        if (G <= 0) return 0;\n\n        vector<int> L(G), R(G);\n        for (int g = 0; g < G; g++) {\n            L[g] = (ll)N * g / G;\n            R[g] = (ll)N * (g + 1) / G;\n        }\n\n        int extra = 0;\n        if (sigma >= 7000 && T >= 3 * N) {\n            int rem = budget - 2 * G;\n            if (rem >= 8) extra = min({4, G, rem / 2});\n        }\n\n        vector<double> dw(G), dh(G);\n        vector<int> cw(G), ch(G);\n        int used = 0;\n\n        for (int g = 0; g < G; g++) {\n            int l = L[g], r = R[g];\n            if (l >= r) continue;\n\n            {\n                auto ops = blockRow(l, r, 0);\n                outputOps(ops);\n                ll Wm, Hm;\n                if (!(cin >> Wm >> Hm)) exit(0);\n                used++;\n                ll s = 0;\n                for (int i = l; i < r; i++) s += rawW[i];\n                dw[g] += Wm - s;\n                cw[g]++;\n            }\n\n            {\n                auto ops = blockCol(l, r, 0);\n                outputOps(ops);\n                ll Wm, Hm;\n                if (!(cin >> Wm >> Hm)) exit(0);\n                used++;\n                ll s = 0;\n                for (int i = l; i < r; i++) s += rawH[i];\n                dh[g] += Hm - s;\n                ch[g]++;\n            }\n\n            if (g < extra) {\n                {\n                    auto ops = blockRow(l, r, 1);\n                    outputOps(ops);\n                    ll Wm, Hm;\n                    if (!(cin >> Wm >> Hm)) exit(0);\n                    used++;\n                    ll s = 0;\n                    for (int i = l; i < r; i++) s += rawH[i];\n                    dh[g] += Wm - s;\n                    ch[g]++;\n                }\n                {\n                    auto ops = blockCol(l, r, 1);\n                    outputOps(ops);\n                    ll Wm, Hm;\n                    if (!(cin >> Wm >> Hm)) exit(0);\n                    used++;\n                    ll s = 0;\n                    for (int i = l; i < r; i++) s += rawW[i];\n                    dw[g] += Hm - s;\n                    cw[g]++;\n                }\n            }\n        }\n\n        w = rawW;\n        h = rawH;\n\n        for (int g = 0; g < G; g++) {\n            int l = L[g], r = R[g], k = r - l;\n            if (k <= 0) continue;\n\n            if (cw[g]) {\n                double d = dw[g] / (1.0 + (double)cw[g] * k);\n                for (int i = l; i < r; i++) w[i] = max(1LL, (ll)llround(rawW[i] + d));\n            }\n            if (ch[g]) {\n                double d = dh[g] / (1.0 + (double)ch[g] * k);\n                for (int i = l; i < r; i++) h[i] = max(1LL, (ll)llround(rawH[i] + d));\n            }\n        }\n\n        return used;\n    }\n\n    struct Seg {\n        bool ok = false;\n        ll bound = 0;\n        ll extent = 0;\n        vector<int> rot;\n    };\n\n    Seg calcSeg(int l, int r, ll limit, bool row, bool needRot) const {\n        vector<ll> cand;\n        cand.reserve(2 * (r - l));\n        for (int i = l; i < r; i++) {\n            cand.push_back(w[i]);\n            cand.push_back(h[i]);\n        }\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n        for (ll B : cand) {\n            ll sum = 0;\n            bool ok = true;\n            vector<int> rots;\n            if (needRot) rots.reserve(r - l);\n\n            for (int i = l; i < r; i++) {\n                ll best = INF;\n                int br = -1;\n\n                if (row) {\n                    if (h[i] <= B) best = w[i], br = 0;\n                    if (w[i] <= B && h[i] < best) best = h[i], br = 1;\n                } else {\n                    if (w[i] <= B) best = h[i], br = 0;\n                    if (h[i] <= B && w[i] < best) best = w[i], br = 1;\n                }\n\n                if (br == -1) {\n                    ok = false;\n                    break;\n                }\n                sum += best;\n                if (sum > limit) {\n                    ok = false;\n                    break;\n                }\n                if (needRot) rots.push_back(br);\n            }\n\n            if (ok) {\n                Seg s;\n                s.ok = true;\n                s.bound = B;\n                s.extent = sum;\n                if (needRot) s.rot = move(rots);\n                return s;\n            }\n        }\n\n        return {};\n    }\n\n    void buildFromPrev(const vector<int>& prv, bool row, ll reconLimit) {\n        if (prv[N] == -1) return;\n\n        vector<pair<int,int>> parts;\n        for (int cur = N; cur > 0; cur = prv[cur]) parts.push_back({prv[cur], cur});\n        reverse(parts.begin(), parts.end());\n\n        vector<int> rot(N, 0);\n        for (auto [l, r] : parts) {\n            Seg s = calcSeg(l, r, reconLimit, row, true);\n            if (!s.ok) return;\n            for (int i = l; i < r; i++) rot[i] = s.rot[i - l];\n        }\n\n        vector<Op> ops;\n        ops.reserve(N);\n        int prevAnchor = -1;\n\n        for (int pi = 0; pi < (int)parts.size(); pi++) {\n            auto [l, r] = parts[pi];\n            int b = (pi == 0 ? -1 : prevAnchor);\n\n            for (int i = l; i < r; i++) {\n                ops.push_back({i, rot[i], row ? 'L' : 'U', b});\n            }\n\n            ll best = -1;\n            int anchor = l;\n            for (int i = l; i < r; i++) {\n                ll val;\n                if (row) val = rot[i] ? w[i] : h[i];\n                else val = rot[i] ? h[i] : w[i];\n\n                if (val > best) {\n                    best = val;\n                    anchor = i;\n                }\n            }\n            prevAnchor = anchor;\n        }\n\n        addSol(ops);\n    }\n\n    void shelf(bool row, ll limit) {\n        vector<vector<ll>> bd(N, vector<ll>(N + 1, INF));\n        vector<vector<ll>> ex(N, vector<ll>(N + 1, INF));\n\n        for (int l = 0; l < N; l++) {\n            for (int r = l + 1; r <= N; r++) {\n                Seg s = calcSeg(l, r, limit, row, false);\n                if (s.ok) {\n                    bd[l][r] = s.bound;\n                    ex[l][r] = s.extent;\n                }\n            }\n        }\n\n        for (int mode = 0; mode < 2; mode++) {\n            vector<ll> dpSum(N + 1, INF), dpMax(N + 1, INF);\n            vector<int> prv(N + 1, -1);\n            dpSum[0] = dpMax[0] = 0;\n\n            for (int i = 1; i <= N; i++) {\n                for (int l = 0; l < i; l++) {\n                    if (dpSum[l] == INF || bd[l][i] == INF) continue;\n\n                    ll ns = dpSum[l] + bd[l][i];\n                    ll nm = max(dpMax[l], ex[l][i]);\n\n                    bool upd = false;\n                    if (mode == 0) {\n                        upd = (ns < dpSum[i] || (ns == dpSum[i] && nm < dpMax[i]));\n                    } else {\n                        ll oldCost = dpSum[i] == INF ? INF : dpSum[i] + dpMax[i];\n                        ll newCost = ns + nm;\n                        upd = (newCost < oldCost || (newCost == oldCost && ns < dpSum[i]));\n                    }\n\n                    if (upd) {\n                        dpSum[i] = ns;\n                        dpMax[i] = nm;\n                        prv[i] = l;\n                    }\n                }\n            }\n\n            buildFromPrev(prv, row, limit);\n            buildFromPrev(prv, row, INF);\n        }\n    }\n\n    void simple() {\n        for (int pol = 0; pol < 4; pol++) {\n            vector<Op> ops;\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (pol == 1) r = 1;\n                else if (pol == 2) r = h[i] < w[i];\n                else if (pol == 3) r = w[i] < h[i];\n                ops.push_back({i, r, 'L', -1});\n            }\n            addSol(ops);\n        }\n\n        for (int pol = 0; pol < 4; pol++) {\n            vector<Op> ops;\n            for (int i = 0; i < N; i++) {\n                int r = 0;\n                if (pol == 1) r = 1;\n                else if (pol == 2) r = h[i] < w[i];\n                else if (pol == 3) r = w[i] < h[i];\n                ops.push_back({i, r, 'U', -1});\n            }\n            addSol(ops);\n        }\n    }\n\n    void greedy(double wp, double wa, double wb, double noiseCoef) {\n        vector<Op> ops;\n        ops.reserve(N);\n\n        vector<ll> X(N), Y(N), RW(N), RH(N);\n        vector<char> used(N, 0);\n        ll curW = 0, curH = 0;\n\n        long double area = 0;\n        for (int i = 0; i < N; i++) area += (long double)w[i] * h[i];\n        double scale = max(1.0, sqrt((double)area));\n\n        uniform_real_distribution<double> ud(0.0, 1.0);\n\n        for (int i = 0; i < N; i++) {\n            double best = 1e100;\n            Op bestOp{i, 0, 'L', -1};\n            ll bx = 0, by = 0, brw = w[i], brh = h[i], bBW = 0, bBH = 0;\n\n            for (int r = 0; r < 2; r++) {\n                ll rw = r ? h[i] : w[i];\n                ll rh = r ? w[i] : h[i];\n\n                for (int dd = 0; dd < 2; dd++) {\n                    char d = dd ? 'L' : 'U';\n\n                    for (int b = -1; b < i; b++) {\n                        ll x = 0, y = 0;\n\n                        if (d == 'U') {\n                            x = (b == -1 ? 0 : X[b] + RW[b]);\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (ov(x, x + rw, X[j], X[j] + RW[j])) {\n                                    y = max(y, Y[j] + RH[j]);\n                                }\n                            }\n                        } else {\n                            y = (b == -1 ? 0 : Y[b] + RH[b]);\n                            for (int j = 0; j < i; j++) if (used[j]) {\n                                if (ov(y, y + rh, Y[j], Y[j] + RH[j])) {\n                                    x = max(x, X[j] + RW[j]);\n                                }\n                            }\n                        }\n\n                        ll BW = max(curW, x + rw);\n                        ll BH = max(curH, y + rh);\n\n                        double cost = 0;\n                        cost += wp * (double)(BW + BH);\n                        cost += wa * ((double)BW * (double)BH / scale);\n                        cost += wb * (double)llabs(BW - BH);\n                        cost += noiseCoef * scale * ud(rng);\n                        cost += 0.0001 * (double)(x + y);\n\n                        if (cost < best) {\n                            best = cost;\n                            bestOp = {i, r, d, b};\n                            bx = x;\n                            by = y;\n                            brw = rw;\n                            brh = rh;\n                            bBW = BW;\n                            bBH = BH;\n                        }\n                    }\n                }\n            }\n\n            ops.push_back(bestOp);\n            X[i] = bx;\n            Y[i] = by;\n            RW[i] = brw;\n            RH[i] = brh;\n            used[i] = 1;\n            curW = bBW;\n            curH = bBH;\n        }\n\n        addSol(ops);\n    }\n\n    vector<ll> limits(int cnt, double lo, double hi) {\n        long double area = 0;\n        ll minSide = 1;\n\n        for (int i = 0; i < N; i++) {\n            area += (long double)w[i] * h[i];\n            minSide = max(minSide, min(w[i], h[i]));\n        }\n\n        double s = sqrt((double)area);\n        vector<ll> res;\n\n        for (int k = 0; k < cnt; k++) {\n            double f = lo + (hi - lo) * k / max(1, cnt - 1);\n            res.push_back(max<ll>(minSide, llround(s * f)));\n        }\n\n        sort(res.begin(), res.end());\n        res.erase(unique(res.begin(), res.end()), res.end());\n        return res;\n    }\n\n    void makeAdjusted() {\n        vector<ll> vals;\n        for (int i = 0; i < N; i++) {\n            vals.push_back(obsW[i]);\n            vals.push_back(obsH[i]);\n        }\n        sort(vals.begin(), vals.end());\n\n        int m = vals.size();\n        double q10 = vals[max(0, min(m - 1, m / 10))];\n\n        double Lhat = (q10 - 10000.0) / 0.9;\n        Lhat = min(50000.0, max(10000.0, Lhat));\n\n        double mean = (Lhat + 100000.0) * 0.5;\n        double var = (100000.0 - Lhat) * (100000.0 - Lhat) / 12.0;\n        double a = var / (var + (double)sigma * sigma);\n\n        a = 1.0 - 1.15 * (1.0 - a);\n        a = min(1.0, max(0.55, a));\n\n        adjW.resize(N);\n        adjH.resize(N);\n\n        for (int i = 0; i < N; i++) {\n            adjW[i] = max(1LL, (ll)llround(a * obsW[i] + (1.0 - a) * mean));\n            adjH[i] = max(1LL, (ll)llround(a * obsH[i] + (1.0 - a) * mean));\n        }\n    }\n\n    void genSet(const vector<ll>& W, const vector<ll>& H,\n                int shelfCnt, double lo, double hi,\n                double timeLimit, int greedyLimit) {\n        w = W;\n        h = H;\n\n        simple();\n\n        auto ls = limits(shelfCnt, lo, hi);\n        for (ll L : ls) {\n            if (elapsed() > timeLimit) break;\n            shelf(true, L);\n            shelf(false, L);\n        }\n\n        uniform_real_distribution<double> ud(0.0, 1.0);\n        int trials = 0;\n\n        while (elapsed() < timeLimit && trials < greedyLimit) {\n            trials++;\n\n            double wp = 1.0;\n            double wa = pow(10.0, -0.45 + 1.35 * ud(rng));\n            double wb = 0.03 + 1.50 * ud(rng);\n            double nz = 0.0;\n\n            if (trials % 3 == 0) nz = 0.01 * ud(rng);\n            if (trials % 7 == 0) nz = 0.05 * ud(rng);\n            if (trials % 19 == 0) nz = 0.10 * ud(rng);\n\n            greedy(wp, wa, wb, nz);\n        }\n    }\n\n    void recompute() {\n        for (auto &s : sols) s.score = mixedScore(s.ops);\n    }\n\n    void improveRot() {\n        recompute();\n        sort(sols.begin(), sols.end(), [](const Sol& a, const Sol& b) {\n            return a.score < b.score;\n        });\n\n        int K = min<int>(45, sols.size());\n        vector<Sol> base(sols.begin(), sols.begin() + K);\n\n        for (int idx = 0; idx < K; idx++) {\n            if (elapsed() > 2.78) break;\n\n            vector<Op> ops = base[idx].ops;\n            ll cur = mixedScore(ops);\n            bool changed = false;\n\n            for (int i = 0; i < N; i++) {\n                if (elapsed() > 2.78) break;\n\n                ops[i].r ^= 1;\n                ll ns = mixedScore(ops);\n\n                if (ns < cur) {\n                    cur = ns;\n                    changed = true;\n                } else {\n                    ops[i].r ^= 1;\n                }\n            }\n\n            if (changed) addSolScored(ops, cur);\n        }\n    }\n\n    void improveDeterministic() {\n        recompute();\n        sort(sols.begin(), sols.end(), [](const Sol& a, const Sol& b) {\n            return a.score < b.score;\n        });\n\n        int K = min<int>(18, sols.size());\n        vector<Sol> base(sols.begin(), sols.begin() + K);\n\n        for (int idx = 0; idx < K; idx++) {\n            if (elapsed() > 2.84) break;\n\n            vector<Op> ops = base[idx].ops;\n            ll cur = mixedScore(ops);\n            bool changed = false;\n\n            for (int i = 0; i < N; i++) {\n                if (elapsed() > 2.84) break;\n\n                Op old = ops[i];\n                vector<Op> cand;\n\n                auto addCand = [&](int r, char d, int b) {\n                    if (b < -1 || b >= i) return;\n                    cand.push_back({i, r, d, b});\n                };\n\n                addCand(old.r ^ 1, old.d, old.b);\n                addCand(old.r, old.d == 'U' ? 'L' : 'U', old.b);\n                addCand(old.r, old.d, -1);\n                addCand(old.r, old.d, i - 1);\n                addCand(old.r, 'U', -1);\n                addCand(old.r, 'L', -1);\n                addCand(old.r, 'U', i - 1);\n                addCand(old.r, 'L', i - 1);\n                addCand(old.r ^ 1, 'U', -1);\n                addCand(old.r ^ 1, 'L', -1);\n\n                Op bestOp = old;\n                ll best = cur;\n\n                for (auto &c : cand) {\n                    ops[i] = c;\n                    ll ns = mixedScore(ops);\n                    if (ns < best) {\n                        best = ns;\n                        bestOp = c;\n                    }\n                }\n\n                ops[i] = bestOp;\n                if (best < cur) {\n                    cur = best;\n                    changed = true;\n                }\n            }\n\n            if (changed) addSolScored(ops, cur);\n        }\n    }\n\n    void improveRandom() {\n        recompute();\n        sort(sols.begin(), sols.end(), [](const Sol& a, const Sol& b) {\n            return a.score < b.score;\n        });\n\n        int K = min<int>(28, sols.size());\n        vector<Sol> base(sols.begin(), sols.begin() + K);\n        uniform_int_distribution<int> coin(0, 99);\n\n        for (int idx = 0; idx < K; idx++) {\n            if (elapsed() > 2.87) break;\n\n            vector<Op> ops = base[idx].ops;\n            auto [curC, curR] = scoreParts(ops);\n            ll curMix = (3 * curC + curR) / 4;\n            ll curRob = max(curC, curR);\n            bool changed = false;\n\n            for (int tr = 0; tr < 90 && elapsed() < 2.87; tr++) {\n                int i = uniform_int_distribution<int>(0, N - 1)(rng);\n                Op old = ops[i];\n\n                int t = coin(rng);\n                if (t < 35) {\n                    ops[i].r ^= 1;\n                } else if (t < 60) {\n                    ops[i].d = (ops[i].d == 'U' ? 'L' : 'U');\n                } else {\n                    ops[i].b = uniform_int_distribution<int>(-1, i - 1)(rng);\n                }\n\n                auto [nc, nr] = scoreParts(ops);\n                ll nmix = (3 * nc + nr) / 4;\n                ll nrob = max(nc, nr);\n\n                bool ok = false;\n                if (nmix < curMix && nrob <= curRob + 2500) ok = true;\n                if (nmix + 1200 < curMix) ok = true;\n\n                if (ok) {\n                    curC = nc;\n                    curR = nr;\n                    curMix = nmix;\n                    curRob = nrob;\n                    changed = true;\n                } else {\n                    ops[i] = old;\n                }\n            }\n\n            if (changed) addSolScored(ops, curMix);\n        }\n    }\n\n    void diversifyFinalOrder() {\n        recompute();\n\n        sort(sols.begin(), sols.end(), [](const Sol& a, const Sol& b) {\n            return a.score < b.score;\n        });\n\n        int M = sols.size();\n        int L = min(M, 250);\n\n        vector<ll> cal(L), raw(L), rob(L);\n        for (int i = 0; i < L; i++) {\n            auto [c, r] = scoreParts(sols[i].ops);\n            cal[i] = c;\n            raw[i] = r;\n            rob[i] = max(c, r);\n        }\n\n        vector<int> byCal(L), byRaw(L), byRob(L);\n        iota(byCal.begin(), byCal.end(), 0);\n        byRaw = byCal;\n        byRob = byCal;\n\n        sort(byCal.begin(), byCal.end(), [&](int a, int b) {\n            return cal[a] < cal[b];\n        });\n        sort(byRaw.begin(), byRaw.end(), [&](int a, int b) {\n            return raw[a] < raw[b];\n        });\n        sort(byRob.begin(), byRob.end(), [&](int a, int b) {\n            return rob[a] < rob[b];\n        });\n\n        vector<Sol> ns;\n        ns.reserve(M);\n        vector<char> used(L, 0);\n\n        auto take = [&](int id) {\n            if (id < 0 || id >= L || used[id]) return;\n            used[id] = 1;\n            ns.push_back(sols[id]);\n        };\n\n        // Preserve the strongest mixed-score prefix.\n        int keepPrefix = min(20, L);\n        for (int i = 0; i < keepPrefix; i++) take(i);\n\n        // Then diversify among different plausible rankings.\n        for (int k = 0; k < L; k++) {\n            take(byCal[k]);\n            take(byRaw[k]);\n            take(byRob[k]);\n            take(k);\n        }\n\n        for (int i = 0; i < L; i++) take(i);\n        for (int i = L; i < M; i++) ns.push_back(sols[i]);\n\n        sols.swap(ns);\n    }\n\n    void generateAll() {\n        st = chrono::steady_clock::now();\n\n        obsW = w;\n        obsH = h;\n        makeAdjusted();\n\n        genSet(obsW, obsH, 52, 0.50, 2.65, 2.26, 610);\n\n        if (elapsed() < 2.46) {\n            genSet(rawW, rawH, 22, 0.55, 2.45, 2.46, 110);\n        }\n\n        if (elapsed() < 2.60) {\n            genSet(adjW, adjH, 16, 0.55, 2.45, 2.60, 60);\n        }\n\n        if (sols.empty()) {\n            w = obsW;\n            h = obsH;\n            vector<Op> ops;\n            for (int i = 0; i < N; i++) ops.push_back({i, 0, 'L', -1});\n            addSol(ops);\n        }\n\n        improveRot();\n        improveDeterministic();\n        improveRandom();\n\n        diversifyFinalOrder();\n    }\n\n    void run() {\n        cin >> N >> T >> sigma;\n\n        w.resize(N);\n        h.resize(N);\n\n        for (int i = 0; i < N; i++) cin >> w[i] >> h[i];\n\n        rawW = w;\n        rawH = h;\n\n        int used = calibrate();\n\n        generateAll();\n\n        for (int t = used; t < T; t++) {\n            const auto &ops = sols[(t - used) % sols.size()].ops;\n            outputOps(ops);\n\n            ll Wm, Hm;\n            if (!(cin >> Wm >> Hm)) return;\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.run();\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 10;\nstatic constexpr int MAXN = 1000;\nstatic constexpr long long NEG = -(1LL << 60);\n\nstruct Edge {\n    int u, v;\n    long long len2;\n};\n\nstruct Solver {\n    int N, M, HH;\n    vector<int> A, xs, ys;\n    vector<Edge> edges;\n    vector<vector<int>> adj;\n    vector<bitset<MAXN>> con;\n\n    mt19937 rng{1234567};\n    chrono::steady_clock::time_point st;\n\n    vector<array<long long, 11>> dp_no, dp_need;\n    vector<vector<int>> children;\n    vector<int> orderHigh, orderLow;\n\n    struct PathState {\n        array<int, 11> node;\n        int len;\n        long long delta;\n    };\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    long long scoreLabels(const vector<int>& d) const {\n        long long s = 0;\n        for (int i = 0; i < N; i++) s += 1LL * (d[i] + 1) * A[i];\n        return s;\n    }\n\n    long long keyPrim(int mode, int from, int to) {\n        long long noise = rng() % 100000;\n        long long dx = xs[from] - xs[to], dy = ys[from] - ys[to];\n        long long len2 = dx * dx + dy * dy;\n\n        if (mode == 0) return 1LL * A[to] * 100000 + noise;\n        if (mode == 1) return 1LL * (101 - A[to]) * 100000 + noise;\n        if (mode == 2) return (long long)(rng() & 0x7fffffff);\n        if (mode == 3) return len2 * 1000 + noise;\n        if (mode == 4) return (2000000LL - min(len2, 2000000LL)) * 1000 + noise;\n        return 1LL * A[to] * 50000 + len2 + noise;\n    }\n\n    vector<int> makePrimTree(int mode) {\n        vector<int> par(N, -2), used(N, 0);\n\n        int start;\n        if (mode == 0 || mode == 5) start = min_element(A.begin(), A.end()) - A.begin();\n        else if (mode == 1) start = max_element(A.begin(), A.end()) - A.begin();\n        else start = rng() % N;\n\n        using T = tuple<long long, int, int>;\n        priority_queue<T, vector<T>, greater<T>> pq;\n\n        used[start] = 1;\n        par[start] = -1;\n        int cnt = 1;\n\n        for (int to : adj[start]) pq.emplace(keyPrim(mode, start, to), start, to);\n\n        while (cnt < N && !pq.empty()) {\n            auto [key, from, v] = pq.top();\n            pq.pop();\n\n            if (used[v]) continue;\n\n            used[v] = 1;\n            par[v] = from;\n            cnt++;\n\n            for (int to : adj[v]) {\n                if (!used[to]) pq.emplace(keyPrim(mode, v, to), v, to);\n            }\n        }\n\n        return par;\n    }\n\n    vector<int> makeDFSTree(int mode) {\n        vector<vector<pair<long long, int>>> ord(N);\n\n        for (int v = 0; v < N; v++) {\n            for (int to : adj[v]) {\n                long long noise = rng() % 100000;\n                long long key;\n\n                if (mode == 0) key = 1LL * A[to] * 100000 + noise;\n                else if (mode == 1) key = 1LL * (101 - A[to]) * 100000 + noise;\n                else key = rng();\n\n                ord[v].push_back({key, to});\n            }\n            sort(ord[v].begin(), ord[v].end());\n        }\n\n        int start;\n        if (mode == 0) start = min_element(A.begin(), A.end()) - A.begin();\n        else if (mode == 1) start = max_element(A.begin(), A.end()) - A.begin();\n        else start = rng() % N;\n\n        vector<int> par(N, -2), used(N, 0), idx(N, 0), stk;\n        stk.push_back(start);\n        used[start] = 1;\n        par[start] = -1;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n\n            while (idx[v] < (int)ord[v].size() && used[ord[v][idx[v]].second]) idx[v]++;\n\n            if (idx[v] == (int)ord[v].size()) {\n                stk.pop_back();\n                continue;\n            }\n\n            int to = ord[v][idx[v]++].second;\n            used[to] = 1;\n            par[to] = v;\n            stk.push_back(to);\n        }\n\n        return par;\n    }\n\n    long long childVal(int c, int childLabel, int parentLabel) const {\n        if (childLabel == 0 || parentLabel == childLabel - 1) return dp_no[c][childLabel];\n        return dp_need[c][childLabel];\n    }\n\n    vector<int> solveOnTree(const vector<int>& treePar) {\n        vector<vector<int>> tadj(N);\n\n        for (int v = 0; v < N; v++) {\n            if (treePar[v] >= 0) {\n                tadj[v].push_back(treePar[v]);\n                tadj[treePar[v]].push_back(v);\n            }\n        }\n\n        children.assign(N, {});\n        vector<int> parent(N, -1), order;\n        order.reserve(N);\n\n        vector<int> stk = {0};\n        parent[0] = -2;\n\n        while (!stk.empty()) {\n            int v = stk.back();\n            stk.pop_back();\n            order.push_back(v);\n\n            for (int to : tadj[v]) {\n                if (to == parent[v]) continue;\n                parent[to] = v;\n                children[v].push_back(to);\n                stk.push_back(to);\n            }\n        }\n\n        dp_no.assign(N, {});\n        dp_need.assign(N, {});\n\n        for (int ii = N - 1; ii >= 0; ii--) {\n            int v = order[ii];\n\n            for (int l = 0; l <= H; l++) {\n                long long base = 1LL * (l + 1) * A[v];\n                long long sum = base;\n                bool ok = true;\n\n                vector<long long> bestChild;\n                bestChild.reserve(children[v].size());\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n\n                    for (int lc = 0; lc <= H; lc++) {\n                        best = max(best, childVal(c, lc, l));\n                    }\n\n                    if (best <= NEG / 2) ok = false;\n\n                    sum += best;\n                    bestChild.push_back(best);\n                }\n\n                dp_no[v][l] = ok ? sum : NEG;\n\n                if (l == 0 || !ok) {\n                    dp_need[v][l] = NEG;\n                } else {\n                    int forcedLabel = l - 1;\n                    long long bestDelta = NEG;\n\n                    for (int idx = 0; idx < (int)children[v].size(); idx++) {\n                        int c = children[v][idx];\n                        long long fv = childVal(c, forcedLabel, l);\n\n                        if (fv <= NEG / 2) continue;\n\n                        bestDelta = max(bestDelta, fv - bestChild[idx]);\n                    }\n\n                    dp_need[v][l] = (bestDelta <= NEG / 2 ? NEG : sum + bestDelta);\n                }\n            }\n        }\n\n        int rootLabel = 0;\n        bool rootNeed = false;\n        long long bestRoot = dp_no[0][0];\n\n        for (int l = 1; l <= H; l++) {\n            if (dp_need[0][l] > bestRoot) {\n                bestRoot = dp_need[0][l];\n                rootLabel = l;\n                rootNeed = true;\n            }\n        }\n\n        vector<int> label(N, 0);\n\n        function<void(int, int, bool)> rec = [&](int v, int l, bool needSupportChild) {\n            label[v] = l;\n\n            int forcedChild = -1;\n\n            if (needSupportChild) {\n                int forcedLabel = l - 1;\n                long long bestDelta = NEG;\n\n                for (int c : children[v]) {\n                    long long best = NEG;\n\n                    for (int lc = 0; lc <= H; lc++) {\n                        best = max(best, childVal(c, lc, l));\n                    }\n\n                    long long fv = childVal(c, forcedLabel, l);\n\n                    if (fv <= NEG / 2) continue;\n\n                    long long delta = fv - best;\n\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        forcedChild = c;\n                    }\n                }\n            }\n\n            for (int c : children[v]) {\n                int lcBest = 0;\n                long long valBest = NEG;\n\n                if (c == forcedChild) {\n                    lcBest = l - 1;\n                } else {\n                    for (int lc = 0; lc <= H; lc++) {\n                        long long val = childVal(c, lc, l);\n\n                        if (val > valBest) {\n                            valBest = val;\n                            lcBest = lc;\n                        }\n                    }\n                }\n\n                bool childNeed = !(lcBest == 0 || l == lcBest - 1);\n                rec(c, lcBest, childNeed);\n            }\n        };\n\n        rec(0, rootLabel, rootNeed);\n        return label;\n    }\n\n    vector<int> calcCnt(const vector<int>& d) const {\n        vector<int> cnt(N, 0);\n\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) continue;\n\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) cnt[v]++;\n            }\n        }\n\n        return cnt;\n    }\n\n    bool canMove(const vector<int>& d, const vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n\n        if (old == nl) return false;\n\n        if (nl > 0) {\n            bool has = false;\n\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) {\n                    has = true;\n                    break;\n                }\n            }\n\n            if (!has) return false;\n        }\n\n        for (int to : adj[v]) {\n            if (d[to] > 0 && d[to] - 1 == old && cnt[to] == 1) return false;\n        }\n\n        return true;\n    }\n\n    bool canMoveExcept(\n        const vector<int>& d,\n        const vector<int>& cnt,\n        int v,\n        int nl,\n        int exceptVertex,\n        int exceptFinalDepth\n    ) const {\n        int old = d[v];\n\n        if (old == nl) return false;\n\n        if (nl > 0) {\n            bool has = false;\n\n            for (int to : adj[v]) {\n                int td = (to == exceptVertex ? exceptFinalDepth : d[to]);\n\n                if (td == nl - 1) {\n                    has = true;\n                    break;\n                }\n            }\n\n            if (!has) return false;\n        }\n\n        for (int to : adj[v]) {\n            if (to == exceptVertex) continue;\n\n            if (d[to] > 0 && d[to] - 1 == old && cnt[to] == 1) return false;\n        }\n\n        return true;\n    }\n\n    void applyMove(vector<int>& d, vector<int>& cnt, int v, int nl) const {\n        int old = d[v];\n\n        for (int to : adj[v]) {\n            if (d[to] > 0) {\n                if (old == d[to] - 1) cnt[to]--;\n                if (nl == d[to] - 1) cnt[to]++;\n            }\n        }\n\n        d[v] = nl;\n\n        if (nl == 0) {\n            cnt[v] = 0;\n        } else {\n            int c = 0;\n\n            for (int to : adj[v]) {\n                if (d[to] == nl - 1) c++;\n            }\n\n            cnt[v] = c;\n        }\n    }\n\n    bool checkFeasible(const vector<int>& d) const {\n        for (int v = 0; v < N; v++) {\n            if (d[v] < 0 || d[v] > H) return false;\n\n            if (d[v] == 0) continue;\n\n            bool ok = false;\n\n            for (int to : adj[v]) {\n                if (d[to] == d[v] - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return false;\n        }\n\n        return true;\n    }\n\n    int depthAfterMoveSet(const vector<int>& d, const vector<pair<int, int>>& mv, int x) const {\n        for (auto [v, nd] : mv) {\n            if (v == x) return nd;\n        }\n        return d[x];\n    }\n\n    bool validateMoveSet(const vector<int>& d, const vector<pair<int, int>>& mv) const {\n        vector<int> affected;\n        vector<char> mark(N, 0);\n\n        auto add = [&](int x) {\n            if (!mark[x]) {\n                mark[x] = 1;\n                affected.push_back(x);\n            }\n        };\n\n        for (auto [v, nd] : mv) {\n            if (nd < 0 || nd > H) return false;\n\n            add(v);\n\n            for (int to : adj[v]) add(to);\n        }\n\n        for (int x : affected) {\n            int dx = depthAfterMoveSet(d, mv, x);\n\n            if (dx == 0) continue;\n\n            bool ok = false;\n\n            for (int to : adj[x]) {\n                if (depthAfterMoveSet(d, mv, to) == dx - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return false;\n        }\n\n        return true;\n    }\n\n    void greedyImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 20; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int old = d[v];\n\n                for (int nl = H; nl > old; nl--) {\n                    if (canMove(d, cnt, v, nl)) {\n                        applyMove(d, cnt, v, nl);\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void supportPairImprove(vector<int>& d) const {\n        vector<int> cnt = calcCnt(d);\n\n        for (int pass = 0; pass < 5; pass++) {\n            bool changed = false;\n\n            for (int v : orderHigh) {\n                int dv = d[v];\n\n                if (dv == H) continue;\n\n                for (int t = H; t > dv; t--) {\n                    if (canMove(d, cnt, v, t)) {\n                        applyMove(d, cnt, v, t);\n                        changed = true;\n                        dv = t;\n                        break;\n                    }\n\n                    int need = t - 1;\n                    int bestU = -1;\n                    long long bestNet = 0;\n\n                    for (int u : adj[v]) {\n                        if (d[u] == need) continue;\n                        if (!canMoveExcept(d, cnt, u, need, v, t)) continue;\n\n                        long long net = 1LL * (t - dv) * A[v] + 1LL * (need - d[u]) * A[u];\n\n                        if (net > bestNet) {\n                            bestNet = net;\n                            bestU = u;\n                        }\n                    }\n\n                    if (bestU != -1) {\n                        int oldU = d[bestU];\n\n                        applyMove(d, cnt, bestU, need);\n\n                        if (canMove(d, cnt, v, t)) {\n                            applyMove(d, cnt, v, t);\n                            changed = true;\n                            dv = t;\n                            break;\n                        } else {\n                            applyMove(d, cnt, bestU, oldU);\n                        }\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n    }\n\n    void groupSupportImprove(vector<int>& d, double timeLimit) {\n        for (int pass = 0; pass < 4 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n            int checked = 0;\n\n            for (int u : orderLow) {\n                if (elapsed() >= timeLimit) break;\n                if (++checked > 850) break;\n\n                long long bestGain = 0;\n                vector<pair<int, int>> bestMoves;\n\n                for (int k = 0; k < H; k++) {\n                    int supportDepth = k;\n                    int childDepth = k + 1;\n\n                    vector<pair<long long, int>> raisable;\n\n                    for (int v : adj[u]) {\n                        if (d[v] < childDepth) {\n                            long long g = 1LL * (childDepth - d[v]) * A[v];\n\n                            if (g > 0) raisable.push_back({g, v});\n                        }\n                    }\n\n                    if (raisable.empty()) continue;\n\n                    sort(raisable.begin(), raisable.end(), greater<pair<long long, int>>());\n\n                    vector<pair<int, int>> mv;\n                    long long gain = 0;\n\n                    if (d[u] != supportDepth) {\n                        mv.push_back({u, supportDepth});\n                        gain += 1LL * (supportDepth - d[u]) * A[u];\n                    }\n\n                    for (auto [g, v] : raisable) {\n                        mv.push_back({v, childDepth});\n                        gain += g;\n\n                        if (gain <= bestGain) continue;\n                        if (!validateMoveSet(d, mv)) continue;\n\n                        bestGain = gain;\n                        bestMoves = mv;\n                    }\n                }\n\n                if (bestGain > 0 && !bestMoves.empty()) {\n                    for (auto [v, nd] : bestMoves) d[v] = nd;\n                    changed = true;\n                }\n            }\n\n            greedyImprove(d);\n            supportPairImprove(d);\n\n            if (!changed) break;\n        }\n    }\n\n    void supportRoleSwapImprove(vector<int>& d, double timeLimit) {\n        for (int pass = 0; pass < 4 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n            vector<int> cnt = calcCnt(d);\n            int checked = 0;\n\n            for (int v : orderHigh) {\n                if (elapsed() >= timeLimit) break;\n                if (++checked > 750) break;\n\n                int k = d[v];\n\n                if (k >= H) continue;\n\n                vector<int> critical;\n\n                for (int to : adj[v]) {\n                    if (d[to] == k + 1 && cnt[to] == 1) critical.push_back(to);\n                }\n\n                if (critical.empty()) continue;\n                if ((int)critical.size() > 10) continue;\n\n                vector<int> cand;\n                vector<char> mark(N, 0);\n\n                auto addCand = [&](int x) {\n                    if (x == v) return;\n\n                    if (!mark[x]) {\n                        mark[x] = 1;\n                        cand.push_back(x);\n                    }\n                };\n\n                for (int c : critical) {\n                    addCand(c);\n\n                    for (int u : adj[c]) addCand(u);\n                }\n\n                long long bestGain = 0;\n                int bestU = -1;\n                int bestT = -1;\n\n                for (int u : cand) {\n                    if (d[u] == k) continue;\n\n                    bool covers = true;\n\n                    for (int c : critical) {\n                        if (u == c) continue;\n\n                        if (!con[u][c]) {\n                            covers = false;\n                            break;\n                        }\n                    }\n\n                    if (!covers) continue;\n\n                    for (int t = H; t > k; t--) {\n                        long long gain = 1LL * (t - k) * A[v] + 1LL * (k - d[u]) * A[u];\n\n                        if (gain <= bestGain) continue;\n                        if (!canMoveExcept(d, cnt, u, k, v, t)) continue;\n\n                        vector<int> td = d;\n                        vector<int> tc = cnt;\n\n                        applyMove(td, tc, u, k);\n\n                        if (!canMove(td, tc, v, t)) continue;\n\n                        applyMove(td, tc, v, t);\n\n                        bool localOk = true;\n\n                        for (int x : critical) {\n                            if (td[x] == 0) continue;\n\n                            bool ok = false;\n\n                            for (int nb : adj[x]) {\n                                if (td[nb] == td[x] - 1) {\n                                    ok = true;\n                                    break;\n                                }\n                            }\n\n                            if (!ok) {\n                                localOk = false;\n                                break;\n                            }\n                        }\n\n                        if (!localOk) continue;\n\n                        bestGain = gain;\n                        bestU = u;\n                        bestT = t;\n                    }\n                }\n\n                if (bestU != -1) {\n                    applyMove(d, cnt, bestU, k);\n                    applyMove(d, cnt, v, bestT);\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n\n            greedyImprove(d);\n            supportPairImprove(d);\n        }\n    }\n\n    void multiSupportRoleImprove(vector<int>& d, double timeLimit) {\n        struct Cand {\n            int u;\n            int mask;\n            long long val;\n        };\n\n        for (int pass = 0; pass < 3 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n            vector<int> cnt = calcCnt(d);\n            int checked = 0;\n\n            for (int v : orderHigh) {\n                if (elapsed() >= timeLimit) break;\n                if (++checked > 720) break;\n\n                int k = d[v];\n\n                if (k >= H) continue;\n\n                vector<int> critical;\n\n                for (int to : adj[v]) {\n                    if (d[to] == k + 1 && cnt[to] == 1) critical.push_back(to);\n                }\n\n                int C = (int)critical.size();\n\n                if (C <= 1 || C > 12) continue;\n\n                vector<int> pool;\n                vector<char> mark(N, 0);\n\n                auto addPool = [&](int x) {\n                    if (x == v) return;\n\n                    if (!mark[x]) {\n                        mark[x] = 1;\n                        pool.push_back(x);\n                    }\n                };\n\n                for (int c : critical) {\n                    addPool(c);\n\n                    for (int u : adj[c]) addPool(u);\n                }\n\n                vector<Cand> cands;\n\n                for (int u : pool) {\n                    int mask = 0;\n\n                    for (int i = 0; i < C; i++) {\n                        int c = critical[i];\n\n                        if (u == c || con[u][c]) mask |= (1 << i);\n                    }\n\n                    if (mask == 0) continue;\n\n                    long long val = 1LL * (k - d[u]) * A[u];\n                    cands.push_back({u, mask, val});\n                }\n\n                if (cands.empty()) continue;\n\n                int S = 1 << C;\n                int full = S - 1;\n                int nC = (int)cands.size();\n\n                vector<long long> dp(S, NEG), ndp(S, NEG);\n                vector<vector<unsigned short>> pre(nC + 1, vector<unsigned short>(S, 65535));\n                vector<vector<unsigned char>> take(nC + 1, vector<unsigned char>(S, 0));\n\n                dp[0] = 0;\n\n                for (int i = 1; i <= nC; i++) {\n                    ndp = dp;\n\n                    int cm = cands[i - 1].mask;\n                    long long cv = cands[i - 1].val;\n\n                    for (int mask = 0; mask < S; mask++) {\n                        if (dp[mask] <= NEG / 2) continue;\n\n                        int nm = mask | cm;\n\n                        if (nm == mask) continue;\n\n                        long long nv = dp[mask] + cv;\n\n                        if (nv > ndp[nm]) {\n                            ndp[nm] = nv;\n                            pre[i][nm] = (unsigned short)mask;\n                            take[i][nm] = 1;\n                        }\n                    }\n\n                    dp.swap(ndp);\n                }\n\n                if (dp[full] <= NEG / 2) continue;\n\n                vector<int> picked;\n                int mask = full;\n\n                for (int i = nC; i >= 1; i--) {\n                    if (take[i][mask]) {\n                        picked.push_back(i - 1);\n                        mask = pre[i][mask];\n                    }\n                }\n\n                if (mask != 0) continue;\n\n                long long bestGain = 0;\n                int bestT = -1;\n                vector<pair<int, int>> bestMoves;\n\n                for (int t = H; t > k; t--) {\n                    vector<pair<int, int>> mv;\n                    long long gain = 1LL * (t - k) * A[v];\n\n                    mv.push_back({v, t});\n\n                    for (int id : picked) {\n                        int u = cands[id].u;\n\n                        if (d[u] == k) continue;\n\n                        mv.push_back({u, k});\n                        gain += 1LL * (k - d[u]) * A[u];\n                    }\n\n                    if (gain <= bestGain) continue;\n                    if (!validateMoveSet(d, mv)) continue;\n\n                    bestGain = gain;\n                    bestT = t;\n                    bestMoves = mv;\n                }\n\n                if (bestT != -1 && bestGain > 0) {\n                    for (auto [x, nd] : bestMoves) d[x] = nd;\n                    changed = true;\n                }\n            }\n\n            greedyImprove(d);\n            supportPairImprove(d);\n\n            if (!changed) break;\n        }\n    }\n\n    bool validatePathMove(const vector<int>& d, const PathState& s, int targetDepth) const {\n        vector<int> affected;\n        vector<int> mark(N, 0);\n\n        auto addAffected = [&](int x) {\n            if (!mark[x]) {\n                mark[x] = 1;\n                affected.push_back(x);\n            }\n        };\n\n        for (int i = 0; i < s.len; i++) {\n            int x = s.node[i];\n\n            addAffected(x);\n\n            for (int to : adj[x]) addAffected(to);\n        }\n\n        auto getDepth = [&](int x) {\n            for (int i = 0; i < s.len; i++) {\n                if (s.node[i] == x) return targetDepth - i;\n            }\n\n            return d[x];\n        };\n\n        for (int x : affected) {\n            int dx = getDepth(x);\n\n            if (dx == 0) continue;\n\n            bool ok = false;\n\n            for (int to : adj[x]) {\n                if (getDepth(to) == dx - 1) {\n                    ok = true;\n                    break;\n                }\n            }\n\n            if (!ok) return false;\n        }\n\n        return true;\n    }\n\n    pair<long long, PathState> findBestPartialPathMove(const vector<int>& d, int v, int targetDepth) const {\n        constexpr int BEAM = 44;\n\n        PathState init;\n        init.node.fill(-1);\n        init.node[0] = v;\n        init.len = 1;\n        init.delta = 1LL * (targetDepth - d[v]) * A[v];\n\n        vector<PathState> beam;\n        beam.push_back(init);\n\n        long long bestGain = NEG;\n        PathState best;\n        best.len = 0;\n        best.delta = NEG;\n\n        for (int dep = targetDepth - 1; dep >= 0; dep--) {\n            vector<PathState> nxt;\n            nxt.reserve(BEAM * 8);\n\n            for (const auto& s : beam) {\n                int cur = s.node[s.len - 1];\n\n                for (int nb : adj[cur]) {\n                    bool used = false;\n\n                    for (int i = 0; i < s.len; i++) {\n                        if (s.node[i] == nb) {\n                            used = true;\n                            break;\n                        }\n                    }\n\n                    if (used) continue;\n\n                    PathState ns = s;\n                    ns.node[ns.len++] = nb;\n                    ns.delta += 1LL * (dep - d[nb]) * A[nb];\n\n                    nxt.push_back(ns);\n\n                    if (ns.delta > bestGain && ns.delta > 0) {\n                        if (validatePathMove(d, ns, targetDepth)) {\n                            bestGain = ns.delta;\n                            best = ns;\n                        }\n                    }\n                }\n            }\n\n            if (nxt.empty()) break;\n\n            sort(nxt.begin(), nxt.end(), [](const PathState& a, const PathState& b) {\n                return a.delta > b.delta;\n            });\n\n            if ((int)nxt.size() > BEAM) nxt.resize(BEAM);\n            beam.swap(nxt);\n        }\n\n        return {bestGain, best};\n    }\n\n    void pathChainImprove(vector<int>& d, double timeLimit) {\n        for (int pass = 0; pass < 3 && elapsed() < timeLimit; pass++) {\n            bool changed = false;\n\n            for (int idx = 0; idx < N && elapsed() < timeLimit; idx++) {\n                int v = orderHigh[idx];\n\n                if (d[v] == H) continue;\n\n                long long bestGain = 0;\n                PathState bestState;\n                int bestTarget = -1;\n\n                for (int t = H; t > d[v]; t--) {\n                    auto [gain, state] = findBestPartialPathMove(d, v, t);\n\n                    if (gain > bestGain) {\n                        bestGain = gain;\n                        bestState = state;\n                        bestTarget = t;\n                    }\n                }\n\n                if (bestGain > 0 && bestTarget >= 0) {\n                    for (int i = 0; i < bestState.len; i++) {\n                        d[bestState.node[i]] = bestTarget - i;\n                    }\n\n                    changed = true;\n                }\n            }\n\n            greedyImprove(d);\n            supportPairImprove(d);\n\n            if (!changed) break;\n        }\n    }\n\n    void lowPerturbAndImprove(vector<int>& d) const {\n        vector<int> best = d;\n        long long bestScore = scoreLabels(d);\n\n        vector<int> cur = d;\n        vector<int> cnt = calcCnt(cur);\n\n        int tried = 0;\n\n        for (int v : orderLow) {\n            if (++tried > 350) break;\n\n            int old = cur[v];\n\n            if (old == 0) continue;\n\n            int chosen = -1;\n\n            for (int nl = 0; nl < old; nl++) {\n                if (!canMove(cur, cnt, v, nl)) continue;\n\n                long long loss = 1LL * A[v] * (old - nl);\n                long long pot = 0;\n\n                for (int to : adj[v]) {\n                    if (cur[to] == nl + 1) pot += A[to];\n\n                    pot += A[to] / 10;\n                }\n\n                if (loss <= 120 + pot) {\n                    chosen = nl;\n                    break;\n                }\n            }\n\n            if (chosen != -1) applyMove(cur, cnt, v, chosen);\n        }\n\n        greedyImprove(cur);\n        supportPairImprove(cur);\n\n        if (scoreLabels(cur) > bestScore) d = cur;\n    }\n\n    void annealImprove(vector<int>& bestLabel, double timeLimit) {\n        vector<int> cur = bestLabel;\n        vector<int> cnt = calcCnt(cur);\n\n        long long curScore = scoreLabels(cur);\n        long long bestScore = curScore;\n\n        double startTime = elapsed();\n        int iter = 0;\n\n        uniform_real_distribution<double> real01(0.0, 1.0);\n\n        while (elapsed() < timeLimit) {\n            iter++;\n\n            double now = elapsed();\n            double progress = (now - startTime) / max(1e-9, timeLimit - startTime);\n            progress = min(1.0, max(0.0, progress));\n\n            double temp = 55.0 * (1.0 - progress) + 1.0 * progress;\n\n            int v;\n\n            if ((rng() % 100) < 70) v = orderHigh[rng() % min(N, 550)];\n            else v = rng() % N;\n\n            int old = cur[v];\n            int nl;\n\n            if ((rng() % 100) < 72 && old < H) nl = old + 1 + (rng() % (H - old));\n            else nl = rng() % (H + 1);\n\n            if (nl == old) continue;\n            if (!canMove(cur, cnt, v, nl)) continue;\n\n            long long delta = 1LL * (nl - old) * A[v];\n\n            bool accept = false;\n\n            if (delta >= 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / temp);\n\n                if (real01(rng) < prob) accept = true;\n            }\n\n            if (accept) {\n                applyMove(cur, cnt, v, nl);\n                curScore += delta;\n\n                if (curScore > bestScore && checkFeasible(cur)) {\n                    bestScore = curScore;\n                    bestLabel = cur;\n                }\n            }\n\n            if (iter % 2500 == 0) {\n                greedyImprove(cur);\n                supportPairImprove(cur);\n\n                cnt = calcCnt(cur);\n                curScore = scoreLabels(cur);\n\n                if (curScore > bestScore && checkFeasible(cur)) {\n                    bestScore = curScore;\n                    bestLabel = cur;\n                }\n\n                if (curScore + 3000 < bestScore || (rng() % 100) < 12) {\n                    cur = bestLabel;\n                    cnt = calcCnt(cur);\n                    curScore = bestScore;\n                }\n            }\n        }\n\n        greedyImprove(bestLabel);\n        supportPairImprove(bestLabel);\n    }\n\n    vector<int> buildParents(const vector<int>& d) const {\n        vector<int> p(N, -1);\n\n        for (int v = 0; v < N; v++) {\n            if (d[v] == 0) {\n                p[v] = -1;\n            } else {\n                int best = -1;\n                int bestA = 1e9;\n\n                for (int to : adj[v]) {\n                    if (d[to] == d[v] - 1) {\n                        if (A[to] < bestA) {\n                            bestA = A[to];\n                            best = to;\n                        }\n                    }\n                }\n\n                p[v] = best;\n            }\n        }\n\n        return p;\n    }\n\n    void safeKeepBest(vector<int>& bestLabel, const vector<int>& cand) const {\n        if (!checkFeasible(cand)) return;\n\n        if (scoreLabels(cand) > scoreLabels(bestLabel)) bestLabel = cand;\n    }\n\n    void run() {\n        cin >> N >> M >> HH;\n\n        A.resize(N);\n\n        for (int i = 0; i < N; i++) cin >> A[i];\n\n        edges.resize(M);\n        adj.assign(N, {});\n        con.assign(N, bitset<MAXN>());\n\n        for (int i = 0; i < M; i++) {\n            int u, v;\n            cin >> u >> v;\n\n            edges[i] = {u, v, 0};\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n            con[u][v] = 1;\n            con[v][u] = 1;\n        }\n\n        xs.resize(N);\n        ys.resize(N);\n\n        for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n        for (auto& e : edges) {\n            long long dx = xs[e.u] - xs[e.v];\n            long long dy = ys[e.u] - ys[e.v];\n\n            e.len2 = dx * dx + dy * dy;\n        }\n\n        orderHigh.resize(N);\n        orderLow.resize(N);\n\n        iota(orderHigh.begin(), orderHigh.end(), 0);\n        iota(orderLow.begin(), orderLow.end(), 0);\n\n        sort(orderHigh.begin(), orderHigh.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] > A[b];\n\n            return adj[a].size() > adj[b].size();\n        });\n\n        sort(orderLow.begin(), orderLow.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] < A[b];\n\n            return adj[a].size() < adj[b].size();\n        });\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestLabel(N, 0);\n        long long bestScore = scoreLabels(bestLabel);\n\n        int iter = 0;\n\n        while (elapsed() < 1.04) {\n            vector<int> treePar;\n\n            if (iter % 5 == 0) treePar = makeDFSTree((iter / 5) % 3);\n            else treePar = makePrimTree(iter % 6);\n\n            vector<int> label = solveOnTree(treePar);\n\n            greedyImprove(label);\n            supportPairImprove(label);\n\n            if (iter % 2 == 0) lowPerturbAndImprove(label);\n\n            long long sc = scoreLabels(label);\n\n            if (sc > bestScore && checkFeasible(label)) {\n                bestScore = sc;\n                bestLabel = label;\n            }\n\n            iter++;\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            supportRoleSwapImprove(cand, 1.20);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            multiSupportRoleImprove(cand, 1.34);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            pathChainImprove(cand, 1.58);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            groupSupportImprove(cand, 1.70);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        {\n            vector<int> cand = bestLabel;\n            supportRoleSwapImprove(cand, 1.76);\n            multiSupportRoleImprove(cand, 1.82);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        annealImprove(bestLabel, 1.88);\n\n        {\n            vector<int> cand = bestLabel;\n            groupSupportImprove(cand, 1.925);\n            multiSupportRoleImprove(cand, 1.955);\n            pathChainImprove(cand, 1.975);\n            supportRoleSwapImprove(cand, 1.988);\n            safeKeepBest(bestLabel, cand);\n        }\n\n        if (!checkFeasible(bestLabel)) fill(bestLabel.begin(), bestLabel.end(), 0);\n\n        vector<int> parent = buildParents(bestLabel);\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n\n            cout << parent[i];\n        }\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.run();\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nchar opposite_dir(char d) {\n    if (d == 'L') return 'R';\n    if (d == 'R') return 'L';\n    if (d == 'U') return 'D';\n    return 'U';\n}\n\nbool apply_shift(vector<string>& b, char d, int p) {\n    if (d == 'L') {\n        if (b[p][0] == 'o') return false;\n        for (int j = 0; j + 1 < N; j++) b[p][j] = b[p][j + 1];\n        b[p][N - 1] = '.';\n    } else if (d == 'R') {\n        if (b[p][N - 1] == 'o') return false;\n        for (int j = N - 1; j >= 1; j--) b[p][j] = b[p][j - 1];\n        b[p][0] = '.';\n    } else if (d == 'U') {\n        if (b[0][p] == 'o') return false;\n        for (int i = 0; i + 1 < N; i++) b[i][p] = b[i + 1][p];\n        b[N - 1][p] = '.';\n    } else {\n        if (b[N - 1][p] == 'o') return false;\n        for (int i = N - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n    return true;\n}\n\nint count_oni(const vector<string>& b) {\n    int c = 0;\n    for (auto& s : b) for (char ch : s) if (ch == 'x') c++;\n    return c;\n}\n\nbool validate_solution(const vector<string>& init, const vector<Op>& ops) {\n    if ((int)ops.size() > 4 * N * N) return false;\n    vector<string> b = init;\n    for (auto [d, p] : ops) {\n        if (p < 0 || p >= N) return false;\n        if (!apply_shift(b, d, p)) return false;\n    }\n    return count_oni(b) == 0;\n}\n\nbool truncate_when_done(const vector<string>& init, vector<Op>& ops) {\n    vector<string> b = init;\n    for (int t = 0; t < (int)ops.size(); t++) {\n        if (!apply_shift(b, ops[t].d, ops[t].p)) return false;\n        if (count_oni(b) == 0) {\n            ops.resize(t + 1);\n            return true;\n        }\n    }\n    return count_oni(b) == 0;\n}\n\n/* -------------------- Restoring set-cover solver -------------------- */\n\nstruct Cand {\n    char d;\n    int p;\n    int s;\n    uint64_t mask;\n};\n\nint eval_cover(const vector<int>& sel, const vector<Cand>& cand, uint64_t allmask) {\n    uint64_t u = 0;\n    int sum = 0, mx = 0;\n    for (int id : sel) {\n        u |= cand[id].mask;\n        sum += cand[id].s;\n        mx = max(mx, cand[id].s);\n    }\n    if (u != allmask) return 1e9;\n    return 2 * sum - mx;\n}\n\nvoid prune_cover(vector<int>& sel, const vector<Cand>& cand, uint64_t allmask, mt19937& rng) {\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        shuffle(sel.begin(), sel.end(), rng);\n        for (int k = 0; k < (int)sel.size(); k++) {\n            uint64_t u = 0;\n            for (int t = 0; t < (int)sel.size(); t++) {\n                if (t != k) u |= cand[sel[t]].mask;\n            }\n            if (u == allmask) {\n                sel.erase(sel.begin() + k);\n                changed = true;\n                break;\n            }\n        }\n    }\n}\n\nvector<Op> build_ops_from_cover_fixed_last(\n    const vector<int>& sel,\n    const vector<Cand>& cand,\n    int last_pos\n) {\n    vector<Op> ops;\n    if (sel.empty()) return ops;\n\n    for (int k = 0; k < (int)sel.size(); k++) {\n        if (k == last_pos) continue;\n        const Cand& c = cand[sel[k]];\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n    }\n\n    const Cand& c = cand[sel[last_pos]];\n    for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n\n    return ops;\n}\n\nvector<Op> build_ops_from_cover_best_last(\n    const vector<string>& init,\n    const vector<int>& sel,\n    const vector<Cand>& cand\n) {\n    vector<Op> best_ops;\n\n    if (sel.empty()) return best_ops;\n\n    for (int last_pos = 0; last_pos < (int)sel.size(); last_pos++) {\n        vector<Op> ops = build_ops_from_cover_fixed_last(sel, cand, last_pos);\n        truncate_when_done(init, ops);\n\n        if (validate_solution(init, ops)) {\n            if (best_ops.empty() || ops.size() < best_ops.size()) {\n                best_ops = std::move(ops);\n            }\n        }\n    }\n\n    // Safety fallback: original policy, largest shift as final.\n    if (best_ops.empty()) {\n        int last_pos = 0;\n        for (int i = 1; i < (int)sel.size(); i++) {\n            if (cand[sel[i]].s > cand[sel[last_pos]].s) last_pos = i;\n        }\n        best_ops = build_ops_from_cover_fixed_last(sel, cand, last_pos);\n        truncate_when_done(init, best_ops);\n    }\n\n    return best_ops;\n}\n\nvector<Op> solve_set_cover(const vector<string>& init, mt19937& rng) {\n    int id[N][N];\n    memset(id, -1, sizeof(id));\n\n    vector<pair<int,int>> oni;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (init[i][j] == 'x') {\n                id[i][j] = (int)oni.size();\n                oni.push_back({i, j});\n            }\n        }\n    }\n\n    int Mx = oni.size();\n    if (Mx == 0) return {};\n\n    uint64_t allmask = (1ULL << Mx) - 1;\n    vector<Cand> cand;\n\n    auto add_cand = [&](char d, int p, int s, uint64_t mask) {\n        if (mask) cand.push_back({d, p, s, mask});\n    };\n\n    for (int i = 0; i < N; i++) {\n        int first_o = N;\n        for (int j = 0; j < N; j++) {\n            if (init[i][j] == 'o') {\n                first_o = j;\n                break;\n            }\n        }\n\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int j = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('L', i, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int j = N - 1; j >= 0; j--) {\n            if (init[i][j] == 'o') {\n                last_o = j;\n                break;\n            }\n        }\n\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int j = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('R', i, s, mask);\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int first_o = N;\n        for (int i = 0; i < N; i++) {\n            if (init[i][j] == 'o') {\n                first_o = i;\n                break;\n            }\n        }\n\n        uint64_t mask = 0;\n        for (int s = 1; s <= first_o; s++) {\n            int i = s - 1;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('U', j, s, mask);\n            }\n        }\n\n        int last_o = -1;\n        for (int i = N - 1; i >= 0; i--) {\n            if (init[i][j] == 'o') {\n                last_o = i;\n                break;\n            }\n        }\n\n        mask = 0;\n        for (int s = 1; s <= N - 1 - last_o; s++) {\n            int i = N - s;\n            if (init[i][j] == 'x') {\n                mask |= 1ULL << id[i][j];\n                add_cand('D', j, s, mask);\n            }\n        }\n    }\n\n    int C = cand.size();\n    vector<int> alive(C, 1);\n    for (int i = 0; i < C; i++) {\n        for (int j = 0; j < C; j++) if (i != j) {\n            bool subset = (cand[i].mask & ~cand[j].mask) == 0;\n            if (subset && (cand[j].s < cand[i].s || (cand[j].s == cand[i].s && j < i))) {\n                alive[i] = 0;\n                break;\n            }\n        }\n    }\n\n    vector<Cand> nc;\n    for (int i = 0; i < C; i++) if (alive[i]) nc.push_back(cand[i]);\n    cand.swap(nc);\n\n    vector<int> best_sel;\n\n    {\n        vector<int> sel;\n        for (int k = 0; k < Mx; k++) {\n            int best = -1;\n            for (int i = 0; i < (int)cand.size(); i++) {\n                if ((cand[i].mask >> k) & 1ULL) {\n                    if (best == -1 || cand[i].s < cand[best].s) best = i;\n                }\n            }\n            if (best != -1) sel.push_back(best);\n        }\n\n        sort(sel.begin(), sel.end());\n        sel.erase(unique(sel.begin(), sel.end()), sel.end());\n        prune_cover(sel, cand, allmask, rng);\n        best_sel = sel;\n    }\n\n    int best_score = eval_cover(best_sel, cand, allmask);\n\n    for (int iter = 0; iter < 5000; iter++) {\n        uint64_t covered = 0;\n        vector<int> sel;\n        double alpha = 1.0 + (rng() % 1200) / 1000.0;\n\n        while (covered != allmask) {\n            vector<pair<double,int>> v;\n\n            for (int i = 0; i < (int)cand.size(); i++) {\n                uint64_t nw = cand[i].mask & ~covered;\n                if (!nw) continue;\n\n                int cnt = __builtin_popcountll(nw);\n                double noise = 0.85 + (rng() % 3000) / 10000.0;\n                double sc = cand[i].s / pow((double)cnt, alpha) * noise;\n                v.push_back({sc, i});\n            }\n\n            if (v.empty()) break;\n            sort(v.begin(), v.end());\n\n            int K = min<int>((int)v.size(), 3 + (rng() % 8));\n            int chosen = v[rng() % K].second;\n            sel.push_back(chosen);\n            covered |= cand[chosen].mask;\n        }\n\n        if (covered != allmask) continue;\n\n        prune_cover(sel, cand, allmask, rng);\n        int sc = eval_cover(sel, cand, allmask);\n\n        if (sc < best_score) {\n            best_score = sc;\n            best_sel = sel;\n        }\n    }\n\n    return build_ops_from_cover_best_last(init, best_sel, cand);\n}\n\n/* -------------------- Dynamic macro solver -------------------- */\n\nstruct DynCand {\n    char d;\n    int p;\n    int s;\n    int rem;\n    bool bounce;\n};\n\nvoid add_dyn_cands_for_line(vector<DynCand>& res, const vector<string>& b, bool bounce_allowed) {\n    for (int i = 0; i < N; i++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[i][s - 1] != 'o'; s++) {\n            if (b[i][s - 1] == 'x') {\n                rem++;\n                res.push_back({'L', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'L', i, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[i][N - s] != 'o'; s++) {\n            if (b[i][N - s] == 'x') {\n                rem++;\n                res.push_back({'R', i, s, rem, false});\n                if (bounce_allowed) res.push_back({'R', i, s, rem, true});\n            }\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int rem = 0;\n        for (int s = 1; s <= N && b[s - 1][j] != 'o'; s++) {\n            if (b[s - 1][j] == 'x') {\n                rem++;\n                res.push_back({'U', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'U', j, s, rem, true});\n            }\n        }\n\n        rem = 0;\n        for (int s = 1; s <= N && b[N - s][j] != 'o'; s++) {\n            if (b[N - s][j] == 'x') {\n                rem++;\n                res.push_back({'D', j, s, rem, false});\n                if (bounce_allowed) res.push_back({'D', j, s, rem, true});\n            }\n        }\n    }\n}\n\nint dyn_cost(const DynCand& c) {\n    return c.s * (c.bounce ? 2 : 1);\n}\n\nbool apply_dyn(vector<string>& b, vector<Op>& ops, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n        ops.push_back({c.d, c.p});\n    }\n\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n            ops.push_back({od, c.p});\n        }\n    }\n\n    return true;\n}\n\nbool apply_dyn_board_only(vector<string>& b, const DynCand& c) {\n    for (int t = 0; t < c.s; t++) {\n        if (!apply_shift(b, c.d, c.p)) return false;\n    }\n\n    if (c.bounce) {\n        char od = opposite_dir(c.d);\n        for (int t = 0; t < c.s; t++) {\n            if (!apply_shift(b, od, c.p)) return false;\n        }\n    }\n\n    return true;\n}\n\nvector<Op> dynamic_trial(const vector<string>& init, mt19937& rng, int mode) {\n    vector<string> b = init;\n    vector<Op> ops;\n\n    double alpha = 1.0 + (rng() % 1400) / 1000.0;\n    bool bounce_allowed = (mode != 0);\n\n    for (int step = 0; step < 45; step++) {\n        int oni = count_oni(b);\n        if (oni == 0) return ops;\n        if ((int)ops.size() > 4 * N * N) return {};\n\n        vector<DynCand> cs;\n        add_dyn_cands_for_line(cs, b, bounce_allowed);\n        if (cs.empty()) return {};\n\n        vector<pair<double,int>> rank;\n\n        for (int i = 0; i < (int)cs.size(); i++) {\n            int cost = dyn_cost(cs[i]);\n            double sc = cost / pow((double)cs[i].rem, alpha);\n\n            if (mode == 0 && cs[i].bounce) continue;\n            if (mode == 1 && cs[i].bounce) sc *= 1.15;\n            if (mode == 2 && !cs[i].bounce) sc *= 0.85;\n            if (mode == 3 && cs[i].bounce) sc *= 0.85;\n\n            double noise = 0.80 + (rng() % 4000) / 10000.0;\n            sc *= noise;\n\n            rank.push_back({sc, i});\n        }\n\n        if (rank.empty()) return {};\n        sort(rank.begin(), rank.end());\n\n        int K = (mode == 4 ? 1 : min<int>((int)rank.size(), 3 + (rng() % 8)));\n        DynCand chosen = cs[rank[(K == 1 ? 0 : (int)(rng() % K))].second];\n\n        if (!apply_dyn(b, ops, chosen)) return {};\n    }\n\n    if (count_oni(b) == 0) return ops;\n    return {};\n}\n\n/* -------------------- Evaluation helpers -------------------- */\n\nuint64_t hash_board(const vector<string>& b) {\n    uint64_t h = 1469598103934665603ULL;\n    for (int i = 0; i < N; i++) {\n        for (char c : b[i]) {\n            h ^= (unsigned char)c;\n            h *= 1099511628211ULL;\n        }\n    }\n    return h;\n}\n\nint sum_visible_min_dist(const vector<string>& b) {\n    int sum = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) if (b[i][j] == 'x') {\n            int best = 25;\n\n            bool ok = true;\n            for (int k = 0; k < j; k++) if (b[i][k] == 'o') ok = false;\n            if (ok) best = min(best, j + 1);\n\n            ok = true;\n            for (int k = j + 1; k < N; k++) if (b[i][k] == 'o') ok = false;\n            if (ok) best = min(best, N - j);\n\n            ok = true;\n            for (int k = 0; k < i; k++) if (b[k][j] == 'o') ok = false;\n            if (ok) best = min(best, i + 1);\n\n            ok = true;\n            for (int k = i + 1; k < N; k++) if (b[k][j] == 'o') ok = false;\n            if (ok) best = min(best, N - i);\n\n            if (best == 25) best = 12;\n            sum += best;\n        }\n    }\n\n    return sum;\n}\n\n/* -------------------- Macro beam solver -------------------- */\n\nstruct BeamNode {\n    vector<string> b;\n    vector<DynCand> path;\n    int cost;\n    int rem;\n    double eval;\n};\n\nvector<Op> build_ops_from_dyn_path(const vector<DynCand>& path) {\n    vector<Op> ops;\n\n    for (auto& c : path) {\n        for (int t = 0; t < c.s; t++) ops.push_back({c.d, c.p});\n        if (c.bounce) {\n            char od = opposite_dir(c.d);\n            for (int t = 0; t < c.s; t++) ops.push_back({od, c.p});\n        }\n    }\n\n    return ops;\n}\n\nvector<Op> beam_search_solver(\n    const vector<string>& init,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline,\n    int incumbent_cost\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    vector<Op> best_ops;\n\n    BeamNode root;\n    root.b = init;\n    root.cost = 0;\n    root.rem = count_oni(init);\n    root.eval = root.rem;\n\n    vector<BeamNode> beam;\n    beam.push_back(root);\n\n    const int BEAM_WIDTH = 120;\n    const int MAX_CAND = 45;\n\n    for (int depth = 0; depth < 45 && elapsed() < deadline; depth++) {\n        vector<BeamNode> nxt;\n        unordered_map<uint64_t, int> seen;\n        seen.reserve(BEAM_WIDTH * MAX_CAND * 2);\n\n        for (auto& node : beam) {\n            if (elapsed() >= deadline) break;\n\n            vector<DynCand> cs;\n            add_dyn_cands_for_line(cs, node.b, true);\n            if (cs.empty()) continue;\n\n            vector<pair<double,int>> ord;\n            ord.reserve(cs.size());\n\n            for (int i = 0; i < (int)cs.size(); i++) {\n                double sc = dyn_cost(cs[i]) / pow((double)cs[i].rem, 1.35);\n                if (cs[i].bounce) sc *= 1.08;\n                sc *= 0.98 + (rng() % 400) / 10000.0;\n                ord.push_back({sc, i});\n            }\n\n            sort(ord.begin(), ord.end());\n            int lim = min<int>(MAX_CAND, ord.size());\n\n            for (int z = 0; z < lim; z++) {\n                const DynCand& c = cs[ord[z].second];\n\n                int ncst = node.cost + dyn_cost(c);\n                if (ncst >= incumbent_cost + 12) continue;\n\n                BeamNode nb;\n                nb.b = node.b;\n\n                if (!apply_dyn_board_only(nb.b, c)) continue;\n\n                nb.rem = count_oni(nb.b);\n                if (nb.rem >= node.rem) continue;\n\n                nb.cost = ncst;\n                nb.path = node.path;\n                nb.path.push_back(c);\n\n                if (nb.rem == 0) {\n                    vector<Op> ops = build_ops_from_dyn_path(nb.path);\n                    truncate_when_done(init, ops);\n\n                    if ((int)ops.size() < incumbent_cost) {\n                        incumbent_cost = ops.size();\n                        best_ops = ops;\n                    }\n                    continue;\n                }\n\n                uint64_t h = hash_board(nb.b);\n                auto it = seen.find(h);\n                if (it != seen.end() && it->second <= nb.cost) continue;\n\n                seen[h] = nb.cost;\n                nb.eval = nb.cost + 1.6 * nb.rem + 0.10 * sum_visible_min_dist(nb.b);\n                nxt.push_back(std::move(nb));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        sort(nxt.begin(), nxt.end(), [](const BeamNode& a, const BeamNode& b) {\n            if (a.eval != b.eval) return a.eval < b.eval;\n            return a.cost < b.cost;\n        });\n\n        if ((int)nxt.size() > BEAM_WIDTH) nxt.resize(BEAM_WIDTH);\n        beam.swap(nxt);\n    }\n\n    return best_ops;\n}\n\n/* -------------------- Single-operation beam solver -------------------- */\n\nstruct StepNode {\n    vector<string> b;\n    vector<Op> path;\n    int rem;\n    double eval;\n};\n\nvector<Op> step_beam_solver(\n    const vector<string>& init,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline,\n    int incumbent\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    const int WIDTH = 170;\n    const int CAND_LIMIT = 30;\n\n    StepNode root;\n    root.b = init;\n    root.rem = count_oni(init);\n    root.eval = root.rem;\n\n    vector<StepNode> beam;\n    beam.push_back(root);\n\n    unordered_map<uint64_t, int> global_seen;\n    global_seen.reserve(30000);\n    global_seen[hash_board(init)] = 0;\n\n    for (int depth = 0; depth + 1 < incumbent && elapsed() < deadline; depth++) {\n        vector<StepNode> nxt;\n        unordered_map<uint64_t, int> layer_seen;\n        layer_seen.reserve(WIDTH * CAND_LIMIT * 2);\n\n        for (auto& node : beam) {\n            if (elapsed() >= deadline) break;\n\n            vector<pair<double, Op>> ord;\n\n            auto try_op_for_rank = [&](char d, int p) {\n                vector<string> nb = node.b;\n                if (!apply_shift(nb, d, p)) return;\n\n                int r = count_oni(nb);\n                int sd = sum_visible_min_dist(nb);\n\n                double ev = (depth + 1) + 2.35 * r + 0.115 * sd;\n                if (r == node.rem) ev += 1.25;\n                ev *= 0.995 + (rng() % 100) / 10000.0;\n\n                ord.push_back({ev, {d, p}});\n            };\n\n            for (int i = 0; i < N; i++) {\n                try_op_for_rank('L', i);\n                try_op_for_rank('R', i);\n            }\n            for (int j = 0; j < N; j++) {\n                try_op_for_rank('U', j);\n                try_op_for_rank('D', j);\n            }\n\n            sort(ord.begin(), ord.end(), [](auto& a, auto& b) {\n                return a.first < b.first;\n            });\n\n            int lim = min<int>(CAND_LIMIT, ord.size());\n\n            for (int z = 0; z < lim; z++) {\n                Op op = ord[z].second;\n\n                StepNode nn;\n                nn.b = node.b;\n\n                if (!apply_shift(nn.b, op.d, op.p)) continue;\n\n                nn.rem = count_oni(nn.b);\n                nn.path = node.path;\n                nn.path.push_back(op);\n\n                if (nn.rem == 0) return nn.path;\n\n                uint64_t h = hash_board(nn.b);\n\n                auto itg = global_seen.find(h);\n                if (itg != global_seen.end() && itg->second <= depth + 1) continue;\n                global_seen[h] = depth + 1;\n\n                auto it = layer_seen.find(h);\n                if (it != layer_seen.end() && it->second <= (int)nn.path.size()) continue;\n                layer_seen[h] = nn.path.size();\n\n                nn.eval = ord[z].first;\n                nxt.push_back(std::move(nn));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        sort(nxt.begin(), nxt.end(), [](const StepNode& a, const StepNode& b) {\n            if (a.eval != b.eval) return a.eval < b.eval;\n            return a.path.size() < b.path.size();\n        });\n\n        if ((int)nxt.size() > WIDTH) nxt.resize(WIDTH);\n        beam.swap(nxt);\n    }\n\n    return {};\n}\n\n/* -------------------- Sequence simplification -------------------- */\n\nvoid postprocess_remove_blocks(\n    const vector<string>& init,\n    vector<Op>& ops,\n    mt19937& rng,\n    const chrono::steady_clock::time_point& start,\n    double deadline\n) {\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    if (!validate_solution(init, ops)) return;\n    truncate_when_done(init, ops);\n\n    bool improved = true;\n\n    while (improved && elapsed() < deadline) {\n        improved = false;\n\n        for (int len = 10; len >= 1 && elapsed() < deadline; len--) {\n            if ((int)ops.size() < len) continue;\n\n            vector<int> idx;\n            for (int i = 0; i + len <= (int)ops.size(); i++) idx.push_back(i);\n\n            if (len <= 4) shuffle(idx.begin(), idx.end(), rng);\n\n            for (int st : idx) {\n                if (elapsed() >= deadline) break;\n                if (st + len > (int)ops.size()) continue;\n\n                vector<Op> cand;\n                cand.reserve(ops.size() - len);\n\n                for (int i = 0; i < (int)ops.size(); i++) {\n                    if (i < st || i >= st + len) cand.push_back(ops[i]);\n                }\n\n                if (validate_solution(init, cand)) {\n                    truncate_when_done(init, cand);\n                    ops.swap(cand);\n                    improved = true;\n                    break;\n                }\n            }\n\n            if (improved) break;\n        }\n    }\n}\n\n/* -------------------- Main -------------------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n\n    vector<string> init(N);\n    for (int i = 0; i < N; i++) cin >> init[i];\n\n    mt19937 rng(1234567);\n    auto start = chrono::steady_clock::now();\n\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    vector<Op> best = solve_set_cover(init, rng);\n    if (!validate_solution(init, best)) best.clear();\n    if (!best.empty()) truncate_when_done(init, best);\n\n    {\n        vector<Op> beam_ops = beam_search_solver(\n            init,\n            rng,\n            start,\n            0.53,\n            best.empty() ? 4 * N * N + 1 : (int)best.size()\n        );\n\n        if (!beam_ops.empty()) {\n            truncate_when_done(init, beam_ops);\n            if ((best.empty() || beam_ops.size() < best.size()) && validate_solution(init, beam_ops)) {\n                best = beam_ops;\n            }\n        }\n    }\n\n    int trial = 0;\n\n    while (elapsed() < 1.72) {\n        int mode;\n        if (trial == 0) mode = 4;\n        else if (trial == 1) mode = 0;\n        else mode = rng() % 5;\n\n        vector<Op> ops = dynamic_trial(init, rng, mode);\n\n        if (!ops.empty()) {\n            truncate_when_done(init, ops);\n            if ((best.empty() || ops.size() < best.size()) && validate_solution(init, ops)) {\n                best = ops;\n            }\n        }\n\n        trial++;\n    }\n\n    if (!best.empty() && elapsed() < 1.84) {\n        vector<Op> step_ops = step_beam_solver(\n            init,\n            rng,\n            start,\n            1.84,\n            (int)best.size()\n        );\n\n        if (!step_ops.empty()) {\n            truncate_when_done(init, step_ops);\n            if ((int)step_ops.size() < (int)best.size() && validate_solution(init, step_ops)) {\n                best = step_ops;\n            }\n        }\n    }\n\n    if (!best.empty()) {\n        postprocess_remove_blocks(init, best, rng, start, 1.94);\n    }\n\n    if (best.empty() || !validate_solution(init, best) || (int)best.size() > 4 * N * N) {\n        rng.seed(42);\n        best = solve_set_cover(init, rng);\n        truncate_when_done(init, best);\n    }\n\n    for (auto [d, p] : best) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T;\nmt19937 rng(123456789);\n\nstruct Graph {\n    array<int, MAXN> a{}, b{}, cnt{};\n    int err = INT_MAX;\n};\n\ndouble elapsed_sec() {\n    static auto st = chrono::steady_clock::now();\n    auto now = chrono::steady_clock::now();\n    return chrono::duration<double>(now - st).count();\n}\n\nGraph evaluate(const array<int, MAXN>& a, const array<int, MAXN>& b) {\n    Graph g;\n    g.a = a;\n    g.b = b;\n    g.cnt.fill(0);\n\n    int cur = 0;\n    g.cnt[cur] = 1;\n\n    for (int step = 1; step < L; step++) {\n        int c = g.cnt[cur];\n        cur = (c & 1) ? a[cur] : b[cur];\n        g.cnt[cur]++;\n    }\n\n    long long e = 0;\n    for (int i = 0; i < N; i++) {\n        e += llabs((long long)g.cnt[i] - T[i]);\n    }\n\n    g.err = (int)e;\n    return g;\n}\n\nint weighted_pick(const vector<int>& v, const vector<int>& w) {\n    long long sum = 0;\n    for (int x : w) sum += x;\n\n    if (sum <= 0) return v[rng() % v.size()];\n\n    long long r = rng() % sum;\n    for (int i = 0; i < (int)v.size(); i++) {\n        if (r < w[i]) return v[i];\n        r -= w[i];\n    }\n\n    return v.back();\n}\n\nstruct Token {\n    int src;\n    int slot;\n    int w;\n};\n\nvoid add_elite(vector<Graph>& elite, const Graph& g, int K = 8) {\n    elite.push_back(g);\n    sort(elite.begin(), elite.end(), [](const Graph& x, const Graph& y) {\n        return x.err < y.err;\n    });\n    if ((int)elite.size() > K) elite.resize(K);\n}\n\nGraph make_cycle_candidate(int id) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    sort(active.begin(), active.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    if (id == 1) {\n        reverse(active.begin(), active.end());\n    } else if (id >= 2) {\n        int m = (int)active.size();\n        int swaps = (id % 9 + 1) * m / 16;\n        for (int k = 0; k < swaps; k++) {\n            int p = rng() % m;\n            int q = rng() % m;\n            swap(active[p], active[q]);\n        }\n    }\n\n    int m = (int)active.size();\n\n    vector<int> succ(N, root);\n    array<long long, MAXN> in{};\n    in.fill(0);\n\n    for (int k = 0; k < m; k++) {\n        int v = active[k];\n        int to = active[(k + 1) % m];\n        succ[v] = to;\n        in[to] += T[v];\n    }\n\n    vector<int> sources = active;\n    sort(sources.begin(), sources.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    vector<int> assigned(N, root);\n\n    for (int s : sources) {\n        long long w = T[s];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(m);\n\n        for (int d : active) {\n            long long before = llabs(in[d] - 2LL * T[d]);\n            long long after = llabs(in[d] + w - 2LL * T[d]);\n            cand.push_back({after - before, d});\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int choose = 0;\n        if (id >= 2) {\n            int lim = min(5, (int)cand.size());\n            choose = rng() % lim;\n        }\n\n        int d = cand[choose].second;\n        assigned[s] = d;\n        in[d] += w;\n    }\n\n    for (int it = 0; it < 45; it++) {\n        long long best_delta = 0;\n        int best_s = -1;\n        int best_d = -1;\n\n        for (int s : sources) {\n            int old = assigned[s];\n            long long w = T[s];\n\n            for (int d : active) {\n                if (d == old) continue;\n\n                long long cur =\n                    llabs(in[old] - 2LL * T[old]) +\n                    llabs(in[d] - 2LL * T[d]);\n\n                long long nxt =\n                    llabs(in[old] - w - 2LL * T[old]) +\n                    llabs(in[d] + w - 2LL * T[d]);\n\n                long long delta = nxt - cur;\n\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    best_s = s;\n                    best_d = d;\n                }\n            }\n        }\n\n        if (best_s == -1) break;\n\n        int old = assigned[best_s];\n        long long w = T[best_s];\n\n        in[old] -= w;\n        in[best_d] += w;\n        assigned[best_s] = best_d;\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            a[i] = succ[i];\n            b[i] = assigned[i];\n            if (id >= 2 && (rng() & 1)) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nGraph make_balanced_candidate(int id, bool parity_mode) {\n    array<int, MAXN> a{}, b{};\n    for (int i = 0; i < N; i++) a[i] = b[i] = 0;\n\n    vector<int> active;\n    for (int i = 0; i < N; i++) {\n        if (T[i] > 0) active.push_back(i);\n    }\n\n    int root = active[0];\n    for (int x : active) {\n        if (T[x] > T[root]) root = x;\n    }\n\n    if ((int)active.size() == 1) {\n        int v = active[0];\n        for (int i = 0; i < N; i++) a[i] = b[i] = v;\n        return evaluate(a, b);\n    }\n\n    vector<Token> tok;\n    tok.reserve(active.size() * 2);\n\n    for (int s : active) {\n        if (!parity_mode) {\n            tok.push_back({s, 0, T[s]});\n            tok.push_back({s, 1, T[s]});\n        } else {\n            int p = T[s] & 1;\n            tok.push_back({s, 0, T[s] + p});\n            tok.push_back({s, 1, T[s] - p});\n        }\n    }\n\n    int M = (int)tok.size();\n\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    vector<int> noise(M);\n    for (int i = 0; i < M; i++) {\n        noise[i] = (int)(rng() & 1023);\n    }\n\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        long long kx = 1000000LL * tok[x].w + noise[x] * (id % 7);\n        long long ky = 1000000LL * tok[y].w + noise[y] * (id % 7);\n\n        if (kx != ky) return kx > ky;\n        return x < y;\n    });\n\n    if (id % 11 == 0) {\n        shuffle(ord.begin(), ord.end(), rng);\n    } else if (id % 5 == 0) {\n        int block = 8 + (id % 7);\n\n        for (int l = 0; l < M; l += block) {\n            int r = min(M, l + block);\n            shuffle(ord.begin() + l, ord.begin() + r, rng);\n        }\n    }\n\n    array<long long, MAXN> rem{};\n    for (int i = 0; i < N; i++) {\n        rem[i] = 2LL * T[i];\n    }\n\n    array<array<int, 2>, MAXN> dest;\n    for (int i = 0; i < N; i++) {\n        dest[i][0] = dest[i][1] = -1;\n    }\n\n    vector<int> token_dest(M, -1);\n\n    bool hard_no_self = (id % 6 == 0 || id % 6 == 3);\n    bool avoid_same = (id % 6 != 1);\n\n    for (int idx : ord) {\n        int s = tok[idx].src;\n        int sl = tok[idx].slot;\n        int w = tok[idx].w;\n        int other = dest[s][1 - sl];\n\n        vector<pair<long long, int>> cand;\n        cand.reserve(active.size());\n\n        for (int d : active) {\n            if (hard_no_self && d == s && active.size() > 1) continue;\n\n            long long delta = llabs(rem[d] - w) - llabs(rem[d]);\n            long long penalty = 0;\n\n            if (d == s) penalty += 2LL * w + 500;\n            if (avoid_same && other == d) penalty += w / 2 + 300;\n\n            long long score =\n                delta * 100000LL +\n                penalty * 100LL +\n                (int)(rng() & 2047);\n\n            cand.push_back({score, d});\n        }\n\n        if (cand.empty()) {\n            for (int d : active) {\n                long long delta = llabs(rem[d] - w) - llabs(rem[d]);\n                cand.push_back({delta * 100000LL + (int)(rng() & 2047), d});\n            }\n        }\n\n        sort(cand.begin(), cand.end());\n\n        int lim = min((int)cand.size(), 1 + (id % 5));\n        if (id % 13 == 0) {\n            lim = min((int)cand.size(), 8);\n        }\n\n        int d = cand[rng() % lim].second;\n\n        dest[s][sl] = d;\n        token_dest[idx] = d;\n        rem[d] -= w;\n    }\n\n    auto violates = [&](int idx, int d) -> bool {\n        int s = tok[idx].src;\n        int sl = tok[idx].slot;\n\n        if (hard_no_self && d == s && active.size() > 1) return true;\n        if (avoid_same && dest[s][1 - sl] == d && active.size() > 2) return true;\n\n        return false;\n    };\n\n    int improve_trials = parity_mode ? 2600 : 3500;\n\n    for (int it = 0; it < improve_trials; it++) {\n        if (rng() & 1) {\n            int idx = rng() % M;\n            int old = token_dest[idx];\n            int d = active[rng() % active.size()];\n\n            if (d == old) continue;\n            if (violates(idx, d)) continue;\n\n            long long w = tok[idx].w;\n\n            long long delta =\n                llabs(rem[old] + w) - llabs(rem[old]) +\n                llabs(rem[d] - w) - llabs(rem[d]);\n\n            if (delta < 0 || (delta == 0 && (rng() & 7) == 0)) {\n                rem[old] += w;\n                rem[d] -= w;\n\n                token_dest[idx] = d;\n                dest[tok[idx].src][tok[idx].slot] = d;\n            }\n        } else {\n            int x = rng() % M;\n            int y = rng() % M;\n\n            if (x == y) continue;\n\n            int dx = token_dest[x];\n            int dy = token_dest[y];\n\n            if (dx == dy) continue;\n            if (violates(x, dy) || violates(y, dx)) continue;\n\n            long long wx = tok[x].w;\n            long long wy = tok[y].w;\n\n            long long before = llabs(rem[dx]) + llabs(rem[dy]);\n\n            long long ndx = rem[dx] + wx - wy;\n            long long ndy = rem[dy] + wy - wx;\n\n            long long after = llabs(ndx) + llabs(ndy);\n            long long delta = after - before;\n\n            if (delta < 0 || (delta == 0 && (rng() & 15) == 0)) {\n                rem[dx] = ndx;\n                rem[dy] = ndy;\n\n                token_dest[x] = dy;\n                token_dest[y] = dx;\n\n                dest[tok[x].src][tok[x].slot] = dy;\n                dest[tok[y].src][tok[y].slot] = dx;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (T[i] == 0) {\n            a[i] = b[i] = root;\n        } else {\n            int x = dest[i][0];\n            int y = dest[i][1];\n\n            if (x < 0) x = root;\n            if (y < 0) y = root;\n\n            a[i] = x;\n            b[i] = y;\n\n            if (!parity_mode && (rng() & 1)) swap(a[i], b[i]);\n        }\n    }\n\n    if (T[0] == 0) {\n        a[0] = b[0] = root;\n    }\n\n    return evaluate(a, b);\n}\n\nvoid phase_optimize(Graph& cur, Graph& best, vector<Graph>& elite, double limit) {\n    for (int pass = 0; pass < 3; pass++) {\n        bool improved = false;\n\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        if (pass) shuffle(ord.begin(), ord.end(), rng);\n\n        for (int i : ord) {\n            if (elapsed_sec() > limit) return;\n            if (cur.a[i] == cur.b[i]) continue;\n\n            swap(cur.a[i], cur.b[i]);\n\n            Graph ng = evaluate(cur.a, cur.b);\n\n            if (ng.err <= cur.err) {\n                cur = ng;\n                improved = true;\n\n                if (cur.err < best.err) {\n                    best = cur;\n                    add_elite(elite, best);\n                }\n            } else {\n                swap(cur.a[i], cur.b[i]);\n            }\n        }\n\n        if (!improved) break;\n    }\n}\n\nvoid final_phase_polish(Graph& best, double limit) {\n    Graph cur = best;\n\n    for (int pass = 0; pass < 2; pass++) {\n        bool improved = false;\n\n        for (int i = 0; i < N; i++) {\n            if (elapsed_sec() > limit) return;\n            if (cur.a[i] == cur.b[i]) continue;\n\n            swap(cur.a[i], cur.b[i]);\n\n            Graph ng = evaluate(cur.a, cur.b);\n\n            if (ng.err <= cur.err) {\n                cur = ng;\n                improved = true;\n                if (cur.err < best.err) best = cur;\n            } else {\n                swap(cur.a[i], cur.b[i]);\n            }\n        }\n\n        if (!improved) break;\n    }\n}\n\nbool make_mutation(const Graph& cur, array<int, MAXN>& na, array<int, MAXN>& nb) {\n    vector<int> over, under, wover, wunder;\n\n    for (int i = 0; i < N; i++) {\n        int d = cur.cnt[i] - T[i];\n\n        if (d > 0) {\n            over.push_back(i);\n            wover.push_back(d);\n        } else if (d < 0) {\n            under.push_back(i);\n            wunder.push_back(-d);\n        }\n    }\n\n    if (over.empty() || under.empty()) return false;\n\n    na = cur.a;\n    nb = cur.b;\n\n    int typ = rng() % 100;\n\n    if (typ < 12) {\n        int x = rng() % (2 * N);\n        int y = rng() % (2 * N);\n        if (x == y) return false;\n\n        int sx = x / 2, tx = x & 1;\n        int sy = y / 2, ty = y & 1;\n\n        int& ex = (tx == 0 ? na[sx] : nb[sx]);\n        int& ey = (ty == 0 ? na[sy] : nb[sy]);\n\n        if (ex == ey) return false;\n        swap(ex, ey);\n    } else if (typ < 27) {\n        int i = rng() % N;\n\n        if (na[i] == nb[i]) return false;\n\n        swap(na[i], nb[i]);\n    } else if (typ < 74) {\n        int v = weighted_pick(over, wover);\n        int u = weighted_pick(under, wunder);\n\n        vector<pair<int, int>> edges;\n\n        for (int i = 0; i < N; i++) {\n            if (na[i] == v) edges.push_back({i, 0});\n            if (nb[i] == v) edges.push_back({i, 1});\n        }\n\n        if (edges.empty()) return false;\n\n        auto [s, slot] = edges[rng() % edges.size()];\n\n        if (slot == 0) na[s] = u;\n        else nb[s] = u;\n    } else if (typ < 90) {\n        int s = weighted_pick(over, wover);\n        int u = weighted_pick(under, wunder);\n\n        if (rng() & 1) na[s] = u;\n        else nb[s] = u;\n    } else {\n        int s = rng() % N;\n        int u = weighted_pick(under, wunder);\n\n        if (rng() & 1) na[s] = u;\n        else nb[s] = u;\n    }\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n\n    uint64_t seed = 1469598103934665603ULL;\n\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n\n        seed ^= (uint64_t)(T[i] + 1000003) * (i + 1009);\n        seed *= 1099511628211ULL;\n    }\n\n    rng.seed((uint32_t)(seed ^ (seed >> 32)));\n\n    Graph best;\n    best.err = INT_MAX;\n\n    vector<Graph> elite;\n\n    auto consider = [&](const Graph& g) {\n        if (g.err < best.err) best = g;\n        add_elite(elite, g);\n    };\n\n    for (int id = 0; id < 35; id++) {\n        if (elapsed_sec() > 0.43) break;\n        consider(make_cycle_candidate(id));\n    }\n\n    for (int id = 0; id < 230; id++) {\n        if (elapsed_sec() > 1.04) break;\n        consider(make_balanced_candidate(id, false));\n    }\n\n    for (int id = 0; id < 35; id++) {\n        if (elapsed_sec() > 1.13) break;\n        consider(make_balanced_candidate(id + 1000, true));\n    }\n\n    sort(elite.begin(), elite.end(), [](const Graph& x, const Graph& y) {\n        return x.err < y.err;\n    });\n\n    int phn = min(3, (int)elite.size());\n    for (int i = 0; i < phn && elapsed_sec() < 1.30; i++) {\n        Graph cur = elite[i];\n        phase_optimize(cur, best, elite, 1.30);\n    }\n\n    Graph cur = best;\n    int no_improve = 0;\n\n    while (elapsed_sec() < 1.88) {\n        double now = elapsed_sec();\n\n        if (no_improve > 70 && !elite.empty() && (rng() % 5 == 0)) {\n            int lim = min(5, (int)elite.size());\n            cur = elite[rng() % lim];\n            no_improve = 0;\n        }\n\n        if (now < 1.64) {\n            array<int, MAXN> na, nb;\n            if (!make_mutation(cur, na, nb)) {\n                no_improve++;\n                continue;\n            }\n\n            Graph ng = evaluate(na, nb);\n\n            bool accept = false;\n\n            if (ng.err <= cur.err) {\n                accept = true;\n            } else {\n                double remain = max(0.0, 1.88 - now);\n\n                int temp = max(1, (int)(850.0 * remain / 1.88));\n                int diff = ng.err - cur.err;\n\n                if (diff < temp && (int)(rng() % temp) < temp - diff) {\n                    accept = true;\n                }\n            }\n\n            if (accept) {\n                cur = ng;\n\n                if (cur.err < best.err) {\n                    best = cur;\n                    add_elite(elite, best);\n                    no_improve = 0;\n                } else {\n                    no_improve++;\n                }\n            } else {\n                no_improve++;\n            }\n        } else {\n            Graph best_ng;\n            best_ng.err = INT_MAX;\n\n            int batch = 4;\n            for (int k = 0; k < batch && elapsed_sec() < 1.88; k++) {\n                array<int, MAXN> na, nb;\n                if (!make_mutation(cur, na, nb)) continue;\n\n                Graph ng = evaluate(na, nb);\n\n                if (ng.err < best_ng.err) {\n                    best_ng = ng;\n                }\n            }\n\n            if (best_ng.err == INT_MAX) break;\n\n            if (best_ng.err <= cur.err) {\n                cur = best_ng;\n\n                if (cur.err < best.err) {\n                    best = cur;\n                    add_elite(elite, best);\n                    no_improve = 0;\n                } else {\n                    no_improve++;\n                }\n            } else {\n                int diff = best_ng.err - cur.err;\n                int temp = 35;\n\n                if (diff < temp && (int)(rng() % temp) < temp - diff) {\n                    cur = best_ng;\n                }\n\n                no_improve++;\n            }\n        }\n    }\n\n    // Extra exact safe polishing using remaining time.\n    final_phase_polish(best, 1.96);\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st = chrono::steady_clock::now();\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<double> cx, cy;\n\ninline double dist2p(double x1, double y1, double x2, double y2) {\n    double dx = x1 - x2, dy = y1 - y2;\n    return dx * dx + dy * dy;\n}\n\ninline double edist(int a, int b) {\n    return sqrt(dist2p(cx[a], cy[a], cx[b], cy[b]));\n}\n\ninline unsigned long long ekey(int a, int b) {\n    if (a > b) swap(a, b);\n    return (unsigned long long)a << 32 | (unsigned int)b;\n}\n\ninline pair<int,int> decode_key(unsigned long long k) {\n    return {(int)(k >> 32), (int)(k & 0xffffffffu)};\n}\n\nlong long hilbert_index(int x, int y, int bits = 14) {\n    long long d = 0;\n    int n = 1 << bits;\n    for (int s = n >> 1; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += 1LL * s * s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = n - 1 - x;\n                y = n - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\ndouble mst_cost(const vector<int>& verts) {\n    int n = (int)verts.size();\n    if (n <= 1) return 0.0;\n    if (n == 2) return edist(verts[0], verts[1]);\n\n    vector<double> minv(n, 1e100);\n    vector<char> used(n, 0);\n    minv[0] = 0.0;\n\n    double res = 0.0;\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n        used[v] = 1;\n        res += best;\n\n        int cv = verts[v];\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(cv, verts[u]);\n                if (d < minv[u]) minv[u] = d;\n            }\n        }\n    }\n    return res;\n}\n\nvector<pair<int,int>> prim_edges(const vector<int>& verts) {\n    int n = (int)verts.size();\n    vector<pair<int,int>> ret;\n    if (n <= 1) return ret;\n    if (n == 2) {\n        ret.push_back({verts[0], verts[1]});\n        return ret;\n    }\n\n    vector<double> minv(n, 1e100);\n    vector<int> par(n, -1);\n    vector<char> used(n, 0);\n    minv[0] = 0.0;\n\n    for (int it = 0; it < n; it++) {\n        int v = -1;\n        double best = 1e100;\n        for (int i = 0; i < n; i++) {\n            if (!used[i] && minv[i] < best) {\n                best = minv[i];\n                v = i;\n            }\n        }\n\n        used[v] = 1;\n        if (par[v] != -1) ret.push_back({verts[v], verts[par[v]]});\n\n        int cv = verts[v];\n        for (int u = 0; u < n; u++) {\n            if (!used[u]) {\n                double d = edist(cv, verts[u]);\n                if (d < minv[u]) {\n                    minv[u] = d;\n                    par[u] = v;\n                }\n            }\n        }\n    }\n    return ret;\n}\n\ndouble total_mst_cost(const vector<vector<int>>& groups) {\n    double s = 0.0;\n    for (auto& g : groups) s += mst_cost(g);\n    return s;\n}\n\nvector<vector<int>> build_from_order(const vector<int>& ord, const vector<int>& perm) {\n    vector<vector<int>> groups(M);\n    int pos = 0;\n    for (int id : perm) {\n        groups[id].assign(ord.begin() + pos, ord.begin() + pos + G[id]);\n        pos += G[id];\n    }\n    return groups;\n}\n\nstruct OrderEvaluator {\n    const vector<int>* ord;\n    unordered_map<int, double> cache;\n\n    OrderEvaluator(const vector<int>& o) : ord(&o) {\n        cache.reserve(6000);\n    }\n\n    double interval_cost(int s, int len) {\n        if (len <= 1) return 0.0;\n        if (len == 2) return edist((*ord)[s], (*ord)[s + 1]);\n\n        int key = s * 1000 + len;\n        auto it = cache.find(key);\n        if (it != cache.end()) return it->second;\n\n        vector<int> verts;\n        verts.reserve(len);\n        for (int i = 0; i < len; i++) verts.push_back((*ord)[s + i]);\n\n        double c = mst_cost(verts);\n        cache[key] = c;\n        return c;\n    }\n\n    vector<int> improve_perm(vector<int> perm, int maxPass = 20) {\n        if (M <= 1) return perm;\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            bool changed = false;\n            vector<int> pref(M + 1, 0);\n            for (int i = 0; i < M; i++) pref[i + 1] = pref[i] + G[perm[i]];\n\n            for (int i = 0; i + 1 < M; i++) {\n                int s = pref[i];\n                int a = perm[i];\n                int b = perm[i + 1];\n\n                double oldc = interval_cost(s, G[a]) + interval_cost(s + G[a], G[b]);\n                double newc = interval_cost(s, G[b]) + interval_cost(s + G[b], G[a]);\n\n                if (newc + 1e-9 < oldc) {\n                    swap(perm[i], perm[i + 1]);\n                    changed = true;\n                    for (int j = i; j < M; j++) {\n                        pref[j + 1] = pref[j] + G[perm[j]];\n                    }\n                }\n            }\n            if (!changed) break;\n        }\n        return perm;\n    }\n};\n\nvector<vector<int>> make_size_perms() {\n    vector<vector<int>> vars;\n\n    vector<int> p(M);\n    iota(p.begin(), p.end(), 0);\n    vars.push_back(p);\n\n    vector<int> r = p;\n    reverse(r.begin(), r.end());\n    vars.push_back(r);\n\n    vector<int> asc = p;\n    sort(asc.begin(), asc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n    vars.push_back(asc);\n\n    vector<int> desc = p;\n    sort(desc.begin(), desc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n    vars.push_back(desc);\n\n    return vars;\n}\n\npair<vector<int>, int> split_group_ids_subset_sum(const vector<int>& gids, int total) {\n    int target = total / 2;\n\n    vector<char> dp(total + 1, 0);\n    vector<int> preSum(total + 1, -1), preId(total + 1, -1);\n    dp[0] = 1;\n\n    for (int id : gids) {\n        int w = G[id];\n        for (int s = total - w; s >= 0; s--) {\n            if (dp[s] && !dp[s + w]) {\n                dp[s + w] = 1;\n                preSum[s + w] = s;\n                preId[s + w] = id;\n            }\n        }\n    }\n\n    int best = -1;\n    for (int d = 0; d <= total; d++) {\n        int s1 = target - d;\n        int s2 = target + d;\n        if (s1 > 0 && s1 < total && dp[s1]) {\n            best = s1;\n            break;\n        }\n        if (s2 > 0 && s2 < total && dp[s2]) {\n            best = s2;\n            break;\n        }\n    }\n\n    if (best == -1) return {{gids[0]}, G[gids[0]]};\n\n    vector<int> left;\n    int cur = best;\n    while (cur > 0) {\n        int id = preId[cur];\n        left.push_back(id);\n        cur = preSum[cur];\n    }\n\n    return {left, best};\n}\n\nvoid recursive_partition(\n    const vector<int>& cities,\n    const vector<int>& gids,\n    int depth,\n    int variant,\n    vector<vector<int>>& groups\n) {\n    if (gids.size() == 1) {\n        groups[gids[0]] = cities;\n        return;\n    }\n\n    int total = (int)cities.size();\n    auto [leftIds, leftCount] = split_group_ids_subset_sum(gids, total);\n\n    vector<char> inLeft(M, 0);\n    for (int id : leftIds) inLeft[id] = 1;\n\n    vector<int> rightIds;\n    for (int id : gids) {\n        if (!inLeft[id]) rightIds.push_back(id);\n    }\n\n    vector<int> sorted = cities;\n\n    if (variant == 0) {\n        double minx = 1e100, maxx = -1e100;\n        double miny = 1e100, maxy = -1e100;\n\n        for (int v : cities) {\n            minx = min(minx, cx[v]);\n            maxx = max(maxx, cx[v]);\n            miny = min(miny, cy[v]);\n            maxy = max(maxy, cy[v]);\n        }\n\n        bool useX = (maxx - minx >= maxy - miny);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            if (useX) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            } else {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            }\n        });\n    } else if (variant == 1) {\n        bool useX = (depth % 2 == 0);\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            if (useX) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            } else {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            }\n        });\n    } else if (variant == 2) {\n        double mx = 0.0, my = 0.0;\n        for (int v : cities) {\n            mx += cx[v];\n            my += cy[v];\n        }\n\n        mx /= cities.size();\n        my /= cities.size();\n\n        double sxx = 0.0, syy = 0.0, sxy = 0.0;\n        for (int v : cities) {\n            double x = cx[v] - mx;\n            double y = cy[v] - my;\n            sxx += x * x;\n            syy += y * y;\n            sxy += x * y;\n        }\n\n        double theta = 0.5 * atan2(2.0 * sxy, sxx - syy);\n        double vx = cos(theta);\n        double vy = sin(theta);\n\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            double pa = cx[a] * vx + cy[a] * vy;\n            double pb = cx[b] * vx + cy[b] * vy;\n            if (pa != pb) return pa < pb;\n            return a < b;\n        });\n    } else {\n        bool diag = (depth % 2 == 0);\n        sort(sorted.begin(), sorted.end(), [&](int a, int b) {\n            double pa = diag ? (cx[a] + cy[a]) : (cx[a] - cy[a]);\n            double pb = diag ? (cx[b] + cy[b]) : (cx[b] - cy[b]);\n            if (pa != pb) return pa < pb;\n            return a < b;\n        });\n    }\n\n    vector<int> leftCities(sorted.begin(), sorted.begin() + leftCount);\n    vector<int> rightCities(sorted.begin() + leftCount, sorted.end());\n\n    recursive_partition(leftCities, leftIds, depth + 1, variant, groups);\n    recursive_partition(rightCities, rightIds, depth + 1, variant, groups);\n}\n\nvector<vector<int>> make_recursive_candidate(int variant) {\n    vector<int> cities(N), gids(M);\n    iota(cities.begin(), cities.end(), 0);\n    iota(gids.begin(), gids.end(), 0);\n\n    vector<vector<int>> groups(M);\n    recursive_partition(cities, gids, 0, variant, groups);\n    return groups;\n}\n\nvector<vector<int>> make_greedy_candidate(int variant) {\n    vector<vector<int>> groups(M);\n    vector<char> used(N, 0);\n\n    vector<int> gids(M);\n    iota(gids.begin(), gids.end(), 0);\n\n    int orderType = variant % 3;\n    int seedType = variant / 3;\n\n    if (orderType == 0) {\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] > G[b];\n            return a < b;\n        });\n    } else if (orderType == 1) {\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] < G[b];\n            return a < b;\n        });\n    }\n\n    vector<long long> hval(N);\n    for (int i = 0; i < N; i++) {\n        int xi = min(16383, max(0, (int)llround(cx[i] * 16383.0 / 10000.0)));\n        int yi = min(16383, max(0, (int)llround(cy[i] * 16383.0 / 10000.0)));\n        hval[i] = hilbert_index(xi, yi);\n    }\n\n    for (int gid : gids) {\n        vector<int> rem;\n        rem.reserve(N);\n\n        for (int i = 0; i < N; i++) {\n            if (!used[i]) rem.push_back(i);\n        }\n\n        if ((int)rem.size() == G[gid]) {\n            groups[gid] = rem;\n            for (int v : rem) used[v] = 1;\n            continue;\n        }\n\n        int seed = rem[0];\n\n        if (seedType == 0) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cx[a] < cx[b];\n            });\n        } else if (seedType == 1) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cx[a] < cx[b];\n            });\n        } else if (seedType == 2) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cy[a] < cy[b];\n            });\n        } else if (seedType == 3) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cy[a] < cy[b];\n            });\n        } else if (seedType == 4) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return hval[a] < hval[b];\n            });\n        } else if (seedType == 5) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return hval[a] < hval[b];\n            });\n        } else if (seedType == 6) {\n            seed = *min_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cx[a] + cy[a] < cx[b] + cy[b];\n            });\n        } else if (seedType == 7) {\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return cx[a] + cy[a] < cx[b] + cy[b];\n            });\n        } else {\n            double mx = 0.0, my = 0.0;\n            for (int v : rem) {\n                mx += cx[v];\n                my += cy[v];\n            }\n            mx /= rem.size();\n            my /= rem.size();\n\n            seed = *max_element(rem.begin(), rem.end(), [&](int a, int b) {\n                return dist2p(cx[a], cy[a], mx, my) < dist2p(cx[b], cy[b], mx, my);\n            });\n        }\n\n        vector<pair<double,int>> cand;\n        cand.reserve(rem.size());\n\n        for (int v : rem) {\n            cand.push_back({dist2p(cx[v], cy[v], cx[seed], cy[seed]), v});\n        }\n\n        sort(cand.begin(), cand.end());\n\n        vector<int> sel;\n        for (int i = 0; i < G[gid]; i++) sel.push_back(cand[i].second);\n\n        if ((int)sel.size() >= 4) {\n            double mx = 0.0, my = 0.0;\n            for (int v : sel) {\n                mx += cx[v];\n                my += cy[v];\n            }\n            mx /= sel.size();\n            my /= sel.size();\n\n            cand.clear();\n            for (int v : rem) {\n                cand.push_back({dist2p(cx[v], cy[v], mx, my), v});\n            }\n\n            sort(cand.begin(), cand.end());\n            sel.clear();\n            for (int i = 0; i < G[gid]; i++) sel.push_back(cand[i].second);\n        }\n\n        groups[gid] = sel;\n        for (int v : sel) used[v] = 1;\n    }\n\n    return groups;\n}\n\nvector<vector<int>> capacitated_lloyd(vector<vector<int>> init, int iterations) {\n    vector<vector<int>> cur = init;\n    vector<vector<int>> best = cur;\n    double bestCost = total_mst_cost(best);\n\n    if (M == 1) return cur;\n\n    for (int it = 0; it < iterations; it++) {\n        vector<double> gx(M, 0.0), gy(M, 0.0);\n\n        for (int gid = 0; gid < M; gid++) {\n            for (int v : cur[gid]) {\n                gx[gid] += cx[v];\n                gy[gid] += cy[v];\n            }\n            gx[gid] /= max(1, (int)cur[gid].size());\n            gy[gid] /= max(1, (int)cur[gid].size());\n        }\n\n        struct Item {\n            double margin;\n            int city;\n            vector<pair<double,int>> ord;\n        };\n\n        vector<Item> items;\n        items.reserve(N);\n\n        for (int v = 0; v < N; v++) {\n            vector<pair<double,int>> ds;\n            ds.reserve(M);\n\n            for (int gid = 0; gid < M; gid++) {\n                double d = dist2p(cx[v], cy[v], gx[gid], gy[gid]);\n                ds.push_back({d, gid});\n            }\n\n            int keep = min(M, max(12, min(36, M)));\n            nth_element(ds.begin(), ds.begin() + keep - 1, ds.end());\n            ds.resize(keep);\n            sort(ds.begin(), ds.end());\n\n            double margin = 1e18;\n            if ((int)ds.size() >= 2) margin = ds[1].first - ds[0].first;\n\n            items.push_back({margin, v, move(ds)});\n        }\n\n        sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n            return a.margin > b.margin;\n        });\n\n        vector<int> rem = G;\n        vector<vector<int>> nxt(M);\n\n        for (auto& item : items) {\n            int chosen = -1;\n\n            for (auto [d, gid] : item.ord) {\n                if (rem[gid] > 0) {\n                    chosen = gid;\n                    break;\n                }\n            }\n\n            if (chosen == -1) {\n                double bd = 1e100;\n                for (int gid = 0; gid < M; gid++) {\n                    if (rem[gid] <= 0) continue;\n                    double d = dist2p(cx[item.city], cy[item.city], gx[gid], gy[gid]);\n                    if (d < bd) {\n                        bd = d;\n                        chosen = gid;\n                    }\n                }\n            }\n\n            nxt[chosen].push_back(item.city);\n            rem[chosen]--;\n        }\n\n        cur.swap(nxt);\n\n        double c = total_mst_cost(cur);\n        if (c < bestCost) {\n            bestCost = c;\n            best = cur;\n        }\n    }\n\n    return best;\n}\n\nstring subset_key(vector<int> v) {\n    sort(v.begin(), v.end());\n    string s;\n    s.reserve(v.size() * 5);\n\n    for (int x : v) {\n        s += to_string(x);\n        s += ',';\n    }\n\n    return s;\n}\n\nvector<pair<int,int>> do_query(const vector<int>& c) {\n    cout << \"? \" << c.size();\n    for (int v : c) cout << ' ' << v;\n    cout << endl;\n    cout.flush();\n\n    vector<pair<int,int>> ret;\n\n    for (int i = 0; i < (int)c.size() - 1; i++) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        ret.push_back({a, b});\n    }\n\n    return ret;\n}\n\nvector<int> nearest_subset_to_seed(const vector<int>& group, int seed) {\n    vector<pair<double,int>> v;\n    v.reserve(group.size());\n\n    for (int x : group) v.push_back({edist(seed, x), x});\n    sort(v.begin(), v.end());\n\n    vector<int> sub;\n    int lim = min(L, (int)v.size());\n    for (int i = 0; i < lim; i++) sub.push_back(v[i].second);\n\n    return sub;\n}\n\nvector<int> nearest_subset_to_edge(const vector<int>& group, int a, int b) {\n    double mx = (cx[a] + cx[b]) * 0.5;\n    double my = (cy[a] + cy[b]) * 0.5;\n\n    vector<pair<double,int>> v;\n    v.reserve(group.size());\n\n    for (int x : group) {\n        double d = dist2p(cx[x], cy[x], mx, my);\n        if (x == a || x == b) d -= 1e18;\n        v.push_back({d, x});\n    }\n\n    sort(v.begin(), v.end());\n\n    vector<int> sub;\n    int lim = min(L, (int)v.size());\n    for (int i = 0; i < lim; i++) sub.push_back(v[i].second);\n\n    bool hasA = false, hasB = false;\n    for (int x : sub) {\n        if (x == a) hasA = true;\n        if (x == b) hasB = true;\n    }\n\n    if (!hasA && !sub.empty()) sub.back() = a;\n\n    hasB = false;\n    for (int x : sub) {\n        if (x == b) hasB = true;\n    }\n\n    if (!hasB && sub.size() >= 2) sub[sub.size() - 2] = b;\n\n    sort(sub.begin(), sub.end());\n    sub.erase(unique(sub.begin(), sub.end()), sub.end());\n\n    for (int x : group) {\n        if ((int)sub.size() >= min(L, (int)group.size())) break;\n        if (find(sub.begin(), sub.end(), x) == sub.end()) sub.push_back(x);\n    }\n\n    return sub;\n}\n\n// Pairwise repartition with local 2-group polishing.\nvoid pair_repartition_refine(\n    vector<vector<int>>& groups,\n    vector<int>& cityGroup,\n    vector<int>& cityPos,\n    vector<double>& groupCost,\n    Timer& timer\n) {\n    if (M <= 1) return;\n\n    for (int pass = 0; pass < 2; pass++) {\n        if (timer.sec() > 1.25) break;\n\n        vector<double> gx(M, 0.0), gy(M, 0.0);\n\n        for (int gid = 0; gid < M; gid++) {\n            for (int v : groups[gid]) {\n                gx[gid] += cx[v];\n                gy[gid] += cy[v];\n            }\n            gx[gid] /= groups[gid].size();\n            gy[gid] /= groups[gid].size();\n        }\n\n        vector<tuple<double,int,int>> pairs;\n\n        for (int a = 0; a < M; a++) {\n            vector<pair<double,int>> near;\n            near.reserve(M - 1);\n\n            for (int b = 0; b < M; b++) {\n                if (a == b) continue;\n                near.push_back({dist2p(gx[a], gy[a], gx[b], gy[b]), b});\n            }\n\n            int k = min(8, (int)near.size());\n            nth_element(near.begin(), near.begin() + k - 1, near.end());\n            near.resize(k);\n\n            for (auto [d, b] : near) {\n                int x = min(a, b);\n                int y = max(a, b);\n                pairs.push_back({d, x, y});\n            }\n        }\n\n        sort(pairs.begin(), pairs.end(), [](auto& a, auto& b) {\n            if (get<1>(a) != get<1>(b)) return get<1>(a) < get<1>(b);\n            if (get<2>(a) != get<2>(b)) return get<2>(a) < get<2>(b);\n            return get<0>(a) < get<0>(b);\n        });\n\n        pairs.erase(unique(pairs.begin(), pairs.end(), [](auto& x, auto& y) {\n            return get<1>(x) == get<1>(y) && get<2>(x) == get<2>(y);\n        }), pairs.end());\n\n        sort(pairs.begin(), pairs.end());\n\n        bool changed = false;\n\n        for (auto [pd, ga, gb] : pairs) {\n            if (timer.sec() > 1.36) break;\n\n            int sa = G[ga];\n            int sb = G[gb];\n\n            vector<int> all;\n            all.reserve(sa + sb);\n\n            for (int v : groups[ga]) all.push_back(v);\n            for (int v : groups[gb]) all.push_back(v);\n\n            double oldCost = groupCost[ga] + groupCost[gb];\n\n            vector<int> bestA, bestB;\n            double bestCost = oldCost;\n\n            auto update_best = [&](vector<int> A, bool polish) {\n                if ((int)A.size() != sa) return;\n\n                vector<char> inA(N, 0);\n                for (int v : A) inA[v] = 1;\n\n                vector<int> B;\n                B.reserve(sb);\n\n                for (int v : all) {\n                    if (!inA[v]) B.push_back(v);\n                }\n\n                if ((int)B.size() != sb) return;\n\n                auto eval_plain = [&](const vector<int>& AA, const vector<int>& BB) {\n                    return mst_cost(AA) + mst_cost(BB);\n                };\n\n                double c = eval_plain(A, B);\n\n                if (c + 2.0 < bestCost) {\n                    bestCost = c;\n                    bestA = A;\n                    bestB = B;\n                }\n\n                if (!polish) return;\n                if ((int)all.size() > 80) return;\n                if (timer.sec() > 1.35) return;\n\n                vector<int> curA = A;\n                vector<int> curB = B;\n                double curCost = c;\n\n                for (int iter = 0; iter < 2; iter++) {\n                    double ax = 0.0, ay = 0.0, bx = 0.0, by = 0.0;\n\n                    for (int v : curA) {\n                        ax += cx[v];\n                        ay += cy[v];\n                    }\n                    for (int v : curB) {\n                        bx += cx[v];\n                        by += cy[v];\n                    }\n\n                    ax /= curA.size();\n                    ay /= curA.size();\n                    bx /= curB.size();\n                    by /= curB.size();\n\n                    vector<pair<double,int>> candA, candB;\n\n                    for (int v : curA) {\n                        double s = dist2p(cx[v], cy[v], bx, by)\n                                 - dist2p(cx[v], cy[v], ax, ay);\n                        candA.push_back({s, v});\n                    }\n\n                    for (int v : curB) {\n                        double s = dist2p(cx[v], cy[v], ax, ay)\n                                 - dist2p(cx[v], cy[v], bx, by);\n                        candB.push_back({s, v});\n                    }\n\n                    sort(candA.begin(), candA.end());\n                    sort(candB.begin(), candB.end());\n\n                    int limA = min(4, (int)candA.size());\n                    int limB = min(4, (int)candB.size());\n\n                    double bestSwapCost = curCost;\n                    int bestAi = -1, bestBi = -1;\n\n                    for (int ia = 0; ia < limA; ia++) {\n                        for (int ib = 0; ib < limB; ib++) {\n                            int va = candA[ia].second;\n                            int vb = candB[ib].second;\n\n                            vector<int> nA = curA;\n                            vector<int> nB = curB;\n\n                            for (int& x : nA) {\n                                if (x == va) {\n                                    x = vb;\n                                    break;\n                                }\n                            }\n\n                            for (int& x : nB) {\n                                if (x == vb) {\n                                    x = va;\n                                    break;\n                                }\n                            }\n\n                            double nc = eval_plain(nA, nB);\n\n                            if (nc + 1.0 < bestSwapCost) {\n                                bestSwapCost = nc;\n                                bestAi = va;\n                                bestBi = vb;\n                            }\n                        }\n                    }\n\n                    if (bestAi == -1) break;\n\n                    for (int& x : curA) {\n                        if (x == bestAi) {\n                            x = bestBi;\n                            break;\n                        }\n                    }\n\n                    for (int& x : curB) {\n                        if (x == bestBi) {\n                            x = bestAi;\n                            break;\n                        }\n                    }\n\n                    curCost = bestSwapCost;\n\n                    if (curCost + 2.0 < bestCost) {\n                        bestCost = curCost;\n                        bestA = curA;\n                        bestB = curB;\n                    }\n                }\n            };\n\n            auto by_key_take = [&](auto keyFunc, bool rev) {\n                vector<pair<double,int>> arr;\n                arr.reserve(all.size());\n\n                for (int v : all) arr.push_back({keyFunc(v), v});\n\n                sort(arr.begin(), arr.end());\n                if (rev) reverse(arr.begin(), arr.end());\n\n                vector<int> A;\n                A.reserve(sa);\n\n                for (int i = 0; i < sa; i++) A.push_back(arr[i].second);\n\n                update_best(move(A), true);\n            };\n\n            auto balanced2 = [&](double ax, double ay, double bx, double by) {\n                vector<int> A;\n\n                for (int it = 0; it < 5; it++) {\n                    vector<pair<double,int>> arr;\n                    arr.reserve(all.size());\n\n                    for (int v : all) {\n                        double da = dist2p(cx[v], cy[v], ax, ay);\n                        double db = dist2p(cx[v], cy[v], bx, by);\n                        arr.push_back({da - db, v});\n                    }\n\n                    sort(arr.begin(), arr.end());\n\n                    A.clear();\n                    A.reserve(sa);\n\n                    vector<char> inA(N, 0);\n\n                    for (int i = 0; i < sa; i++) {\n                        A.push_back(arr[i].second);\n                        inA[arr[i].second] = 1;\n                    }\n\n                    update_best(A, true);\n\n                    double nax = 0.0, nay = 0.0;\n                    double nbx = 0.0, nby = 0.0;\n                    int ca = 0, cb = 0;\n\n                    for (int v : all) {\n                        if (inA[v]) {\n                            nax += cx[v];\n                            nay += cy[v];\n                            ca++;\n                        } else {\n                            nbx += cx[v];\n                            nby += cy[v];\n                            cb++;\n                        }\n                    }\n\n                    if (ca > 0) {\n                        ax = nax / ca;\n                        ay = nay / ca;\n                    }\n                    if (cb > 0) {\n                        bx = nbx / cb;\n                        by = nby / cb;\n                    }\n                }\n            };\n\n            by_key_take([&](int v) {\n                return dist2p(cx[v], cy[v], gx[ga], gy[ga])\n                     - dist2p(cx[v], cy[v], gx[gb], gy[gb]);\n            }, false);\n\n            by_key_take([&](int v) {\n                return dist2p(cx[v], cy[v], gx[ga], gy[ga]);\n            }, false);\n\n            by_key_take([&](int v) {\n                return dist2p(cx[v], cy[v], gx[gb], gy[gb]);\n            }, true);\n\n            double vx = gx[gb] - gx[ga];\n            double vy = gy[gb] - gy[ga];\n\n            if (vx * vx + vy * vy < 1e-9) {\n                vx = 1.0;\n                vy = 0.0;\n            }\n\n            vector<pair<double,double>> dirs = {\n                {vx, vy}, {-vy, vx}, {1.0, 0.0}, {0.0, 1.0},\n                {1.0, 1.0}, {1.0, -1.0}, {2.0, 1.0}, {1.0, 2.0}\n            };\n\n            for (auto [dx, dy] : dirs) {\n                by_key_take([&](int v) {\n                    return cx[v] * dx + cy[v] * dy;\n                }, false);\n\n                by_key_take([&](int v) {\n                    return cx[v] * dx + cy[v] * dy;\n                }, true);\n            }\n\n            balanced2(gx[ga], gy[ga], gx[gb], gy[gb]);\n            balanced2(gx[gb], gy[gb], gx[ga], gy[ga]);\n\n            int p0 = all[0], p1 = all[0];\n\n            for (int v : all) {\n                if (cx[v] + cy[v] < cx[p0] + cy[p0]) p0 = v;\n                if (cx[v] + cy[v] > cx[p1] + cy[p1]) p1 = v;\n            }\n\n            balanced2(cx[p0], cy[p0], cx[p1], cy[p1]);\n            balanced2(cx[p1], cy[p1], cx[p0], cy[p0]);\n\n            if (bestCost + 2.0 < oldCost) {\n                groups[ga] = bestA;\n                groups[gb] = bestB;\n                groupCost[ga] = mst_cost(groups[ga]);\n                groupCost[gb] = mst_cost(groups[gb]);\n\n                for (int p = 0; p < (int)groups[ga].size(); p++) {\n                    cityGroup[groups[ga][p]] = ga;\n                    cityPos[groups[ga][p]] = p;\n                }\n\n                for (int p = 0; p < (int)groups[gb].size(); p++) {\n                    cityGroup[groups[gb][p]] = gb;\n                    cityPos[groups[gb][p]] = p;\n                }\n\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n}\n\n// Triple repartition with small additional 3-group swap polishing.\nvoid triple_repartition_refine(\n    vector<vector<int>>& groups,\n    vector<int>& cityGroup,\n    vector<int>& cityPos,\n    vector<double>& groupCost,\n    Timer& timer\n) {\n    if (M <= 2) return;\n    if (timer.sec() > 1.36) return;\n\n    vector<double> gx(M, 0.0), gy(M, 0.0);\n\n    for (int gid = 0; gid < M; gid++) {\n        for (int v : groups[gid]) {\n            gx[gid] += cx[v];\n            gy[gid] += cy[v];\n        }\n        gx[gid] /= groups[gid].size();\n        gy[gid] /= groups[gid].size();\n    }\n\n    vector<array<int,3>> triples;\n    set<array<int,3>> seen;\n\n    for (int a = 0; a < M; a++) {\n        vector<pair<double,int>> near;\n        for (int b = 0; b < M; b++) {\n            if (a == b) continue;\n            near.push_back({dist2p(gx[a], gy[a], gx[b], gy[b]), b});\n        }\n\n        int k = min(4, (int)near.size());\n        nth_element(near.begin(), near.begin() + k - 1, near.end());\n        near.resize(k);\n        sort(near.begin(), near.end());\n\n        for (int i = 0; i < k; i++) {\n            for (int j = i + 1; j < k; j++) {\n                array<int,3> t = {a, near[i].second, near[j].second};\n                sort(t.begin(), t.end());\n\n                int sz = G[t[0]] + G[t[1]] + G[t[2]];\n                if (sz > 90) continue;\n\n                if (seen.insert(t).second) triples.push_back(t);\n            }\n        }\n    }\n\n    sort(triples.begin(), triples.end(), [&](const array<int,3>& A, const array<int,3>& B) {\n        double ax = (gx[A[0]] + gx[A[1]] + gx[A[2]]) / 3.0;\n        double ay = (gy[A[0]] + gy[A[1]] + gy[A[2]]) / 3.0;\n        double bx = (gx[B[0]] + gx[B[1]] + gx[B[2]]) / 3.0;\n        double by = (gy[B[0]] + gy[B[1]] + gy[B[2]]) / 3.0;\n\n        double da = dist2p(gx[A[0]], gy[A[0]], ax, ay)\n                  + dist2p(gx[A[1]], gy[A[1]], ax, ay)\n                  + dist2p(gx[A[2]], gy[A[2]], ax, ay);\n        double db = dist2p(gx[B[0]], gy[B[0]], bx, by)\n                  + dist2p(gx[B[1]], gy[B[1]], bx, by)\n                  + dist2p(gx[B[2]], gy[B[2]], bx, by);\n        return da < db;\n    });\n\n    if ((int)triples.size() > 180) triples.resize(180);\n\n    auto eval_partition = [&](const array<vector<int>,3>& part) {\n        return mst_cost(part[0]) + mst_cost(part[1]) + mst_cost(part[2]);\n    };\n\n    for (auto ids : triples) {\n        if (timer.sec() > 1.43) break;\n\n        int g0 = ids[0], g1 = ids[1], g2 = ids[2];\n        int s0 = G[g0], s1 = G[g1], s2 = G[g2];\n\n        vector<int> all;\n        for (int id : ids) {\n            for (int v : groups[id]) all.push_back(v);\n        }\n\n        double oldCost = groupCost[g0] + groupCost[g1] + groupCost[g2];\n        double bestCost = oldCost;\n        array<vector<int>,3> bestPart;\n\n        auto polish3 = [&](array<vector<int>,3> part) {\n            if ((int)all.size() > 75) return part;\n            if (timer.sec() > 1.42) return part;\n\n            double curCost = eval_partition(part);\n\n            for (int iter = 0; iter < 2; iter++) {\n                array<double,3> px{}, py{};\n                for (int k = 0; k < 3; k++) {\n                    for (int v : part[k]) {\n                        px[k] += cx[v];\n                        py[k] += cy[v];\n                    }\n                    px[k] /= max(1, (int)part[k].size());\n                    py[k] /= max(1, (int)part[k].size());\n                }\n\n                double bestSwap = curCost;\n                int ba = -1, bb = -1, va = -1, vb = -1;\n\n                for (int a = 0; a < 3; a++) {\n                    for (int b = a + 1; b < 3; b++) {\n                        vector<pair<double,int>> ca, cb;\n\n                        for (int v : part[a]) {\n                            double s = dist2p(cx[v], cy[v], px[b], py[b])\n                                     - dist2p(cx[v], cy[v], px[a], py[a]);\n                            ca.push_back({s, v});\n                        }\n\n                        for (int v : part[b]) {\n                            double s = dist2p(cx[v], cy[v], px[a], py[a])\n                                     - dist2p(cx[v], cy[v], px[b], py[b]);\n                            cb.push_back({s, v});\n                        }\n\n                        sort(ca.begin(), ca.end());\n                        sort(cb.begin(), cb.end());\n\n                        int la = min(3, (int)ca.size());\n                        int lb = min(3, (int)cb.size());\n\n                        for (int ia = 0; ia < la; ia++) {\n                            for (int ib = 0; ib < lb; ib++) {\n                                array<vector<int>,3> np = part;\n                                int x = ca[ia].second;\n                                int y = cb[ib].second;\n\n                                for (int& z : np[a]) {\n                                    if (z == x) {\n                                        z = y;\n                                        break;\n                                    }\n                                }\n\n                                for (int& z : np[b]) {\n                                    if (z == y) {\n                                        z = x;\n                                        break;\n                                    }\n                                }\n\n                                double nc = eval_partition(np);\n                                if (nc + 1.0 < bestSwap) {\n                                    bestSwap = nc;\n                                    ba = a;\n                                    bb = b;\n                                    va = x;\n                                    vb = y;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (ba == -1) break;\n\n                for (int& z : part[ba]) {\n                    if (z == va) {\n                        z = vb;\n                        break;\n                    }\n                }\n                for (int& z : part[bb]) {\n                    if (z == vb) {\n                        z = va;\n                        break;\n                    }\n                }\n\n                curCost = bestSwap;\n            }\n\n            return part;\n        };\n\n        auto update = [&](array<vector<int>,3> part, bool polish) {\n            if ((int)part[0].size() != s0) return;\n            if ((int)part[1].size() != s1) return;\n            if ((int)part[2].size() != s2) return;\n\n            double c = eval_partition(part);\n            if (c + 2.0 < bestCost) {\n                bestCost = c;\n                bestPart = part;\n            }\n\n            if (polish) {\n                auto pp = polish3(part);\n                double pc = eval_partition(pp);\n                if (pc + 2.0 < bestCost) {\n                    bestCost = pc;\n                    bestPart = pp;\n                }\n            }\n        };\n\n        auto greedy3 = [&](array<double,3> x, array<double,3> y) {\n            array<vector<int>,3> part;\n\n            for (int it = 0; it < 5; it++) {\n                struct Item {\n                    double margin;\n                    int v;\n                    array<pair<double,int>,3> ord;\n                };\n\n                vector<Item> items;\n\n                for (int v : all) {\n                    array<pair<double,int>,3> ds;\n                    for (int k = 0; k < 3; k++) {\n                        ds[k] = {dist2p(cx[v], cy[v], x[k], y[k]), k};\n                    }\n                    sort(ds.begin(), ds.end());\n                    items.push_back({ds[1].first - ds[0].first, v, ds});\n                }\n\n                sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n                    return a.margin > b.margin;\n                });\n\n                array<int,3> rem = {s0, s1, s2};\n                for (auto& p : part) p.clear();\n\n                for (auto& item : items) {\n                    int chosen = -1;\n                    for (auto [d, k] : item.ord) {\n                        if (rem[k] > 0) {\n                            chosen = k;\n                            break;\n                        }\n                    }\n\n                    if (chosen == -1) {\n                        for (int k = 0; k < 3; k++) {\n                            if (rem[k] > 0) {\n                                chosen = k;\n                                break;\n                            }\n                        }\n                    }\n\n                    part[chosen].push_back(item.v);\n                    rem[chosen]--;\n                }\n\n                update(part, true);\n\n                for (int k = 0; k < 3; k++) {\n                    double sx = 0.0, sy = 0.0;\n                    for (int v : part[k]) {\n                        sx += cx[v];\n                        sy += cy[v];\n                    }\n                    if (!part[k].empty()) {\n                        x[k] = sx / part[k].size();\n                        y[k] = sy / part[k].size();\n                    }\n                }\n            }\n        };\n\n        {\n            array<double,3> x = {gx[g0], gx[g1], gx[g2]};\n            array<double,3> y = {gy[g0], gy[g1], gy[g2]};\n            greedy3(x, y);\n        }\n\n        {\n            vector<pair<double,double>> dirs = {\n                {1, 0}, {0, 1}, {1, 1}, {1, -1},\n                {gx[g1] - gx[g0], gy[g1] - gy[g0]},\n                {gx[g2] - gx[g0], gy[g2] - gy[g0]},\n                {gx[g2] - gx[g1], gy[g2] - gy[g1]}\n            };\n\n            for (auto [dx, dy] : dirs) {\n                if (fabs(dx) + fabs(dy) < 1e-9) continue;\n\n                vector<pair<double,int>> arr;\n                for (int v : all) arr.push_back({cx[v] * dx + cy[v] * dy, v});\n                sort(arr.begin(), arr.end());\n\n                array<int,3> order = {0, 1, 2};\n                sort(order.begin(), order.end(), [&](int a, int b) {\n                    int ga = ids[a];\n                    int gb = ids[b];\n                    return gx[ga] * dx + gy[ga] * dy < gx[gb] * dx + gy[gb] * dy;\n                });\n\n                array<vector<int>,3> part;\n                int pos = 0;\n                array<int,3> sizes = {s0, s1, s2};\n\n                for (int oi = 0; oi < 3; oi++) {\n                    int k = order[oi];\n                    for (int t = 0; t < sizes[k]; t++) {\n                        part[k].push_back(arr[pos++].second);\n                    }\n                }\n                update(part, true);\n\n                reverse(arr.begin(), arr.end());\n                for (auto& p : part) p.clear();\n                pos = 0;\n\n                for (int oi = 0; oi < 3; oi++) {\n                    int k = order[oi];\n                    for (int t = 0; t < sizes[k]; t++) {\n                        part[k].push_back(arr[pos++].second);\n                    }\n                }\n                update(part, true);\n            }\n        }\n\n        if (bestCost + 2.0 < oldCost) {\n            groups[g0] = bestPart[0];\n            groups[g1] = bestPart[1];\n            groups[g2] = bestPart[2];\n\n            groupCost[g0] = mst_cost(groups[g0]);\n            groupCost[g1] = mst_cost(groups[g1]);\n            groupCost[g2] = mst_cost(groups[g2]);\n\n            for (int kk = 0; kk < 3; kk++) {\n                int gid = ids[kk];\n                for (int p = 0; p < (int)groups[gid].size(); p++) {\n                    cityGroup[groups[gid][p]] = gid;\n                    cityPos[groups[gid][p]] = p;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> N >> M >> Q >> L >> W;\n\n    G.resize(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    cx.resize(N);\n    cy.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        int lx, rx, ly, ry;\n        cin >> lx >> rx >> ly >> ry;\n        cx[i] = (lx + rx) * 0.5;\n        cy[i] = (ly + ry) * 0.5;\n    }\n\n    vector<vector<vector<int>>> candidates;\n    auto perms = make_size_perms();\n\n    auto add_order_candidates = [&](const vector<int>& ord) {\n        OrderEvaluator ev(ord);\n\n        for (auto p : perms) {\n            candidates.push_back(build_from_order(ord, p));\n\n            if (timer.sec() < 0.75) {\n                vector<int> imp = ev.improve_perm(p, 18);\n                candidates.push_back(build_from_order(ord, imp));\n            }\n        }\n    };\n\n    for (int t = 0; t < 8; t++) {\n        vector<pair<long long,int>> v;\n\n        for (int i = 0; i < N; i++) {\n            double x = cx[i], y = cy[i];\n            double X = x, Y = y;\n\n            if (t == 0) { X = x; Y = y; }\n            if (t == 1) { X = y; Y = x; }\n            if (t == 2) { X = 10000 - x; Y = y; }\n            if (t == 3) { X = x; Y = 10000 - y; }\n            if (t == 4) { X = 10000 - x; Y = 10000 - y; }\n            if (t == 5) { X = y; Y = 10000 - x; }\n            if (t == 6) { X = 10000 - y; Y = x; }\n            if (t == 7) { X = 10000 - y; Y = 10000 - x; }\n\n            int xi = min(16383, max(0, (int)llround(X * 16383.0 / 10000.0)));\n            int yi = min(16383, max(0, (int)llround(Y * 16383.0 / 10000.0)));\n\n            v.push_back({hilbert_index(xi, yi), i});\n        }\n\n        sort(v.begin(), v.end());\n\n        vector<int> ord;\n        ord.reserve(N);\n        for (auto [d, i] : v) ord.push_back(i);\n\n        add_order_candidates(ord);\n    }\n\n    const double PI = acos(-1.0);\n\n    for (int t = 0; t < 14; t++) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        double ang = (t >= 6 ? (t - 6) * PI / 14.0 : 0.0);\n        double vx = cos(ang);\n        double vy = sin(ang);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            double ka, kb;\n\n            if (t == 0) ka = cx[a], kb = cx[b];\n            else if (t == 1) ka = cy[a], kb = cy[b];\n            else if (t == 2) ka = cx[a] + cy[a], kb = cx[b] + cy[b];\n            else if (t == 3) ka = cx[a] - cy[a], kb = cx[b] - cy[b];\n            else if (t == 4) ka = -cx[a] + cy[a], kb = -cx[b] + cy[b];\n            else if (t == 5) ka = -cx[a] - cy[a], kb = -cx[b] - cy[b];\n            else ka = cx[a] * vx + cy[a] * vy, kb = cx[b] * vx + cy[b] * vy;\n\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n\n        add_order_candidates(ord);\n    }\n\n    for (int v = 0; v < 4; v++) {\n        candidates.push_back(make_recursive_candidate(v));\n    }\n\n    for (int v = 0; v < 27; v++) {\n        if (timer.sec() > 1.05) break;\n        candidates.push_back(make_greedy_candidate(v));\n    }\n\n    vector<pair<double,int>> candScores;\n    candScores.reserve(candidates.size());\n\n    double bestScore = 1e100;\n    vector<vector<int>> groups;\n\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        double sc = total_mst_cost(candidates[i]);\n        candScores.push_back({sc, i});\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = candidates[i];\n        }\n    }\n\n    sort(candScores.begin(), candScores.end());\n\n    int lloydTried = 0;\n    for (auto [sc0, idx] : candScores) {\n        if (lloydTried >= 4) break;\n        if (timer.sec() > 1.12) break;\n\n        auto km = capacitated_lloyd(candidates[idx], 4);\n        double sc = total_mst_cost(km);\n\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = km;\n        }\n\n        lloydTried++;\n    }\n\n    vector<int> cityGroup(N), cityPos(N);\n    vector<double> groupCost(M);\n\n    for (int gid = 0; gid < M; gid++) {\n        for (int p = 0; p < (int)groups[gid].size(); p++) {\n            cityGroup[groups[gid][p]] = gid;\n            cityPos[groups[gid][p]] = p;\n        }\n        groupCost[gid] = mst_cost(groups[gid]);\n    }\n\n    pair_repartition_refine(groups, cityGroup, cityPos, groupCost, timer);\n    triple_repartition_refine(groups, cityGroup, cityPos, groupCost, timer);\n\n    const int KNN = 28;\n    vector<vector<int>> knn(N);\n\n    for (int i = 0; i < N; i++) {\n        vector<pair<double,int>> v;\n        v.reserve(N - 1);\n\n        for (int j = 0; j < N; j++) {\n            if (i == j) continue;\n            v.push_back({edist(i, j), j});\n        }\n\n        nth_element(v.begin(), v.begin() + KNN, v.end());\n        v.resize(KNN);\n        sort(v.begin(), v.end());\n\n        for (auto [d, j] : v) knn[i].push_back(j);\n    }\n\n    auto mst_cost_with_swap = [&](int gid, int outCity, int inCity) {\n        vector<int> tmp = groups[gid];\n        int p = cityPos[outCity];\n        tmp[p] = inCity;\n        return mst_cost(tmp);\n    };\n\n    for (int pass = 0; pass < 7; pass++) {\n        if (timer.sec() > 1.38) break;\n\n        vector<double> gx(M, 0.0), gy(M, 0.0);\n\n        for (int gid = 0; gid < M; gid++) {\n            for (int v : groups[gid]) {\n                gx[gid] += cx[v];\n                gy[gid] += cy[v];\n            }\n\n            gx[gid] /= groups[gid].size();\n            gy[gid] /= groups[gid].size();\n        }\n\n        struct Cand {\n            double approx;\n            int a, b;\n        };\n\n        vector<Cand> sw;\n        unordered_set<unsigned long long> seen;\n        seen.reserve(N * 64);\n\n        auto add_swap_cand = [&](int a, int b) {\n            int ga = cityGroup[a];\n            int gb = cityGroup[b];\n\n            if (ga == gb) return;\n\n            unsigned long long key = ekey(a, b);\n            if (seen.count(key)) return;\n            seen.insert(key);\n\n            double da1 = sqrt(dist2p(cx[a], cy[a], gx[ga], gy[ga]));\n            double db1 = sqrt(dist2p(cx[b], cy[b], gx[gb], gy[gb]));\n            double da2 = sqrt(dist2p(cx[a], cy[a], gx[gb], gy[gb]));\n            double db2 = sqrt(dist2p(cx[b], cy[b], gx[ga], gy[ga]));\n            double approx = da2 + db2 - da1 - db1;\n\n            if (approx < 800.0) {\n                sw.push_back({approx, a, b});\n            }\n        };\n\n        for (int a = 0; a < N; a++) {\n            for (int b : knn[a]) {\n                add_swap_cand(a, b);\n            }\n        }\n\n        if (M > 1) {\n            for (int a = 0; a < N; a++) {\n                int ga = cityGroup[a];\n\n                vector<pair<double,int>> tg;\n                tg.reserve(M - 1);\n\n                for (int gid = 0; gid < M; gid++) {\n                    if (gid == ga) continue;\n                    double d = dist2p(cx[a], cy[a], gx[gid], gy[gid]);\n                    tg.push_back({d, gid});\n                }\n\n                int tk = min(4, (int)tg.size());\n                nth_element(tg.begin(), tg.begin() + tk - 1, tg.end());\n                tg.resize(tk);\n\n                for (auto [dcent, gb] : tg) {\n                    vector<pair<double,int>> bs;\n                    bs.reserve(groups[gb].size());\n\n                    for (int b : groups[gb]) {\n                        double d = dist2p(cx[b], cy[b], gx[ga], gy[ga]);\n                        bs.push_back({d, b});\n                    }\n\n                    int bk = min(3, (int)bs.size());\n                    nth_element(bs.begin(), bs.begin() + bk - 1, bs.end());\n                    bs.resize(bk);\n\n                    for (auto [db, b] : bs) {\n                        add_swap_cand(a, b);\n                    }\n                }\n            }\n        }\n\n        sort(sw.begin(), sw.end(), [](const Cand& x, const Cand& y) {\n            return x.approx < y.approx;\n        });\n\n        if ((int)sw.size() > 12000) sw.resize(12000);\n\n        bool changed = false;\n\n        for (auto c : sw) {\n            if (timer.sec() > 1.55) break;\n\n            int a = c.a;\n            int b = c.b;\n            int ga = cityGroup[a];\n            int gb = cityGroup[b];\n\n            if (ga == gb) continue;\n\n            double oldCost = groupCost[ga] + groupCost[gb];\n            double na = mst_cost_with_swap(ga, a, b);\n            double nb = mst_cost_with_swap(gb, b, a);\n            double newCost = na + nb;\n\n            if (newCost + 1e-7 < oldCost) {\n                int pa = cityPos[a];\n                int pb = cityPos[b];\n\n                groups[ga][pa] = b;\n                groups[gb][pb] = a;\n\n                cityGroup[a] = gb;\n                cityGroup[b] = ga;\n                cityPos[a] = pb;\n                cityPos[b] = pa;\n\n                groupCost[ga] = na;\n                groupCost[gb] = nb;\n\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n\n    vector<vector<pair<int,int>>> backupEdges(M);\n\n    for (int gid = 0; gid < M; gid++) {\n        backupEdges[gid] = prim_edges(groups[gid]);\n    }\n\n    vector<vector<pair<int,int>>> finalEdges(M);\n    vector<unordered_map<unsigned long long,int>> oracleEdges(M);\n\n    struct PlannedQuery {\n        int gid;\n        vector<int> cities;\n        bool exactSmall;\n    };\n\n    vector<PlannedQuery> queries;\n    unordered_set<string> usedSubset;\n    usedSubset.reserve(2000);\n\n    auto add_query = [&](int gid, const vector<int>& c, bool exactSmall) -> bool {\n        if ((int)queries.size() >= Q) return false;\n        if ((int)c.size() < 2 || (int)c.size() > L) return false;\n\n        string key = subset_key(c);\n\n        if (usedSubset.count(key)) return false;\n        usedSubset.insert(key);\n\n        queries.push_back({gid, c, exactSmall});\n        return true;\n    };\n\n    vector<int> smallIds;\n\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n        if (3 <= g && g <= L) smallIds.push_back(gid);\n    }\n\n    sort(smallIds.begin(), smallIds.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    for (int gid : smallIds) {\n        add_query(gid, groups[gid], true);\n    }\n\n    vector<int> largeIds;\n\n    for (int gid = 0; gid < M; gid++) {\n        if ((int)groups[gid].size() > L) largeIds.push_back(gid);\n    }\n\n    sort(largeIds.begin(), largeIds.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    vector<vector<pair<double,pair<int,int>>>> longEdges(M);\n\n    for (int gid : largeIds) {\n        for (auto [a, b] : backupEdges[gid]) {\n            longEdges[gid].push_back({edist(a, b), {a, b}});\n        }\n\n        sort(longEdges[gid].begin(), longEdges[gid].end(), [](auto& x, auto& y) {\n            return x.first > y.first;\n        });\n    }\n\n    int round = 0;\n\n    while ((int)queries.size() < Q && !largeIds.empty()) {\n        bool any = false;\n\n        for (int gid : largeIds) {\n            if ((int)queries.size() >= Q) break;\n\n            int g = groups[gid].size();\n            vector<int> sub;\n\n            if (round < (int)longEdges[gid].size()) {\n                auto [a, b] = longEdges[gid][round].second;\n                sub = nearest_subset_to_edge(groups[gid], a, b);\n            } else {\n                int idx = (round - (int)longEdges[gid].size()) % g;\n                int seed = groups[gid][idx];\n                sub = nearest_subset_to_seed(groups[gid], seed);\n            }\n\n            if (add_query(gid, sub, false)) any = true;\n        }\n\n        round++;\n        if (!any && round > 2 * N + 20) break;\n    }\n\n    for (auto& qu : queries) {\n        auto ret = do_query(qu.cities);\n        int gid = qu.gid;\n\n        for (auto [a, b] : ret) {\n            oracleEdges[gid][ekey(a, b)]++;\n        }\n\n        if (qu.exactSmall) {\n            finalEdges[gid] = ret;\n        }\n    }\n\n    for (int gid = 0; gid < M; gid++) {\n        int g = groups[gid].size();\n\n        if (g <= 1) {\n            finalEdges[gid].clear();\n        } else if (g == 2) {\n            finalEdges[gid] = {{groups[gid][0], groups[gid][1]}};\n        } else if (g <= L && !finalEdges[gid].empty()) {\n            // Exact MST already obtained.\n        } else {\n            struct EdgeCand {\n                double w;\n                int a, b;\n            };\n\n            vector<EdgeCand> cand;\n\n            for (auto& kv : oracleEdges[gid]) {\n                auto [a, b] = decode_key(kv.first);\n                int cnt = kv.second;\n                double factor = 0.56 - 0.04 * min(4, cnt - 1);\n                cand.push_back({edist(a, b) * factor, a, b});\n            }\n\n            for (auto [a, b] : backupEdges[gid]) {\n                cand.push_back({edist(a, b), a, b});\n            }\n\n            for (int a : groups[gid]) {\n                vector<pair<double,int>> near;\n\n                for (int b : groups[gid]) {\n                    if (a == b) continue;\n                    near.push_back({edist(a, b), b});\n                }\n\n                sort(near.begin(), near.end());\n\n                int lim = min(5, (int)near.size());\n                for (int i = 0; i < lim; i++) {\n                    int b = near[i].second;\n                    cand.push_back({near[i].first * 1.04, a, b});\n                }\n            }\n\n            sort(cand.begin(), cand.end(), [](const EdgeCand& x, const EdgeCand& y) {\n                if (x.w != y.w) return x.w < y.w;\n                if (x.a != y.a) return x.a < y.a;\n                return x.b < y.b;\n            });\n\n            DSU dsu(N);\n            vector<pair<int,int>> tree;\n            tree.reserve(g - 1);\n\n            for (auto& e : cand) {\n                if (dsu.unite(e.a, e.b)) {\n                    tree.push_back({e.a, e.b});\n                    if ((int)tree.size() == g - 1) break;\n                }\n            }\n\n            if ((int)tree.size() != g - 1) {\n                tree = backupEdges[gid];\n            }\n\n            finalEdges[gid] = tree;\n        }\n    }\n\n    cout << \"!\" << '\\n';\n\n    for (int gid = 0; gid < M; gid++) {\n        for (int i = 0; i < (int)groups[gid].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[gid][i];\n        }\n        cout << '\\n';\n\n        for (auto [a, b] : finalEdges[gid]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Act {\n    char a, d;\n};\n\nconst int MAXC = 400;\nconst int INF = 1e9;\n\nint N, M;\nvector<int> pos_id;\nvector<bitset<MAXC>> future_mask;\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\nauto START_TIME = chrono::steady_clock::now();\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\ninline int id(int r, int c) { return r * N + c; }\ninline int rr(int x) { return x / N; }\ninline int cc(int x) { return x % N; }\ninline bool inside(int r, int c) { return 0 <= r && r < N && 0 <= c && c < N; }\n\ninline bool blocked(const bitset<MAXC>& g, int r, int c) {\n    if (!inside(r, c)) return true;\n    return g[id(r, c)];\n}\n\nint slide_stop(const bitset<MAXC>& g, int s, int dir) {\n    int r = rr(s), c = cc(s);\n    while (true) {\n        int nr = r + dr[dir], nc = c + dc[dir];\n        if (blocked(g, nr, nc)) break;\n        r = nr;\n        c = nc;\n    }\n    return id(r, c);\n}\n\nstruct BFSRes {\n    array<int, MAXC> dist;\n    array<int, MAXC> par;\n    array<char, MAXC> pact;\n    array<char, MAXC> pdir;\n};\n\nBFSRes forward_bfs(const bitset<MAXC>& g, int start, int forbid_stop = -1) {\n    BFSRes res;\n    res.dist.fill(INF);\n    res.par.fill(-1);\n    res.pact.fill(0);\n    res.pdir.fill(0);\n\n    if (g[start]) return res;\n\n    int q[MAXC], head = 0, tail = 0;\n    res.dist[start] = 0;\n    q[tail++] = start;\n\n    while (head < tail) {\n        int v = q[head++];\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            int nr = r + dr[d], nc = c + dc[d];\n\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (to != forbid_stop && res.dist[to] == INF) {\n                    res.dist[to] = res.dist[v] + 1;\n                    res.par[to] = v;\n                    res.pact[to] = 'M';\n                    res.pdir[to] = dch[d];\n                    q[tail++] = to;\n                }\n            }\n\n            int to = slide_stop(g, v, d);\n            if (to != v && to != forbid_stop && res.dist[to] == INF) {\n                res.dist[to] = res.dist[v] + 1;\n                res.par[to] = v;\n                res.pact[to] = 'S';\n                res.pdir[to] = dch[d];\n                q[tail++] = to;\n            }\n        }\n    }\n\n    return res;\n}\n\narray<int, MAXC> reverse_bfs_dist(const bitset<MAXC>& g, int target) {\n    array<int, MAXC> dist;\n    dist.fill(INF);\n\n    if (g[target]) return dist;\n\n    int q[MAXC], head = 0, tail = 0;\n    dist[target] = 0;\n    q[tail++] = target;\n\n    while (head < tail) {\n        int v = q[head++];\n        int r = rr(v), c = cc(v);\n\n        for (int d = 0; d < 4; d++) {\n            int pr = r - dr[d], pc = c - dc[d];\n\n            if (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q[tail++] = u;\n                }\n            }\n\n            int br = r + dr[d], bc = c + dc[d];\n            if (!blocked(g, br, bc)) continue;\n\n            pr = r - dr[d];\n            pc = c - dc[d];\n\n            while (inside(pr, pc) && !g[id(pr, pc)]) {\n                int u = id(pr, pc);\n                if (dist[u] == INF) {\n                    dist[u] = dist[v] + 1;\n                    q[tail++] = u;\n                }\n                pr -= dr[d];\n                pc -= dc[d];\n            }\n        }\n    }\n\n    return dist;\n}\n\nvector<Act> restore_forward(const BFSRes& bfs, int start, int goal) {\n    vector<Act> rev;\n    int cur = goal;\n\n    while (cur != start) {\n        if (cur < 0 || bfs.par[cur] < 0) return {};\n        rev.push_back({bfs.pact[cur], bfs.pdir[cur]});\n        cur = bfs.par[cur];\n    }\n\n    reverse(rev.begin(), rev.end());\n    return rev;\n}\n\nvector<Act> restore_by_reverse_dist(\n    const bitset<MAXC>& g,\n    const array<int, MAXC>& dist,\n    int start,\n    int target\n) {\n    vector<Act> ret;\n    int cur = start;\n\n    while (cur != target) {\n        int cd = dist[cur];\n        bool found = false;\n\n        for (int d = 0; d < 4 && !found; d++) {\n            int r = rr(cur), c = cc(cur);\n\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && !g[id(nr, nc)]) {\n                int to = id(nr, nc);\n                if (dist[to] == cd - 1) {\n                    ret.push_back({'M', dch[d]});\n                    cur = to;\n                    found = true;\n                    break;\n                }\n            }\n\n            int to = slide_stop(g, cur, d);\n            if (to != cur && dist[to] == cd - 1) {\n                ret.push_back({'S', dch[d]});\n                cur = to;\n                found = true;\n                break;\n            }\n        }\n\n        if (!found) {\n            ret.clear();\n            return ret;\n        }\n    }\n\n    return ret;\n}\n\nint dir_from_to(int p, int b) {\n    int pr = rr(p), pc = cc(p);\n    int br = rr(b), bc = cc(b);\n\n    for (int d = 0; d < 4; d++) {\n        if (pr + dr[d] == br && pc + dc[d] == bc) return d;\n    }\n    return -1;\n}\n\nstruct State {\n    bitset<MAXC> grid;\n    int cost = 0;\n    vector<Act> acts;\n};\n\nstruct Params {\n    bool allow_future_target_block;\n    int beam_w;\n    int cost_first_keep;\n    int h_weight;\n    int bf_penalty;\n    int top_k;\n    int allow_extra;\n    double deadline;\n};\n\nstruct Option {\n    int cost;\n    int b;\n    int p;\n};\n\nint manhattan_id(int a, int b) {\n    return abs(rr(a) - rr(b)) + abs(cc(a) - cc(b));\n}\n\nint blocked_future_count(const bitset<MAXC>& g, int from_index) {\n    int cnt = 0;\n    for (int k = from_index; k < M; k++) {\n        if (g[pos_id[k]]) cnt++;\n    }\n    return cnt;\n}\n\nint one_step_heuristic(const State& st, int leg, const Params& prm) {\n    if (prm.h_weight == 0) return 0;\n    if (leg + 1 >= M) return 0;\n    if (elapsed_sec() > prm.deadline - 0.12) return 0;\n\n    int s = pos_id[leg];\n    int t = pos_id[leg + 1];\n\n    BFSRes bfs = forward_bfs(st.grid, s, -1);\n    int d = bfs.dist[t];\n\n    if (d >= INF) return manhattan_id(s, t) + 20;\n    return d;\n}\n\nvector<State> expand_state(const State& st, int leg, const Params& prm) {\n    vector<State> res;\n\n    int start = pos_id[leg - 1];\n    int target = pos_id[leg];\n\n    BFSRes bfs_normal = forward_bfs(st.grid, start, -1);\n    BFSRes bfs_avoid = forward_bfs(st.grid, start, target);\n\n    int base_cost = bfs_normal.dist[target];\n    vector<Act> base_path;\n\n    if (base_cost < INF) {\n        base_path = restore_forward(bfs_normal, start, target);\n\n        State ns;\n        ns.grid = st.grid;\n        ns.acts = st.acts;\n        ns.acts.insert(ns.acts.end(), base_path.begin(), base_path.end());\n        ns.cost = (int)ns.acts.size();\n        res.push_back(std::move(ns));\n\n        for (int d = 0; d < 4; d++) {\n            int br = rr(target) + dr[d];\n            int bc = cc(target) + dc[d];\n            if (!inside(br, bc)) continue;\n\n            int b = id(br, bc);\n\n            if (!prm.allow_future_target_block && !st.grid[b] && future_mask[leg + 1][b]) {\n                continue;\n            }\n\n            bitset<MAXC> g2 = st.grid;\n            g2.flip(b);\n\n            if (g2[target]) continue;\n\n            State ps;\n            ps.grid = g2;\n            ps.acts = st.acts;\n            ps.acts.insert(ps.acts.end(), base_path.begin(), base_path.end());\n            ps.acts.push_back({'A', dch[d]});\n            ps.cost = (int)ps.acts.size();\n            res.push_back(std::move(ps));\n        }\n    }\n\n    if (elapsed_sec() > prm.deadline - 0.16) return res;\n\n    vector<Option> opts;\n\n    for (int b = 0; b < N * N; b++) {\n        if ((b & 31) == 0 && elapsed_sec() > prm.deadline - 0.07) break;\n\n        if (!prm.allow_future_target_block && !st.grid[b] && future_mask[leg][b]) {\n            continue;\n        }\n\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(b);\n\n        if (g2[target]) continue;\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n\n        int best_cost = INF;\n        int best_p = -1;\n\n        int br = rr(b), bc = cc(b);\n\n        for (int d = 0; d < 4; d++) {\n            int pr = br - dr[d], pc = bc - dc[d];\n            if (!inside(pr, pc)) continue;\n\n            int p = id(pr, pc);\n\n            if (st.grid[p]) continue;\n            if (g2[p]) continue;\n            if (bfs_avoid.dist[p] >= INF) continue;\n            if (dist_to_target[p] >= INF) continue;\n\n            int cand = bfs_avoid.dist[p] + 1 + dist_to_target[p];\n\n            if (cand < best_cost) {\n                best_cost = cand;\n                best_p = p;\n            }\n        }\n\n        if (best_p < 0) continue;\n        if (base_cost < INF && best_cost > base_cost + prm.allow_extra) continue;\n\n        opts.push_back({best_cost, b, best_p});\n    }\n\n    sort(opts.begin(), opts.end(), [](const Option& x, const Option& y) {\n        return x.cost < y.cost;\n    });\n\n    if ((int)opts.size() > prm.top_k) opts.resize(prm.top_k);\n\n    for (const auto& op : opts) {\n        bitset<MAXC> g2 = st.grid;\n        g2.flip(op.b);\n\n        auto dist_to_target = reverse_bfs_dist(g2, target);\n\n        if (dist_to_target[op.p] >= INF) continue;\n\n        auto path1 = restore_forward(bfs_avoid, start, op.p);\n        if (path1.empty() && op.p != start) continue;\n\n        int ad = dir_from_to(op.p, op.b);\n        if (ad < 0) continue;\n\n        auto path2 = restore_by_reverse_dist(g2, dist_to_target, op.p, target);\n        if (path2.empty() && op.p != target) continue;\n\n        State ns;\n        ns.grid = g2;\n        ns.acts = st.acts;\n        ns.acts.insert(ns.acts.end(), path1.begin(), path1.end());\n        ns.acts.push_back({'A', dch[ad]});\n        ns.acts.insert(ns.acts.end(), path2.begin(), path2.end());\n        ns.cost = (int)ns.acts.size();\n\n        res.push_back(std::move(ns));\n    }\n\n    return res;\n}\n\nvector<Act> simple_fallback_empty_board() {\n    vector<Act> ret;\n    int cur = pos_id[0];\n\n    for (int k = 1; k < M; k++) {\n        int t = pos_id[k];\n\n        int r = rr(cur), c = cc(cur);\n        int tr = rr(t), tc = cc(t);\n\n        while (r < tr) {\n            ret.push_back({'M', 'D'});\n            r++;\n        }\n        while (r > tr) {\n            ret.push_back({'M', 'U'});\n            r--;\n        }\n        while (c < tc) {\n            ret.push_back({'M', 'R'});\n            c++;\n        }\n        while (c > tc) {\n            ret.push_back({'M', 'L'});\n            c--;\n        }\n\n        cur = t;\n    }\n\n    return ret;\n}\n\nint dir_index(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\nbool simulate_skip(const vector<Act>& acts, int skip = -1) {\n    int effective_len = (int)acts.size() - (skip >= 0);\n    if (effective_len > 2 * N * M) return false;\n\n    bitset<MAXC> g;\n    int cur = pos_id[0];\n    int nxt = 1;\n\n    for (int idx = 0; idx < (int)acts.size(); idx++) {\n        if (idx == skip) continue;\n\n        auto [a, ch] = acts[idx];\n        int d = dir_index(ch);\n        int r = rr(cur), c = cc(cur);\n\n        if (a == 'M') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n\n            int to = id(nr, nc);\n            if (g[to]) return false;\n\n            cur = to;\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'S') {\n            while (true) {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (!inside(nr, nc) || g[id(nr, nc)]) break;\n                r = nr;\n                c = nc;\n            }\n\n            cur = id(r, c);\n            if (nxt < M && cur == pos_id[nxt]) nxt++;\n        } else if (a == 'A') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n\n            int b = id(nr, nc);\n            g.flip(b);\n        } else {\n            return false;\n        }\n    }\n\n    return nxt == M;\n}\n\nbool simulate(const vector<Act>& acts) {\n    return simulate_skip(acts, -1);\n}\n\nvector<Act> solve_variant(const Params& prm) {\n    vector<State> beam;\n\n    State init;\n    init.grid.reset();\n    init.cost = 0;\n    beam.push_back(init);\n\n    for (int leg = 1; leg < M; leg++) {\n        vector<State> candidates;\n\n        for (const auto& st : beam) {\n            auto ex = expand_state(st, leg, prm);\n            for (auto& ns : ex) candidates.push_back(std::move(ns));\n        }\n\n        if (candidates.empty()) return simple_fallback_empty_board();\n\n        sort(candidates.begin(), candidates.end(), [](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        vector<State> unique_candidates;\n        unique_candidates.reserve(candidates.size());\n\n        for (auto& st : candidates) {\n            bool dup = false;\n            for (const auto& u : unique_candidates) {\n                if (u.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) unique_candidates.push_back(std::move(st));\n        }\n\n        candidates.swap(unique_candidates);\n\n        vector<State> nb;\n\n        sort(candidates.begin(), candidates.end(), [](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        for (auto& st : candidates) {\n            bool dup = false;\n            for (const auto& kept : nb) {\n                if (kept.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (dup) continue;\n\n            nb.push_back(st);\n            if ((int)nb.size() >= prm.cost_first_keep) break;\n        }\n\n        struct Ranked {\n            long long score;\n            int cost;\n            int idx;\n        };\n\n        vector<Ranked> rank;\n        rank.reserve(candidates.size());\n\n        for (int i = 0; i < (int)candidates.size(); i++) {\n            int h = one_step_heuristic(candidates[i], leg, prm);\n            int bf = prm.bf_penalty ? blocked_future_count(candidates[i].grid, leg + 1) : 0;\n\n            long long sc =\n                100LL * candidates[i].cost +\n                1LL * prm.h_weight * h +\n                1LL * prm.bf_penalty * bf;\n\n            rank.push_back({sc, candidates[i].cost, i});\n        }\n\n        sort(rank.begin(), rank.end(), [](const Ranked& a, const Ranked& b) {\n            if (a.score != b.score) return a.score < b.score;\n            return a.cost < b.cost;\n        });\n\n        for (const auto& rnk : rank) {\n            const State& st = candidates[rnk.idx];\n\n            bool dup = false;\n            for (const auto& kept : nb) {\n                if (kept.grid == st.grid) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (dup) continue;\n\n            nb.push_back(st);\n            if ((int)nb.size() >= prm.beam_w) break;\n        }\n\n        if (nb.empty()) return simple_fallback_empty_board();\n\n        beam = std::move(nb);\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)beam.size(); i++) {\n        if (beam[i].cost < beam[best].cost) best = i;\n    }\n\n    return beam[best].acts;\n}\n\nvoid erase_one(vector<Act>& ans, int skip) {\n    vector<Act> nxt;\n    nxt.reserve(ans.size() - 1);\n\n    for (int i = 0; i < (int)ans.size(); i++) {\n        if (i != skip) nxt.push_back(ans[i]);\n    }\n\n    ans.swap(nxt);\n}\n\nvoid greedy_delete_limited(vector<Act>& ans) {\n    int i = 0;\n\n    while (i < (int)ans.size()) {\n        if (elapsed_sec() > 1.90) break;\n\n        if (simulate_skip(ans, i)) {\n            erase_one(ans, i);\n        } else {\n            i++;\n        }\n    }\n}\n\nvoid consider_answer(vector<Act>& best, const vector<Act>& cand) {\n    if (!simulate(cand)) return;\n\n    if (best.empty() || cand.size() < best.size()) {\n        best = cand;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    pos_id.resize(M);\n    for (int k = 0; k < M; k++) {\n        int r, c;\n        cin >> r >> c;\n        pos_id[k] = id(r, c);\n    }\n\n    future_mask.assign(M + 1, bitset<MAXC>());\n    future_mask[M].reset();\n\n    for (int k = M - 1; k >= 0; k--) {\n        future_mask[k] = future_mask[k + 1];\n        future_mask[k].set(pos_id[k]);\n    }\n\n    vector<Act> best;\n\n    // Variant 1: current strongest wider-search policy.\n    {\n        Params prm;\n        prm.allow_future_target_block = true;\n        prm.beam_w = 6;\n        prm.cost_first_keep = 4;\n        prm.h_weight = 12;\n        prm.bf_penalty = 10;\n        prm.top_k = 7;\n        prm.allow_extra = 5;\n        prm.deadline = 1.18;\n\n        auto ans = solve_variant(prm);\n        consider_answer(best, ans);\n    }\n\n    // Variant 2: safer policy, forbid newly blocking future targets.\n    if (elapsed_sec() < 1.50) {\n        Params prm;\n        prm.allow_future_target_block = false;\n        prm.beam_w = 5;\n        prm.cost_first_keep = 2;\n        prm.h_weight = 12;\n        prm.bf_penalty = 0;\n        prm.top_k = 6;\n        prm.allow_extra = 4;\n        prm.deadline = 1.72;\n\n        auto ans = solve_variant(prm);\n        consider_answer(best, ans);\n    }\n\n    // Variant 3: legacy narrower policy.\n    // Some public cases preferred this over the wider top_k=7 setting.\n    if (elapsed_sec() < 1.58) {\n        Params prm;\n        prm.allow_future_target_block = true;\n        prm.beam_w = 6;\n        prm.cost_first_keep = 4;\n        prm.h_weight = 12;\n        prm.bf_penalty = 10;\n        prm.top_k = 5;\n        prm.allow_extra = 4;\n        prm.deadline = 1.80;\n\n        auto ans = solve_variant(prm);\n        consider_answer(best, ans);\n    }\n\n    // Variant 4: cost-focused variant, if time remains.\n    if (elapsed_sec() < 1.64) {\n        Params prm;\n        prm.allow_future_target_block = true;\n        prm.beam_w = 5;\n        prm.cost_first_keep = 5;\n        prm.h_weight = 0;\n        prm.bf_penalty = 6;\n        prm.top_k = 7;\n        prm.allow_extra = 5;\n        prm.deadline = 1.84;\n\n        auto ans = solve_variant(prm);\n        consider_answer(best, ans);\n    }\n\n    // Variant 5: legacy safe policy, only when there is clear spare time.\n    if (elapsed_sec() < 1.70) {\n        Params prm;\n        prm.allow_future_target_block = false;\n        prm.beam_w = 5;\n        prm.cost_first_keep = 2;\n        prm.h_weight = 12;\n        prm.bf_penalty = 0;\n        prm.top_k = 5;\n        prm.allow_extra = 4;\n        prm.deadline = 1.86;\n\n        auto ans = solve_variant(prm);\n        consider_answer(best, ans);\n    }\n\n    if (best.empty()) {\n        best = simple_fallback_empty_board();\n    }\n\n    if (!simulate(best)) {\n        best = simple_fallback_empty_board();\n    } else {\n        greedy_delete_limited(best);\n    }\n\n    if (!simulate(best)) {\n        best = simple_fallback_empty_board();\n    }\n\n    for (auto [a, d] : best) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"}}}