{"model_name":"gpt-5.4-mini-high","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstruct Cand {\n    long long diff;     // |areaL * T - A * TL|\n    long long denom;    // TL * TR\n    long long balance;  // shape tie-break: smaller is better\n    long double val;    // diff / denom, used for random pool threshold\n    int orient;         // 0: vertical, 1: horizontal\n    int cut;            // selected cut coordinate\n    int lo, hi;         // allowed cut interval\n};\n\nstatic const int B = 10000;\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\n\nstatic inline long long absl(long long x) { return x < 0 ? -x : x; }\n\nbool candLess(const Cand& a, const Cand& b) {\n    __int128 lhs = (__int128)a.diff * b.denom;\n    __int128 rhs = (__int128)b.diff * a.denom;\n    if (lhs != rhs) return lhs < rhs;\n    if (a.balance != b.balance) return a.balance < b.balance;\n    int spanA = a.hi - a.lo, spanB = b.hi - b.lo;\n    if (spanA != spanB) return spanA > spanB; // more flexibility\n    if (a.orient != b.orient) return a.orient < b.orient;\n    return a.cut < b.cut;\n}\n\nvoid addCandidates(\n    const vector<int>& ids,\n    int lx, int ly, int rx, int ry,\n    int orient,\n    vector<Cand>& cands\n) {\n    int m = (int)ids.size();\n    if (m <= 1) return;\n\n    long long T = 0;\n    for (int id : ids) T += rs[id];\n    if (T <= 0) return;\n\n    long long A = 1LL * (rx - lx) * (ry - ly);\n\n    if (orient == 0) {\n        int W = rx - lx;\n        int H = ry - ly;\n        if (W < 2) return;\n\n        vector<int> ord = ids;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            return a < b;\n        });\n\n        long long pref = 0;\n        for (int i = 0; i + 1 < m; ++i) {\n            pref += rs[ord[i]];\n            if (xs[ord[i]] == xs[ord[i + 1]]) continue;\n\n            int lo = max(lx + 1, xs[ord[i]] + 1);\n            int hi = min(rx - 1, xs[ord[i + 1]]);\n            if (lo > hi) continue;\n\n            long long num = A * pref;\n            long long den = 1LL * H * T;\n            long long w = num / den;\n            if ((num % den) * 2 >= den) ++w;\n\n            long long cutll = lx + w;\n            cutll = max<long long>(lo, min<long long>(hi, cutll));\n            int cut = (int)cutll;\n\n            long long areaL = 1LL * (cut - lx) * H;\n            long long diff = absl(areaL * T - A * pref);\n            long long TL = pref, TR = T - pref;\n            long long denom = TL * TR;\n            if (denom <= 0) continue;\n\n            long long balance = absl(2LL * (cut - lx) - W);\n            long double val = (long double)diff / (long double)denom;\n            cands.push_back({diff, denom, balance, val, orient, cut, lo, hi});\n        }\n    } else {\n        int W = rx - lx;\n        int H = ry - ly;\n        if (H < 2) return;\n\n        vector<int> ord = ids;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            return a < b;\n        });\n\n        long long pref = 0;\n        for (int i = 0; i + 1 < m; ++i) {\n            pref += rs[ord[i]];\n            if (ys[ord[i]] == ys[ord[i + 1]]) continue;\n\n            int lo = max(ly + 1, ys[ord[i]] + 1);\n            int hi = min(ry - 1, ys[ord[i + 1]]);\n            if (lo > hi) continue;\n\n            long long num = A * pref;\n            long long den = 1LL * W * T;\n            long long h = num / den;\n            if ((num % den) * 2 >= den) ++h;\n\n            long long cutll = ly + h;\n            cutll = max<long long>(lo, min<long long>(hi, cutll));\n            int cut = (int)cutll;\n\n            long long areaL = 1LL * W * (cut - ly);\n            long long diff = absl(areaL * T - A * pref);\n            long long TL = pref, TR = T - pref;\n            long long denom = TL * TR;\n            if (denom <= 0) continue;\n\n            long long balance = absl(2LL * (cut - ly) - H);\n            long double val = (long double)diff / (long double)denom;\n            cands.push_back({diff, denom, balance, val, orient, cut, lo, hi});\n        }\n    }\n}\n\nCand chooseCandidate(\n    vector<Cand>& cands,\n    bool randomize,\n    mt19937_64& rng,\n    long double slack_ratio,\n    int best_prob\n) {\n    sort(cands.begin(), cands.end(), candLess);\n    Cand best = cands[0];\n\n    if (!randomize || cands.size() == 1) return best;\n\n    long double lim = best.val * (1.0L + slack_ratio) + 1e-18L;\n    vector<int> pool;\n    for (int i = 0; i < (int)cands.size(); ++i) {\n        if (cands[i].val <= lim) pool.push_back(i);\n        else break;\n    }\n\n    if ((int)pool.size() <= 1) return best;\n\n    // Usually keep the best; sometimes explore a nearby candidate.\n    if ((int)(rng() % 1000) < best_prob) return best;\n\n    int take = min<int>(5, (int)pool.size());\n    if (take <= 1) return best;\n\n    int idx = pool[1 + (int)(rng() % (take - 1))];\n    return cands[idx];\n}\n\nvoid build(\n    int lx, int ly, int rx, int ry,\n    const vector<int>& ids,\n    vector<Rect>& ans,\n    bool randomize,\n    mt19937_64& rng,\n    long double slack_ratio,\n    int best_prob,\n    int perturb_max\n) {\n    if (ids.size() == 1) {\n        ans[ids[0]] = {lx, ly, rx, ry};\n        return;\n    }\n\n    vector<Cand> cands;\n    cands.reserve(ids.size() * 2);\n\n    addCandidates(ids, lx, ly, rx, ry, 0, cands);\n    addCandidates(ids, lx, ly, rx, ry, 1, cands);\n\n    if (cands.empty()) {\n        // Robust fallback: split by the longer side using a simple median boundary.\n        // This should almost never be needed.\n        if (rx - lx >= ry - ly && rx - lx >= 2) {\n            vector<int> ord = ids;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                return a < b;\n            });\n            int m = (int)ord.size();\n            int mid = m / 2 - 1;\n            if (mid < 0) mid = 0;\n            while (mid + 1 < m && xs[ord[mid]] == xs[ord[mid + 1]]) ++mid;\n            if (mid + 1 >= m) mid = m / 2 - 1;\n            int cut = xs[ord[mid]] + 1;\n            cut = max(lx + 1, min(rx - 1, cut));\n\n            vector<int> left, right;\n            left.reserve(ids.size());\n            right.reserve(ids.size());\n            for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n            if (left.empty() || right.empty()) {\n                cut = lx + 1;\n                left.clear(); right.clear();\n                for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n            }\n            build(lx, ly, cut, ry, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            build(cut, ly, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            return;\n        } else {\n            vector<int> ord = ids;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                return a < b;\n            });\n            int m = (int)ord.size();\n            int mid = m / 2 - 1;\n            if (mid < 0) mid = 0;\n            while (mid + 1 < m && ys[ord[mid]] == ys[ord[mid + 1]]) ++mid;\n            if (mid + 1 >= m) mid = m / 2 - 1;\n            int cut = ys[ord[mid]] + 1;\n            cut = max(ly + 1, min(ry - 1, cut));\n\n            vector<int> left, right;\n            left.reserve(ids.size());\n            right.reserve(ids.size());\n            for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n            if (left.empty() || right.empty()) {\n                cut = ly + 1;\n                left.clear(); right.clear();\n                for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n            }\n            build(lx, ly, rx, cut, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            build(lx, cut, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            return;\n        }\n    }\n\n    Cand ch = chooseCandidate(cands, randomize, rng, slack_ratio, best_prob);\n    int cut = ch.cut;\n\n    if (randomize && perturb_max > 0 && ch.lo < ch.hi) {\n        int span = min(perturb_max, max(1, (ch.hi - ch.lo) / 4));\n        if (span > 0) {\n            int off = (int)(rng() % (2ULL * span + 1ULL)) - span;\n            cut = max(ch.lo, min(ch.hi, cut + off));\n        }\n    }\n\n    vector<int> left, right;\n    left.reserve(ids.size());\n    right.reserve(ids.size());\n\n    if (ch.orient == 0) {\n        for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n        if (left.empty() || right.empty()) {\n            // Extremely defensive fallback.\n            int med = lx + (rx - lx) / 2;\n            left.clear(); right.clear();\n            for (int id : ids) (xs[id] < med ? left : right).push_back(id);\n            cut = med;\n        }\n        build(lx, ly, cut, ry, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n        build(cut, ly, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n    } else {\n        for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n        if (left.empty() || right.empty()) {\n            int med = ly + (ry - ly) / 2;\n            left.clear(); right.clear();\n            for (int id : ids) (ys[id] < med ? left : right).push_back(id);\n            cut = med;\n        }\n        build(lx, ly, rx, cut, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n        build(lx, cut, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n    }\n}\n\nlong double evaluate(const vector<Rect>& ans) {\n    long double sum = 0.0L;\n    for (int i = 0; i < n; ++i) {\n        long long s = 1LL * (ans[i].x2 - ans[i].x1) * (ans[i].y2 - ans[i].y1);\n        long long r = rs[i];\n        long long mn = min(s, r), mx = max(s, r);\n        long double t = (long double)mn / (long double)mx;\n        long double p = 1.0L - (1.0L - t) * (1.0L - t);\n        sum += p;\n    }\n    return sum / n;\n}\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_ans(n);\n    long double best_score = -1.0L;\n\n    auto start = chrono::steady_clock::now();\n    uint64_t base_seed = chrono::steady_clock::now().time_since_epoch().count();\n\n    const int MAX_ATTEMPTS = 200;\n\n    for (int attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) {\n        if (attempt > 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > 4.7) break;\n        }\n\n        bool randomize = (attempt != 0);\n        long double slack_ratio = 0.0L;\n        int best_prob = 1000;   // probability (permille) of keeping the best candidate\n        int perturb_max = 0;\n\n        if (randomize) {\n            if (attempt < 10) {\n                slack_ratio = 0.02L;\n                best_prob = 950;\n                perturb_max = 3;\n            } else if (attempt < 30) {\n                slack_ratio = 0.05L;\n                best_prob = 850;\n                perturb_max = 10;\n            } else {\n                slack_ratio = 0.15L;\n                best_prob = 700;\n                perturb_max = 30;\n            }\n        }\n\n        vector<Rect> ans(n);\n        vector<int> ids(n);\n        iota(ids.begin(), ids.end(), 0);\n\n        mt19937_64 rng(base_seed + 1000003ULL * (uint64_t)attempt + 1234567ULL);\n\n        build(0, 0, B, B, ids, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n\n        long double score = evaluate(ans);\n        if (score > best_score) {\n            best_score = score;\n            best_ans = ans;\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        cout << best_ans[i].x1 << ' ' << best_ans[i].y1 << ' '\n             << best_ans[i].x2 << ' ' << best_ans[i].y2 << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 50;\nstatic constexpr int W = 50;\nstatic constexpr int N = H * W;\nstatic constexpr int WORDS = (N + 63) / 64;\n\nstruct Cand {\n    int next = -1;\n    char mv = '?';\n    int value = 0;\n    int deg = 0;\n    int future = 0;\n};\n\nstruct State {\n    array<uint64_t, WORDS> vis{};\n    int pos = 0;\n    int score = 0;\n    int parent = -1;\n    char mv = 0;\n    int pri = 0;\n};\n\nstruct Result {\n    string path;\n    int score = -1;\n};\n\nint si, sj;\nint tileId[H][W];\nint valGrid[H][W];\n\nint tileOf[N];\nint valueOf[N];\n\nint adjCnt[N];\nint adjTo[N][4];\nchar adjMv[N][4];\n\ninline bool isVisited(const array<uint64_t, WORDS>& vis, int tid) {\n    return (vis[tid >> 6] >> (tid & 63)) & 1ULL;\n}\ninline void setVisited(array<uint64_t, WORDS>& vis, int tid) {\n    vis[tid >> 6] |= (1ULL << (tid & 63));\n}\n\ninline int idOf(int r, int c) { return r * W + c; }\n\ninline void applyMove(State& st, const Cand& c) {\n    st.pos = c.next;\n    st.score += c.value;\n    setVisited(st.vis, tileOf[c.next]);\n}\n\ninline void collectMoves(const State& st, Cand cands[4], int& cnt, bool& hasPositiveDeg) {\n    cnt = 0;\n    hasPositiveDeg = false;\n    for (int k = 0; k < adjCnt[st.pos]; ++k) {\n        int nxt = adjTo[st.pos][k];\n        int tid = tileOf[nxt];\n        if (isVisited(st.vis, tid)) continue;\n\n        int deg = 0;\n        int b1 = 0, b2 = 0;\n        for (int kk = 0; kk < adjCnt[nxt]; ++kk) {\n            int to = adjTo[nxt][kk];\n            int tid2 = tileOf[to];\n            if (tid2 == tid) continue;              // same tile is forbidden\n            if (isVisited(st.vis, tid2)) continue;\n            ++deg;\n            int v = valueOf[to];\n            if (v > b1) {\n                b2 = b1;\n                b1 = v;\n            } else if (v > b2) {\n                b2 = v;\n            }\n        }\n\n        cands[cnt++] = {nxt, adjMv[st.pos][k], valueOf[nxt], deg, b1 + b2};\n        if (deg > 0) hasPositiveDeg = true;\n    }\n}\n\ninline bool chooseLocalStep(const State& st, int degWeight, Cand& best) {\n    Cand cands[4];\n    int cnt = 0;\n    bool hasPositive = false;\n    collectMoves(st, cands, cnt, hasPositive);\n    if (cnt == 0) return false;\n\n    bool found = false;\n    int bestScore = INT_MIN;\n    for (int i = 0; i < cnt; ++i) {\n        if (hasPositive && cands[i].deg == 0) continue; // never end early if avoidable\n        int sc = cands[i].value + cands[i].future - degWeight * cands[i].deg;\n        if (!found || sc > bestScore ||\n            (sc == bestScore && (cands[i].deg < best.deg ||\n                                 (cands[i].deg == best.deg && (cands[i].value > best.value ||\n                                 (cands[i].value == best.value && cands[i].next < best.next)))))) {\n            best = cands[i];\n            bestScore = sc;\n            found = true;\n        }\n    }\n    return found;\n}\n\ninline int estimateAfterMove(State st, int steps, int degWeight) {\n    int add = 0;\n    for (int i = 0; i < steps; ++i) {\n        Cand best;\n        if (!chooseLocalStep(st, degWeight, best)) break;\n        applyMove(st, best);\n        add += best.value;\n    }\n    return add;\n}\n\ninline bool chooseMoveWithLookahead(const State& st, int degWeight, int horizon, Cand& chosen) {\n    Cand cands[4];\n    int cnt = 0;\n    bool hasPositive = false;\n    collectMoves(st, cands, cnt, hasPositive);\n    if (cnt == 0) return false;\n\n    bool found = false;\n    int bestEst = INT_MIN;\n    for (int i = 0; i < cnt; ++i) {\n        if (hasPositive && cands[i].deg == 0) continue;\n        State tmp = st;\n        applyMove(tmp, cands[i]);\n        int est = cands[i].value;\n        if (horizon > 1) est += estimateAfterMove(tmp, horizon - 1, degWeight);\n\n        if (!found || est > bestEst ||\n            (est == bestEst && (cands[i].deg < chosen.deg ||\n                                (cands[i].deg == chosen.deg && (cands[i].value > chosen.value ||\n                                (cands[i].value == chosen.value && cands[i].next < chosen.next)))))) {\n            chosen = cands[i];\n            bestEst = est;\n            found = true;\n        }\n    }\n\n    // If all positive-degree candidates were filtered out somehow, fall back to any candidate.\n    if (!found) {\n        for (int i = 0; i < cnt; ++i) {\n            State tmp = st;\n            applyMove(tmp, cands[i]);\n            int est = cands[i].value;\n            if (horizon > 1) est += estimateAfterMove(tmp, horizon - 1, degWeight);\n            if (!found || est > bestEst ||\n                (est == bestEst && (cands[i].deg < chosen.deg ||\n                                    (cands[i].deg == chosen.deg && (cands[i].value > chosen.value ||\n                                    (cands[i].value == chosen.value && cands[i].next < chosen.next)))))) {\n                chosen = cands[i];\n                bestEst = est;\n                found = true;\n            }\n        }\n    }\n    return found;\n}\n\ninline pair<bool, int> simulatePath(const string& path) {\n    array<uint64_t, WORDS> vis{};\n    int pos = idOf(si, sj);\n    int score = valueOf[pos];\n    setVisited(vis, tileOf[pos]);\n\n    for (char ch : path) {\n        int nxt = -1;\n        for (int k = 0; k < adjCnt[pos]; ++k) {\n            if (adjMv[pos][k] == ch) {\n                nxt = adjTo[pos][k];\n                break;\n            }\n        }\n        if (nxt == -1) return {false, -1};\n        int tid = tileOf[nxt];\n        if (isVisited(vis, tid)) return {false, -1};\n        setVisited(vis, tid);\n        score += valueOf[nxt];\n        pos = nxt;\n    }\n    return {true, score};\n}\n\nResult runGreedyAttempt(int degWeight, int horizon, chrono::steady_clock::time_point deadline) {\n    State st;\n    int start = idOf(si, sj);\n    st.pos = start;\n    st.score = valueOf[start];\n    setVisited(st.vis, tileOf[start]);\n\n    string path;\n    path.reserve(3000);\n\n    while (chrono::steady_clock::now() < deadline) {\n        Cand best;\n        if (!chooseMoveWithLookahead(st, degWeight, horizon, best)) break;\n        applyMove(st, best);\n        path.push_back(best.mv);\n    }\n    return {path, st.score};\n}\n\nstring reconstructPrefix(const vector<State>& pool, int idx) {\n    string s;\n    while (idx != -1 && pool[idx].parent != -1) {\n        s.push_back(pool[idx].mv);\n        idx = pool[idx].parent;\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nResult runBeamAttempt(int beamDepth, int beamWidth, int topK, int degWeight,\n                      int beamLookahead, int completeLookahead,\n                      chrono::steady_clock::time_point deadline) {\n    vector<State> pool;\n    pool.reserve(100000);\n\n    State root;\n    int start = idOf(si, sj);\n    root.pos = start;\n    root.score = valueOf[start];\n    setVisited(root.vis, tileOf[start]);\n    root.parent = -1;\n    root.mv = 0;\n    root.pri = root.score;\n\n    pool.push_back(root);\n\n    vector<int> beam = {0};\n\n    int bestTerminalIdx = -1;\n    int bestTerminalScore = -1;\n\n    for (int depth = 0; depth < beamDepth; ++depth) {\n        if (chrono::steady_clock::now() >= deadline) break;\n\n        vector<int> nxt;\n        nxt.reserve(beam.size() * 4);\n\n        for (int idx : beam) {\n            const State cur = pool[idx];\n\n            Cand cands[4];\n            int cnt = 0;\n            bool hasPositive = false;\n            collectMoves(cur, cands, cnt, hasPositive);\n            if (cnt == 0) {\n                if (cur.score > bestTerminalScore) {\n                    bestTerminalScore = cur.score;\n                    bestTerminalIdx = idx;\n                }\n                continue;\n            }\n\n            for (int i = 0; i < cnt; ++i) {\n                if (hasPositive && cands[i].deg == 0) continue;\n\n                State child = cur;\n                applyMove(child, cands[i]);\n                child.parent = idx;\n                child.mv = cands[i].mv;\n                child.pri = child.score + estimateAfterMove(child, beamLookahead, degWeight);\n\n                pool.push_back(child);\n                nxt.push_back((int)pool.size() - 1);\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        if ((int)nxt.size() > beamWidth) {\n            nth_element(nxt.begin(), nxt.begin() + beamWidth, nxt.end(),\n                        [&](int a, int b) {\n                            if (pool[a].pri != pool[b].pri) return pool[a].pri > pool[b].pri;\n                            if (pool[a].score != pool[b].score) return pool[a].score > pool[b].score;\n                            return a < b;\n                        });\n            nxt.resize(beamWidth);\n        }\n\n        beam.swap(nxt);\n    }\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[idOf(si, sj)];\n\n    // terminal state found during beam stage\n    if (bestTerminalIdx != -1) {\n        string prefix = reconstructPrefix(pool, bestTerminalIdx);\n        Result r{prefix, bestTerminalScore};\n        if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) best = std::move(r);\n    }\n\n    // also try the current beam frontier\n    sort(beam.begin(), beam.end(), [&](int a, int b) {\n        if (pool[a].pri != pool[b].pri) return pool[a].pri > pool[b].pri;\n        if (pool[a].score != pool[b].score) return pool[a].score > pool[b].score;\n        return a < b;\n    });\n\n    int useK = min(topK, (int)beam.size());\n    if (useK > 0) {\n        // Also include the highest actual-score beam state.\n        int bestScoreIdx = beam[0];\n        for (int idx : beam) {\n            if (pool[idx].score > pool[bestScoreIdx].score) bestScoreIdx = idx;\n        }\n\n        vector<int> selected;\n        selected.reserve(useK + 1);\n        auto addUnique = [&](int x) {\n            if (find(selected.begin(), selected.end(), x) == selected.end()) selected.push_back(x);\n        };\n        for (int i = 0; i < useK; ++i) addUnique(beam[i]);\n        addUnique(bestScoreIdx);\n\n        for (int idx : selected) {\n            if (chrono::steady_clock::now() >= deadline) break;\n\n            string path = reconstructPrefix(pool, idx);\n            State st = pool[idx];\n\n            while (chrono::steady_clock::now() < deadline) {\n                Cand bestCand;\n                if (!chooseMoveWithLookahead(st, degWeight, completeLookahead, bestCand)) break;\n                applyMove(st, bestCand);\n                path.push_back(bestCand.mv);\n            }\n\n            Result r{path, st.score};\n            if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) best = std::move(r);\n        }\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> tileId[i][j];\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> valGrid[i][j];\n    }\n\n    int maxTile = -1;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            tileOf[id] = tileId[i][j];\n            valueOf[id] = valGrid[i][j];\n            maxTile = max(maxTile, tileId[i][j]);\n        }\n    }\n\n    // Build adjacency\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            adjCnt[id] = 0;\n            if (i > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i - 1, j);\n                adjMv[id][adjCnt[id]++] = 'U';\n            }\n            if (i + 1 < H) {\n                adjTo[id][adjCnt[id]] = idOf(i + 1, j);\n                adjMv[id][adjCnt[id]++] = 'D';\n            }\n            if (j > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i, j - 1);\n                adjMv[id][adjCnt[id]++] = 'L';\n            }\n            if (j + 1 < W) {\n                adjTo[id][adjCnt[id]] = idOf(i, j + 1);\n                adjMv[id][adjCnt[id]++] = 'R';\n            }\n        }\n    }\n\n    auto startTime = chrono::steady_clock::now();\n    auto deadline = startTime + chrono::milliseconds(1850);\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[idOf(si, sj)];\n\n    auto consider = [&](Result r) {\n        auto [ok, sc] = simulatePath(r.path);\n        if (!ok) return;\n        r.score = sc;\n        if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) {\n            best = std::move(r);\n        }\n    };\n\n    // Baseline greedy attempts\n    if (chrono::steady_clock::now() < deadline) consider(runGreedyAttempt(15, 3, deadline));\n    if (chrono::steady_clock::now() < deadline) consider(runGreedyAttempt(35, 4, deadline));\n    if (chrono::steady_clock::now() < deadline) consider(runGreedyAttempt(55, 5, deadline));\n\n    // Beam + completion attempts\n    if (chrono::steady_clock::now() < deadline) {\n        consider(runBeamAttempt(60, 80, 8, 25, 2, 4, deadline));\n    }\n    if (chrono::steady_clock::now() < deadline) {\n        consider(runBeamAttempt(90, 100, 10, 45, 2, 4, deadline));\n    }\n    if (chrono::steady_clock::now() < deadline) {\n        consider(runBeamAttempt(120, 120, 12, 55, 3, 5, deadline));\n    }\n\n    // Final verification\n    auto [ok, sc] = simulatePath(best.path);\n    if (ok) best.score = sc;\n    else best.path.clear();\n\n    cout << best.path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr double INIT_W = 5000.0;\nstatic constexpr double MIN_W = 1000.0;\nstatic constexpr double MAX_W = 9000.0;\nstatic constexpr double SMOOTH = 5.0;   // row/column prior strength\nstatic constexpr double BASE_LR = 0.50;  // update strength\n\ndouble H[N][N - 1];\ndouble V[N - 1][N];\nint cntH[N][N - 1];\nint cntV[N - 1][N];\n\nmt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\ninline double clampw(double x) {\n    return max(MIN_W, min(MAX_W, x));\n}\n\ninline bool betterCand(double cand, double best) {\n    const double EPS = 1e-9;\n    if (cand + EPS < best) return true;\n    if (fabs(cand - best) <= EPS) return (rng() & 1);\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            H[i][j] = INIT_W;\n            cntH[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            V[i][j] = INIT_W;\n            cntV[i][j] = 0;\n        }\n    }\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        int dy = abs(ti - si);\n        int dx = abs(tj - sj);\n        int sv = (ti >= si ? 1 : -1);\n        int sh = (tj >= sj ? 1 : -1);\n\n        double rowMean[N], colMean[N];\n        for (int i = 0; i < N; ++i) {\n            double s = 0.0;\n            for (int j = 0; j < N - 1; ++j) s += H[i][j];\n            rowMean[i] = s / (N - 1);\n        }\n        for (int j = 0; j < N; ++j) {\n            double s = 0.0;\n            for (int i = 0; i < N - 1; ++i) s += V[i][j];\n            colMean[j] = s / (N - 1);\n        }\n\n        static double dp[N][N];\n        static char par[N][N];\n\n        for (int i = 0; i <= dy; ++i) {\n            for (int j = 0; j <= dx; ++j) {\n                dp[i][j] = 1e100;\n                par[i][j] = 0;\n            }\n        }\n        dp[0][0] = 0.0;\n\n        for (int i = 0; i <= dy; ++i) {\n            for (int j = 0; j <= dx; ++j) {\n                if (i == 0 && j == 0) continue;\n\n                double best = 1e100;\n                char bestPar = 0;\n\n                // From vertical move\n                if (i > 0) {\n                    int px = si + sv * (i - 1);\n                    int py = sj + sh * j;\n                    int ex = (sv == 1 ? px : px - 1);\n                    int ey = py;\n                    double est = (V[ex][ey] * cntV[ex][ey] + colMean[ey] * SMOOTH) /\n                                 (cntV[ex][ey] + SMOOTH);\n                    double cand = dp[i - 1][j] + est;\n                    if (betterCand(cand, best)) {\n                        best = cand;\n                        bestPar = (sv == 1 ? 'D' : 'U');\n                    }\n                }\n\n                // From horizontal move\n                if (j > 0) {\n                    int px = si + sv * i;\n                    int py = sj + sh * (j - 1);\n                    int ex = px;\n                    int ey = (sh == 1 ? py : py - 1);\n                    double est = (H[ex][ey] * cntH[ex][ey] + rowMean[ex] * SMOOTH) /\n                                 (cntH[ex][ey] + SMOOTH);\n                    double cand = dp[i][j - 1] + est;\n                    if (betterCand(cand, best)) {\n                        best = cand;\n                        bestPar = (sh == 1 ? 'R' : 'L');\n                    }\n                }\n\n                dp[i][j] = best;\n                par[i][j] = bestPar;\n            }\n        }\n\n        string path;\n        path.reserve(dx + dy);\n        for (int i = dy, j = dx; i > 0 || j > 0; ) {\n            char c = par[i][j];\n            path.push_back(c);\n            if (c == 'D' || c == 'U') --i;\n            else --j;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << '\\n' << flush;\n\n        long long obs;\n        cin >> obs;\n\n        // Predict length of the chosen path using current raw estimates\n        double pred = 0.0;\n        int x = si, y = sj;\n        for (char c : path) {\n            if (c == 'D') {\n                pred += V[x][y];\n                ++x;\n            } else if (c == 'U') {\n                pred += V[x - 1][y];\n                --x;\n            } else if (c == 'R') {\n                pred += H[x][y];\n                ++y;\n            } else { // 'L'\n                pred += H[x][y - 1];\n                --y;\n            }\n        }\n\n        double residual = (double)obs - pred;\n        double unit = residual / (double)path.size();\n\n        // Update edges on the chosen path\n        x = si; y = sj;\n        for (char c : path) {\n            if (c == 'D') {\n                int ex = x, ey = y;\n                double eta = BASE_LR / sqrt((double)cntV[ex][ey] + 1.0);\n                V[ex][ey] = clampw(V[ex][ey] + eta * unit);\n                ++cntV[ex][ey];\n                ++x;\n            } else if (c == 'U') {\n                int ex = x - 1, ey = y;\n                double eta = BASE_LR / sqrt((double)cntV[ex][ey] + 1.0);\n                V[ex][ey] = clampw(V[ex][ey] + eta * unit);\n                ++cntV[ex][ey];\n                --x;\n            } else if (c == 'R') {\n                int ex = x, ey = y;\n                double eta = BASE_LR / sqrt((double)cntH[ex][ey] + 1.0);\n                H[ex][ey] = clampw(H[ex][ey] + eta * unit);\n                ++cntH[ex][ey];\n                ++y;\n            } else { // 'L'\n                int ex = x, ey = y - 1;\n                double eta = BASE_LR / sqrt((double)cntH[ex][ey] + 1.0);\n                H[ex][ey] = clampw(H[ex][ey] + eta * unit);\n                ++cntH[ex][ey];\n                --y;\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\n\nstruct Word {\n    string s;\n    int len;\n};\n\nusing Board = array<array<char, N>, N>;\n\nstruct Cand {\n    int m;\n    bool horiz;\n    int a; // row if horiz, col if vertical\n    int b; // start\n};\n\nstatic inline int matchCount(const char* line, const char* s, int L) {\n    int m = 0;\n    for (int i = 0; i < L; ++i) m += (line[i] == s[i]);\n    return m;\n}\n\nstatic void buildBuffers(const Board& b, char rowbuf[N][2 * N], char colbuf[N][2 * N]) {\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            rowbuf[i][j] = b[i][j];\n            rowbuf[i][j + N] = b[i][j];\n            colbuf[i][j] = b[j][i];\n            colbuf[i][j + N] = b[j][i];\n        }\n    }\n}\n\nstatic int exactScore(const Board& b, const vector<Word>& words) {\n    char rowbuf[N][2 * N];\n    char colbuf[N][2 * N];\n    buildBuffers(b, rowbuf, colbuf);\n\n    int score = 0;\n    for (const auto& w : words) {\n        const char* sp = w.s.data();\n        int L = w.len;\n        bool ok = false;\n\n        for (int r = 0; r < N && !ok; ++r) {\n            for (int st = 0; st < N; ++st) {\n                if (memcmp(rowbuf[r] + st, sp, L) == 0) {\n                    ok = true;\n                    break;\n                }\n            }\n        }\n        for (int c = 0; c < N && !ok; ++c) {\n            for (int st = 0; st < N; ++st) {\n                if (memcmp(colbuf[c] + st, sp, L) == 0) {\n                    ok = true;\n                    break;\n                }\n            }\n        }\n        score += ok;\n    }\n    return score;\n}\n\nstatic void iterateBoard(Board& b, const vector<Word>& words, const vector<int>& useIdx, int topK) {\n    char rowbuf[N][2 * N];\n    char colbuf[N][2 * N];\n    buildBuffers(b, rowbuf, colbuf);\n\n    static int cnt[N][N][8];\n    memset(cnt, 0, sizeof(cnt));\n\n    for (int idx : useIdx) {\n        const auto& w = words[idx];\n        const char* sp = w.s.data();\n        int L = w.len;\n\n        Cand best[3];\n        for (int k = 0; k < 3; ++k) best[k] = {-1, true, 0, 0};\n\n        auto relax = [&](int m, bool horiz, int a, int st) {\n            if (m > best[0].m) {\n                best[2] = best[1];\n                best[1] = best[0];\n                best[0] = {m, horiz, a, st};\n            } else if (m > best[1].m) {\n                best[2] = best[1];\n                best[1] = {m, horiz, a, st};\n            } else if (m > best[2].m) {\n                best[2] = {m, horiz, a, st};\n            }\n        };\n\n        for (int r = 0; r < N; ++r) {\n            for (int st = 0; st < N; ++st) {\n                const char* line = rowbuf[r] + st;\n                int m = matchCount(line, sp, L);\n                relax(m, true, r, st);\n            }\n        }\n        for (int c = 0; c < N; ++c) {\n            for (int st = 0; st < N; ++st) {\n                const char* line = colbuf[c] + st;\n                int m = matchCount(line, sp, L);\n                relax(m, false, c, st);\n            }\n        }\n\n        static const int factor[3] = {4, 2, 1};\n        for (int k = 0; k < topK; ++k) {\n            if (best[k].m < 0) continue;\n            int wgt = factor[k] * ((best[k].m + 1) * (best[k].m + 1));\n            if (best[k].m == L) wgt += factor[k] * 100;\n\n            if (best[k].horiz) {\n                int r = best[k].a;\n                int pos = best[k].b;\n                for (int t = 0; t < L; ++t) {\n                    cnt[r][pos][sp[t] - 'A'] += wgt;\n                    if (++pos == N) pos = 0;\n                }\n            } else {\n                int c = best[k].a;\n                int pos = best[k].b;\n                for (int t = 0; t < L; ++t) {\n                    cnt[pos][c][sp[t] - 'A'] += wgt;\n                    if (++pos == N) pos = 0;\n                }\n            }\n        }\n    }\n\n    // inertia for current board\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            cnt[r][c][b[r][c] - 'A'] += 20;\n        }\n    }\n\n    Board nb = b;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int bestk = b[r][c] - 'A';\n            int bestv = cnt[r][c][bestk];\n            for (int k = 0; k < 8; ++k) {\n                if (cnt[r][c][k] > bestv) {\n                    bestv = cnt[r][c][k];\n                    bestk = k;\n                }\n            }\n            nb[r][c] = char('A' + bestk);\n        }\n    }\n    b = nb;\n}\n\nstatic Board makeInitialBoard(const vector<Word>& words, const vector<int>& seedIdx, mt19937_64& rng, int restartId) {\n    Board b;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            b[i][j] = char('A' + (rng() % 8));\n\n    int seedCnt = min<int>(20, (int)seedIdx.size());\n    bool swapOrient = (restartId & 1);\n\n    // Use disjoint seed rows/cols to avoid too many conflicts.\n    // First 10 seeds on rows 0..9, next 10 on cols 10..19 (or swapped on odd restarts).\n    for (int k = 0; k < seedCnt; ++k) {\n        const auto& w = words[seedIdx[k]].s;\n        int L = w.size();\n        int st = int(rng() % N);\n\n        if (!swapOrient) {\n            if (k < 10) {\n                int r = k;\n                for (int t = 0; t < L; ++t) {\n                    b[r][(st + t) % N] = w[t];\n                }\n            } else {\n                int c = 10 + (k - 10);\n                for (int t = 0; t < L; ++t) {\n                    b[(st + t) % N][c] = w[t];\n                }\n            }\n        } else {\n            if (k < 10) {\n                int c = k;\n                for (int t = 0; t < L; ++t) {\n                    b[(st + t) % N][c] = w[t];\n                }\n            } else {\n                int r = 10 + (k - 10);\n                for (int t = 0; t < L; ++t) {\n                    b[r][(st + t) % N] = w[t];\n                }\n            }\n        }\n    }\n\n    return b;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Ninput, M;\n    cin >> Ninput >> M;\n    vector<Word> words(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> words[i].s;\n        words[i].len = (int)words[i].s.size();\n    }\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (words[a].len != words[b].len) return words[a].len > words[b].len;\n        return a < b;\n    });\n\n    vector<int> phaseA;\n    for (int id : order) {\n        if (words[id].len >= 6) phaseA.push_back(id);\n    }\n    if (phaseA.size() > 250) phaseA.resize(250);\n    if (phaseA.empty()) phaseA = order;\n\n    vector<int> seedIdx = phaseA;\n    if ((int)seedIdx.size() > 20) seedIdx.resize(20);\n\n    Board bestBoard;\n    int bestScore = -1;\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    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    const int RESTARTS = 6;\n    for (int rt = 0; rt < RESTARTS; ++rt) {\n        if (elapsed() > 2.85) break;\n\n        Board b = makeInitialBoard(words, seedIdx, rng, rt);\n        int localBestScore = exactScore(b, words);\n        Board localBestBoard = b;\n\n        // 6 iterations total:\n        //  - first 2: only long strings, soft top-3 votes\n        //  - next 4: all strings, hard top-1/top-3\n        for (int it = 0; it < 6; ++it) {\n            if (elapsed() > 2.90) break;\n\n            if (it < 2) {\n                iterateBoard(b, words, phaseA, 3);\n            } else {\n                vector<int> allIdx(M);\n                iota(allIdx.begin(), allIdx.end(), 0);\n                iterateBoard(b, words, allIdx, 1);\n            }\n\n            int sc = exactScore(b, words);\n            if (sc > localBestScore) {\n                localBestScore = sc;\n                localBestBoard = b;\n            }\n            if (sc == M) break;\n        }\n\n        if (localBestScore > bestScore) {\n            bestScore = localBestScore;\n            bestBoard = localBestBoard;\n        }\n    }\n\n    // Final small polish from the best board.\n    {\n        Board b = bestBoard;\n        for (int it = 0; it < 2; ++it) {\n            if (elapsed() > 2.95) break;\n            vector<int> allIdx(M);\n            iota(allIdx.begin(), allIdx.end(), 0);\n            iterateBoard(b, words, allIdx, 1);\n            int sc = exactScore(b, words);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestBoard = b;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cout << bestBoard[i][j];\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INF = (1LL << 60);\n\nstruct HSeg { int row, l, r; };\nstruct VSeg { int col, u, d; };\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> g(N);\n    for (int i = 0; i < N; ++i) cin >> g[i];\n\n    int M = N * N;\n    vector<char> road(M, 0);\n    vector<int> wt(M, 0), rowOf(M), colOf(M);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            rowOf[idx] = i;\n            colOf[idx] = j;\n            if (g[i][j] != '#') {\n                road[idx] = 1;\n                wt[idx] = g[i][j] - '0';\n            }\n        }\n    }\n\n    // Build maximal horizontal segments (on even rows)\n    vector<HSeg> hsegs;\n    vector<int> hOf(M, -1);\n    for (int i = 0; i < N; i += 2) {\n        int j = 0;\n        while (j < N) {\n            while (j < N && !road[i * N + j]) ++j;\n            if (j >= N) break;\n            int l = j;\n            while (j < N && road[i * N + j]) ++j;\n            int r = j - 1;\n            int id = (int)hsegs.size();\n            hsegs.push_back({i, l, r});\n            for (int k = l; k <= r; ++k) hOf[i * N + k] = id;\n        }\n    }\n\n    // Build maximal vertical segments (on even cols)\n    vector<VSeg> vsegs;\n    vector<int> vOf(M, -1);\n    for (int j = 0; j < N; j += 2) {\n        int i = 0;\n        while (i < N) {\n            while (i < N && !road[i * N + j]) ++i;\n            if (i >= N) break;\n            int u = i;\n            while (i < N && road[i * N + j]) ++i;\n            int d = i - 1;\n            int id = (int)vsegs.size();\n            vsegs.push_back({j, u, d});\n            for (int k = u; k <= d; ++k) vOf[k * N + j] = id;\n        }\n    }\n\n    // Build original and reversed adjacency.\n    vector<vector<pair<int,int>>> adj(M), radj(M);\n    int dx[4] = {-1, 1, 0, 0};\n    int dy[4] = {0, 0, -1, 1};\n\n    for (int idx = 0; idx < M; ++idx) {\n        if (!road[idx]) continue;\n        int i = rowOf[idx], j = colOf[idx];\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + dx[dir], nj = j + dy[dir];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            int v = ni * N + nj;\n            if (!road[v]) continue;\n            // Original: idx -> v costs wt[v]\n            adj[idx].push_back({v, wt[v]});\n            // Reverse graph: v -> idx costs wt[v]\n            radj[v].push_back({idx, wt[v]});\n        }\n    }\n\n    auto dijkstra = [&](int src, const vector<vector<pair<int,int>>>& graph,\n                        vector<ll>& dist, vector<int>& par) {\n        dist.assign(M, INF);\n        par.assign(M, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[src] = 0;\n        par[src] = src;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, c] : graph[u]) {\n                ll nd = d + c;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    par[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    };\n\n    // Candidate cells:\n    // - all intersection cells\n    // - one representative (center) per horizontal segment\n    // - one representative (center) per vertical segment\n    vector<int> candidates;\n    vector<char> isCand(M, 0);\n    auto addCand = [&](int idx) {\n        if (idx < 0 || idx >= M) return;\n        if (!road[idx]) return;\n        if (!isCand[idx]) {\n            isCand[idx] = 1;\n            candidates.push_back(idx);\n        }\n    };\n\n    for (int idx = 0; idx < M; ++idx) {\n        if (!road[idx]) continue;\n        if (hOf[idx] != -1 && vOf[idx] != -1) addCand(idx);\n    }\n    for (const auto& s : hsegs) {\n        int idx = s.row * N + (s.l + s.r) / 2;\n        addCand(idx);\n    }\n    for (const auto& s : vsegs) {\n        int idx = ((s.u + s.d) / 2) * N + s.col;\n        addCand(idx);\n    }\n\n    int totalSeg = (int)hsegs.size() + (int)vsegs.size();\n    vector<char> coveredH(hsegs.size(), 0), coveredV(vsegs.size(), 0);\n    int coveredCount = 0;\n\n    auto coverCell = [&](int idx) -> int {\n        int add = 0;\n        int h = hOf[idx];\n        if (h != -1 && !coveredH[h]) {\n            coveredH[h] = 1;\n            ++add;\n        }\n        int v = vOf[idx];\n        if (v != -1 && !coveredV[v]) {\n            coveredV[v] = 1;\n            ++add;\n        }\n        coveredCount += add;\n        return add;\n    };\n\n    int start = si * N + sj;\n    coverCell(start);\n\n    // Precompute reverse distances to start (cost from cell -> start in the original graph)\n    vector<ll> retDist;\n    vector<int> dummyPar;\n    dijkstra(start, radj, retDist, dummyPar);\n\n    vector<ll> dist;\n    vector<int> par;\n    vector<int> seenH(hsegs.size(), 0), seenV(vsegs.size(), 0);\n    int stamp = 0;\n\n    string ans;\n    ans.reserve(20000);\n\n    int current = start;\n\n    auto appendPath = [&](const vector<int>& path) {\n        int prevIdx = current;\n        for (int idx : path) {\n            int pr = rowOf[prevIdx], pc = colOf[prevIdx];\n            int r = rowOf[idx], c = colOf[idx];\n            if (r == pr - 1 && c == pc) ans.push_back('U');\n            else if (r == pr + 1 && c == pc) ans.push_back('D');\n            else if (r == pr && c == pc - 1) ans.push_back('L');\n            else if (r == pr && c == pc + 1) ans.push_back('R');\n            else {\n                // Should never happen on a valid shortest path.\n            }\n            coverCell(idx);\n            prevIdx = idx;\n        }\n        current = prevIdx;\n    };\n\n    while (coveredCount < totalSeg) {\n        dijkstra(current, adj, dist, par);\n\n        int rem = totalSeg - coveredCount;\n        long double bonus, retCoef;\n        if (rem * 3 > totalSeg * 2) {\n            bonus = 20.0L;\n            retCoef = 0.05L;\n        } else if (rem * 3 > totalSeg) {\n            bonus = 17.0L;\n            retCoef = 0.10L;\n        } else {\n            bonus = 14.0L;\n            retCoef = 0.20L;\n        }\n\n        long double bestScore = -1e100L;\n        int bestCand = -1;\n        int bestGain = -1;\n        ll bestDist = INF, bestRet = INF;\n        vector<int> bestPath;\n\n        vector<int> tmp;\n        tmp.reserve(256);\n\n        for (int cand : candidates) {\n            if (dist[cand] >= INF / 2) continue;\n\n            tmp.clear();\n            int x = cand;\n            bool ok = true;\n            while (x != current) {\n                if (x < 0 || x >= M || par[x] == -1) { ok = false; break; }\n                tmp.push_back(x);\n                x = par[x];\n            }\n            if (!ok || tmp.empty()) continue;\n\n            int gain = 0;\n            ++stamp;\n            for (int idx : tmp) {\n                int h = hOf[idx];\n                if (h != -1 && !coveredH[h] && seenH[h] != stamp) {\n                    seenH[h] = stamp;\n                    ++gain;\n                }\n                int v = vOf[idx];\n                if (v != -1 && !coveredV[v] && seenV[v] != stamp) {\n                    seenV[v] = stamp;\n                    ++gain;\n                }\n            }\n            if (gain == 0) continue;\n\n            long double score = bonus * gain - (long double)dist[cand] - retCoef * (long double)retDist[cand];\n\n            if (score > bestScore + 1e-12L ||\n                (fabsl(score - bestScore) <= 1e-12L &&\n                 (gain > bestGain ||\n                  (gain == bestGain && (dist[cand] < bestDist ||\n                                        (dist[cand] == bestDist && retDist[cand] < bestRet)))))) {\n                bestScore = score;\n                bestCand = cand;\n                bestGain = gain;\n                bestDist = dist[cand];\n                bestRet = retDist[cand];\n                bestPath = tmp;\n                reverse(bestPath.begin(), bestPath.end()); // current -> cand\n            }\n        }\n\n        if (bestCand == -1) {\n            // Safety fallback: choose any candidate that directly lies on an uncovered segment.\n            bool found = false;\n            for (int cand : candidates) {\n                if (dist[cand] >= INF / 2) continue;\n                int h = hOf[cand], v = vOf[cand];\n                if ((h != -1 && !coveredH[h]) || (v != -1 && !coveredV[v])) {\n                    tmp.clear();\n                    int x = cand;\n                    bool ok = true;\n                    while (x != current) {\n                        if (x < 0 || x >= M || par[x] == -1) { ok = false; break; }\n                        tmp.push_back(x);\n                        x = par[x];\n                    }\n                    if (!ok || tmp.empty()) continue;\n                    bestPath = tmp;\n                    reverse(bestPath.begin(), bestPath.end());\n                    bestCand = cand;\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) break; // Should not happen if candidate set is correct.\n        }\n\n        appendPath(bestPath);\n    }\n\n    // Return to start by the shortest path.\n    if (current != start) {\n        dijkstra(current, adj, dist, par);\n        vector<int> back;\n        int x = start;\n        bool ok = true;\n        while (x != current) {\n            if (x < 0 || x >= M || par[x] == -1) { ok = false; break; }\n            back.push_back(x);\n            x = par[x];\n        }\n        if (ok) {\n            reverse(back.begin(), back.end());\n            appendPath(back);\n        }\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskNode {\n    long long pr;\n    int id;\n};\n\nstruct TaskCmp {\n    bool operator()(const TaskNode& a, const TaskNode& b) const {\n        if (a.pr != b.pr) return a.pr < b.pr; // max-heap by priority\n        return a.id > b.id;                  // smaller id first on tie\n    }\n};\n\nstatic const double INIT_SKILL = 5.0;\n\nvector<int> hungarian_min_cost(const vector<vector<double>>& a) {\n    int n = (int)a.size();\n    const double INF = 1e100;\n    vector<double> u(n + 1, 0.0), v(n + 1, 0.0), minv(n + 1);\n    vector<int> p(n + 1, 0), way(n + 1, 0);\n\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        fill(minv.begin(), minv.end(), INF);\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            double delta = INF;\n            int j1 = 0;\n\n            for (int j = 1; j <= n; ++j) {\n                if (used[j]) continue;\n                double cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n\n            for (int j = 0; j <= n; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    vector<int> ans(n, -1);\n    for (int j = 1; j <= n; ++j) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<vector<int>> d(N, vector<int>(K));\n    vector<long long> sumd(N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            cin >> d[i][k];\n            sumd[i] += d[i][k];\n        }\n    }\n\n    vector<vector<int>> succ(N);\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Weighted criticality: own difficulty + longest downstream chain difficulty.\n    vector<long long> workRemain(N, 0), height(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        long long bestWork = 0;\n        long long bestH = 0;\n        for (int v : succ[i]) {\n            bestWork = max(bestWork, workRemain[v]);\n            bestH = max(bestH, height[v]);\n        }\n        workRemain[i] = sumd[i] + bestWork;\n        height[i] = 1 + bestH;\n    }\n\n    vector<long long> priority(N, 0);\n    for (int i = 0; i < N; ++i) {\n        priority[i] = workRemain[i] * 1000LL + height[i];\n    }\n\n    priority_queue<TaskNode, vector<TaskNode>, TaskCmp> pq;\n    for (int i = 0; i < N; ++i) {\n        if (indeg[i] == 0) pq.push({priority[i], i});\n    }\n\n    vector<int> busyTask(M, -1);\n    vector<int> startDay(M, -1);\n    vector<int> taskStatus(N, 0); // 0=not started, 1=started, 2=done\n    vector<vector<double>> skill(M, vector<double>(K, INIT_SKILL));\n    vector<int> obsCnt(M, 0);\n\n    auto predict_duration = [&](int mem, int task) -> double {\n        double w = 0.0;\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill[mem][k]) {\n                w += (double)d[task][k] - skill[mem][k];\n            }\n        }\n        return max(1.0, w);\n    };\n\n    auto update_skill = [&](int mem, int task, int dur) {\n        double w = 0.0;\n        vector<double> gap(K, 0.0);\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill[mem][k]) {\n                gap[k] = (double)d[task][k] - skill[mem][k];\n                w += gap[k];\n            }\n        }\n\n        double pred = max(1.0, w);\n        double err = (double)dur - pred;\n        err = max(-4.0, min(4.0, err));\n\n        double eta = 0.5 / sqrt((double)obsCnt[mem] + 1.0);\n\n        if (w > 1e-9) {\n            for (int k = 0; k < K; ++k) {\n                if (gap[k] <= 0.0) continue;\n                skill[mem][k] -= eta * err * (gap[k] / w);\n                if (skill[mem][k] < 0.0) skill[mem][k] = 0.0;\n                if (skill[mem][k] > 100.0) skill[mem][k] = 100.0;\n            }\n        } else if (err > 0.0) {\n            // If predicted exactly 1, but actual duration was longer, lower all skills slightly.\n            double dec = eta * err / max(1, K);\n            for (int k = 0; k < K; ++k) {\n                skill[mem][k] = max(0.0, skill[mem][k] - dec);\n            }\n        }\n\n        obsCnt[mem]++;\n    };\n\n    int day = 1;\n    while (true) {\n        vector<int> freeMembers;\n        freeMembers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (busyTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        int freeCount = (int)freeMembers.size();\n        int take = min(freeCount, (int)pq.size());\n\n        vector<int> selected;\n        selected.reserve(take);\n        for (int t = 0; t < take; ++t) {\n            selected.push_back(pq.top().id);\n            pq.pop();\n        }\n\n        vector<pair<int,int>> outPairs;\n\n        if (freeCount > 0 && !selected.empty()) {\n            int n = freeCount;\n            int L = (int)selected.size();\n\n            vector<vector<double>> cost(n, vector<double>(n, 0.0));\n            for (int r = 0; r < n; ++r) {\n                int mem = freeMembers[r];\n                for (int c = 0; c < L; ++c) {\n                    cost[r][c] = predict_duration(mem, selected[c]);\n                }\n                for (int c = L; c < n; ++c) {\n                    cost[r][c] = 0.0; // dummy task\n                }\n            }\n\n            vector<int> assign = hungarian_min_cost(cost);\n\n            for (int r = 0; r < n; ++r) {\n                int c = assign[r];\n                if (c >= 0 && c < L) {\n                    int mem = freeMembers[r];\n                    int task = selected[c];\n                    outPairs.push_back({mem, task});\n                    busyTask[mem] = task;\n                    startDay[mem] = day;\n                    taskStatus[task] = 1;\n                }\n            }\n        }\n\n        cout << outPairs.size();\n        for (auto &p : outPairs) {\n            cout << ' ' << (p.first + 1) << ' ' << (p.second + 1);\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        vector<int> finished(cnt);\n        for (int i = 0; i < cnt; ++i) cin >> finished[i];\n\n        for (int mem1 : finished) {\n            int mem = mem1 - 1;\n            int task = busyTask[mem];\n            if (task < 0) continue;\n\n            int dur = day - startDay[mem] + 1;\n            update_skill(mem, task, dur);\n\n            busyTask[mem] = -1;\n            startDay[mem] = -1;\n            taskStatus[task] = 2;\n\n            for (int v : succ[task]) {\n                if (--indeg[v] == 0) {\n                    pq.push({priority[v], v});\n                }\n            }\n        }\n\n        day++;\n    }\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Order {\n    Point p, q;   // pickup, delivery\n    ll op, oq;    // dist to office\n    ll pq;        // pickup-delivery distance\n};\n\nstruct Event {\n    int pos;   // position in selected subset [0..49]\n    int type;  // 0 = pickup, 1 = delivery\n};\n\nstruct RouteResult {\n    ll cost;\n    vector<Point> pts;\n};\n\nstatic constexpr Point OFFICE{400, 400};\n\nstatic inline ll absll(ll x) { return x >= 0 ? x : -x; }\nstatic inline ll md(const Point& a, const Point& b) {\n    return absll((ll)a.x - b.x) + absll((ll)a.y - b.y);\n}\n\nstatic inline Point getPoint(const Event& e, const vector<Point>& P, const vector<Point>& Q) {\n    return (e.type == 0 ? P[e.pos] : Q[e.pos]);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 1000;\n    vector<Order> ord(N);\n\n    for (int i = 0; i < N; ++i) {\n        cin >> ord[i].p.x >> ord[i].p.y >> ord[i].q.x >> ord[i].q.y;\n        ord[i].op = md(ord[i].p, OFFICE);\n        ord[i].oq = md(ord[i].q, OFFICE);\n        ord[i].pq = md(ord[i].p, ord[i].q);\n    }\n\n    auto selectTop50 = [&](auto scorer) -> vector<int> {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = scorer(i);\n\n        vector<int> idx(N);\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int a, int b) {\n            if (sc[a] != sc[b]) return sc[a] < sc[b];\n            return a < b;\n        });\n\n        vector<int> sel(idx.begin(), idx.begin() + 50);\n        sort(sel.begin(), sel.end());\n        return sel;\n    };\n\n    auto insideR = [&](int i, int R) -> bool {\n        return abs(ord[i].p.x - 400) <= R && abs(ord[i].p.y - 400) <= R &&\n               abs(ord[i].q.x - 400) <= R && abs(ord[i].q.y - 400) <= R;\n    };\n\n    vector<vector<int>> candidates;\n    auto addCand = [&](vector<int> sel) {\n        candidates.push_back(std::move(sel));\n    };\n\n    // Several different compactness scores.\n    addCand(selectTop50([&](int i) { return ord[i].op + ord[i].oq + ord[i].pq; }));\n    addCand(selectTop50([&](int i) { return max(ord[i].op, ord[i].oq) + ord[i].pq; }));\n    addCand(selectTop50([&](int i) { return ord[i].op + ord[i].oq + 2LL * ord[i].pq; }));\n    addCand(selectTop50([&](int i) { return max(ord[i].op, ord[i].oq) + 2LL * ord[i].pq; }));\n    addCand(selectTop50([&](int i) { return ord[i].op + ord[i].oq; }));\n    addCand(selectTop50([&](int i) { return max(ord[i].op, ord[i].oq); }));\n\n    // Central-square-biased candidates.\n    const ll PEN = 1'000'000'000LL;\n    for (int R : {150, 170, 190, 210, 230}) {\n        addCand(selectTop50([&](int i) {\n            ll s = ord[i].op + ord[i].oq + ord[i].pq;\n            if (!insideR(i, R)) s += PEN;\n            return s;\n        }));\n        addCand(selectTop50([&](int i) {\n            ll s = max(ord[i].op, ord[i].oq) + ord[i].pq;\n            if (!insideR(i, R)) s += PEN;\n            return s;\n        }));\n    }\n\n    auto buildRoute = [&](const vector<int>& sel, int alpha, bool lookahead) -> RouteResult {\n        const int M = 50;\n        vector<Point> P(M), Q(M);\n        vector<ll> pairLen(M);\n        vector<int> origIdx(M);\n\n        for (int i = 0; i < M; ++i) {\n            int id = sel[i];\n            P[i] = ord[id].p;\n            Q[i] = ord[id].q;\n            pairLen[i] = ord[id].pq;\n            origIdx[i] = id;\n        }\n\n        // Initial feasible sequence by greedy choice among available events.\n        vector<int> st(M, 0); // 0: pickup not done, 1: picked, 2: delivered\n        vector<Event> seq;\n        seq.reserve(2 * M);\n        Point cur = OFFICE;\n\n        for (int step = 0; step < 2 * M; ++step) {\n            tuple<ll, int, ll, int> bestKey = { (1LL << 60), 2, (1LL << 60), (1LL << 60) };\n            int bestPos = -1;\n\n            for (int pos = 0; pos < M; ++pos) {\n                if (st[pos] == 2) continue;\n\n                int tp = st[pos];\n                Point nxt = (tp == 0 ? P[pos] : Q[pos]);\n                ll d1 = md(cur, nxt);\n\n                // Base score: distance from current.\n                ll sc = d1 * 10;\n\n                // Slightly prefer pickups with short pickup-delivery distance.\n                if (tp == 0) sc += (ll)alpha * pairLen[pos];\n\n                if (lookahead) {\n                    st[pos]++;\n                    ll d2 = (1LL << 60);\n                    for (int j = 0; j < M; ++j) {\n                        if (st[j] == 2) continue;\n                        Point cand = (st[j] == 0 ? P[j] : Q[j]);\n                        d2 = min(d2, md(nxt, cand));\n                    }\n                    st[pos]--;\n                    if (d2 == (1LL << 60)) d2 = 0;\n                    sc += d2 * 10;\n                }\n\n                int typePriority = (tp == 1 ? 0 : 1); // delivery first on ties\n                tuple<ll, int, ll, int> key = { sc, typePriority, d1, origIdx[pos] };\n                if (key < bestKey) {\n                    bestKey = key;\n                    bestPos = pos;\n                }\n            }\n\n            seq.push_back({bestPos, st[bestPos]});\n            cur = (st[bestPos] == 0 ? P[bestPos] : Q[bestPos]);\n            st[bestPos]++;\n        }\n\n        // Local improvement: adjacent swaps of different orders are precedence-safe.\n        auto improve = [&]() {\n            const int L = (int)seq.size();\n            for (int iter = 0; iter < 30; ++iter) {\n                bool changed = false;\n                for (int i = 0; i + 1 < L; ++i) {\n                    if (seq[i].pos == seq[i + 1].pos) continue; // same order => cannot swap\n\n                    Point A = getPoint(seq[i], P, Q);\n                    Point B = getPoint(seq[i + 1], P, Q);\n                    Point prev = (i == 0 ? OFFICE : getPoint(seq[i - 1], P, Q));\n                    Point nxt = (i + 2 == L ? OFFICE : getPoint(seq[i + 2], P, Q));\n\n                    ll before = md(prev, A) + md(A, B) + md(B, nxt);\n                    ll after  = md(prev, B) + md(B, A) + md(A, nxt);\n\n                    if (after < before) {\n                        swap(seq[i], seq[i + 1]);\n                        changed = true;\n                    }\n                }\n                if (!changed) break;\n            }\n        };\n\n        improve();\n\n        vector<Point> pts;\n        pts.reserve(2 * M + 2);\n        pts.push_back(OFFICE);\n        for (const auto& e : seq) {\n            pts.push_back(getPoint(e, P, Q));\n        }\n        pts.push_back(OFFICE);\n\n        ll cost = 0;\n        for (int i = 0; i + 1 < (int)pts.size(); ++i) cost += md(pts[i], pts[i + 1]);\n\n        return {cost, pts};\n    };\n\n    RouteResult bestRes;\n    bestRes.cost = (1LL << 60);\n    vector<int> bestSel;\n\n    // Try several route policies for each candidate subset.\n    vector<pair<int, bool>> policies = {\n        {0, false},\n        {0, true},\n        {2, false},\n        {2, true}\n    };\n\n    for (const auto& sel : candidates) {\n        for (auto [alpha, look] : policies) {\n            RouteResult res = buildRoute(sel, alpha, look);\n            if (res.cost < bestRes.cost) {\n                bestRes = std::move(res);\n                bestSel = sel;\n            }\n        }\n    }\n\n    // Output.\n    cout << 50;\n    for (int id : bestSel) cout << ' ' << (id + 1);\n    cout << '\\n';\n\n    cout << bestRes.pts.size();\n    for (const auto& p : bestRes.pts) {\n        cout << ' ' << p.x << ' ' << p.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        iota(p.begin(), p.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        long long dx = (long long)x[edges[i].u] - x[edges[i].v];\n        long long dy = (long long)y[edges[i].u] - y[edges[i].v];\n        long long s = dx * dx + dy * dy;\n        long double r = sqrt((long double)s);\n        edges[i].d = (int)floor(r + 0.5L); // round to nearest integer\n    }\n\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (edges[a].d != edges[b].d) return edges[a].d < edges[b].d;\n        return a < b;\n    });\n\n    DSU dsu(N);\n    vector<char> take(M, 0);\n    for (int id : ord) {\n        if (dsu.unite(edges[id].u, edges[id].v)) {\n            take[id] = 1;\n        }\n    }\n\n    // Online phase: read each l_i and immediately answer.\n    for (int i = 0; i < M; ++i) {\n        int li;\n        cin >> li; // We don't use it; the tree is fixed beforehand.\n        cout << (take[i] ? 1 : 0) << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstatic const int HN = 30;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<Point> pets(N);\n    vector<int> ptype(N);\n    vector<vector<int>> petOcc(HN + 1, vector<int>(HN + 1, 0));\n\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> ptype[i];\n        petOcc[pets[i].x][pets[i].y]++;\n    }\n\n    int M;\n    cin >> M;\n    vector<Point> humans(M);\n    for (int i = 0; i < M; ++i) cin >> humans[i].x >> humans[i].y;\n\n    // Prefix sum of initial pet positions\n    vector<vector<int>> ps(HN + 1 + 1, vector<int>(HN + 1 + 1, 0)); // 32 x 32 enough\n    for (int i = 1; i <= HN; ++i) {\n        for (int j = 1; j <= HN; ++j) {\n            ps[i][j] = petOcc[i][j] + ps[i - 1][j] + ps[i][j - 1] - ps[i - 1][j - 1];\n        }\n    }\n\n    auto rectSum = [&](int r1, int c1, int r2, int c2) -> int {\n        if (r1 > r2 || c1 > c2) return 0;\n        return ps[r2][c2] - ps[r1 - 1][c2] - ps[r2][c1 - 1] + ps[r1 - 1][c1 - 1];\n    };\n\n    auto clampv = [](int v, int l, int r) {\n        return max(l, min(r, v));\n    };\n\n    auto distRect = [&](Point p, int r1, int r2, int c1, int c2) -> int {\n        int dx = 0, dy = 0;\n        if (p.x < r1) dx = r1 - p.x;\n        else if (p.x > r2) dx = p.x - r2;\n        if (p.y < c1) dy = c1 - p.y;\n        else if (p.y > c2) dy = p.y - c2;\n        return dx + dy;\n    };\n\n    struct BestRect {\n        int r1 = -1, r2 = -1, c1 = -1, c2 = -1;\n        long long score = LLONG_MIN;\n        int area = 0;\n    } best;\n\n    // Search an empty rectangle Q.\n    // Final safe area is the inner rectangle Q shrunk by 2 cells on each side.\n    for (int r1 = 1; r1 <= HN; ++r1) {\n        for (int r2 = r1 + 4; r2 <= HN; ++r2) { // height >= 5\n            for (int c1 = 1; c1 <= HN; ++c1) {\n                for (int c2 = c1 + 4; c2 <= HN; ++c2) { // width >= 5\n                    if (rectSum(r1, c1, r2, c2) != 0) continue;\n\n                    int h = r2 - r1 + 1;\n                    int w = c2 - c1 + 1;\n                    int innerH = h - 4;\n                    int innerW = w - 4;\n                    if (innerH <= 0 || innerW <= 0) continue;\n\n                    long long area = 1LL * innerH * innerW;\n                    long long perim = 2LL * (h + w);\n\n                    long long pen = 0;\n                    for (auto &p : pets) {\n                        int d = distRect(p, r1, r2, c1, c2);\n                        pen += 1000LL / (d + 1);\n                    }\n\n                    long long score = area * 100000LL - perim * 1000LL - pen;\n\n                    if (score > best.score) {\n                        best.score = score;\n                        best.r1 = r1; best.r2 = r2;\n                        best.c1 = c1; best.c2 = c2;\n                        best.area = (int)area;\n                    }\n                }\n            }\n        }\n    }\n\n    // If no usable rectangle is found, fall back to doing nothing.\n    if (best.r1 == -1 || best.area <= 0) {\n        for (int turn = 0; turn < 300; ++turn) {\n            cout << string(M, '.') << '\\n' << flush;\n            for (int i = 0; i < N; ++i) {\n                string s;\n                cin >> s;\n            }\n        }\n        return 0;\n    }\n\n    int r1 = best.r1, r2 = best.r2, c1 = best.c1, c2 = best.c2;\n    int x1 = r1 + 2, x2 = r2 - 2;\n    int y1 = c1 + 2, y2 = c2 - 2;\n    int H = x2 - x1 + 1; // inner height\n    int W = y2 - y1 + 1; // inner width\n\n    // Roles:\n    // 0: TOP    - start at (x1, y1), wall up, move right\n    // 1: LEFT   - start at (x1, y1), wall left, move down\n    // 2: BOTTOM - start at (x2, y1), wall down, move right\n    // 3: RIGHT  - start at (x1, y2), wall right, move down\n    enum Role { IDLE = 0, TOP = 1, LEFT = 2, BOTTOM = 3, RIGHT = 4 };\n\n    vector<int> role(M, IDLE);\n    vector<Point> target(M);\n\n    Point topStart{ x1, y1 };\n    Point leftStart{ x1, y1 };\n    Point bottomStart{ x2, y1 };\n    Point rightStart{ x1, y2 };\n\n    Point centerTarget{ clampv((x1 + x2) / 2, x1, x2), clampv((y1 + y2) / 2, y1, y2) };\n\n    // Choose 4 distinct humans for the 4 builder roles.\n    long long bestEval = LLONG_MAX;\n    array<int, 4> bestPick{-1, -1, -1, -1};\n\n    auto dman = [&](int i, Point t) -> int {\n        return abs(humans[i].x - t.x) + abs(humans[i].y - t.y);\n    };\n\n    vector<Point> roleTargets = { topStart, leftStart, bottomStart, rightStart };\n\n    for (int a = 0; a < M; ++a) for (int b = 0; b < M; ++b) if (b != a)\n    for (int c = 0; c < M; ++c) if (c != a && c != b)\n    for (int d = 0; d < M; ++d) if (d != a && d != b && d != c) {\n        array<int, 4> pick{a, b, c, d};\n\n        long long mx = 0, sum = 0;\n        bool used[20] = {};\n        for (int id : pick) used[id] = true;\n\n        mx = max<long long>(mx, dman(a, roleTargets[0]));\n        mx = max<long long>(mx, dman(b, roleTargets[1]));\n        mx = max<long long>(mx, dman(c, roleTargets[2]));\n        mx = max<long long>(mx, dman(d, roleTargets[3]));\n        sum += dman(a, roleTargets[0]);\n        sum += dman(b, roleTargets[1]);\n        sum += dman(c, roleTargets[2]);\n        sum += dman(d, roleTargets[3]);\n\n        for (int i = 0; i < M; ++i) if (!used[i]) {\n            Point t{ clampv(humans[i].x, x1, x2), clampv(humans[i].y, y1, y2) };\n            int dd = dman(i, t);\n            mx = max<long long>(mx, dd);\n            sum += dd;\n        }\n\n        long long eval = mx * 100000LL + sum;\n        if (eval < bestEval) {\n            bestEval = eval;\n            bestPick = pick;\n        }\n    }\n\n    // Assign roles\n    vector<Point> idleTarget(M);\n    for (int i = 0; i < M; ++i) idleTarget[i] = { clampv(humans[i].x, x1, x2), clampv(humans[i].y, y1, y2) };\n\n    role[bestPick[0]] = TOP;\n    role[bestPick[1]] = LEFT;\n    role[bestPick[2]] = BOTTOM;\n    role[bestPick[3]] = RIGHT;\n\n    target[bestPick[0]] = topStart;\n    target[bestPick[1]] = leftStart;\n    target[bestPick[2]] = bottomStart;\n    target[bestPick[3]] = rightStart;\n\n    for (int i = 0; i < M; ++i) {\n        if (role[i] == IDLE) target[i] = idleTarget[i];\n    }\n\n    // Movement phase duration\n    int moveTurns = 0;\n    for (int i = 0; i < M; ++i) {\n        moveTurns = max(moveTurns, abs(humans[i].x - target[i].x) + abs(humans[i].y - target[i].y));\n    }\n\n    // Builder state\n    struct BuilderState {\n        int idx = 0;\n        bool needWall = true;\n        bool done = false;\n    };\n    vector<BuilderState> bs(M);\n\n    auto inBoard = [](int x, int y) {\n        return 1 <= x && x <= HN && 1 <= y && y <= HN;\n    };\n\n    vector<vector<int>> humanOcc(HN + 1, vector<int>(HN + 1, 0));\n    for (auto &h : humans) humanOcc[h.x][h.y]++;\n\n    auto rebuildHumanOcc = [&]() {\n        for (int i = 1; i <= HN; ++i) fill(humanOcc[i].begin(), humanOcc[i].end(), 0);\n        for (auto &h : humans) humanOcc[h.x][h.y]++;\n    };\n\n    auto safeToWall = [&](int x, int y) -> bool {\n        if (!inBoard(x, y)) return false;\n        if (petOcc[x][y] > 0) return false;\n        if (humanOcc[x][y] > 0) return false;\n        static int dx[4] = {-1, 1, 0, 0};\n        static int dy[4] = {0, 0, -1, 1};\n        for (int dir = 0; dir < 4; ++dir) {\n            int nx = x + dx[dir], ny = y + dy[dir];\n            if (inBoard(nx, ny) && petOcc[nx][ny] > 0) return false;\n        }\n        return true;\n    };\n\n    auto petInsideTarget = [&]() -> bool {\n        for (auto &p : pets) {\n            if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) return true;\n        }\n        return false;\n    };\n\n    auto wallChar = [&](int r) -> char {\n        if (r == TOP) return 'u';\n        if (r == BOTTOM) return 'd';\n        if (r == LEFT) return 'l';\n        return 'r';\n    };\n\n    auto moveChar = [&](int r) -> char {\n        if (r == TOP || r == BOTTOM) return 'R';\n        return 'D';\n    };\n\n    auto wallTarget = [&](int r, const Point &p) -> Point {\n        if (r == TOP) return { p.x - 1, p.y };\n        if (r == BOTTOM) return { p.x + 1, p.y };\n        if (r == LEFT) return { p.x, p.y - 1 };\n        return { p.x, p.y + 1 };\n    };\n\n    auto sideLen = [&](int r) -> int {\n        if (r == TOP || r == BOTTOM) return W;\n        if (r == LEFT || r == RIGHT) return H;\n        return 0;\n    };\n\n    // To reduce risk of pets wandering into the target area while we wait,\n    // we allow a short waiting period after humans reach their targets.\n    const int WAIT_LIMIT = 20;\n\n    for (int turn = 0; turn < 300; ++turn) {\n        string out(M, '.');\n        vector<Point> nextPos = humans;\n\n        if (turn < moveTurns) {\n            // Move each human toward its assigned target.\n            for (int i = 0; i < M; ++i) {\n                if (humans[i].x < target[i].x) {\n                    out[i] = 'D';\n                    nextPos[i].x++;\n                } else if (humans[i].x > target[i].x) {\n                    out[i] = 'U';\n                    nextPos[i].x--;\n                } else if (humans[i].y < target[i].y) {\n                    out[i] = 'R';\n                    nextPos[i].y++;\n                } else if (humans[i].y > target[i].y) {\n                    out[i] = 'L';\n                    nextPos[i].y--;\n                } else {\n                    out[i] = '.';\n                }\n            }\n        } else {\n            bool forced = (turn >= moveTurns + WAIT_LIMIT);\n            bool canBuild = forced || !petInsideTarget();\n\n            if (canBuild) {\n                for (int i = 0; i < M; ++i) {\n                    if (role[i] == IDLE) continue;\n                    if (bs[i].done) continue;\n\n                    int len = sideLen(role[i]);\n                    if (len <= 0) {\n                        bs[i].done = true;\n                        continue;\n                    }\n\n                    if (bs[i].needWall) {\n                        Point wt = wallTarget(role[i], humans[i]);\n                        if (safeToWall(wt.x, wt.y)) {\n                            out[i] = wallChar(role[i]);\n                            // Wall built (or already impassable) if target is safe.\n                            // Mark it in our local map.\n                            // (If the cell was already impassable, this is harmless.)\n                            // We only need the wall map implicitly for safety checks.\n                            // No separate wall grid is necessary for the logic.\n                            // The target is inside the board by construction.\n                            // If the current cell is the last one, finish after walling.\n                            if (bs[i].idx == len - 1) {\n                                bs[i].done = true;\n                            } else {\n                                bs[i].needWall = false;\n                            }\n                        } else {\n                            out[i] = '.';\n                        }\n                    } else {\n                        if (bs[i].idx + 1 < len) {\n                            out[i] = moveChar(role[i]);\n                            if (role[i] == TOP || role[i] == BOTTOM) nextPos[i].y++;\n                            else nextPos[i].x++;\n                            bs[i].idx++;\n                            bs[i].needWall = true;\n                        } else {\n                            bs[i].done = true;\n                            out[i] = '.';\n                        }\n                    }\n                }\n            } else {\n                // Wait a bit for pets to leave the target area.\n                // All humans do nothing.\n            }\n        }\n\n        cout << out << '\\n' << flush;\n\n        // Apply human moves\n        humans = nextPos;\n        rebuildHumanOcc();\n\n        // Read pet movement strings and update pet positions.\n        vector<string> mv(N);\n        for (int i = 0; i < N; ++i) cin >> mv[i];\n\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].x, y = pets[i].y;\n            for (char ch : mv[i]) {\n                if (ch == 'U') --x;\n                else if (ch == 'D') ++x;\n                else if (ch == 'L') --y;\n                else if (ch == 'R') ++y;\n            }\n            pets[i] = {x, y};\n        }\n\n        // Rebuild pet occupancy\n        for (int i = 1; i <= HN; ++i) fill(petOcc[i].begin(), petOcc[i].end(), 0);\n        for (auto &p : pets) petOcc[p.x][p.y]++;\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj, ti, tj;\n    double p;\n    cin >> si >> sj >> ti >> tj >> p;\n\n    vector<string> h(20), v(19);\n    for (int i = 0; i < 20; ++i) cin >> h[i];\n    for (int i = 0; i < 19; ++i) cin >> v[i];\n\n    vector<vector<int>> dist(20, vector<int>(20, -1));\n    vector<vector<pair<int,int>>> parent(20, vector<pair<int,int>>(20, {-1, -1}));\n    vector<vector<char>> pdir(20, vector<char>(20, '?'));\n\n    queue<pair<int,int>> q;\n    dist[si][sj] = 0;\n    q.push({si, sj});\n\n    auto push = [&](int ni, int nj, int pi, int pj, char c) {\n        if (dist[ni][nj] != -1) return;\n        dist[ni][nj] = dist[pi][pj] + 1;\n        parent[ni][nj] = {pi, pj};\n        pdir[ni][nj] = c;\n        q.push({ni, nj});\n    };\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        if (i == ti && j == tj) break;\n\n        // Up\n        if (i > 0 && v[i - 1][j] == '0') push(i - 1, j, i, j, 'U');\n        // Down\n        if (i < 19 && v[i][j] == '0') push(i + 1, j, i, j, 'D');\n        // Left\n        if (j > 0 && h[i][j - 1] == '0') push(i, j - 1, i, j, 'L');\n        // Right\n        if (j < 19 && h[i][j] == '0') push(i, j + 1, i, j, 'R');\n    }\n\n    string path;\n    {\n        int i = ti, j = tj;\n        while (!(i == si && j == sj)) {\n            path.push_back(pdir[i][j]);\n            auto [pi, pj] = parent[i][j];\n            i = pi;\n            j = pj;\n        }\n        reverse(path.begin(), path.end());\n    }\n\n    // Pad to length 200 with arbitrary characters.\n    if ((int)path.size() < 200) {\n        path += string(200 - path.size(), 'R');\n    } else if ((int)path.size() > 200) {\n        path.resize(200);\n    }\n\n    cout << path << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int S = N * N;\nstatic constexpr int ST = S * 4;\n\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\n// base to-table from the statement\nint baseTo[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1},\n};\n\nint nxtDir[8][4][4]; // nxtDir[t][rot][entry_dir] -> exit_dir, or -1\n\nusing RotArr = array<uint8_t, S>;\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 Key {\n    uint64_t a, b;\n    bool operator==(const Key& other) const { return a == other.a && b == other.b; }\n};\nstruct KeyHash {\n    size_t operator()(const Key& k) const {\n        uint64_t x = k.a ^ (k.b + 0x9e3779b97f4a7c15ULL + (k.a << 6) + (k.a >> 2));\n        return (size_t)splitmix64(x);\n    }\n};\n\nint booth_min_rotation(const vector<int>& s) {\n    int n = (int)s.size();\n    if (n == 0) return 0;\n    vector<int> ss(2 * n);\n    for (int i = 0; i < 2 * n; ++i) ss[i] = s[i % n];\n\n    int i = 0, j = 1, k = 0;\n    while (i < n && j < n && k < n) {\n        int a = ss[i + k], b = ss[j + k];\n        if (a == b) {\n            ++k;\n            continue;\n        }\n        if (a > b) {\n            i += k + 1;\n            if (i <= j) i = j + 1;\n        } else {\n            j += k + 1;\n            if (j <= i) j = i + 1;\n        }\n        k = 0;\n    }\n    return min(i, j);\n}\n\nvector<int> canonical_cycle(const vector<int>& cyc) {\n    int n = (int)cyc.size();\n    vector<int> a = cyc;\n    int s1 = booth_min_rotation(a);\n    vector<int> c1(n);\n    for (int i = 0; i < n; ++i) c1[i] = a[(s1 + i) % n];\n\n    vector<int> b(n);\n    for (int i = 0; i < n; ++i) b[i] = cyc[n - 1 - i];\n    int s2 = booth_min_rotation(b);\n    vector<int> c2(n);\n    for (int i = 0; i < n; ++i) c2[i] = b[(s2 + i) % n];\n\n    if (lexicographical_compare(c2.begin(), c2.end(), c1.begin(), c1.end()))\n        return c2;\n    return c1;\n}\n\nKey hash_cycle(const vector<int>& cyc) {\n    vector<int> can = canonical_cycle(cyc);\n    uint64_t h1 = 1469598103934665603ULL;\n    uint64_t h2 = 0xcbf29ce484222325ULL;\n    for (int x : can) {\n        uint64_t y = splitmix64((uint64_t)x + 1);\n        h1 ^= y;\n        h1 *= 1099511628211ULL;\n        h2 += y + 0x9e3779b97f4a7c15ULL + (h2 << 6) + (h2 >> 2);\n    }\n    return Key{h1, h2};\n}\n\nstruct EvalResult {\n    long long score = 0;\n    vector<int> hotCells; // cell indices appearing in the two best unique cycles\n};\n\nEvalResult evaluate(const RotArr& rot, const array<int, S>& tile) {\n    static int succ[ST];\n    static uint8_t vis[ST];\n    static int pos[ST];\n    memset(vis, 0, sizeof(vis));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = (i * N + j) * 4;\n            int t = tile[i * N + j];\n            int r = rot[i * N + j];\n            for (int d = 0; d < 4; ++d) {\n                int d2 = nxtDir[t][r][d];\n                if (d2 < 0) {\n                    succ[idx + d] = -1;\n                    continue;\n                }\n                int ni = i + di[d2];\n                int nj = j + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    succ[idx + d] = -1;\n                    continue;\n                }\n                int nd = (d2 + 2) & 3;\n                succ[idx + d] = (ni * N + nj) * 4 + nd;\n            }\n        }\n    }\n\n    vector<vector<int>> uniq_cycles;\n    vector<int> uniq_len;\n    unordered_set<Key, KeyHash> seen;\n    seen.reserve(1024);\n\n    vector<int> st;\n    st.reserve(ST);\n\n    for (int s = 0; s < ST; ++s) {\n        if (vis[s]) continue;\n        int cur = s;\n        st.clear();\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;\n            pos[cur] = (int)st.size();\n            st.push_back(cur);\n            cur = succ[cur];\n        }\n        if (cur != -1 && vis[cur] == 1) {\n            vector<int> cyc(st.begin() + pos[cur], st.end());\n            Key k = hash_cycle(cyc);\n            if (seen.insert(k).second) {\n                uniq_len.push_back((int)cyc.size());\n                uniq_cycles.push_back(move(cyc));\n            }\n        }\n        for (int v : st) vis[v] = 2;\n    }\n\n    vector<int> ord(uniq_cycles.size());\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (uniq_len[a] != uniq_len[b]) return uniq_len[a] > uniq_len[b];\n        return a < b;\n    });\n\n    EvalResult res;\n    if ((int)ord.size() >= 2) {\n        res.score = 1LL * uniq_len[ord[0]] * uniq_len[ord[1]];\n    } else {\n        res.score = 0;\n    }\n\n    vector<char> mark(S, 0);\n    for (int t = 0; t < (int)ord.size() && t < 2; ++t) {\n        for (int stid : uniq_cycles[ord[t]]) {\n            mark[stid / 4] = 1;\n        }\n    }\n    for (int i = 0; i < S; ++i) if (mark[i]) res.hotCells.push_back(i);\n\n    return res;\n}\n\nint formula_value(int cid, int i, int j, uint64_t seed) {\n    switch (cid) {\n        case 0:  return 0;\n        case 1:  return i + j;\n        case 2:  return i - j + 30;\n        case 3:  return 2 * i + j;\n        case 4:  return i + 2 * j;\n        case 5:  return (i / 2) + (j / 2);\n        case 6:  return (i / 2) - (j / 2) + 30;\n        case 7:  return min(min(i, 29 - i), min(j, 29 - j));\n        case 8:  return (i & 1) * 2 + (j & 1);\n        case 9:  return (i % 3) * 3 + (j % 3);\n        case 10: return (int)(splitmix64(seed + (uint64_t)i * 10007ULL + (uint64_t)j * 10009ULL) & 1023ULL);\n        case 11: return (int)(splitmix64(seed + (uint64_t)i * 20011ULL + (uint64_t)j * 20021ULL) & 1023ULL);\n        case 12: return i ^ j;\n        case 13: return 3 * i + 5 * j;\n        case 14: return (i / 3) * 7 + (j / 3);\n        default: return i + j;\n    }\n}\n\nRotArr make_candidate(const array<int, S>& tile, int cid) {\n    RotArr rot{};\n    uint64_t seed = 0x123456789abcdef0ULL ^ (uint64_t)cid * 0x9e3779b97f4a7c15ULL;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int t = tile[i * N + j];\n            int f = formula_value(cid, i, j, seed);\n            int r;\n            if (t >= 6) {\n                r = (f + t + cid) & 1; // straight tiles: 0/1 enough\n            } else {\n                r = (f + t + cid) & 3;\n            }\n            rot[i * N + j] = (uint8_t)r;\n        }\n    }\n    return rot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    array<int, S> tile{};\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) tile[i * N + j] = s[j] - '0';\n    }\n\n    // Precompute rotated transition tables.\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            for (int d = 0; d < 4; ++d) {\n                int bd = (d + r) & 3; // world dir -> base dir\n                int be = baseTo[t][bd];\n                if (be < 0) nxtDir[t][r][d] = -1;\n                else nxtDir[t][r][d] = (be - r + 4) & 3;\n            }\n        }\n    }\n\n    vector<int> candidate_ids = {0, 1, 2, 3, 4, 5, 7, 8, 9, 12, 13, 14, 10, 11};\n\n    RotArr best_rot{};\n    EvalResult best_eval;\n    best_eval.score = -1;\n\n    for (int cid : candidate_ids) {\n        RotArr cur = make_candidate(tile, cid);\n        EvalResult ev = evaluate(cur, tile);\n        if (ev.score > best_eval.score) {\n            best_eval = ev;\n            best_rot = cur;\n        }\n    }\n\n    // Hill-climbing around the best candidate.\n    RotArr cur = best_rot;\n    EvalResult cur_eval = best_eval;\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85;\n\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int noImprove = 0;\n    while (elapsed() < TIME_LIMIT) {\n        int cell;\n        if (!cur_eval.hotCells.empty() && (rng() % 100) < 70) {\n            cell = cur_eval.hotCells[rng() % cur_eval.hotCells.size()];\n        } else {\n            cell = rng() % S;\n        }\n\n        int oldr = cur[cell];\n        int nr = (int)(rng() & 3);\n        if (nr == oldr) nr = (nr + 1) & 3;\n\n        cur[cell] = (uint8_t)nr;\n        EvalResult ev = evaluate(cur, tile);\n\n        bool accept = false;\n        if (ev.score > cur_eval.score) accept = true;\n        else if (ev.score == cur_eval.score && (rng() % 5 == 0)) accept = true;\n\n        if (accept) {\n            cur_eval = move(ev);\n            noImprove = 0;\n            if (cur_eval.score > best_eval.score) {\n                best_eval = cur_eval;\n                best_rot = cur;\n            }\n        } else {\n            cur[cell] = (uint8_t)oldr;\n            ++noImprove;\n        }\n\n        if (noImprove >= 200) {\n            // Small random shake to escape plateaus.\n            for (int k = 0; k < 3; ++k) {\n                int c = rng() % S;\n                cur[c] = (uint8_t)(rng() & 3);\n            }\n            cur_eval = evaluate(cur, tile);\n            if (cur_eval.score > best_eval.score) {\n                best_eval = cur_eval;\n                best_rot = cur;\n            }\n            noImprove = 0;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << int(best_rot[i * N + j]);\n        }\n    }\n    cout << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100;\n\nstruct EvalRes {\n    int exact;  // size of largest tree component\n    int proxy;  // heuristic potential\n};\n\nstruct Node {\n    array<uint8_t, MAXC> bd{};\n    int parent = -1;\n    int blank = -1;\n    int moveDir = -1;   // 0:U, 1:D, 2:L, 3:R; -1 for root\n    char moveChar = '?';\n    int depth = 0;\n    int exact = 0;\n    int proxy = 0;\n};\n\nint N, T;\nint cells;\nint fullV;\n\nint neighCnt[MAXC];\nint neighIdx[MAXC][4];\nint neighDir[MAXC][4];\n\nint oppDir[4] = {1, 0, 3, 2};\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\ninline int parseHex(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + (c - 'a');\n}\n\ninline EvalRes evaluate(const array<uint8_t, MAXC>& bd) {\n    int id[MAXC];\n    int V = 0;\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] != 0) id[i] = V++;\n        else id[i] = -1;\n    }\n\n    int deg[MAXC];\n    int adj[MAXC][4];\n    memset(deg, 0, sizeof(deg));\n\n    int E = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int m = bd[idx];\n            if (!m) continue;\n\n            if (j + 1 < N) {\n                int idx2 = idx + 1;\n                int m2 = bd[idx2];\n                if (m2 && (m & 4) && (m2 & 1)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n            if (i + 1 < N) {\n                int idx2 = idx + N;\n                int m2 = bd[idx2];\n                if (m2 && (m & 8) && (m2 & 2)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n        }\n    }\n\n    bool vis[MAXC];\n    memset(vis, 0, sizeof(vis));\n    int q[MAXC];\n\n    int bestTree = 1;\n    int largestComp = 0;\n    int comps = 0;\n\n    for (int s = 0; s < V; ++s) {\n        if (vis[s]) continue;\n        ++comps;\n\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n\n        int cnt = 0;\n        int sumdeg = 0;\n\n        while (head < tail) {\n            int x = q[head++];\n            ++cnt;\n            sumdeg += deg[x];\n            for (int k = 0; k < deg[x]; ++k) {\n                int y = adj[x][k];\n                if (!vis[y]) {\n                    vis[y] = true;\n                    q[tail++] = y;\n                }\n            }\n        }\n\n        int edges = sumdeg / 2;\n        largestComp = max(largestComp, cnt);\n        if (edges == cnt - 1) bestTree = max(bestTree, cnt);\n    }\n\n    int cycleRank = E - V + comps;\n    if (cycleRank < 0) cycleRank = 0;\n\n    // Heuristic proxy:\n    // - larger connected component is good\n    // - more edges is good\n    // - cycles are bad\n    int proxy = largestComp * 20 + E - cycleRank * 40;\n\n    return {bestTree, proxy};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    cells = N * N;\n    fullV = cells - 1;\n\n    vector<string> s(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n\n    array<uint8_t, MAXC> init{};\n    int blankPos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int v = parseHex(s[i][j]);\n            init[i * N + j] = (uint8_t)v;\n            if (v == 0) blankPos = i * N + j;\n        }\n    }\n\n    // Precompute legal blank moves for each cell.\n    for (int idx = 0; idx < cells; ++idx) neighCnt[idx] = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            if (i > 0) {\n                neighIdx[idx][neighCnt[idx]] = idx - N;\n                neighDir[idx][neighCnt[idx]++] = 0; // U\n            }\n            if (i + 1 < N) {\n                neighIdx[idx][neighCnt[idx]] = idx + N;\n                neighDir[idx][neighCnt[idx]++] = 1; // D\n            }\n            if (j > 0) {\n                neighIdx[idx][neighCnt[idx]] = idx - 1;\n                neighDir[idx][neighCnt[idx]++] = 2; // L\n            }\n            if (j + 1 < N) {\n                neighIdx[idx][neighCnt[idx]] = idx + 1;\n                neighDir[idx][neighCnt[idx]++] = 3; // R\n            }\n        }\n    }\n\n    // Root node.\n    vector<Node> nodes;\n    nodes.reserve((size_t)T * 80 + 100);\n\n    Node root;\n    root.bd = init;\n    root.blank = blankPos;\n    root.parent = -1;\n    root.moveDir = -1;\n    root.moveChar = '?';\n    root.depth = 0;\n    auto ev0 = evaluate(root.bd);\n    root.exact = ev0.exact;\n    root.proxy = ev0.proxy;\n\n    nodes.push_back(root);\n\n    // If already full tree, do nothing.\n    if (root.exact == fullV) {\n        cout << '\\n';\n        return 0;\n    }\n\n    const int BEAM = 80;\n    const int KEEP_EXACT = 30;\n\n    vector<int> beam = {0};\n    int bestId = 0;\n    int bestExact = root.exact;\n    int bestProxy = root.proxy;\n\n    auto startTime = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    };\n\n    bool foundFull = false;\n    int fullId = -1;\n\n    for (int depth = 0; depth < T && !beam.empty(); ++depth) {\n        if (depth % 20 == 0 && elapsed() > 2.80) break;\n\n        vector<int> cand;\n        cand.reserve(beam.size() * 4);\n\n        bool layerFull = false;\n        int layerFullId = -1;\n        int layerFullProxy = INT_MIN;\n\n        for (int bid : beam) {\n            Node cur = nodes[bid];\n\n            for (int k = 0; k < neighCnt[cur.blank]; ++k) {\n                int nb = neighIdx[cur.blank][k];\n                int dir = neighDir[cur.blank][k];\n\n                if (cur.moveDir != -1 && dir == oppDir[cur.moveDir]) continue;\n\n                Node ch = cur;\n                swap(ch.bd[cur.blank], ch.bd[nb]);\n                ch.blank = nb;\n                ch.parent = bid;\n                ch.moveDir = dir;\n                ch.moveChar = dirChar[dir];\n                ch.depth = cur.depth + 1;\n\n                auto ev = evaluate(ch.bd);\n                ch.exact = ev.exact;\n                ch.proxy = ev.proxy;\n\n                int id = (int)nodes.size();\n                nodes.push_back(ch);\n                cand.push_back(id);\n\n                if (ch.exact > bestExact || (ch.exact == bestExact && ch.proxy > bestProxy)) {\n                    bestExact = ch.exact;\n                    bestProxy = ch.proxy;\n                    bestId = id;\n                }\n\n                if (ch.exact == fullV) {\n                    layerFull = true;\n                    if (ch.proxy > layerFullProxy) {\n                        layerFullProxy = ch.proxy;\n                        layerFullId = id;\n                    }\n                }\n            }\n        }\n\n        if (layerFull) {\n            foundFull = true;\n            fullId = layerFullId;\n            break;\n        }\n\n        if (cand.empty()) break;\n\n        if ((int)cand.size() > BEAM) {\n            vector<int> next;\n            next.reserve(BEAM);\n\n            // 1) keep states with the best exact score\n            sort(cand.begin(), cand.end(), [&](int a, int b) {\n                if (nodes[a].exact != nodes[b].exact) return nodes[a].exact > nodes[b].exact;\n                return nodes[a].proxy > nodes[b].proxy;\n            });\n            for (int i = 0; i < (int)cand.size() && (int)next.size() < KEEP_EXACT; ++i) {\n                next.push_back(cand[i]);\n            }\n\n            // 2) also keep states with the best proxy score\n            sort(cand.begin(), cand.end(), [&](int a, int b) {\n                if (nodes[a].proxy != nodes[b].proxy) return nodes[a].proxy > nodes[b].proxy;\n                return nodes[a].exact > nodes[b].exact;\n            });\n            for (int id : cand) {\n                if ((int)next.size() >= BEAM) break;\n                bool used = false;\n                for (int x : next) {\n                    if (x == id) {\n                        used = true;\n                        break;\n                    }\n                }\n                if (!used) next.push_back(id);\n            }\n\n            beam.swap(next);\n        } else {\n            beam.swap(cand);\n        }\n    }\n\n    int chosen = foundFull ? fullId : bestId;\n\n    string ans;\n    for (int cur = chosen; nodes[cur].parent != -1; cur = nodes[cur].parent) {\n        ans.push_back(nodes[cur].moveChar);\n    }\n    reverse(ans.begin(), ans.end());\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int L = -9999;\nstatic constexpr int R = 9999;\nstatic constexpr int SZ = R - L + 1;   // 19999\nstatic constexpr int MAXS = 101;       // strips = cuts + 1, cuts <= 100\nstatic constexpr int INF_INT = 1e9;\n\nstruct AxisData {\n    vector<vector<int>> bounds; // bounds[s] = cut coordinates for s strips\n    vector<vector<int>> bin;    // bin[s][i] = strip index of point i\n};\n\nAxisData buildAxis(const vector<int>& vals, int N) {\n    vector<int> cnt(SZ, 0);\n    for (int v : vals) cnt[v - L]++;\n\n    vector<int> pref(SZ + 1, 0);\n    for (int i = 0; i < SZ; i++) pref[i + 1] = pref[i] + cnt[i];\n\n    vector<int> allowed;\n    vector<int> leftCnt;\n    allowed.reserve(SZ);\n    leftCnt.reserve(SZ);\n\n    for (int c = L; c <= R; c++) {\n        int idx = c - L;\n        if (cnt[idx] == 0) {\n            allowed.push_back(c);\n            leftCnt.push_back(pref[idx]); // number of points with coord < c\n        }\n    }\n\n    vector<vector<int>> bounds(MAXS + 1);\n    bounds[1] = {};\n\n    for (int s = 2; s <= MAXS; s++) {\n        vector<int> b;\n        b.reserve(s - 1);\n\n        int start = 0; // earliest allowed coordinate index for this boundary\n        for (int j = 1; j <= s - 1; j++) {\n            int target = (int)((1LL * j * N + s / 2) / s); // rounded quantile\n\n            auto it = lower_bound(leftCnt.begin() + start, leftCnt.end(), target);\n            int idx = (int)(it - leftCnt.begin());\n            if (idx >= (int)allowed.size()) idx = (int)allowed.size() - 1;\n\n            int chosen = idx;\n            if (idx > start) {\n                int prev = idx - 1;\n                long long dcur = llabs((long long)leftCnt[idx] - target);\n                long long dprev = llabs((long long)leftCnt[prev] - target);\n                if (dprev <= dcur) chosen = prev;\n            }\n\n            if (chosen < start) chosen = start; // safety\n            b.push_back(allowed[chosen]);\n            start = chosen + 1;\n            if (start >= (int)allowed.size()) start = (int)allowed.size() - 1;\n        }\n        bounds[s] = std::move(b);\n    }\n\n    vector<vector<int>> bin(MAXS + 1, vector<int>(N, 0));\n    for (int s = 1; s <= MAXS; s++) {\n        const auto& b = bounds[s];\n        for (int i = 0; i < N; i++) {\n            // boundaries are unused coordinates, so lower_bound is safe\n            bin[s][i] = (int)(lower_bound(b.begin(), b.end(), vals[i]) - b.begin());\n        }\n    }\n\n    return {std::move(bounds), std::move(bin)};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n\n    array<int, 11> a{};\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n    AxisData ax = buildAxis(xs, N);\n    AxisData ay = buildAxis(ys, N);\n\n    long long bestScore = -1;\n    int bestR = 1, bestC = 1;\n    int bestCuts = INF_INT;\n\n    static int cell[2601]; // max under r + c <= 102 is 51 * 51 = 2601\n\n    for (int r = 1; r <= MAXS; r++) {\n        for (int c = 1; c <= MAXS; c++) {\n            int cuts = (r - 1) + (c - 1);\n            if (cuts > K) continue;\n\n            int m = r * c;\n            fill(cell, cell + m, 0);\n\n            for (int i = 0; i < N; i++) {\n                int bx = ax.bin[r][i];\n                int by = ay.bin[c][i];\n                cell[bx * c + by]++;\n            }\n\n            int hist[11] = {};\n            for (int i = 0; i < m; i++) {\n                int v = cell[i];\n                if (1 <= v && v <= 10) hist[v]++;\n            }\n\n            long long score = 0;\n            for (int d = 1; d <= 10; d++) {\n                score += min(a[d], hist[d]);\n            }\n\n            if (score > bestScore || (score == bestScore && cuts < bestCuts)) {\n                bestScore = score;\n                bestCuts = cuts;\n                bestR = r;\n                bestC = c;\n            }\n        }\n    }\n\n    cout << bestCuts << '\\n';\n\n    for (int x : ax.bounds[bestR]) {\n        cout << x << ' ' << -1000000000 << ' ' << x << ' ' << 1000000000 << '\\n';\n    }\n    for (int y : ay.bounds[bestC]) {\n        cout << -1000000000 << ' ' << y << ' ' << 1000000000 << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    array<int, 4> v; // cyclic order around the perimeter\n};\n\nstruct Op {\n    array<int, 8> a;\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    auto id = [&](int x, int y) { return x * N + y; };\n    int V = N * N;\n    long long c = (N - 1) / 2;\n\n    vector<long long> wt(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long dx = x - c, dy = y - c;\n            wt[id(x, y)] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    vector<char> initOcc(V, 0);\n    vector<int> initIds;\n    long long initSum = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        int v = id(x, y);\n        if (!initOcc[v]) {\n            initOcc[v] = 1;\n            initIds.push_back(v);\n            initSum += wt[v];\n        }\n    }\n\n    // Precompute families\n    vector<Rect> axis[2];\n    vector<Rect> diaX[2];\n    vector<Rect> diaY[2];\n\n    // Axis-aligned unit squares: parity by (x+y)%2\n    for (int p = 0; p < 2; ++p) {\n        for (int x = 0; x + 1 < N; ++x) {\n            for (int y = 0; y + 1 < N; ++y) {\n                if (((x + y) & 1) != p) continue;\n                Rect r;\n                r.v = { id(x, y), id(x + 1, y), id(x + 1, y + 1), id(x, y + 1) };\n                axis[p].push_back(r);\n            }\n        }\n    }\n\n    // 45-degree unit diamonds, grouped by x parity\n    for (int p = 0; p < 2; ++p) {\n        for (int x = 1; x + 1 < N; ++x) {\n            if ((x & 1) != p) continue;\n            for (int y = 1; y + 1 < N; ++y) {\n                Rect r;\n                r.v = { id(x, y + 1), id(x + 1, y), id(x, y - 1), id(x - 1, y) };\n                diaX[p].push_back(r);\n            }\n        }\n    }\n\n    // 45-degree unit diamonds, grouped by y parity\n    for (int p = 0; p < 2; ++p) {\n        for (int y = 1; y + 1 < N; ++y) {\n            if ((y & 1) != p) continue;\n            for (int x = 1; x + 1 < N; ++x) {\n                Rect r;\n                r.v = { id(x, y + 1), id(x + 1, y), id(x, y - 1), id(x - 1, y) };\n                diaY[p].push_back(r);\n            }\n        }\n    }\n\n    auto simulate = [&](int axisParity, int diaMode) -> pair<long long, vector<Op>> {\n        // diaMode:\n        // 0,1 => x-parity 0/1\n        // 2,3 => y-parity 0/1\n        vector<Rect> rects;\n        vector<vector<int>> inc(V);\n\n        auto add_family = [&](const vector<Rect>& fam) {\n            for (const auto& r : fam) {\n                int rid = (int)rects.size();\n                rects.push_back(r);\n                for (int k = 0; k < 4; ++k) inc[r.v[k]].push_back(rid);\n            }\n        };\n\n        add_family(axis[axisParity]);\n        if (diaMode < 2) add_family(diaX[diaMode]);\n        else add_family(diaY[diaMode - 2]);\n\n        vector<char> occ = initOcc;\n        vector<int> cnt(rects.size(), 0);\n        vector<char> used(rects.size(), 0);\n\n        for (int v : initIds) {\n            for (int rid : inc[v]) ++cnt[rid];\n        }\n\n        vector<int> q;\n        q.reserve(rects.size());\n\n        for (int rid = 0; rid < (int)rects.size(); ++rid) {\n            if (cnt[rid] == 3) q.push_back(rid);\n        }\n\n        long long sum = initSum;\n        vector<Op> ops;\n        ops.reserve(rects.size());\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int rid = q[head];\n            if (used[rid] || cnt[rid] != 3) continue;\n\n            const auto& r = rects[rid];\n            int miss = -1;\n            for (int k = 0; k < 4; ++k) {\n                if (!occ[r.v[k]]) {\n                    miss = k;\n                    break;\n                }\n            }\n            if (miss < 0) continue; // stale\n\n            int nv = r.v[miss];\n            used[rid] = 1;\n            occ[nv] = 1;\n            sum += wt[nv];\n\n            Op op;\n            for (int t = 0; t < 4; ++t) {\n                int v = r.v[(miss + t) % 4];\n                op.a[2 * t]     = v / N;\n                op.a[2 * t + 1] = v % N;\n            }\n            ops.push_back(op);\n\n            for (int rr : inc[nv]) {\n                if (used[rr]) continue;\n                ++cnt[rr];\n                if (cnt[rr] == 3) q.push_back(rr);\n            }\n        }\n\n        return {sum, ops};\n    };\n\n    long long bestSum = -1;\n    vector<Op> bestOps;\n\n    for (int a = 0; a < 2; ++a) {\n        for (int d = 0; d < 4; ++d) {\n            auto [sum, ops] = simulate(a, d);\n            if (sum > bestSum || (sum == bestSum && ops.size() > bestOps.size())) {\n                bestSum = sum;\n                bestOps = move(ops);\n            }\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n    for (const auto& op : bestOps) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << op.a[i];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int COLORS = 3;\nstatic constexpr int THRESH = 5;\n\nstruct Board {\n    uint8_t a[N][N]{};\n};\n\nint F[100];\nint tot[4];\nint prefCnt[101][4];\nint remainAfter[101][4];\n\n// flavor rank by total count (0: largest, 1: second, 2: third)\nint rankOfFlavor[4];\n\n// bonus table by rank and direction index\n// direction order: F, B, L, R\ndouble bonusTable[3][4] = {\n    {0.30, 0.10, 0.20, 0.00}, // top-left-like\n    {0.30, 0.10, 0.00, 0.20}, // top-right-like\n    {0.10, 0.30, 0.00, 0.20}  // bottom-right-like\n};\n\ninline int dirIndex(char d) {\n    if (d == 'F') return 0;\n    if (d == 'B') return 1;\n    if (d == 'L') return 2;\n    return 3; // R\n}\n\ninline Board tilt(const Board& b, char d) {\n    Board r{};\n    if (d == 'L') {\n        for (int i = 0; i < N; i++) {\n            int w = 0;\n            for (int j = 0; j < N; j++) {\n                if (b.a[i][j]) r.a[i][w++] = b.a[i][j];\n            }\n        }\n    } else if (d == 'R') {\n        for (int i = 0; i < N; i++) {\n            int w = N - 1;\n            for (int j = N - 1; j >= 0; j--) {\n                if (b.a[i][j]) r.a[i][w--] = b.a[i][j];\n            }\n        }\n    } else if (d == 'F') {\n        for (int j = 0; j < N; j++) {\n            int w = 0;\n            for (int i = 0; i < N; i++) {\n                if (b.a[i][j]) r.a[w++][j] = b.a[i][j];\n            }\n        }\n    } else { // 'B'\n        for (int j = 0; j < N; j++) {\n            int w = N - 1;\n            for (int i = N - 1; i >= 0; i--) {\n                if (b.a[i][j]) r.a[w--][j] = b.a[i][j];\n            }\n        }\n    }\n    return r;\n}\n\ninline pair<int,int> kthEmpty(const Board& b, int p) {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0) {\n                --p;\n                if (p == 0) return {i, j};\n            }\n        }\n    }\n    return {-1, -1};\n}\n\nstruct Analysis {\n    long long sumSq = 0;\n    int mx[4]{};\n    int adj = 0;\n};\n\ninline Analysis analyze(const Board& b) {\n    Analysis res{};\n    bool vis[N][N]{};\n    int qx[N * N], qy[N * N];\n    static const int dr[4] = {1, -1, 0, 0};\n    static const int dc[4] = {0, 0, 1, -1};\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0 || vis[i][j]) continue;\n            uint8_t col = b.a[i][j];\n            int head = 0, tail = 0;\n            qx[tail] = i; qy[tail] = j; tail++;\n            vis[i][j] = true;\n            int sz = 0;\n\n            while (head < tail) {\n                int x = qx[head], y = qy[head];\n                head++;\n                sz++;\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + dr[k], ny = y + dc[k];\n                    if ((unsigned)nx < N && (unsigned)ny < N &&\n                        !vis[nx][ny] && b.a[nx][ny] == col) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx; qy[tail] = ny; tail++;\n                    }\n                }\n            }\n\n            res.sumSq += 1LL * sz * sz;\n            res.mx[col] = max(res.mx[col], sz);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0) continue;\n            if (i + 1 < N && b.a[i + 1][j] == b.a[i][j]) res.adj++;\n            if (j + 1 < N && b.a[i][j + 1] == b.a[i][j]) res.adj++;\n        }\n    }\n\n    return res;\n}\n\ninline long long exactScore(const Board& b) {\n    bool vis[N][N]{};\n    int qx[N * N], qy[N * N];\n    static const int dr[4] = {1, -1, 0, 0};\n    static const int dc[4] = {0, 0, 1, -1};\n\n    long long ans = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0 || vis[i][j]) continue;\n            uint8_t col = b.a[i][j];\n            int head = 0, tail = 0;\n            qx[tail] = i; qy[tail] = j; tail++;\n            vis[i][j] = true;\n            int sz = 0;\n\n            while (head < tail) {\n                int x = qx[head], y = qy[head];\n                head++;\n                sz++;\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + dr[k], ny = y + dc[k];\n                    if ((unsigned)nx < N && (unsigned)ny < N &&\n                        !vis[nx][ny] && b.a[nx][ny] == col) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx; qy[tail] = ny; tail++;\n                    }\n                }\n            }\n\n            ans += 1LL * sz * sz;\n        }\n    }\n    return ans;\n}\n\ndouble expectimax(const Board& b, int next_idx) {\n    // next_idx: index of the next candy to be inserted (0-based)\n    // if next_idx == 99, this is the last candy; insert it and finish.\n    if (next_idx == 99) {\n        Board t = b;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (t.a[i][j] == 0) {\n                    t.a[i][j] = F[next_idx];\n                    return (double)exactScore(t);\n                }\n            }\n        }\n        return (double)exactScore(t);\n    }\n\n    pair<int,int> empties[N * N];\n    int ec = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0) empties[ec++] = {i, j};\n        }\n    }\n\n    static const char dirs[4] = {'F', 'B', 'L', 'R'};\n    double sum = 0.0;\n\n    for (int e = 0; e < ec; e++) {\n        Board t = b;\n        auto [r, c] = empties[e];\n        t.a[r][c] = F[next_idx];\n\n        double best = -1e100;\n        for (char d : dirs) {\n            Board u = tilt(t, d);\n            double val = expectimax(u, next_idx + 1);\n            if (val > best) best = val;\n        }\n        sum += best;\n    }\n\n    return sum / ec;\n}\n\ndouble heuristic(const Board& b, int next_idx) {\n    Analysis an = analyze(b);\n    double score = (double)an.sumSq;\n\n    for (int c = 1; c <= 3; c++) {\n        score += 2.0 * (double)an.mx[c] * (double)remainAfter[next_idx][c];\n    }\n\n    score += 0.02 * (double)an.adj;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 100; i++) {\n        cin >> F[i];\n        tot[F[i]]++;\n    }\n\n    // prefix counts\n    for (int i = 0; i < 100; i++) {\n        for (int c = 1; c <= 3; c++) prefCnt[i + 1][c] = prefCnt[i][c];\n        prefCnt[i + 1][F[i]]++;\n    }\n    for (int i = 0; i <= 100; i++) {\n        for (int c = 1; c <= 3; c++) {\n            remainAfter[i][c] = tot[c] - prefCnt[i][c];\n        }\n    }\n\n    // flavor ranking by total counts\n    vector<pair<int,int>> ord;\n    for (int c = 1; c <= 3; c++) ord.push_back({tot[c], c});\n    sort(ord.begin(), ord.end(), [](auto& x, auto& y){\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n    for (int r = 0; r < 3; r++) {\n        rankOfFlavor[ord[r].second] = r;\n    }\n\n    Board board{};\n\n    static const char dirs[4] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n\n        Board cur = board;\n        auto [r, c] = kthEmpty(cur, p);\n        cur.a[r][c] = F[t];\n\n        if (t == 99) {\n            // Nothing happens on the last tilt.\n            board = cur;\n            break;\n        }\n\n        int next_idx = t + 1;\n        int remaining_after = 99 - t; // candies still to come after this tilt\n\n        double bestScore = -1e100;\n        Board bestBoard = cur;\n        char bestDir = 'F';\n\n        int rank = rankOfFlavor[F[t]];\n\n        for (char d : dirs) {\n            Board cand = tilt(cur, d);\n            double sc;\n            if (remaining_after <= THRESH) {\n                sc = expectimax(cand, next_idx);\n            } else {\n                sc = heuristic(cand, next_idx);\n            }\n            sc += bonusTable[rank][dirIndex(d)];\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestBoard = cand;\n                bestDir = d;\n            }\n        }\n\n        board = bestBoard;\n        cout << bestDir << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Triple {\n    int a, b, c;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    long double eps;\n    cin >> M >> eps;\n\n    const int N = 100;\n    const int T = N * (N - 1) / 2;\n\n    // Build a pool of 100 codewords:\n    // (a, b, c) = (5+x, 27+y, 68-x-y), x,y in [0,9].\n    // They are three disjoint cliques of these sizes.\n    vector<Triple> pool;\n    pool.reserve(100);\n    for (int x = 0; x < 10; ++x) {\n        for (int y = 0; y < 10; ++y) {\n            pool.push_back({5 + x, 27 + y, 68 - x - y});\n        }\n    }\n\n    auto dist = [&](const Triple& p, const Triple& q) -> int {\n        return abs(p.a - q.a) + abs(p.b - q.b) + abs(p.c - q.c);\n    };\n\n    // Farthest-point ordering over the 100 triples.\n    vector<int> order;\n    order.reserve(100);\n    vector<char> used(100, 0);\n    vector<int> best(100, INT_MAX);\n\n    int start = 0; // (5,27,68)\n    order.push_back(start);\n    used[start] = 1;\n    for (int i = 0; i < 100; ++i) best[i] = dist(pool[i], pool[start]);\n    best[start] = -1;\n\n    for (int step = 1; step < 100; ++step) {\n        int u = -1, val = -1;\n        for (int i = 0; i < 100; ++i) {\n            if (used[i]) continue;\n            if (u == -1 || best[i] > val || (best[i] == val && i < u)) {\n                u = i;\n                val = best[i];\n            }\n        }\n        order.push_back(u);\n        used[u] = 1;\n        for (int i = 0; i < 100; ++i) {\n            if (!used[i]) best[i] = min(best[i], dist(pool[i], pool[u]));\n        }\n    }\n\n    // Select M codewords from the ordered pool.\n    vector<Triple> cand;\n    cand.reserve(M);\n    for (int i = 0; i < M; ++i) cand.push_back(pool[order[i]]);\n\n    // Precompute expected degree means for clique sizes.\n    vector<long double> mu(N + 1, 0.0L);\n    for (int s = 1; s <= N; ++s) {\n        mu[s] = eps * (N - 1) + (1.0L - 2.0L * eps) * (s - 1);\n    }\n\n    auto build_graph = [&](const Triple& t) -> string {\n        string s;\n        s.resize(T);\n        int pos = 0;\n        auto part = [&](int v) -> int {\n            if (v < t.a) return 0;\n            if (v < t.a + t.b) return 1;\n            return 2;\n        };\n        for (int i = 0; i < N; ++i) {\n            int pi = part(i);\n            for (int j = i + 1; j < N; ++j) {\n                s[pos++] = (pi == part(j) ? '1' : '0');\n            }\n        }\n        return s;\n    };\n\n    // Output N and the M graphs.\n    cout << N << '\\n';\n    for (const auto& t : cand) {\n        cout << build_graph(t) << '\\n';\n    }\n    cout.flush();\n\n    // Answer 100 queries.\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n\n        vector<int> deg(N, 0);\n        int idx = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j, ++idx) {\n                if (H[idx] == '1') {\n                    ++deg[i];\n                    ++deg[j];\n                }\n            }\n        }\n\n        sort(deg.begin(), deg.end()); // ascending\n\n        vector<long double> pref(N + 1, 0.0L), pref2(N + 1, 0.0L);\n        for (int i = 0; i < N; ++i) {\n            pref[i + 1] = pref[i] + deg[i];\n            pref2[i + 1] = pref2[i] + (long double)deg[i] * (long double)deg[i];\n        }\n\n        auto seg_score = [&](int l, int r, long double m) -> long double {\n            long double sum = pref[r] - pref[l];\n            long double sum2 = pref2[r] - pref2[l];\n            long double len = (long double)(r - l);\n            return sum2 - 2.0L * m * sum + len * m * m;\n        };\n\n        int best_id = 0;\n        long double best_score = 1e100L;\n\n        for (int id = 0; id < M; ++id) {\n            const auto& t = cand[id];\n            long double sc = 0.0L;\n            sc += seg_score(0, t.a, mu[t.a]);\n            sc += seg_score(t.a, t.a + t.b, mu[t.b]);\n            sc += seg_score(t.a + t.b, N, mu[t.c]);\n\n            if (sc < best_score) {\n                best_score = sc;\n                best_id = id;\n            }\n        }\n\n        cout << best_id << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ld = long double;\n\nstruct Edge {\n    int u, v;\n    ll w;\n    ld imp = 0.0L;\n};\n\nstatic inline ll sqdist(int x1, int y1, int x2, int y2) {\n    ll dx = (ll)x1 - x2;\n    ll dy = (ll)y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> g(N);\n    vector<int> deg(N, 0);\n\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w, 0.0L};\n        g[u].push_back({v, i});\n        g[v].push_back({u, i});\n        deg[u]++; deg[v]++;\n    }\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> xs[i] >> ys[i];\n    }\n\n    // ---- Sample sources (farthest-point style, starting from max degree vertex) ----\n    int S = min(N, 60);\n    vector<int> sources;\n    sources.reserve(S);\n\n    int first = 0;\n    for (int i = 1; i < N; ++i) {\n        if (deg[i] > deg[first]) first = i;\n    }\n    sources.push_back(first);\n\n    vector<ll> mind2(N, (1LL << 62));\n    for (int v = 0; v < N; ++v) {\n        mind2[v] = sqdist(xs[v], ys[v], xs[first], ys[first]);\n    }\n\n    vector<char> usedSrc(N, false);\n    usedSrc[first] = true;\n\n    for (int t = 1; t < S; ++t) {\n        int best = -1;\n        ll bestd = -1;\n        for (int v = 0; v < N; ++v) if (!usedSrc[v]) {\n            if (mind2[v] > bestd || (mind2[v] == bestd && best != -1 && deg[v] > deg[best])) {\n                best = v;\n                bestd = mind2[v];\n            } else if (best == -1) {\n                best = v;\n                bestd = mind2[v];\n            }\n        }\n        sources.push_back(best);\n        usedSrc[best] = true;\n        for (int v = 0; v < N; ++v) if (!usedSrc[v]) {\n            mind2[v] = min(mind2[v], sqdist(xs[v], ys[v], xs[best], ys[best]));\n        }\n    }\n\n    // ---- Estimate edge importance using sampled shortest-path trees ----\n    vector<ld> score(M, 0.0L);\n    const ll INF = (1LL << 62);\n\n    vector<ll> dist(N);\n    vector<int> parent(N), parentEdge(N), order;\n    order.reserve(N);\n\n    for (int s : sources) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(parent.begin(), parent.end(), -1);\n        fill(parentEdge.begin(), parentEdge.end(), -1);\n        order.clear();\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 [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n            order.push_back(v);\n\n            for (auto [to, eid] : g[v]) {\n                ll nd = d + edges[eid].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    parent[to] = v;\n                    parentEdge[to] = eid;\n                    pq.push({nd, to});\n                } else if (nd == dist[to]) {\n                    // deterministic tie-break for equal shortest paths\n                    if (parent[to] == -1 || v < parent[to] || (v == parent[to] && eid < parentEdge[to])) {\n                        parent[to] = v;\n                        parentEdge[to] = eid;\n                    }\n                }\n            }\n        }\n\n        vector<int> sub(N, 1);\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int v = order[i];\n            int p = parent[v];\n            if (p != -1) sub[p] += sub[v];\n        }\n\n        for (int v = 0; v < N; ++v) {\n            if (v == s) continue;\n            int eid = parentEdge[v];\n            if (eid >= 0) {\n                score[eid] += (ld)sub[v] * (N - sub[v]);\n            }\n        }\n    }\n\n    // Slight length bias for tie-breaking / robustness\n    for (int i = 0; i < M; ++i) {\n        score[i] /= (ld)S;\n        score[i] += (ld)edges[i].w * 0.001L;\n        edges[i].imp = score[i];\n    }\n\n    // Total importance, used for count balancing coefficient\n    ld totalImp = 0.0L;\n    for (int i = 0; i < M; ++i) totalImp += edges[i].imp;\n    ld avgImp = totalImp / (ld)M;\n    if (avgImp <= 0) avgImp = 1.0L;\n\n    // Sort edges by importance descending, with per-attempt random tie breaking\n    vector<int> baseOrd(M);\n    iota(baseOrd.begin(), baseOrd.end(), 0);\n\n    uint64_t baseSeed = 88172645463393265ULL\n                      ^ (uint64_t)N * 1000003ULL\n                      ^ (uint64_t)M * 10007ULL\n                      ^ (uint64_t)D * 1000000007ULL\n                      ^ (uint64_t)K * 1000000009ULL;\n\n    int attempts = 6;\n    vector<int> bestAns(M, 1);\n    ll bestConflict = (1LL << 62);\n    ld bestLoadVar = numeric_limits<ld>::infinity();\n    ll bestCountVar = (1LL << 62);\n\n    vector<ld> confFactors = {300.0L, 1500.0L, 6000.0L};\n\n    for (int attempt = 0; attempt < attempts; ++attempt) {\n        mt19937_64 rng(baseSeed + 1234567ULL * (attempt + 1));\n        vector<uint64_t> tieKey(M);\n        for (int i = 0; i < M; ++i) tieKey[i] = rng();\n\n        vector<int> ord = baseOrd;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n            if (tieKey[a] != tieKey[b]) return tieKey[a] < tieKey[b];\n            if (edges[a].w != edges[b].w) return edges[a].w > edges[b].w;\n            return a < b;\n        });\n\n        ld confWeight = avgImp * confFactors[attempt % confFactors.size()];\n        ld countCoef = avgImp;\n\n        vector<ld> dayLoad(D, 0.0L);\n        vector<int> dayCnt(D, 0);\n        vector<vector<int>> vertexColorCnt(N, vector<int>(D, 0));\n        vector<int> ans(M, -1);\n\n        for (int ei : ord) {\n            int u = edges[ei].u;\n            int v = edges[ei].v;\n\n            int bestDay = -1;\n            ld bestScore = numeric_limits<ld>::infinity();\n\n            for (int d = 0; d < D; ++d) {\n                if (dayCnt[d] >= K) continue;\n                int conf = vertexColorCnt[u][d] + vertexColorCnt[v][d];\n                ld sc = dayLoad[d] + countCoef * (ld)dayCnt[d] + confWeight * (ld)conf;\n\n                if (bestDay == -1 || sc < bestScore\n                    || (fabsl(sc - bestScore) <= 1e-18L && dayCnt[d] < dayCnt[bestDay])) {\n                    bestScore = sc;\n                    bestDay = d;\n                }\n            }\n\n            if (bestDay == -1) {\n                // Fallback; should not happen because D*K > M\n                bestDay = 0;\n                for (int d = 1; d < D; ++d) {\n                    if (dayCnt[d] < dayCnt[bestDay]) bestDay = d;\n                }\n            }\n\n            ans[ei] = bestDay + 1;\n            dayCnt[bestDay]++;\n            dayLoad[bestDay] += edges[ei].imp;\n            vertexColorCnt[u][bestDay]++;\n            vertexColorCnt[v][bestDay]++;\n        }\n\n        // Surrogate evaluation\n        ll conflictPairs = 0;\n        ll countVar = 0;\n        ld loadVar = 0.0L;\n\n        for (int vtx = 0; vtx < N; ++vtx) {\n            for (int d = 0; d < D; ++d) {\n                ll c = vertexColorCnt[vtx][d];\n                conflictPairs += c * (c - 1) / 2;\n            }\n        }\n        for (int d = 0; d < D; ++d) {\n            countVar += 1LL * dayCnt[d] * dayCnt[d];\n            loadVar += dayLoad[d] * dayLoad[d];\n        }\n\n        if (conflictPairs < bestConflict ||\n            (conflictPairs == bestConflict && loadVar < bestLoadVar) ||\n            (conflictPairs == bestConflict && fabsl(loadVar - bestLoadVar) <= 1e-18L && countVar < bestCountVar)) {\n            bestConflict = conflictPairs;\n            bestLoadVar = loadVar;\n            bestCountVar = countVar;\n            bestAns = std::move(ans);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << bestAns[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y, z;\n};\n\nstatic pair<vector<int>, int> build_object(int D, const vector<string>& f, const vector<string>& r) {\n    vector<Pos> cells;\n    cells.reserve(D * D);\n\n    for (int z = 0; z < D; ++z) {\n        vector<int> xs, ys;\n        for (int x = 0; x < D; ++x) if (f[z][x] == '1') xs.push_back(x);\n        for (int y = 0; y < D; ++y) if (r[z][y] == '1') ys.push_back(y);\n\n        if (xs.size() >= ys.size()) {\n            for (size_t i = 0; i < ys.size(); ++i) {\n                cells.push_back({xs[i], ys[i], z});\n            }\n            for (size_t i = ys.size(); i < xs.size(); ++i) {\n                cells.push_back({xs[i], ys[0], z});\n            }\n        } else {\n            for (size_t i = 0; i < xs.size(); ++i) {\n                cells.push_back({xs[i], ys[i], z});\n            }\n            for (size_t i = xs.size(); i < ys.size(); ++i) {\n                cells.push_back({xs[0], ys[i], z});\n            }\n        }\n    }\n\n    vector<int> arr(D * D * D, 0);\n    for (int id = 0; id < (int)cells.size(); ++id) {\n        const auto& p = cells[id];\n        arr[p.x * D * D + p.y * D + p.z] = id + 1; // 1-based block IDs\n    }\n\n    return {arr, (int)cells.size()};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; ++t) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int i = 0; i < D; ++i) cin >> f[t][i];\n        for (int i = 0; i < D; ++i) cin >> r[t][i];\n    }\n\n    auto [b1, v1] = build_object(D, f[0], r[0]);\n    auto [b2, v2] = build_object(D, f[1], r[1]);\n\n    int n = max(v1, v2);\n    cout << n << '\\n';\n\n    auto print_arr = [&](const vector<int>& b) {\n        for (int i = 0; i < (int)b.size(); ++i) {\n            if (i) cout << ' ';\n            cout << b[i];\n        }\n        cout << '\\n';\n    };\n\n    print_arr(b1);\n    print_arr(b2);\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INFLL = (1LL << 60);\nstatic const ll PENALTY = 100000000000000LL; // 1e14\nstatic const ll LIM2 = 25000000LL; // 5000^2\n\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n + 1);\n        sz.assign(n + 1, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstatic int N, M, K;\nstatic vector<int> xs, ys;\nstatic vector<int> ax, ay;\nstatic vector<Edge> edges;\n\nstatic vector<vector<ll>> distGraph;\nstatic vector<vector<int>> nxtHop;\nstatic vector<vector<int>> edgeId;\nstatic vector<vector<ll>> dist2SR;   // station-resident squared distances\nstatic vector<vector<int>> ceilDistSR; // ceil(sqrt(dist2SR))\n\nstatic auto startTime = chrono::steady_clock::now();\n\nstatic inline bool time_over() {\n    using namespace chrono;\n    return duration_cast<milliseconds>(steady_clock::now() - startTime).count() > 1850;\n}\n\nstatic int ceil_sqrt_ll(ll x) {\n    long double y = sqrt((long double)x);\n    int r = (int)y;\n    while ((ll)r * r < x) ++r;\n    while (r > 0 && (ll)(r - 1) * (r - 1) >= x) --r;\n    return r;\n}\n\nstruct State {\n    vector<int> sel;                 // selected broadcast stations, sorted, includes 1\n    vector<char> inSel;              // size N+1\n    vector<ll> bestD2;               // nearest selected station squared distance for each resident\n    vector<int> bestStation;         // nearest selected station\n    vector<int> radiusMax;           // radius per station (selected only), size N+1\n    int uncovered = 0;\n    ll coverageCost = 0;\n    ll connCost = 0;\n    ll totalCost = INFLL;\n};\n\nstatic ll build_connection(const vector<int>& terminals, vector<char>* outUsed = nullptr) {\n    if (terminals.size() <= 1) {\n        if (outUsed) outUsed->assign(M, 0);\n        return 0;\n    }\n\n    int t = (int)terminals.size();\n\n    // Prim on terminal metric closure\n    vector<ll> best(t, INFLL);\n    vector<int> parent(t, -1);\n    vector<char> used(t, 0);\n    best[0] = 0;\n\n    vector<pair<int,int>> termEdges;\n    termEdges.reserve(t - 1);\n\n    for (int it = 0; it < t; ++it) {\n        int x = -1;\n        ll bd = INFLL;\n        for (int i = 0; i < t; ++i) {\n            if (!used[i] && best[i] < bd) {\n                bd = best[i];\n                x = i;\n            }\n        }\n        used[x] = 1;\n        if (parent[x] != -1) {\n            termEdges.push_back({terminals[x], terminals[parent[x]]});\n        }\n        for (int y = 0; y < t; ++y) {\n            if (!used[y]) {\n                ll d = distGraph[terminals[x]][terminals[y]];\n                if (d < best[y]) {\n                    best[y] = d;\n                    parent[y] = x;\n                }\n            }\n        }\n    }\n\n    // Expand shortest paths of terminal MST edges -> union edges\n    vector<char> unionUsed(M, 0);\n    vector<int> unionIds;\n    unionIds.reserve(M);\n\n    for (auto [u, v] : termEdges) {\n        int a = u;\n        while (a != v) {\n            int b = nxtHop[a][v];\n            int id = edgeId[a][b];\n            if (!unionUsed[id]) {\n                unionUsed[id] = 1;\n                unionIds.push_back(id);\n            }\n            a = b;\n        }\n    }\n\n    // Kruskal on the union subgraph\n    sort(unionIds.begin(), unionIds.end(), [&](int i, int j) {\n        if (edges[i].w != edges[j].w) return edges[i].w < edges[j].w;\n        return i < j;\n    });\n\n    DSU dsu(N);\n    vector<char> treeUsed(M, 0);\n    vector<int> treeEdges;\n    treeEdges.reserve((int)unionIds.size());\n\n    ll cost = 0;\n    for (int id : unionIds) {\n        if (dsu.unite(edges[id].u, edges[id].v)) {\n            treeUsed[id] = 1;\n            treeEdges.push_back(id);\n            cost += edges[id].w;\n        }\n    }\n\n    // Prune non-terminal leaves from the tree\n    vector<int> deg(N + 1, 0);\n    vector<char> terminal(N + 1, 0);\n    for (int s : terminals) terminal[s] = 1;\n\n    for (int id : treeEdges) {\n        deg[edges[id].u]++;\n        deg[edges[id].v]++;\n    }\n\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int v = 1; v <= N; ++v) {\n            if (terminal[v] || deg[v] != 1) continue;\n            int remId = -1, other = -1;\n            for (int id : treeEdges) {\n                if (!treeUsed[id]) continue;\n                int a = edges[id].u, b = edges[id].v;\n                if (a == v || b == v) {\n                    remId = id;\n                    other = (a == v ? b : a);\n                    break;\n                }\n            }\n            if (remId == -1) continue;\n            treeUsed[remId] = 0;\n            cost -= edges[remId].w;\n            deg[v]--;\n            deg[other]--;\n            changed = true;\n        }\n    }\n\n    if (outUsed) {\n        outUsed->assign(M, 0);\n        for (int id : treeEdges) {\n            if (treeUsed[id]) (*outUsed)[id] = 1;\n        }\n    }\n\n    return cost;\n}\n\nstatic State recompute_state(vector<int> selInput) {\n    State st;\n    sort(selInput.begin(), selInput.end());\n    selInput.erase(unique(selInput.begin(), selInput.end()), selInput.end());\n    st.sel = selInput;\n    st.inSel.assign(N + 1, 0);\n    for (int s : st.sel) st.inSel[s] = 1;\n\n    st.bestD2.assign(K, INFLL);\n    st.bestStation.assign(K, -1);\n\n    for (int k = 0; k < K; ++k) {\n        for (int s : st.sel) {\n            ll d2 = dist2SR[s][k];\n            if (d2 < st.bestD2[k]) {\n                st.bestD2[k] = d2;\n                st.bestStation[k] = s;\n            }\n        }\n    }\n\n    st.radiusMax.assign(N + 1, 0);\n    st.uncovered = 0;\n    for (int k = 0; k < K; ++k) {\n        if (st.bestD2[k] > LIM2) {\n            st.uncovered++;\n            continue;\n        }\n        int s = st.bestStation[k];\n        int r = ceilDistSR[s][k];\n        if (r > st.radiusMax[s]) st.radiusMax[s] = r;\n    }\n\n    st.coverageCost = 0;\n    for (int s : st.sel) st.coverageCost += 1LL * st.radiusMax[s] * st.radiusMax[s];\n\n    st.connCost = build_connection(st.sel, nullptr);\n    st.totalCost = st.coverageCost + st.connCost + PENALTY * st.uncovered;\n\n    return st;\n}\n\nstatic ll eval_add(const State& cur, int v) {\n    if (cur.inSel[v]) return INFLL;\n\n    vector<int> radiusMax(N + 1, 0);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; ++k) {\n        ll d2 = cur.bestD2[k];\n        int st = cur.bestStation[k];\n\n        ll nd2 = dist2SR[v][k];\n        if (nd2 < d2) {\n            d2 = nd2;\n            st = v;\n        }\n\n        if (d2 > LIM2) {\n            uncovered++;\n            continue;\n        }\n\n        int r = ceilDistSR[st][k];\n        if (r > radiusMax[st]) radiusMax[st] = r;\n    }\n\n    ll coverage = 0;\n    for (int s : cur.sel) coverage += 1LL * radiusMax[s] * radiusMax[s];\n    coverage += 1LL * radiusMax[v] * radiusMax[v];\n\n    vector<int> tmp = cur.sel;\n    tmp.push_back(v);\n    ll conn = build_connection(tmp, nullptr);\n\n    return coverage + conn + PENALTY * uncovered;\n}\n\nstatic void improve_state(State& st) {\n    // A few cycles of greedy add / prune\n    for (int cycle = 0; cycle < 2; ++cycle) {\n        if (time_over()) return;\n\n        // Greedy additions\n        while (!time_over()) {\n            ll bestTotal = st.totalCost;\n            int bestV = -1;\n\n            for (int v = 1; v <= N; ++v) {\n                if (st.inSel[v]) continue;\n                ll t = eval_add(st, v);\n                if (t < bestTotal) {\n                    bestTotal = t;\n                    bestV = v;\n                }\n            }\n\n            if (bestV == -1) break;\n            st.sel.push_back(bestV);\n            st = recompute_state(st.sel);\n        }\n\n        // Prune redundant stations\n        while (!time_over()) {\n            ll bestTotal = st.totalCost;\n            int removePos = -1;\n            State bestCand;\n            bool found = false;\n\n            for (int i = 0; i < (int)st.sel.size(); ++i) {\n                int s = st.sel[i];\n                if (s == 1) continue; // never remove root\n\n                vector<int> tmp;\n                tmp.reserve(st.sel.size() - 1);\n                for (int x : st.sel) if (x != s) tmp.push_back(x);\n\n                State cand = recompute_state(tmp);\n                if (cand.totalCost < bestTotal) {\n                    bestTotal = cand.totalCost;\n                    removePos = i;\n                    bestCand = std::move(cand);\n                    found = true;\n                }\n            }\n\n            if (!found) break;\n            st = std::move(bestCand);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    xs.resize(N + 1);\n    ys.resize(N + 1);\n    for (int i = 1; i <= N; ++i) cin >> xs[i] >> ys[i];\n\n    edges.resize(M);\n    edgeId.assign(N + 1, vector<int>(N + 1, -1));\n    distGraph.assign(N + 1, vector<ll>(N + 1, INFLL));\n    nxtHop.assign(N + 1, vector<int>(N + 1, -1));\n\n    for (int i = 1; i <= N; ++i) {\n        distGraph[i][i] = 0;\n        nxtHop[i][i] = i;\n    }\n\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n        edgeId[u][v] = edgeId[v][u] = j;\n        distGraph[u][v] = distGraph[v][u] = min(distGraph[u][v], w);\n        nxtHop[u][v] = v;\n        nxtHop[v][u] = u;\n    }\n\n    ax.resize(K);\n    ay.resize(K);\n    for (int i = 0; i < K; ++i) cin >> ax[i] >> ay[i];\n\n    // All-pairs shortest paths\n    for (int k = 1; k <= N; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            if (distGraph[i][k] >= INFLL / 4) continue;\n            for (int j = 1; j <= N; ++j) {\n                if (distGraph[k][j] >= INFLL / 4) continue;\n                ll nd = distGraph[i][k] + distGraph[k][j];\n                if (nd < distGraph[i][j]) {\n                    distGraph[i][j] = nd;\n                    nxtHop[i][j] = nxtHop[i][k];\n                }\n            }\n        }\n    }\n\n    // Precompute station-resident distances\n    dist2SR.assign(N + 1, vector<ll>(K, 0));\n    ceilDistSR.assign(N + 1, vector<int>(K, 0));\n    for (int s = 1; s <= N; ++s) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = (ll)xs[s] - ax[k];\n            ll dy = (ll)ys[s] - ay[k];\n            ll d2 = dx * dx + dy * dy;\n            dist2SR[s][k] = d2;\n            ceilDistSR[s][k] = ceil_sqrt_ll(d2);\n        }\n    }\n\n    // Determine promising initial stations by singleton cost\n    vector<pair<ll,int>> candidates;\n    candidates.reserve(N - 1);\n    for (int i = 2; i <= N; ++i) {\n        vector<int> sel = {1, i};\n        State st = recompute_state(sel);\n        candidates.push_back({st.totalCost, i});\n    }\n    sort(candidates.begin(), candidates.end());\n\n    vector<int> b1 = {1};\n    int best1 = candidates[0].second;\n    b1.push_back(best1);\n\n    int best2 = -1;\n    {\n        vector<pair<ll,int>> cand2;\n        for (int i = 2; i <= N; ++i) {\n            if (i == best1) continue;\n            vector<int> sel = {1, best1, i};\n            State st = recompute_state(sel);\n            cand2.push_back({st.totalCost, i});\n        }\n        sort(cand2.begin(), cand2.end());\n        best2 = cand2[0].second;\n    }\n\n    vector<vector<int>> seeds;\n    seeds.push_back({1});\n    seeds.push_back({1, best1});\n    seeds.push_back({1, best1, best2});\n\n    ll bestTotal = INFLL;\n    vector<int> bestSel;\n\n    for (auto seed : seeds) {\n        if (time_over()) break;\n        State st = recompute_state(seed);\n        improve_state(st);\n\n        if (st.totalCost < bestTotal) {\n            bestTotal = st.totalCost;\n            bestSel = st.sel;\n        }\n    }\n\n    if (bestSel.empty()) bestSel = {1};\n\n    // Ensure feasibility: if still uncovered, add stations greedily.\n    // This should rarely be necessary, but it guarantees legal output.\n    State finalState = recompute_state(bestSel);\n    while (finalState.uncovered > 0) {\n        int bestV = -1;\n        ll bestT = INFLL;\n        for (int v = 1; v <= N; ++v) {\n            if (finalState.inSel[v]) continue;\n            ll t = eval_add(finalState, v);\n            if (t < bestT) {\n                bestT = t;\n                bestV = v;\n            }\n        }\n        if (bestV == -1) break;\n        finalState.sel.push_back(bestV);\n        finalState = recompute_state(finalState.sel);\n    }\n\n    // Recompute final solution exactly\n    finalState = recompute_state(finalState.sel);\n\n    vector<char> usedEdges;\n    ll finalConn = build_connection(finalState.sel, &usedEdges);\n    finalState.connCost = finalConn;\n    finalState.totalCost = finalState.coverageCost + finalConn + PENALTY * finalState.uncovered;\n\n    // Output P\n    vector<int> P(N + 1, 0);\n    for (int s : finalState.sel) {\n        P[s] = finalState.radiusMax[s];\n    }\n\n    for (int i = 1; i <= N; ++i) {\n        if (i > 1) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n\n    // Output B\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (usedEdges[j] ? 1 : 0);\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const int V = N * (N + 1) / 2;\n    const int INF = 1e9;\n    const int LIMIT = 10000;\n\n    auto ID = [&](int x, int y) -> int {\n        return x * (x + 1) / 2 + y;\n    };\n\n    vector<pair<int,int>> coord(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            coord[ID(x, y)] = {x, y};\n        }\n    }\n\n    vector<vector<int>> adj(V), children(V);\n    vector<int> needParents(V, 0);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = ID(x, y);\n\n            // Children first (helps path selection prefer lower routes)\n            if (x + 1 < N) {\n                int d1 = ID(x + 1, y);\n                int d2 = ID(x + 1, y + 1);\n                adj[u].push_back(d1);\n                adj[u].push_back(d2);\n                children[u].push_back(d1);\n                children[u].push_back(d2);\n            }\n\n            // Same row\n            if (y > 0) adj[u].push_back(ID(x, y - 1));\n            if (y < x) adj[u].push_back(ID(x, y + 1));\n\n            // Parents\n            if (x > 0) {\n                if (y > 0) adj[u].push_back(ID(x - 1, y - 1));\n                if (y < x) adj[u].push_back(ID(x - 1, y));\n            }\n\n            if (x == 0) needParents[u] = 0;\n            else needParents[u] = (y > 0 && y < x) ? 2 : 1;\n        }\n    }\n\n    vector<int> board(V), pos(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            int u = ID(x, y);\n            board[u] = v;\n            pos[v] = u;\n        }\n    }\n\n    vector<char> fixed(V, 0), avail(V, 0);\n    vector<int> parentCnt(V, 0);\n    vector<int> availList;\n    availList.reserve(V);\n\n    int top = ID(0, 0);\n    avail[top] = 1;\n    availList.push_back(top);\n\n    vector<Op> ops;\n    ops.reserve(LIMIT);\n\n    for (int num = 0; num < V; ++num) {\n        int s = pos[num];\n\n        // BFS over unfixed cells\n        vector<int> dist(V, -1);\n        vector<int> order;\n        order.reserve(V);\n        dist[s] = 0;\n        order.push_back(s);\n\n        for (size_t head = 0; head < order.size(); ++head) {\n            int u = order[head];\n            for (int v : adj[u]) {\n                if (fixed[v] || dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                order.push_back(v);\n            }\n        }\n\n        // On shortest-path DAG, minimize number of upward moves\n        vector<int> bestPen(V, INF), bestPar(V, -1);\n        bestPen[s] = 0;\n\n        auto better_parent = [&](int a, int b) -> bool {\n            if (b == -1) return true;\n            if (coord[a].first != coord[b].first) return coord[a].first > coord[b].first;\n            return coord[a].second > coord[b].second;\n        };\n\n        for (int u : order) {\n            if (bestPen[u] == INF) continue;\n            for (int v : adj[u]) {\n                if (fixed[v] || dist[v] != dist[u] + 1) continue;\n                int add = (coord[v].first < coord[u].first ? 1 : 0); // upward move\n                int cand = bestPen[u] + add;\n                if (cand < bestPen[v] || (cand == bestPen[v] && better_parent(u, bestPar[v]))) {\n                    bestPen[v] = cand;\n                    bestPar[v] = u;\n                }\n            }\n        }\n\n        // Choose nearest available reachable cell\n        int target = -1;\n        tuple<int,int,int,int> best = {INF, INF, INF, INF};\n        for (int id : availList) {\n            if (!avail[id] || dist[id] == -1 || bestPen[id] == INF) continue;\n            auto cand = make_tuple(dist[id], bestPen[id], coord[id].first, coord[id].second);\n            if (cand < best) {\n                best = cand;\n                target = id;\n            }\n        }\n\n        if (target == -1) {\n            break; // Should not happen, but keep output legal\n        }\n\n        // Reconstruct path from s to target\n        vector<int> path;\n        for (int v = target;; v = bestPar[v]) {\n            path.push_back(v);\n            if (v == s) break;\n        }\n        reverse(path.begin(), path.end());\n\n        int needSwaps = (int)path.size() - 1;\n        if ((int)ops.size() + needSwaps > LIMIT) {\n            break; // keep output legal\n        }\n\n        // Apply swaps along the path\n        for (int i = 0; i < needSwaps; ++i) {\n            int a = path[i];\n            int b = path[i + 1];\n            int va = board[a];\n            int vb = board[b];\n            swap(board[a], board[b]);\n            pos[va] = b;\n            pos[vb] = a;\n            ops.push_back({coord[a].first, coord[a].second, coord[b].first, coord[b].second});\n        }\n\n        // Fix target cell\n        fixed[target] = 1;\n        avail[target] = 0;\n\n        for (int c : children[target]) {\n            if (fixed[c]) continue;\n            ++parentCnt[c];\n            if (parentCnt[c] == needParents[c] && !avail[c]) {\n                avail[c] = 1;\n                availList.push_back(c);\n            }\n        }\n    }\n\n    cout << ops.size() << '\\n';\n    for (auto &op : ops) {\n        cout << op.x1 << ' ' << op.y1 << ' ' << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Node {\n    int r = -1, c = -1;\n    int parent = 0;\n    int disc = -1;                 // BFS discovery order in the rooted tree\n    vector<int> child;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    const int er = 0;\n    const int ec = (D - 1) / 2;\n\n    auto inside = [&](int r, int c) {\n        return 0 <= r && r < D && 0 <= c && c < D;\n    };\n    auto free_cell = [&](int r, int c) {\n        return inside(r, c) && !obstacle[r][c] && !(r == er && c == ec);\n    };\n\n    // Compress free cells (excluding the entrance) into nodes 1..M.\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<pair<int,int>> pos(1); // node 0 = dummy root (entrance)\n    int M = 0;\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (free_cell(r, c)) {\n                id[r][c] = ++M;\n                pos.push_back({r, c});\n            }\n        }\n    }\n\n    vector<Node> nodes(M + 1);\n    for (int i = 1; i <= M; ++i) {\n        nodes[i].r = pos[i].first;\n        nodes[i].c = pos[i].second;\n    }\n\n    // Build a rooted BFS spanning tree from the entrance.\n    // The order of discovery is used as a static key for storage decisions.\n    vector<vector<bool>> vis(D, vector<bool>(D, false));\n    queue<int> q; // node ids\n    int discCnt = 0;\n\n    const int dr[4] = {1, 0, 0, -1}; // down, left, right, up\n    const int dc[4] = {0, -1, 1, 0};\n\n    auto add_if_free = [&](int nr, int nc, int parentId) {\n        if (!free_cell(nr, nc) || vis[nr][nc]) return;\n        int v = id[nr][nc];\n        vis[nr][nc] = true;\n        nodes[v].parent = parentId;\n        nodes[v].disc = discCnt++;\n        nodes[parentId].child.push_back(v);\n        q.push(v);\n    };\n\n    // Start from the 3 cells adjacent to the entrance.\n    for (int k = 0; k < 4; ++k) {\n        int nr = er + dr[k], nc = ec + dc[k];\n        add_if_free(nr, nc, 0);\n    }\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        int r = nodes[u].r, c = nodes[u].c;\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            add_if_free(nr, nc, u);\n        }\n    }\n\n    // Sanity: all free cells should be visited.\n    // (Guaranteed by the statement.)\n    // cerr << \"M=\" << M << \" discCnt=\" << discCnt << \"\\n\";\n\n    vector<int> remChild(M + 1);\n    for (int i = 0; i <= M; ++i) remChild[i] = (int)nodes[i].child.size();\n\n    vector<bool> occupied(M + 1, false);\n    vector<int> assigned(M + 1, -1);\n\n    // Online storage:\n    // among current leaves of the rooted tree, choose the one whose BFS discovery\n    // index is closest to the arriving number.\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        vector<int> leaves;\n        leaves.reserve(M);\n        for (int i = 1; i <= M; ++i) {\n            if (!occupied[i] && remChild[i] == 0) leaves.push_back(i);\n        }\n\n        int chosen = leaves[0];\n        int bestDiff = abs(nodes[chosen].disc - t);\n        for (int u : leaves) {\n            int d = abs(nodes[u].disc - t);\n            if (d < bestDiff || (d == bestDiff && nodes[u].disc < nodes[chosen].disc)) {\n                bestDiff = d;\n                chosen = u;\n            }\n        }\n\n        occupied[chosen] = true;\n        assigned[chosen] = t;\n\n        int p = nodes[chosen].parent;\n        if (p != 0) --remChild[p];\n\n        cout << nodes[chosen].r << ' ' << nodes[chosen].c << '\\n' << flush;\n    }\n\n    // Final removal order:\n    // tree-topological greedy: always take the available node with smallest label.\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int v : nodes[0].child) {\n        pq.push({assigned[v], v});\n    }\n\n    vector<int> outOrder;\n    outOrder.reserve(M);\n\n    while (!pq.empty()) {\n        auto [val, u] = pq.top();\n        pq.pop();\n        outOrder.push_back(u);\n        for (int v : nodes[u].child) {\n            pq.push({assigned[v], v});\n        }\n    }\n\n    for (int u : outOrder) {\n        cout << nodes[u].r << ' ' << nodes[u].c << '\\n';\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXM = 100;\nstatic const int MAXV = MAXN * MAXN;\n\nint n, m, N;\nvector<int> initBoard, boardCur;\narray<array<int, 4>, MAXV> nb;\nint distToBorder[MAXV];\nint sameDegOrig[MAXV];\nbool origB[MAXM + 1];\nbool origAdj[MAXM + 1][MAXM + 1];\nbool frozenCell[MAXV];\n\nint curCnt[MAXM + 1];\nint curTouch0[MAXM + 1];\nint curAdj[MAXM + 1][MAXM + 1];\n\nint visStamp[MAXV];\nint stampNow = 1;\n\ninline int id(int i, int j) { return i * n + j; }\n\nvoid recomputeStats() {\n    memset(curCnt, 0, sizeof(curCnt));\n    memset(curTouch0, 0, sizeof(curTouch0));\n    memset(curAdj, 0, sizeof(curAdj));\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c == 0) continue;\n        curCnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c == 0) continue;\n\n        if (origB[c]) {\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[idx][d];\n                if (v == -1 || boardCur[v] == 0) curTouch0[c]++;\n            }\n        }\n\n        int r = idx / n, ccol = idx % n;\n        // Count only right/down to avoid double counting.\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = boardCur[right];\n            if (d > 0 && origB[c] && origB[d] && c < d) {\n                curAdj[c][d]++;\n                curAdj[d][c]++;\n            }\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = boardCur[down];\n            if (d > 0 && origB[c] && origB[d] && c < d) {\n                curAdj[c][d]++;\n                curAdj[d][c]++;\n            }\n        }\n    }\n}\n\nbool canRemove(int idx) {\n    int c = boardCur[idx];\n    if (c == 0) return false;\n    if (!origB[c]) return false;\n    if (frozenCell[idx]) return false;\n\n    int same = 0;\n    int loss0 = 0;\n    int loss[MAXM + 1];\n    memset(loss, 0, sizeof(loss));\n\n    bool frontier = false;\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            frontier = true;\n            loss0++;\n        } else {\n            int t = boardCur[v];\n            if (t == c) {\n                same++;\n            } else {\n                if (!origB[t]) return false; // would expose a non-B color to 0\n                loss[t]++;\n            }\n        }\n    }\n\n    if (!frontier) return false;\n    if (curCnt[c] <= 1) return false;\n\n    int newTouch0 = curTouch0[c] - loss0 + same;\n    if (newTouch0 <= 0) return false; // boundary-adjacent colors must keep touching 0\n\n    for (int t = 1; t <= m; ++t) {\n        if (loss[t] == 0) continue;\n        if (curAdj[c][t] <= loss[t]) return false; // original adjacency edge would disappear\n    }\n\n    if (same <= 1) return true;\n\n    // Connectivity check for color c after removing idx.\n    ++stampNow;\n    vector<int> q;\n    q.reserve(N);\n\n    int start = -1;\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v != -1 && boardCur[v] == c) {\n            start = v;\n            break;\n        }\n    }\n    if (start == -1) return false;\n\n    q.push_back(start);\n    visStamp[start] = stampNow;\n    int seen = 1;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[u][d];\n            if (v == -1 || v == idx) continue;\n            if (boardCur[v] == c && visStamp[v] != stampNow) {\n                visStamp[v] = stampNow;\n                q.push_back(v);\n                ++seen;\n            }\n        }\n    }\n\n    return seen == curCnt[c] - 1;\n}\n\nbool validate(const vector<int>& b) {\n    bool outAdj[MAXM + 1][MAXM + 1];\n    memset(outAdj, 0, sizeof(outAdj));\n    bool outTouch0[MAXM + 1];\n    memset(outTouch0, 0, sizeof(outTouch0));\n\n    vector<int> cnt(MAXM + 1, 0);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c > 0) cnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c == 0) continue;\n\n        int i = idx / n, j = idx % n;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1 || b[v] == 0) outTouch0[c] = true;\n            else {\n                int t = b[v];\n                if (t != c) {\n                    outAdj[c][t] = outAdj[t][c] = true;\n                }\n            }\n        }\n    }\n\n    for (int c = 1; c <= m; ++c) {\n        if (outTouch0[c] != origB[c]) return false;\n        for (int d = 1; d <= m; ++d) {\n            if (outAdj[c][d] != origAdj[c][d]) return false;\n        }\n    }\n\n    // Connectivity of each color 1..m\n    vector<int> seen(N, 0);\n    int stamp = 1;\n    vector<int> q;\n    q.reserve(N);\n\n    for (int c = 1; c <= m; ++c) {\n        int start = -1;\n        for (int idx = 0; idx < N; ++idx) {\n            if (b[idx] == c) { start = idx; break; }\n        }\n        if (start == -1) return false;\n\n        ++stamp;\n        q.clear();\n        q.push_back(start);\n        seen[start] = stamp;\n        int got = 1;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == c && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                    ++got;\n                }\n            }\n        }\n\n        if (got != cnt[c]) return false;\n    }\n\n    // 0-color connectivity through outside: all 0-cells must be reachable from a boundary 0-cell.\n    int zeroCnt = 0;\n    for (int idx = 0; idx < N; ++idx) if (b[idx] == 0) zeroCnt++;\n    if (zeroCnt > 0) {\n        ++stamp;\n        q.clear();\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    int idx = id(i, j);\n                    if (b[idx] == 0 && seen[idx] != stamp) {\n                        seen[idx] = stamp;\n                        q.push_back(idx);\n                    }\n                }\n            }\n        }\n        if (q.empty()) return false;\n\n        int got = 0;\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            ++got;\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == 0 && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                }\n            }\n        }\n        if (got != zeroCnt) return false;\n    }\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    N = n * n;\n\n    initBoard.assign(N, 0);\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c;\n            cin >> c;\n            initBoard[id(i, j)] = c;\n        }\n    }\n\n    // Precompute neighbors and distances.\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = id(i, j);\n            nb[idx][0] = (i == 0 ? -1 : id(i - 1, j));\n            nb[idx][1] = (i + 1 == n ? -1 : id(i + 1, j));\n            nb[idx][2] = (j == 0 ? -1 : id(i, j - 1));\n            nb[idx][3] = (j + 1 == n ? -1 : id(i, j + 1));\n            distToBorder[idx] = min(min(i, j), min(n - 1 - i, n - 1 - j));\n        }\n    }\n\n    // Original boundary-adjacent colors.\n    memset(origB, 0, sizeof(origB));\n    for (int i = 0; i < n; ++i) {\n        origB[initBoard[id(i, 0)]] = true;\n        origB[initBoard[id(i, n - 1)]] = true;\n    }\n    for (int j = 0; j < n; ++j) {\n        origB[initBoard[id(0, j)]] = true;\n        origB[initBoard[id(n - 1, j)]] = true;\n    }\n\n    // Original adjacency among colors.\n    memset(origAdj, 0, sizeof(origAdj));\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = initBoard[right];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = initBoard[down];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n    }\n\n    // Same-color degree in the original map.\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int s = 0;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v != -1 && initBoard[v] == c) s++;\n        }\n        sameDegOrig[idx] = s;\n    }\n\n    // Frozen cells: any cell adjacent to a non-boundary-adjacent different color can never be removed.\n    memset(frozenCell, 0, sizeof(frozenCell));\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        if (!origB[c]) continue;\n        bool frozen = false;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1) continue;\n            int t = initBoard[v];\n            if (t != c && !origB[t]) {\n                frozen = true;\n                break;\n            }\n        }\n        frozenCell[idx] = frozen;\n    }\n\n    // Candidate list.\n    vector<int> cand;\n    cand.reserve(N);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        if (origB[c] && !frozenCell[idx]) cand.push_back(idx);\n    }\n\n    sort(cand.begin(), cand.end(), [&](int a, int b) {\n        if (distToBorder[a] != distToBorder[b]) return distToBorder[a] < distToBorder[b];\n        if (sameDegOrig[a] != sameDegOrig[b]) return sameDegOrig[a] < sameDegOrig[b];\n        return a < b;\n    });\n    vector<int> candRev = cand;\n    reverse(candRev.begin(), candRev.end());\n\n    boardCur = initBoard;\n    recomputeStats();\n\n    // Greedy peeling with two scan orders.\n    for (int round = 0; round < 100; ++round) {\n        bool changed = false;\n        for (int phase = 0; phase < 2; ++phase) {\n            const vector<int>& ord = (phase == 0 ? cand : candRev);\n            for (int idx : ord) {\n                if (boardCur[idx] == 0) continue;\n                if (canRemove(idx)) {\n                    boardCur[idx] = 0;\n                    recomputeStats();\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n    }\n\n    // Safety validation; if anything goes wrong, fall back to the original map.\n    vector<int> out = boardCur;\n    if (!validate(out)) out = initBoard;\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << out[id(i, j)];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ld = long double;\n\nstatic const ld EPS = 1e-15L;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, D, Q;\n    cin >> N >> D >> Q;\n\n    vector<ld> win(N, 0.0L);\n    vector<int> deg(N, 0);\n\n    // Deterministic seed is enough; weights are random w.r.t. indices.\n    uint64_t seed = 0x9e3779b97f4a7c15ULL\n                    ^ (uint64_t)N * 1000003ULL\n                    ^ (uint64_t)D * 10007ULL\n                    ^ (uint64_t)Q * 10000019ULL;\n    mt19937_64 rng(seed);\n\n    auto ask = [&](int a, int b) -> int {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n' << flush;\n        char c;\n        cin >> c;\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    };\n\n    auto do_query = [&](int a, int b) {\n        int r = ask(a, b);\n        deg[a]++; deg[b]++;\n        if (r > 0) {\n            win[a] += 1.0L;\n        } else if (r < 0) {\n            win[b] += 1.0L;\n        } else {\n            win[a] += 0.5L;\n            win[b] += 0.5L;\n        }\n    };\n\n    // Random matchings: each round compares as many disjoint pairs as possible.\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n\n    int pairsPerRound = N / 2;\n    int fullRounds = Q / pairsPerRound;\n    int rem = Q % pairsPerRound;\n\n    for (int r = 0; r < fullRounds; ++r) {\n        shuffle(perm.begin(), perm.end(), rng);\n        for (int i = 0; i + 1 < N; i += 2) {\n            do_query(perm[i], perm[i + 1]);\n        }\n    }\n    if (rem > 0) {\n        shuffle(perm.begin(), perm.end(), rng);\n        for (int i = 0; i + 1 < 2 * rem; i += 2) {\n            do_query(perm[i], perm[i + 1]);\n        }\n    }\n\n    // Estimated percentile from win rate.\n    vector<ld> pdir(N);\n    for (int i = 0; i < N; ++i) {\n        pdir[i] = (win[i] + 0.5L) / (deg[i] + 1.0L);\n        pdir[i] = max((ld)1e-15L, min((ld)1.0L - 1e-15L, pdir[i]));\n    }\n\n    // Truncation threshold in normalized units (1e5 scale).\n    // We estimate weights in units of 1e5, so z_max = N / D.\n    ld zmax = (ld)N / (ld)D;\n    ld cap = 1.0L - expl(-zmax);\n\n    // First ranking by raw percentile.\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    stable_sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (fabsl(pdir[a] - pdir[b]) > 1e-18L) return pdir[a] > pdir[b];\n        return a < b;\n    });\n\n    // Shrink each item's percentile toward the expected rank percentile.\n    // Then convert to a normalized weight estimate.\n    vector<ld> est(N);\n    for (int rank = 0; rank < N; ++rank) {\n        int id = ord[rank];\n        ld prior_p = (ld)(N - rank) / (ld)(N + 1.0L); // expected percentile by rank\n        ld alpha = min((ld)1.0L, (ld)deg[id] / 16.0L);\n        ld p = alpha * pdir[id] + (1.0L - alpha) * prior_p;\n        p = max((ld)1e-15L, min((ld)1.0L - 1e-15L, p));\n\n        // Inverse CDF of truncated exponential on normalized scale.\n        est[id] = -log1pl(-cap * p);\n    }\n\n    // Sort by estimated weight descending.\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (fabsl(est[a] - est[b]) > 1e-18L) return est[a] > est[b];\n        return a < b;\n    });\n\n    // Greedy LPT assignment.\n    vector<vector<int>> bins(D);\n    vector<ld> load(D, 0.0L);\n    vector<int> where(N, -1), pos(N, -1);\n\n    for (int id : ord) {\n        int best = 0;\n        for (int d = 1; d < D; ++d) {\n            if (load[d] < load[best]) best = d;\n        }\n        where[id] = best;\n        pos[id] = (int)bins[best].size();\n        bins[best].push_back(id);\n        load[best] += est[id];\n    }\n\n    auto remove_from_bin = [&](int item, int b) {\n        int idx = pos[item];\n        int last = bins[b].back();\n        bins[b][idx] = last;\n        pos[last] = idx;\n        bins[b].pop_back();\n    };\n\n    auto add_to_bin = [&](int item, int b) {\n        where[item] = b;\n        pos[item] = (int)bins[b].size();\n        bins[b].push_back(item);\n    };\n\n    auto apply_move = [&](int item, int from, int to) {\n        remove_from_bin(item, from);\n        load[from] -= est[item];\n        add_to_bin(item, to);\n        load[to] += est[item];\n    };\n\n    auto apply_swap = [&](int x, int bx, int y, int by) {\n        int ix = pos[x], iy = pos[y];\n        bins[bx][ix] = y;\n        bins[by][iy] = x;\n        pos[y] = ix;\n        pos[x] = iy;\n        where[x] = by;\n        where[y] = bx;\n        load[bx] += est[y] - est[x];\n        load[by] += est[x] - est[y];\n    };\n\n    // Local search on estimated loads.\n    for (int iter = 0; iter < 120; ++iter) {\n        ld bestDelta = 0.0L;\n        int bestType = 0; // 1: move, 2: swap\n        int ba = -1, bb = -1, bx = -1, by = -1;\n\n        for (int a = 0; a < D; ++a) {\n            for (int b = 0; b < D; ++b) {\n                if (load[a] <= load[b] + EPS) continue;\n                ld d = load[a] - load[b];\n\n                // Move one item from a to b (keep source non-empty).\n                if ((int)bins[a].size() > 1) {\n                    for (int x : bins[a]) {\n                        ld w = est[x];\n                        ld delta = 2.0L * w * (w - d);\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestType = 1;\n                            ba = a; bb = b; bx = x;\n                        }\n                    }\n                }\n\n                // Swap one item between a and b.\n                for (int x : bins[a]) {\n                    for (int y : bins[b]) {\n                        ld diff = est[x] - est[y];\n                        ld delta = 2.0L * diff * (diff - d);\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestType = 2;\n                            ba = a; bb = b; bx = x; by = y;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (bestDelta >= -1e-12L) break;\n\n        if (bestType == 1) {\n            apply_move(bx, ba, bb);\n        } else if (bestType == 2) {\n            apply_swap(bx, ba, by, bb);\n        }\n    }\n\n    vector<int> ans(N);\n    for (int b = 0; b < D; ++b) {\n        for (int x : bins[b]) ans[x] = b;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << ans[i];\n    }\n    cout << '\\n' << flush;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int M = 10;\nstatic constexpr int MAXV = 205;\n\nint n, m;\n\nstruct Board {\n    int st[M][MAXV];\n    int len[M];\n    int stack_id[MAXV];\n    int idx[MAXV];\n    char removed[MAXV];\n    int cur; // smallest not yet removed\n};\n\ninline void updatePos(Board &b, int s) {\n    for (int i = 0; i < b.len[s]; ++i) {\n        int v = b.st[s][i];\n        b.stack_id[v] = s;\n        b.idx[v] = i;\n    }\n}\n\ninline void removeTop(Board &b, int s, vector<pair<int,int>> *ops) {\n    int v = b.st[s][b.len[s] - 1];\n    if (ops) ops->push_back({v, 0});\n    b.removed[v] = 1;\n    b.len[s]--;\n    updatePos(b, s);\n    while (b.cur <= n && b.removed[b.cur]) ++b.cur;\n}\n\ninline void flush(Board &b, vector<pair<int,int>> *ops) {\n    while (true) {\n        while (b.cur <= n && b.removed[b.cur]) ++b.cur;\n        if (b.cur > n) break;\n        int s = b.stack_id[b.cur];\n        if (b.idx[b.cur] != b.len[s] - 1) break;\n        removeTop(b, s, ops);\n    }\n}\n\ninline void applyMove(Board &b, int dest, vector<pair<int,int>> *ops) {\n    int x = b.cur;\n    int s = b.stack_id[x];\n    int idx = b.idx[x];\n    int cut = idx + 1;               // move boxes above x\n    int k = b.len[s] - cut;          // number of moved boxes\n\n    int moved[MAXV];\n    for (int i = 0; i < k; ++i) moved[i] = b.st[s][cut + i];\n\n    if (ops) ops->push_back({moved[0], dest + 1});\n\n    // source becomes prefix [0..cut-1], destination appends moved segment\n    b.len[s] = cut;\n    for (int i = 0; i < k; ++i) b.st[dest][b.len[dest]++] = moved[i];\n\n    updatePos(b, dest);\n\n    // x is now the top of source stack, so it can be removed for free\n    removeTop(b, s, ops);\n\n    // more free removals may become possible\n    flush(b, ops);\n}\n\ninline ll scoreBoard(const Board &b) {\n    ll P = 0;        // bad pairs inside stacks\n    ll T = 0;        // weighted depth of small labels\n    ll topSum = 0;\n    int empties = 0;\n    int maxH = 0;\n\n    for (int s = 0; s < m; ++s) {\n        int h = b.len[s];\n        maxH = max(maxH, h);\n        if (h == 0) {\n            ++empties;\n            continue;\n        }\n        topSum += b.st[s][h - 1];\n        for (int i = 0; i < h; ++i) {\n            int a = b.st[s][i];\n            for (int j = i + 1; j < h; ++j) {\n                if (a < b.st[s][j]) ++P;\n            }\n            int depthFromTop = h - 1 - i;\n            T += 1LL * depthFromTop * (n - a + 1);\n        }\n    }\n\n    // Smaller is better.\n    // P dominates, but we also reward progress and easier future states.\n    return 20000LL * P\n         + T\n         + 10LL * topSum\n         - 5000LL * b.cur\n         - 1000LL * empties\n         + maxH;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    Board b{};\n    b.cur = 1;\n\n    for (int s = 0; s < m; ++s) {\n        int h = n / m;\n        b.len[s] = h;\n        for (int i = 0; i < h; ++i) {\n            cin >> b.st[s][i];\n            b.removed[b.st[s][i]] = 0;\n        }\n    }\n\n    for (int s = 0; s < m; ++s) updatePos(b, s);\n\n    vector<pair<int,int>> ops;\n    ops.reserve(5000);\n\n    // remove everything that is already removable\n    flush(b, &ops);\n\n    while (b.cur <= n) {\n        int s = b.stack_id[b.cur];\n\n        ll bestScore = (1LL << 62);\n        int bestDest = -1;\n\n        for (int d = 0; d < m; ++d) {\n            if (d == s) continue;\n            Board tmp = b;\n            applyMove(tmp, d, nullptr);\n            ll sc = scoreBoard(tmp);\n            if (sc < bestScore || (sc == bestScore && (bestDest == -1 || d < bestDest))) {\n                bestScore = sc;\n                bestDest = d;\n            }\n        }\n\n        applyMove(b, bestDest, &ops);\n\n        if ((int)ops.size() > 5000) {\n            // Should not happen with this strategy, but keep the output legal.\n            break;\n        }\n    }\n\n    for (auto [v, i] : ops) {\n        cout << v << ' ' << i << '\\n';\n    }\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to, dir;\n};\n\nstatic const int DR[4] = {-1, 1, 0, 0};\nstatic const int DC[4] = {0, 0, -1, 1};\nstatic const int REV[4] = {1, 0, 3, 2};\nstatic const char CH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Cand {\n    int id;\n    long double proxy;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n\n    int TOT = N * N;\n    auto id = [&](int r, int c) { return r * N + c; };\n    auto rc = [&](int x) { return pair<int,int>{x / N, x % N}; };\n\n    vector<int> d(TOT);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> d[id(i, j)];\n        }\n    }\n\n    vector<array<int,4>> nxt(TOT);\n    for (int i = 0; i < TOT; ++i) nxt[i].fill(-1);\n\n    vector<vector<Edge>> adj(TOT);\n    auto add_edge = [&](int u, int vtx, int dir_uv, int dir_vu) {\n        adj[u].push_back({vtx, dir_uv});\n        adj[vtx].push_back({u, dir_vu});\n        nxt[u][dir_uv] = vtx;\n        nxt[vtx][dir_vu] = u;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                int vtx = id(i + 1, j);\n                add_edge(u, vtx, 1, 0); // D / U\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                int vtx = id(i, j + 1);\n                add_edge(u, vtx, 3, 2); // R / L\n            }\n        }\n    }\n\n    vector<long long> cellScore(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        long long s = d[u];\n        for (auto e : adj[u]) s += d[e.to];\n        cellScore[u] = s;\n    }\n\n    vector<vector<Edge>> sortedNbr = adj;\n    for (int u = 0; u < TOT; ++u) {\n        sort(sortedNbr[u].begin(), sortedNbr[u].end(), [&](const Edge& a, const Edge& b) {\n            if (cellScore[a.to] != cellScore[b.to]) return cellScore[a.to] > cellScore[b.to];\n            if (d[a.to] != d[b.to]) return d[a.to] > d[b.to];\n            return a.to < b.to;\n        });\n    }\n\n    // BFS from origin for candidate selection and path reconstruction\n    vector<int> dist0(TOT, -1), par0(TOT, -1), pdir0(TOT, -1), order0;\n    queue<int> q;\n    dist0[0] = 0;\n    par0[0] = 0;\n    q.push(0);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        order0.push_back(u);\n        for (auto e : sortedNbr[u]) {\n            int vtx = e.to;\n            if (dist0[vtx] == -1) {\n                dist0[vtx] = dist0[u] + 1;\n                par0[vtx] = u;\n                pdir0[vtx] = e.dir;\n                q.push(vtx);\n            }\n        }\n    }\n\n    vector<vector<int>> pathFrom0(TOT);\n    for (int t = 0; t < TOT; ++t) {\n        vector<int> p;\n        int x = t;\n        while (x != 0) {\n            p.push_back(pdir0[x]);\n            x = par0[x];\n        }\n        reverse(p.begin(), p.end());\n        pathFrom0[t] = move(p);\n    }\n\n    vector<Cand> ranked;\n    ranked.reserve(TOT);\n    for (int u = 0; u < TOT; ++u) {\n        long double proxy = (long double)cellScore[u] / (dist0[u] + 1);\n        ranked.push_back({u, proxy});\n    }\n    sort(ranked.begin(), ranked.end(), [&](const Cand& a, const Cand& b) {\n        if (fabsl(a.proxy - b.proxy) > 1e-18L) return a.proxy > b.proxy;\n        if (cellScore[a.id] != cellScore[b.id]) return cellScore[a.id] > cellScore[b.id];\n        if (d[a.id] != d[b.id]) return d[a.id] > d[b.id];\n        return a.id < b.id;\n    });\n\n    auto add_unique = [&](vector<int>& vec, int x) {\n        for (int y : vec) if (y == x) return;\n        vec.push_back(x);\n    };\n\n    // Root candidates: origin + top few by proxy\n    vector<int> rootIds;\n    rootIds.push_back(0);\n    for (int i = 0; i < min(4, (int)ranked.size()); ++i) {\n        if (ranked[i].id != 0) add_unique(rootIds, ranked[i].id);\n    }\n\n    // Loop candidates: top few by proxy (excluding origin)\n    vector<int> loopIds;\n    for (int i = 0; i < (int)ranked.size() && (int)loopIds.size() < 5; ++i) {\n        if (ranked[i].id != 0) add_unique(loopIds, ranked[i].id);\n    }\n\n    // Prepare root-specific coverage vectors\n    struct RootData {\n        int root;\n        vector<int> cov;\n    };\n    vector<RootData> roots;\n\n    for (int root : rootIds) {\n        vector<int> par(TOT, -1), pdir(TOT, -1), order;\n        vector<vector<pair<int,int>>> children(TOT);\n        queue<int> qq;\n        par[root] = root;\n        qq.push(root);\n\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            order.push_back(u);\n            for (auto e : sortedNbr[u]) {\n                int vtx = e.to;\n                if (par[vtx] == -1) {\n                    par[vtx] = u;\n                    pdir[vtx] = e.dir;\n                    children[u].push_back({vtx, e.dir});\n                    qq.push(vtx);\n                }\n            }\n        }\n\n        vector<long long> sub(TOT);\n        for (int u = 0; u < TOT; ++u) sub[u] = d[u];\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int u = order[i];\n            if (u != root) sub[par[u]] += sub[u];\n        }\n\n        for (int u = 0; u < TOT; ++u) {\n            sort(children[u].begin(), children[u].end(), [&](const auto& A, const auto& B) {\n                if (sub[A.first] != sub[B.first]) return sub[A.first] < sub[B.first];\n                if (d[A.first] != d[B.first]) return d[A.first] < d[B.first];\n                return A.first < B.first;\n            });\n        }\n\n        vector<int> cov;\n        cov.reserve((int)pathFrom0[root].size() * 2 + 2 * (TOT - 1));\n        for (int dir : pathFrom0[root]) cov.push_back(dir);\n\n        auto dfs_emit = [&](auto&& self, int u) -> void {\n            for (auto [vtx, dir] : children[u]) {\n                cov.push_back(dir);\n                self(self, vtx);\n                cov.push_back(REV[dir]);\n            }\n        };\n        dfs_emit(dfs_emit, root);\n\n        for (auto it = pathFrom0[root].rbegin(); it != pathFrom0[root].rend(); ++it) {\n            cov.push_back(REV[*it]);\n        }\n\n        roots.push_back({root, move(cov)});\n    }\n\n    struct LoopData {\n        int id;\n        vector<int> rt; // roundtrip from origin to id and back\n    };\n    vector<LoopData> loops;\n    for (int lid : loopIds) {\n        vector<int> rt = pathFrom0[lid];\n        for (auto it = pathFrom0[lid].rbegin(); it != pathFrom0[lid].rend(); ++it) rt.push_back(REV[*it]);\n        if (!rt.empty()) loops.push_back({lid, move(rt)});\n    }\n\n    const int LIMIT = 100000;\n\n    auto better = [&]( __int128 s1, int l1, __int128 s2, int l2 ) -> bool {\n        return s1 * (__int128)l2 < s2 * (__int128)l1;\n    };\n\n    bool hasBest = false;\n    __int128 bestSum = 0;\n    int bestLen = 1;\n    string bestRoute;\n\n    auto evaluate = [&](const vector<int>& rt, const vector<int>& cov, int M) {\n        long long len = (long long)cov.size() + (long long)M * (long long)rt.size();\n        if (len > LIMIT) return;\n\n        vector<int> first(TOT, -1), last(TOT, -1);\n        vector<long long> part(TOT, 0);\n        string route;\n        route.reserve((size_t)len);\n\n        int cur = 0, t = 0;\n        auto apply = [&](int dir) {\n            route.push_back(CH[dir]);\n            cur = nxt[cur][dir];\n            ++t;\n            if (first[cur] == -1) {\n                first[cur] = last[cur] = t;\n            } else {\n                int gap = t - last[cur];\n                part[cur] += 1LL * gap * (gap - 1) / 2;\n                last[cur] = t;\n            }\n        };\n\n        for (int rep = 0; rep < M; ++rep) {\n            for (int dir : rt) apply(dir);\n        }\n        for (int dir : cov) apply(dir);\n\n        __int128 total = 0;\n        for (int c = 0; c < TOT; ++c) {\n            if (first[c] == -1) return; // should not happen\n            int gap = first[c] + t - last[c];\n            part[c] += 1LL * gap * (gap - 1) / 2;\n            total += (__int128)part[c] * (__int128)d[c];\n        }\n\n        if (!hasBest || better(total, t, bestSum, bestLen)) {\n            hasBest = true;\n            bestSum = total;\n            bestLen = t;\n            bestRoute = move(route);\n        }\n    };\n\n    auto start = chrono::steady_clock::now();\n\n    for (const auto& rootData : roots) {\n        const vector<int>& cov = rootData.cov;\n        int covLen = (int)cov.size();\n\n        for (const auto& loopData : loops) {\n            const vector<int>& rt = loopData.rt;\n            if (rt.empty()) continue;\n            int loopLen = (int)rt.size();\n            int maxM = (LIMIT - covLen) / loopLen;\n            if (maxM < 0) continue;\n\n            vector<int> Ms = {0, 1, maxM / 4, maxM / 2, maxM};\n            sort(Ms.begin(), Ms.end());\n            Ms.erase(unique(Ms.begin(), Ms.end()), Ms.end());\n\n            for (int M : Ms) {\n                if (M < 0) continue;\n                evaluate(rt, cov, M);\n                if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count() > 1850) {\n                    break;\n                }\n            }\n            if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count() > 1850) {\n                break;\n            }\n        }\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count() > 1850) {\n            break;\n        }\n    }\n\n    // Fallback: baseline DFS from origin if somehow no candidate chosen\n    if (!hasBest) {\n        // This should practically never happen.\n        bestRoute = \"\";\n        auto& cov = roots[0].cov;\n        bestRoute.reserve(cov.size());\n        for (int dir : cov) bestRoute.push_back(CH[dir]);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nstatic constexpr int MAXNODES = 405;   // 200 initial + 199 merges\nstatic constexpr int CELLS = 225;\nstatic constexpr int INF = 1e9;\nstatic constexpr ull BASE1 = 911382323ULL;\nstatic constexpr ull BASE2 = 972663749ULL;\n\nstruct FastRng {\n    ull x;\n    explicit FastRng(ull seed) : x(seed) {}\n    ull next() {\n        ull z = (x += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n};\n\nstruct HStr {\n    string s;\n    int len = 0;\n    vector<ull> h1, h2;\n};\n\nint N, M, si, sj;\nvector<string> words;\n\nint distCell[CELLS][CELLS];\nint mindist[26][26];\nvector<int> cellsByChar[26];\n\nvector<ull> pw1, pw2;\n\ninline pair<ull, ull> subHash(const HStr& t, int l, int r) {\n    return {\n        t.h1[r] - t.h1[l] * pw1[r - l],\n        t.h2[r] - t.h2[l] * pw2[r - l]\n    };\n}\n\nHStr buildHS(const string& s) {\n    HStr t;\n    t.s = s;\n    t.len = (int)s.size();\n    t.h1.assign(t.len + 1, 0);\n    t.h2.assign(t.len + 1, 0);\n    for (int i = 0; i < t.len; i++) {\n        ull x = (ull)(s[i] - 'A' + 1);\n        t.h1[i + 1] = t.h1[i] * BASE1 + x;\n        t.h2[i + 1] = t.h2[i] * BASE2 + x;\n    }\n    return t;\n}\n\nint overlapHash(const HStr& a, const HStr& b) {\n    int lo = 0, hi = min(a.len, b.len);\n    while (lo < hi) {\n        int mid = (lo + hi + 1) >> 1;\n        if (subHash(a, a.len - mid, a.len) == subHash(b, 0, mid)) lo = mid;\n        else hi = mid - 1;\n    }\n    return lo;\n}\n\nint overlapRaw(const string& a, const string& b) {\n    int hi = min(a.size(), b.size());\n    for (int k = hi; k >= 0; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[(int)a.size() - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nvector<HStr> baseNodes;\nint baseOv[MAXNODES][MAXNODES];\n\nstring concatCandidate(bool reverseOrder) {\n    string s;\n    s.reserve(5 * M);\n    if (!reverseOrder) {\n        for (auto& w : words) s += w;\n    } else {\n        for (int i = M - 1; i >= 0; --i) s += words[i];\n    }\n    return s;\n}\n\nstring greedyCandidate(int alpha, ull seed) {\n    FastRng rng(seed);\n\n    vector<HStr> nodes = baseNodes;\n    nodes.reserve(MAXNODES);\n\n    static int ov[MAXNODES][MAXNODES];\n    memcpy(ov, baseOv, sizeof(baseOv));\n\n    vector<int> active;\n    active.reserve(MAXNODES);\n    for (int i = 0; i < M; i++) active.push_back(i);\n\n    while (active.size() > 1) {\n        long long bestScore = LLONG_MIN;\n        int bestMerged = INT_MAX;\n        int ca = -1, cb = -1;\n        ull cnt = 0;\n\n        for (int a : active) {\n            for (int b : active) {\n                if (a == b) continue;\n                int o = ov[a][b];\n                int mergedLen = nodes[a].len + nodes[b].len - o;\n\n                int boundary = 0;\n                if (o < nodes[b].len) {\n                    boundary = mindist[nodes[a].s.back() - 'A'][nodes[b].s[o] - 'A'];\n                }\n\n                long long score = 1LL * alpha * o - boundary;\n\n                if (score > bestScore || (score == bestScore && mergedLen < bestMerged)) {\n                    bestScore = score;\n                    bestMerged = mergedLen;\n                    ca = a;\n                    cb = b;\n                    cnt = 1;\n                } else if (score == bestScore && mergedLen == bestMerged) {\n                    ++cnt;\n                    if (rng.next() % cnt == 0) {\n                        ca = a;\n                        cb = b;\n                    }\n                }\n            }\n        }\n\n        int o = ov[ca][cb];\n        string ns;\n        ns.reserve(nodes[ca].len + nodes[cb].len - o);\n        ns += nodes[ca].s;\n        ns.append(nodes[cb].s.begin() + o, nodes[cb].s.end());\n\n        int nid = (int)nodes.size();\n        nodes.push_back(buildHS(ns));\n\n        vector<int> nxt;\n        nxt.reserve(active.size() - 1);\n        for (int id : active) {\n            if (id != ca && id != cb) nxt.push_back(id);\n        }\n\n        for (int id : nxt) {\n            ov[nid][id] = overlapHash(nodes[nid], nodes[id]);\n            ov[id][nid] = overlapHash(nodes[id], nodes[nid]);\n        }\n        nxt.push_back(nid);\n        active.swap(nxt);\n    }\n\n    return nodes[active[0]].s;\n}\n\nstruct SolveResult {\n    long long cost;\n    vector<int> path; // cell indices\n};\n\nSolveResult solveTyping(const string& s) {\n    int L = (int)s.size();\n    vector<array<int16_t, CELLS>> par(L);\n\n    vector<int> dp(CELLS, INF), ndp(CELLS, INF);\n    int start = si * N + sj;\n    dp[start] = 0;\n\n    for (int i = 0; i < L; i++) {\n        fill(ndp.begin(), ndp.end(), INF);\n        par[i].fill(-1);\n\n        int c = s[i] - 'A';\n        for (int q : cellsByChar[c]) {\n            int best = INF, bestp = -1;\n            for (int p = 0; p < CELLS; p++) {\n                if (dp[p] >= INF) continue;\n                int cand = dp[p] + distCell[p][q] + 1;\n                if (cand < best) {\n                    best = cand;\n                    bestp = p;\n                }\n            }\n            ndp[q] = best;\n            par[i][q] = (int16_t)bestp;\n        }\n        dp.swap(ndp);\n    }\n\n    int lastC = s.back() - 'A';\n    int end = -1, best = INF;\n    for (int q : cellsByChar[lastC]) {\n        if (dp[q] < best) {\n            best = dp[q];\n            end = q;\n        }\n    }\n\n    vector<int> path(L);\n    int cur = end;\n    for (int i = L - 1; i >= 0; i--) {\n        path[i] = cur;\n        cur = par[i][cur];\n    }\n\n    return {best, move(path)};\n}\n\nbool validCandidate(const string& cand) {\n    for (const string& w : words) {\n        if (cand.find(w) == string::npos) return false;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    cin >> si >> sj;\n    words.resize(M);\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n    for (int i = 0; i < M; i++) cin >> words[i];\n\n    // Precompute cells and Manhattan distances.\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int idx = i * N + j;\n            int c = grid[i][j] - 'A';\n            cellsByChar[c].push_back(idx);\n        }\n    }\n\n    for (int a = 0; a < CELLS; a++) {\n        int x1 = a / N, y1 = a % N;\n        for (int b = 0; b < CELLS; b++) {\n            int x2 = b / N, y2 = b % N;\n            distCell[a][b] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    for (int c = 0; c < 26; c++) {\n        for (int d = 0; d < 26; d++) mindist[c][d] = 1e9;\n    }\n    for (int a = 0; a < CELLS; a++) {\n        int ca = grid[a / N][a % N] - 'A';\n        for (int b = 0; b < CELLS; b++) {\n            int cb = grid[b / N][b % N] - 'A';\n            mindist[ca][cb] = min(mindist[ca][cb], distCell[a][b]);\n        }\n    }\n\n    // Powers for hashing.\n    int MAXP = 6005;\n    pw1.assign(MAXP + 1, 0);\n    pw2.assign(MAXP + 1, 0);\n    pw1[0] = 1;\n    pw2[0] = 1;\n    for (int i = 0; i < MAXP; i++) {\n        pw1[i + 1] = pw1[i] * BASE1;\n        pw2[i + 1] = pw2[i] * BASE2;\n    }\n\n    // Base nodes and initial overlap matrix.\n    baseNodes.resize(M);\n    for (int i = 0; i < M; i++) baseNodes[i] = buildHS(words[i]);\n\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i == j) baseOv[i][j] = 0;\n            else baseOv[i][j] = overlapRaw(words[i], words[j]);\n        }\n    }\n\n    vector<string> candidates;\n    candidates.push_back(concatCandidate(false));\n    candidates.push_back(concatCandidate(true));\n\n    // Several greedy variants.\n    vector<pair<int, ull>> greedyModes = {\n        {1000, 1},\n        {1000, 2},\n        {1000, 3},\n        {1000, 4},\n        {20,   5},\n        {5,    6},\n        {1,    7},\n        {0,    8},\n    };\n\n    for (auto [alpha, seed] : greedyModes) {\n        candidates.push_back(greedyCandidate(alpha, seed));\n    }\n\n    long long bestCost = (1LL << 60);\n    vector<int> bestPath;\n\n    for (const string& cand : candidates) {\n        if (!validCandidate(cand)) continue;\n        auto res = solveTyping(cand);\n        if (res.cost < bestCost) {\n            bestCost = res.cost;\n            bestPath = move(res.path);\n        }\n    }\n\n    // Fallback (should never be needed).\n    if (bestPath.empty()) {\n        auto res = solveTyping(concatCandidate(false));\n        bestPath = move(res.path);\n    }\n\n    for (int idx : bestPath) {\n        cout << idx / N << ' ' << idx % N << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Block {\n    vector<pair<int,int>> cells;\n};\n\nint N, M;\ndouble eps;\n\nvector<vector<int>> revealed;   // -1 = not drilled, otherwise exact value\nvector<vector<bool>> is_pos;\n\nstatic inline double transformed_estimate(double avg_raw, int k, double eps) {\n    return (avg_raw - k * eps) / (1.0 - 2.0 * eps);\n}\n\nvoid drill_cell(int i, int j) {\n    if (revealed[i][j] != -1) return;\n    cout << \"q 1 \" << i << ' ' << j << '\\n' << flush;\n    int v;\n    cin >> v;\n    revealed[i][j] = v;\n    if (v > 0) is_pos[i][j] = true;\n}\n\ndouble query_block_estimate(const vector<pair<int,int>>& cells, int reps) {\n    int k = (int)cells.size();\n    long double sum_raw = 0;\n    for (int t = 0; t < reps; ++t) {\n        cout << \"q \" << k;\n        for (auto [i, j] : cells) {\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << '\\n' << flush;\n\n        int resp;\n        cin >> resp;\n        sum_raw += resp;\n    }\n    double avg_raw = (double)(sum_raw / reps);\n    return transformed_estimate(avg_raw, k, eps);\n}\n\nvector<pair<int,int>> build_segments(int n, int first_len) {\n    vector<pair<int,int>> segs;\n    int s = 0;\n    if (s < n) {\n        int e = min(n, s + first_len);\n        segs.push_back({s, e});\n        s = e;\n    }\n    while (s < n) {\n        int e = min(n, s + 4);\n        segs.push_back({s, e});\n        s = e;\n    }\n    return segs;\n}\n\nvector<Block> build_blocks(int n, int first_len) {\n    auto rows = build_segments(n, first_len);\n    auto cols = build_segments(n, first_len);\n    vector<Block> blocks;\n    for (auto [r1, r2] : rows) {\n        for (auto [c1, c2] : cols) {\n            Block b;\n            for (int i = r1; i < r2; ++i) {\n                for (int j = c1; j < c2; ++j) {\n                    b.cells.push_back({i, j});\n                }\n            }\n            blocks.push_back(move(b));\n        }\n    }\n    return blocks;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> eps;\n\n    // Read prior info about shapes (unused in this heuristic).\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        for (int t = 0; t < d; ++t) {\n            int i, j;\n            cin >> i >> j;\n        }\n    }\n\n    revealed.assign(N, vector<int>(N, -1));\n    is_pos.assign(N, vector<bool>(N, false));\n\n    vector<Block> blocks;\n    {\n        auto b0 = build_blocks(N, 4); // regular partition\n        auto b1 = build_blocks(N, 2); // shifted partition\n        blocks.insert(blocks.end(), b0.begin(), b0.end());\n        blocks.insert(blocks.end(), b1.begin(), b1.end());\n    }\n\n    // Process larger blocks first so overlap helps reduce later work.\n    sort(blocks.begin(), blocks.end(),\n         [](const Block& a, const Block& b) {\n             return a.cells.size() > b.cells.size();\n         });\n\n    const int DIRECT_DRILL_LIMIT = 8;   // small blocks are drilled directly\n    const int QUERY_REPS = 4;           // repeated noisy estimates\n    const double POS_THR = 0.20;        // estimated sum threshold to drill\n\n    for (const auto& block : blocks) {\n        vector<pair<int,int>> pending;\n        pending.reserve(block.cells.size());\n        for (auto [i, j] : block.cells) {\n            if (revealed[i][j] == -1) pending.push_back({i, j});\n        }\n        if (pending.empty()) continue;\n\n        if ((int)pending.size() <= DIRECT_DRILL_LIMIT) {\n            for (auto [i, j] : pending) {\n                drill_cell(i, j);\n            }\n            continue;\n        }\n\n        double est = query_block_estimate(pending, QUERY_REPS);\n        if (est >= POS_THR) {\n            for (auto [i, j] : pending) {\n                drill_cell(i, j);\n            }\n        }\n    }\n\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (is_pos[i][j]) ans.push_back({i, j});\n        }\n    }\n\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) {\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << '\\n' << flush;\n\n    int ok;\n    cin >> ok;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) cin >> a[d][k];\n    }\n\n    const int S = W; // 1000\n    const int H = W; // 1000\n    const long long INF = (1LL << 62);\n\n    auto sid = [&](int s, int h) -> size_t {\n        return (size_t)s * (H + 1) + h;\n    };\n    auto cid = [&](int i, int s, int h) -> size_t {\n        return ((size_t)i * (S + 1) + s) * (H + 1) + h;\n    };\n\n    // cost[k][h] = total shortage cost over all days if strip k has height h\n    vector<vector<long long>> cost(N, vector<long long>(H + 1, 0));\n    for (int k = 0; k < N; ++k) {\n        for (int h = 1; h <= H; ++h) {\n            long long area = 1LL * W * h;\n            long long shortage = 0;\n            for (int d = 0; d < D; ++d) {\n                if (a[d][k] > area) shortage += (long long)a[d][k] - area;\n            }\n            cost[k][h] = shortage * 100LL;\n        }\n    }\n\n    // DP layers\n    vector<long long> prev((S + 1) * (H + 1), INF), cur((S + 1) * (H + 1), INF);\n\n    // parent choice for reconstruction:\n    // parent[i][s][h] = previous height used before strip i-1, for state (i,s,h)\n    vector<uint16_t> parent((size_t)(N + 1) * (S + 1) * (H + 1), 0);\n\n    // First strip\n    int firstMax = S - (N - 1); // leave at least 1 for each remaining strip\n    for (int h = 1; h <= firstMax; ++h) {\n        prev[sid(h, h)] = cost[0][h];\n        parent[cid(1, h, h)] = 0;\n    }\n\n    // Transition\n    for (int i = 2; i <= N; ++i) {\n        fill(cur.begin(), cur.end(), INF);\n\n        int prevMinSum = i - 1;\n        int prevMaxSum = S - (N - (i - 1));\n        int curMaxSum = S - (N - i);\n\n        array<long long, 1001> prefVal;\n        array<uint16_t, 1001> prefArg;\n\n        for (int sp = prevMinSum; sp <= prevMaxSum; ++sp) {\n            long long best = INF;\n            uint16_t besth = 0;\n\n            prefVal[0] = INF;\n            prefArg[0] = 0;\n\n            for (int h = 1; h <= H; ++h) {\n                long long v = prev[sid(sp, h)];\n                if (v < best) {\n                    best = v;\n                    besth = (uint16_t)h;\n                }\n                prefVal[h] = best;\n                prefArg[h] = besth;\n            }\n\n            int maxh = min(H, curMaxSum - sp);\n            for (int h = 1; h <= maxh; ++h) {\n                if (prefVal[h] >= INF) continue;\n                int s = sp + h;\n                long long cand = prefVal[h] + cost[i - 1][h];\n                size_t idx = sid(s, h);\n                if (cand < cur[idx]) {\n                    cur[idx] = cand;\n                    parent[cid(i, s, h)] = prefArg[h];\n                }\n            }\n        }\n\n        swap(prev, cur);\n    }\n\n    // Find best final height\n    long long bestCost = INF;\n    int lastH = 1;\n    for (int h = 1; h <= H; ++h) {\n        long long v = prev[sid(S, h)];\n        if (v < bestCost) {\n            bestCost = v;\n            lastH = h;\n        }\n    }\n\n    // Reconstruct heights\n    vector<int> heights(N);\n    int s = S;\n    int h = lastH;\n    for (int i = N; i >= 1; --i) {\n        heights[i - 1] = h;\n        if (i > 1) {\n            uint16_t ph = parent[cid(i, s, h)];\n            s -= h;\n            h = (int)ph;\n        }\n    }\n\n    // Build fixed rectangles: N horizontal strips, same every day\n    vector<array<int,4>> rect(N);\n    int y = 0;\n    for (int k = 0; k < N; ++k) {\n        rect[k] = {0, y, W, y + heights[k]};\n        y += heights[k];\n    }\n\n    // Output the same layout for every day\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [x0, y0, x1, y1] = rect[k];\n            cout << x0 << ' ' << y0 << ' ' << x1 << ' ' << y1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr ll MOD = 998244353LL;\nstatic constexpr int H = 9;\nstatic constexpr int W = 9;\nstatic constexpr int CELLS = 81;\nstatic constexpr int S = 3;\nstatic constexpr int POS = H - S + 1;   // 7\nstatic constexpr int TOP = 5;\n\nstruct Action {\n    int m = -1, p = -1, q = -1;\n    array<int, CELLS> add{};   // contribution on each cell (0 if unaffected)\n    array<int, 9> cells{};     // the 9 affected cells\n    array<int, 9> vals{};      // stamp values on those cells\n};\n\nstruct Result {\n    array<int, CELLS> cur{};\n    ll score = 0;\n    vector<int> seq;           // action ids, ACTIONS means no-op\n};\n\nint N, M, K;\nint ACTIONS;\n\nvector<array<array<int, S>, S>> stamps;\nvector<Action> acts;\narray<int, CELLS> initBoard{};\nll initScore = 0;\n\ninline ll calc_score(const array<int, CELLS>& b) {\n    ll s = 0;\n    for (int x : b) s += x;\n    return s;\n}\n\ninline void apply_action(array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    for (int t = 0; t < 9; ++t) {\n        int c = ac.cells[t];\n        ll x = (ll)board[c] + ac.vals[t];\n        if (x >= MOD) x -= MOD;\n        board[c] = (int)x;\n    }\n}\n\ninline void insertTop(array<pair<ll, int>, TOP>& top, int& topn, ll gain, int id) {\n    if (topn < TOP) {\n        int pos = topn++;\n        while (pos > 0 && top[pos - 1].first < gain) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {gain, id};\n    } else if (gain > top[TOP - 1].first) {\n        int pos = TOP - 1;\n        while (pos > 0 && top[pos - 1].first < gain) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {gain, id};\n    }\n}\n\nResult build_initial(int mode, mt19937_64& rng) {\n    Result res;\n    res.cur = initBoard;\n    res.score = initScore;\n    res.seq.assign(K, ACTIONS);\n\n    for (int step = 0; step < K; ++step) {\n        array<pair<ll, int>, TOP> top;\n        int topn = 0;\n\n        for (int id = 0; id < ACTIONS; ++id) {\n            ll gain = 0;\n            const auto& ac = acts[id];\n            for (int t = 0; t < 9; ++t) {\n                int c = ac.cells[t];\n                int w = ac.vals[t];\n                ll x = res.cur[c];\n                gain += (x >= MOD - w ? (ll)w - MOD : (ll)w);\n            }\n            insertTop(top, topn, gain, id);\n        }\n\n        ll chosenGain = 0;\n        int chosenId = ACTIONS;\n\n        if (mode == 0) {\n            // deterministic, use all K slots\n            chosenId = top[0].second;\n            chosenGain = top[0].first;\n        } else if (mode == 1) {\n            // randomized, use all K slots\n            int pick = ((rng() & 3) != 0 ? 0 : (int)(rng() % topn)); // 75% best\n            chosenId = top[pick].second;\n            chosenGain = top[pick].first;\n        } else if (mode == 2) {\n            // deterministic, stop when no positive gain\n            if (top[0].first <= 0) break;\n            chosenId = top[0].second;\n            chosenGain = top[0].first;\n        } else {\n            // randomized, stop when no positive gain\n            if (top[0].first <= 0) break;\n            int posn = 0;\n            while (posn < topn && top[posn].first > 0) ++posn;\n            int pick = ((rng() & 3) != 0 ? 0 : (int)(rng() % posn)); // 75% best among positive\n            chosenId = top[pick].second;\n            chosenGain = top[pick].first;\n        }\n\n        apply_action(res.cur, chosenId);\n        res.score += chosenGain;\n        res.seq[step] = chosenId;\n    }\n\n    res.score = calc_score(res.cur);\n    return res;\n}\n\nvoid refine(Result& res, int passes, mt19937_64& rng) {\n    vector<int> ord(K);\n    iota(ord.begin(), ord.end(), 0);\n\n    for (int pass = 0; pass < passes; ++pass) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool any = false;\n\n        for (int idx : ord) {\n            int old = res.seq[idx];\n            ll bestDelta = 0;\n            int bestId = old;\n\n            const int* oa = acts[old].add.data();\n\n            for (int id = 0; id <= ACTIONS; ++id) {\n                if (id == old) continue;\n                const int* na = acts[id].add.data();\n\n                ll delta = 0;\n                for (int c = 0; c < CELLS; ++c) {\n                    int a = oa[c], b = na[c];\n                    if (a == b) continue;\n\n                    ll x = (ll)res.cur[c] - a;\n                    if (x < 0) x += MOD;\n                    x += b;\n                    if (x >= MOD) x -= MOD;\n                    delta += x - res.cur[c];\n                }\n\n                if (delta > bestDelta) {\n                    bestDelta = delta;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != old && bestDelta > 0) {\n                const int* na = acts[bestId].add.data();\n                for (int c = 0; c < CELLS; ++c) {\n                    int a = oa[c], b = na[c];\n                    if (a == b) continue;\n\n                    ll x = (ll)res.cur[c] - a;\n                    if (x < 0) x += MOD;\n                    x += b;\n                    if (x >= MOD) x -= MOD;\n                    res.cur[c] = (int)x;\n                }\n                res.score += bestDelta;\n                res.seq[idx] = bestId;\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    res.score = calc_score(res.cur);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n\n    vector<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    stamps.assign(M, {});\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < S; ++i) {\n            for (int j = 0; j < S; ++j) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    ACTIONS = M * POS * POS;\n    acts.assign(ACTIONS + 1, Action{});\n\n    int id = 0;\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < POS; ++p) {\n            for (int q = 0; q < POS; ++q) {\n                Action ac;\n                ac.m = m;\n                ac.p = p;\n                ac.q = q;\n\n                int t = 0;\n                for (int di = 0; di < S; ++di) {\n                    for (int dj = 0; dj < S; ++dj) {\n                        int c = (p + di) * W + (q + dj);\n                        int w = stamps[m][di][dj];\n                        ac.cells[t] = c;\n                        ac.vals[t] = w;\n                        ac.add[c] = w;\n                        ++t;\n                    }\n                }\n                acts[id++] = ac;\n            }\n        }\n    }\n    acts[ACTIONS] = Action{}; // no-op\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            initBoard[i * W + j] = a[i][j];\n        }\n    }\n    initScore = calc_score(initBoard);\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> modes = {0, 1, 2, 3};\n    Result best;\n    best.score = -1;\n\n    for (int mode : modes) {\n        Result cur = build_initial(mode, rng);\n        refine(cur, 2, rng);\n        if (cur.score > best.score) best = std::move(cur);\n    }\n\n    // one more polish on the best candidate\n    refine(best, 1, rng);\n\n    vector<tuple<int, int, int>> ans;\n    ans.reserve(K);\n    for (int id : best.seq) {\n        if (id == ACTIONS) continue;\n        ans.emplace_back(acts[id].m, acts[id].p, acts[id].q);\n    }\n\n    cout << ans.size() << '\\n';\n    for (auto [m, p, q] : ans) {\n        cout << m << ' ' << p << ' ' << q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N; // always 5\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> A[i][j];\n    }\n\n    // Merge the 5 source rows by current front value.\n    struct Node {\n        int val, row, idx;\n        bool operator>(const Node& other) const {\n            if (val != other.val) return val > other.val;\n            if (row != other.row) return row > other.row;\n            return idx > other.idx;\n        }\n    };\n\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    for (int i = 0; i < N; ++i) pq.push({A[i][0], i, 0});\n\n    vector<pair<int,int>> order; // (source row, container value)\n    order.reserve(N * N);\n    while (!pq.empty()) {\n        auto cur = pq.top(); pq.pop();\n        order.push_back({cur.row, cur.val});\n        if (cur.idx + 1 < N) {\n            pq.push({A[cur.row][cur.idx + 1], cur.row, cur.idx + 1});\n        }\n    }\n\n    string big;\n    int x = 0, y = 0; // large crane position\n\n    auto emit = [&](char c) {\n        big.push_back(c);\n    };\n\n    auto move_to = [&](int nx, int ny) {\n        while (y < ny) { emit('R'); ++y; }\n        while (y > ny) { emit('L'); --y; }\n        while (x < nx) { emit('D'); ++x; }\n        while (x > nx) { emit('U'); --x; }\n    };\n\n    for (auto [src_row, val] : order) {\n        // Go to source gate (src_row, 0)\n        move_to(src_row, 0);\n        emit('P');\n\n        // Deliver to correct dispatch gate row = val / N\n        int dst_row = val / N;\n        move_to(dst_row, N - 1);\n        emit('Q');\n    }\n\n    int T = (int)big.size();\n    vector<string> ans(N, string(T, '.'));\n\n    // Large crane\n    ans[0] = big;\n\n    // Small cranes: bomb on turn 1, then do nothing\n    for (int i = 1; i < N; ++i) {\n        ans[i][0] = 'B';\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct P {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> H[i][j];\n    }\n\n    auto gen_base_cycle = [&](int N) {\n        vector<P> seq;\n        seq.reserve(N * N);\n        seq.push_back({0, 0});\n        for (int y = 1; y < N; ++y) seq.push_back({0, y});\n\n        for (int x = 1; x <= N - 2; ++x) {\n            if (x % 2 == 1) {\n                for (int y = N - 1; y >= 1; --y) seq.push_back({x, y});\n            } else {\n                for (int y = 1; y <= N - 1; ++y) seq.push_back({x, y});\n            }\n        }\n\n        for (int y = N - 1; y >= 0; --y) seq.push_back({N - 1, y});\n        for (int x = N - 2; x >= 1; --x) seq.push_back({x, 0});\n        return seq;\n    };\n\n    auto transform = [&](const P& p, int t) -> P {\n        int x = p.x, y = p.y;\n        switch (t) {\n            case 0: return {x, y};\n            case 1: return {x, N - 1 - y};\n            case 2: return {N - 1 - x, y};\n            case 3: return {N - 1 - x, N - 1 - y};\n            case 4: return {y, x};\n            case 5: return {y, N - 1 - x};\n            case 6: return {N - 1 - y, x};\n            case 7: return {N - 1 - y, N - 1 - x};\n        }\n        return {x, y};\n    };\n\n    vector<P> base = gen_base_cycle(N);\n\n    ll bestCost = (1LL << 60);\n    vector<P> bestSeq;\n    int bestStart = 0;\n\n    auto eval_candidate = [&](vector<P> seq) {\n        int L = (int)seq.size();\n        vector<ll> pref(L + 1, 0);\n        for (int i = 0; i < L; ++i) {\n            pref[i + 1] = pref[i] + H[seq[i].x][seq[i].y];\n        }\n\n        ll mn = pref[0];\n        for (int i = 1; i < L; ++i) mn = min(mn, pref[i]);\n\n        for (int s = 0; s < L; ++s) {\n            if (pref[s] != mn) continue; // valid rotation start\n\n            ll cost = 100LL * (seq[s].x + seq[s].y); // empty move to the start cell\n            ll cur = 0;\n            for (int k = 0; k < L; ++k) {\n                const P& p = seq[(s + k) % L];\n                cur += H[p.x][p.y];\n                if (k + 1 < L) cost += 100 + cur; // move to next cell\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSeq = seq;\n                bestStart = s;\n            }\n        }\n    };\n\n    for (int t = 0; t < 8; ++t) {\n        vector<P> seq;\n        seq.reserve(base.size());\n        for (const auto& p : base) seq.push_back(transform(p, t));\n\n        eval_candidate(seq);\n        reverse(seq.begin(), seq.end());\n        eval_candidate(seq);\n    }\n\n    // Output operations\n    vector<string> ops;\n    ops.reserve(1000);\n\n    auto add_op = [&](const string& s) {\n        ops.push_back(s);\n    };\n\n    // Move empty from (0,0) to the chosen start cell\n    int cx = 0, cy = 0;\n    P startP = bestSeq[bestStart];\n    while (cx < startP.x) {\n        add_op(\"D\");\n        ++cx;\n    }\n    while (cx > startP.x) {\n        add_op(\"U\");\n        --cx;\n    }\n    while (cy < startP.y) {\n        add_op(\"R\");\n        ++cy;\n    }\n    while (cy > startP.y) {\n        add_op(\"L\");\n        --cy;\n    }\n\n    int L = (int)bestSeq.size();\n    for (int step = 0; step < L; ++step) {\n        int idx = (bestStart + step) % L;\n        P p = bestSeq[idx];\n        int h = H[p.x][p.y];\n        if (h > 0) {\n            add_op(\"+\" + to_string(h));\n        } else if (h < 0) {\n            add_op(\"-\" + to_string(-h));\n        }\n\n        if (step + 1 < L) {\n            P q = bestSeq[(bestStart + step + 1) % L];\n            if (q.x == p.x + 1 && q.y == p.y) add_op(\"D\");\n            else if (q.x == p.x - 1 && q.y == p.y) add_op(\"U\");\n            else if (q.x == p.x && q.y == p.y + 1) add_op(\"R\");\n            else if (q.x == p.x && q.y == p.y - 1) add_op(\"L\");\n            else {\n                // Should never happen for our Hamiltonian cycle.\n                // If it does, the output would be invalid, so keep a safe fallback.\n                // But in practice, this branch is unreachable.\n            }\n        }\n    }\n\n    for (const auto& s : ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXM = 15;\n\nstruct Seed {\n    array<int, MAXM> x{};\n    int sum = 0;\n};\n\nstruct Sol {\n    long long arrObj = -(1LL << 60);\n    long long coverage = 0;\n    vector<int> sel;   // original seed ids, size 36\n    vector<int> perm;  // local indices on grid positions 0..35\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    if (!(cin >> N >> M >> T)) return 0;\n\n    int S = 2 * N * (N - 1); // 60\n    int P = N * N;           // 36\n\n    vector<Seed> seeds(S);\n    for (int i = 0; i < S; i++) {\n        int s = 0;\n        for (int j = 0; j < M; j++) {\n            cin >> seeds[i].x[j];\n            s += seeds[i].x[j];\n        }\n        seeds[i].sum = s;\n    }\n\n    // Grid edges\n    vector<pair<int,int>> edges;\n    edges.reserve(S);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if (i + 1 < N) edges.push_back({id, (i + 1) * N + j});\n            if (j + 1 < N) edges.push_back({id, i * N + (j + 1)});\n        }\n    }\n\n    // Cell orders\n    vector<int> posDeg, posSnake;\n    {\n        vector<tuple<int,int,int>> cells;\n        cells.reserve(P);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int deg = (i > 0) + (i + 1 < N) + (j > 0) + (j + 1 < N);\n                int dist = abs(2 * i - (N - 1)) + abs(2 * j - (N - 1));\n                cells.emplace_back(-deg, dist, i * N + j);\n            }\n        }\n        sort(cells.begin(), cells.end());\n        for (auto &t : cells) posDeg.push_back(get<2>(t));\n\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; j++) posSnake.push_back(i * N + j);\n            } else {\n                for (int j = N - 1; j >= 0; j--) posSnake.push_back(i * N + j);\n            }\n        }\n    }\n\n    mt19937 rng(712367821);\n    uniform_real_distribution<double> ur(0.0, 1.0);\n\n    for (int turn = 0; turn < T; turn++) {\n        // Pair scores for all current seeds\n        vector<vector<int>> Wall(S, vector<int>(S, 0));\n        vector<long long> connAll(S, 0);\n        for (int i = 0; i < S; i++) {\n            for (int j = i + 1; j < S; j++) {\n                int w = 0;\n                for (int l = 0; l < M; l++) {\n                    w += max(seeds[i].x[l], seeds[j].x[l]);\n                }\n                Wall[i][j] = Wall[j][i] = w;\n                connAll[i] += w;\n                connAll[j] += w;\n            }\n        }\n\n        vector<long long> baseScore(S);\n        for (int i = 0; i < S; i++) {\n            baseScore[i] = connAll[i] + 20LL * seeds[i].sum;\n        }\n\n        // Candidate A: top by global compatibility\n        vector<int> candA(S);\n        iota(candA.begin(), candA.end(), 0);\n        sort(candA.begin(), candA.end(), [&](int a, int b) {\n            if (baseScore[a] != baseScore[b]) return baseScore[a] > baseScore[b];\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            return a < b;\n        });\n        candA.resize(P);\n\n        // Candidate D: top by sum\n        vector<int> candD(S);\n        iota(candD.begin(), candD.end(), 0);\n        sort(candD.begin(), candD.end(), [&](int a, int b) {\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            if (baseScore[a] != baseScore[b]) return baseScore[a] > baseScore[b];\n            return a < b;\n        });\n        candD.resize(P);\n\n        // Candidate B: greedy coverage + compatibility\n        vector<int> candB;\n        vector<char> usedB(S, 0);\n        array<int, MAXM> bestTrait{};\n        bestTrait.fill(0);\n        for (int cnt = 0; cnt < P; cnt++) {\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < S; i++) if (!usedB[i]) {\n                long long gain = 0;\n                for (int l = 0; l < M; l++) {\n                    if (seeds[i].x[l] > bestTrait[l]) gain += seeds[i].x[l] - bestTrait[l];\n                }\n                long long sc;\n                if (candB.empty()) {\n                    sc = baseScore[i];\n                } else {\n                    long long pairSum = 0;\n                    for (int j : candB) pairSum += Wall[i][j];\n                    long long pairAvg = pairSum / (long long)candB.size();\n                    sc = (long long)seeds[i].sum + gain + pairAvg / 4;\n                }\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            usedB[best] = 1;\n            candB.push_back(best);\n            for (int l = 0; l < M; l++) bestTrait[l] = max(bestTrait[l], seeds[best].x[l]);\n        }\n\n        // Candidate C: top 2 seeds per trait, then greedy fill by compatibility\n        vector<int> candC;\n        vector<char> usedC(S, 0);\n        for (int l = 0; l < M; l++) {\n            vector<int> ord(S);\n            iota(ord.begin(), ord.end(), 0);\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (seeds[a].x[l] != seeds[b].x[l]) return seeds[a].x[l] > seeds[b].x[l];\n                if (baseScore[a] != baseScore[b]) return baseScore[a] > baseScore[b];\n                return a < b;\n            });\n            int taken = 0;\n            for (int id : ord) {\n                if (!usedC[id]) {\n                    usedC[id] = 1;\n                    candC.push_back(id);\n                    if (++taken == 2) break;\n                }\n            }\n        }\n        while ((int)candC.size() < P) {\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < S; i++) if (!usedC[i]) {\n                long long pairSum = 0;\n                for (int j : candC) pairSum += Wall[i][j];\n                long long pairAvg = pairSum / max(1, (int)candC.size());\n                long long sc = baseScore[i] + pairAvg / 8;\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            usedC[best] = 1;\n            candC.push_back(best);\n        }\n\n        // Solve one candidate subset by arranging it on the grid\n        auto solveCandidate = [&](const vector<int>& sel) -> Sol {\n            int s = (int)sel.size(); // always 36\n\n            vector<vector<int>> W(s, vector<int>(s, 0));\n            vector<long long> conn(s, 0);\n            vector<int> sumLocal(s, 0);\n\n            for (int i = 0; i < s; i++) {\n                sumLocal[i] = seeds[sel[i]].sum;\n                for (int j = 0; j < s; j++) {\n                    W[i][j] = Wall[sel[i]][sel[j]];\n                    conn[i] += W[i][j];\n                }\n            }\n\n            long long coverage = 0;\n            for (int l = 0; l < M; l++) {\n                int mx = 0;\n                for (int i = 0; i < s; i++) mx = max(mx, seeds[sel[i]].x[l]);\n                coverage += mx;\n            }\n\n            auto makePerm = [&](const vector<int>& order, const vector<int>& cellOrder) {\n                vector<int> perm(P, -1);\n                for (int t = 0; t < P; t++) perm[cellOrder[t]] = order[t];\n                return perm;\n            };\n\n            auto eval = [&](const vector<int>& perm) -> long long {\n                long long res = 0;\n                for (auto [u, v] : edges) res += W[perm[u]][perm[v]];\n                return res;\n            };\n\n            auto localSearch = [&](vector<int> perm) -> pair<long long, vector<int>> {\n                long long cur = eval(perm);\n                long long best = cur;\n                vector<int> bestPerm = perm;\n\n                uniform_int_distribution<int> distPos(0, P - 1);\n                const int ITER = 4000;\n                for (int it = 0; it < ITER; it++) {\n                    int a = distPos(rng);\n                    int b = distPos(rng);\n                    if (a == b) continue;\n\n                    swap(perm[a], perm[b]);\n                    long long nv = eval(perm);\n\n                    double temp = 2000.0 * (1.0 - (double)it / (double)ITER) + 1.0;\n                    bool accept = (nv >= cur);\n                    if (!accept) {\n                        double prob = exp((double)(nv - cur) / temp);\n                        if (ur(rng) < prob) accept = true;\n                    }\n\n                    if (accept) {\n                        cur = nv;\n                        if (cur > best) {\n                            best = cur;\n                            bestPerm = perm;\n                        }\n                    } else {\n                        swap(perm[a], perm[b]);\n                    }\n                }\n                return {best, bestPerm};\n            };\n\n            // Start 1: connect order on degree-based positions\n            vector<int> order1(s);\n            iota(order1.begin(), order1.end(), 0);\n            sort(order1.begin(), order1.end(), [&](int a, int b) {\n                if (conn[a] != conn[b]) return conn[a] > conn[b];\n                if (sumLocal[a] != sumLocal[b]) return sumLocal[a] > sumLocal[b];\n                return sel[a] < sel[b];\n            });\n            vector<int> perm1 = makePerm(order1, posDeg);\n            auto [obj1, bestPerm1] = localSearch(perm1);\n\n            // Start 2: greedy chain on snake positions\n            vector<int> order2;\n            vector<char> used2(s, 0);\n            int start = (int)(max_element(conn.begin(), conn.end()) - conn.begin());\n            order2.push_back(start);\n            used2[start] = 1;\n            while ((int)order2.size() < s) {\n                int last = order2.back();\n                int best = -1;\n                long long bestSc = -(1LL << 60);\n                for (int i = 0; i < s; i++) if (!used2[i]) {\n                    long long sc = 1000LL * W[last][i] + conn[i];\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n                used2[best] = 1;\n                order2.push_back(best);\n            }\n            vector<int> perm2 = makePerm(order2, posSnake);\n            auto [obj2, bestPerm2] = localSearch(perm2);\n\n            // Start 3: random order on degree-based positions\n            vector<int> order3(s);\n            iota(order3.begin(), order3.end(), 0);\n            shuffle(order3.begin(), order3.end(), rng);\n            vector<int> perm3 = makePerm(order3, posDeg);\n            auto [obj3, bestPerm3] = localSearch(perm3);\n\n            Sol ret;\n            ret.arrObj = obj1;\n            ret.perm = bestPerm1;\n            if (obj2 > ret.arrObj) {\n                ret.arrObj = obj2;\n                ret.perm = bestPerm2;\n            }\n            if (obj3 > ret.arrObj) {\n                ret.arrObj = obj3;\n                ret.perm = bestPerm3;\n            }\n            ret.coverage = coverage;\n            ret.sel = sel;\n            return ret;\n        };\n\n        Sol solA = solveCandidate(candA);\n        Sol solB = solveCandidate(candB);\n        Sol solC = solveCandidate(candC);\n        Sol solD = solveCandidate(candD);\n\n        double remRatio = (T <= 1 ? 0.0 : (double)(T - 1 - turn) / (double)(T - 1));\n        double alpha = 6.0 * sqrt(max(0.0, remRatio));\n\n        auto fitness = [&](const Sol& s) -> double {\n            return (double)s.arrObj + alpha * (double)s.coverage;\n        };\n\n        Sol bestSol = solA;\n        double bestFit = fitness(solA);\n        auto consider = [&](const Sol& s) {\n            double f = fitness(s);\n            if (f > bestFit) {\n                bestFit = f;\n                bestSol = s;\n            }\n        };\n        consider(solB);\n        consider(solC);\n        consider(solD);\n\n        // Output the chosen grid\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int pos = i * N + j;\n                int localIdx = bestSol.perm[pos];\n                int seedId = bestSol.sel[localIdx];\n                cout << seedId << (j + 1 == N ? '\\n' : ' ');\n            }\n        }\n        cout.flush();\n\n        // Read the next generation\n        for (int i = 0; i < S; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstruct Edge {\n    int to;\n    char mv, rot;\n};\n\nstruct BfsRes {\n    int bestDist = -1;\n    vector<int> goals;          // all goal states with minimal distance\n    vector<int> prev;\n    vector<char> pmv, prot;\n};\n\nstatic const int DX4[4] = {0, 1, 0, -1};   // R, D, L, U\nstatic const int DY4[4] = {1, 0, -1, 0};\nstatic const char MOVEC[5] = {'.', 'U', 'D', 'L', 'R'};\nstatic const int MDX[5] = {0, -1, 1, 0, 0};\nstatic const int MDY[5] = {0, 0, 0, -1, 1};\nstatic const char ROTC[3] = {'.', 'L', 'R'};\nstatic const int RDELTA[3] = {0, 3, 1}; // L = -1 mod 4, R = +1 mod 4\n\nint N, M, V;\nvector<string> S, T;\n\nint SSTATE;\nvector<vector<Edge>> adj;\nvector<int> rootX, rootY, dirD;\n\n// cellGoals[c] = all states whose fingertip is on cell c\nvector<vector<int>> cellGoals;\n\ninline int cellId(int x, int y) { return x * N + y; }\ninline int stateId(int x, int y, int d) { return ((x * N + y) << 2) | d; }\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\ninline int orientDiff(int d1, int d2) {\n    int diff = abs(d1 - d2);\n    return min(diff, 4 - diff);\n}\n\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    if (n == 0) return {};\n    const int INF = 1e9;\n\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, 0);\n        do {\n            used[j0] = 1;\n            int i0 = p[j0], j1 = 0;\n            int delta = INF;\n            for (int j = 1; j <= n; j++) if (!used[j]) {\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n\n    vector<int> ans(n);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nBfsRes bfs_collect(int start, const vector<int>& goals) {\n    const int INF = 1e9;\n    vector<int> dist(SSTATE, -1), prev(SSTATE, -1);\n    vector<char> pmv(SSTATE, '.'), prot(SSTATE, '.');\n    vector<char> isGoal(SSTATE, 0);\n    for (int g : goals) isGoal[g] = 1;\n\n    vector<int> q;\n    q.reserve(SSTATE);\n    q.push_back(start);\n    dist[start] = 0;\n\n    int best = -1;\n    vector<int> found;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        int du = dist[u];\n        if (best != -1 && du > best) break;\n\n        if (isGoal[u]) {\n            if (best == -1) best = du;\n            if (du == best) found.push_back(u);\n            continue;\n        }\n        if (best != -1) continue; // do not expand nodes beyond minimal goal distance\n\n        for (const auto& e : adj[u]) {\n            if (dist[e.to] == -1) {\n                dist[e.to] = du + 1;\n                prev[e.to] = u;\n                pmv[e.to] = e.mv;\n                prot[e.to] = e.rot;\n                q.push_back(e.to);\n            }\n        }\n    }\n\n    BfsRes res;\n    res.bestDist = best;\n    res.goals = std::move(found);\n    res.prev = std::move(prev);\n    res.pmv = std::move(pmv);\n    res.prot = std::move(prot);\n    return res;\n}\n\nint chooseGoalByRef(const vector<int>& goals, const vector<int>& refGoals, int startState) {\n    auto score = [&](int g) {\n        int refDist;\n        if (!refGoals.empty()) {\n            refDist = 1e9;\n            for (int r : refGoals) {\n                refDist = min(refDist, manhattan(rootX[g], rootY[g], rootX[r], rootY[r]));\n            }\n        } else {\n            refDist = manhattan(rootX[g], rootY[g], rootX[startState], rootY[startState]);\n        }\n        int startDist = manhattan(rootX[g], rootY[g], rootX[startState], rootY[startState]);\n        int od = orientDiff(dirD[g], dirD[startState]);\n        return tuple<int, int, int>(refDist, startDist, od);\n    };\n\n    int best = goals[0];\n    auto bestScore = score(best);\n    for (int i = 1; i < (int)goals.size(); i++) {\n        auto sc = score(goals[i]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            best = goals[i];\n        }\n    }\n    return best;\n}\n\nvector<int> buildPathStates(const BfsRes& res, int start, int goal) {\n    vector<int> seq;\n    for (int v = goal; v != start; v = res.prev[v]) seq.push_back(v);\n    reverse(seq.begin(), seq.end());\n    return seq;\n}\n\nint rootDistToCellFromRootPos(int rx, int ry, const vector<int>& goals) {\n    int best = 1e9;\n    for (int g : goals) {\n        best = min(best, manhattan(rx, ry, rootX[g], rootY[g]));\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> V;\n    S.assign(N, string());\n    T.assign(N, string());\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, tgt;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool a = (S[i][j] == '1');\n            bool b = (T[i][j] == '1');\n            if (a && !b) src.push_back({i, j});\n            if (b && !a) tgt.push_back({i, j});\n        }\n    }\n\n    int K = (int)src.size();\n    // Overlaps are already correct; remaining counts must match.\n    if ((int)tgt.size() != K) {\n        // Should not happen, but keep safe.\n        int mn = min((int)src.size(), (int)tgt.size());\n        src.resize(mn);\n        tgt.resize(mn);\n        K = mn;\n    }\n\n    vector<int> assign;\n    if (K > 0) {\n        vector<vector<int>> cost(K, vector<int>(K));\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < K; j++) {\n                cost[i][j] = manhattan(src[i].x, src[i].y, tgt[j].x, tgt[j].y);\n            }\n        }\n        assign = hungarian(cost);\n    }\n\n    struct Pair {\n        Pos s, t;\n    };\n    vector<Pair> pairs;\n    pairs.reserve(K);\n    for (int i = 0; i < K; i++) {\n        pairs.push_back({src[i], tgt[assign[i]]});\n    }\n\n    // Greedy order by closeness of current root to a possible pickup-root.\n    vector<int> order;\n    order.reserve(K);\n    vector<int> rem(K);\n    iota(rem.begin(), rem.end(), 0);\n\n    int curRootX = N / 2;\n    int curRootY = max(0, N / 2 - 1); // initial tip points to the center\n    while (!rem.empty()) {\n        int bestPos = 0;\n        tuple<int, int, int, int> bestScore = {1e9, 1e9, 1e9, 1e9}; // pickDist, src-tgt, sx, sy\n        for (int pos = 0; pos < (int)rem.size(); pos++) {\n            int idx = rem[pos];\n            auto [s, t] = pairs[idx];\n            int pickDist = 1e9;\n            for (int d = 0; d < 4; d++) {\n                int rx = s.x - DX4[d];\n                int ry = s.y - DY4[d];\n                if (!inside(rx, ry)) continue;\n                pickDist = min(pickDist, manhattan(curRootX, curRootY, rx, ry));\n            }\n            int st = manhattan(s.x, s.y, t.x, t.y);\n            auto sc = make_tuple(pickDist, st, s.x, s.y);\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestPos = pos;\n            }\n        }\n        int chosen = rem[bestPos];\n        order.push_back(chosen);\n        rem[bestPos] = rem.back();\n        rem.pop_back();\n    }\n\n    // Precompute state graph and goal states for each cell.\n    SSTATE = N * N * 4;\n    adj.assign(SSTATE, {});\n    rootX.assign(SSTATE, 0);\n    rootY.assign(SSTATE, 0);\n    dirD.assign(SSTATE, 0);\n    cellGoals.assign(N * N, {});\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            for (int d = 0; d < 4; d++) {\n                int id = stateId(x, y, d);\n                rootX[id] = x;\n                rootY[id] = y;\n                dirD[id] = d;\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            int cid = cellId(x, y);\n            for (int d = 0; d < 4; d++) {\n                int rx = x - DX4[d];\n                int ry = y - DY4[d];\n                if (inside(rx, ry)) {\n                    cellGoals[cid].push_back(stateId(rx, ry, d));\n                }\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            for (int d = 0; d < 4; d++) {\n                int id = stateId(x, y, d);\n                for (int m = 0; m < 5; m++) {\n                    for (int r = 0; r < 3; r++) {\n                        if (m == 0 && r == 0) continue;\n                        int nx = x + MDX[m];\n                        int ny = y + MDY[m];\n                        if (!inside(nx, ny)) continue;\n                        int nd = (d + RDELTA[r]) & 3;\n                        int to = stateId(nx, ny, nd);\n                        adj[id].push_back({to, MOVEC[m], ROTC[r]});\n                    }\n                }\n            }\n        }\n    }\n\n    // Output tree: a single fingertip.\n    cout << 2 << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n    cout << curRootX << ' ' << curRootY << '\\n';\n\n    auto emitTurn = [&](char mv, char rot, char act) {\n        char buf[4] = {mv, rot, '.', act};\n        cout.write(buf, 4);\n        cout.put('\\n');\n    };\n\n    int curState = stateId(curRootX, curRootY, 0); // initial direction: right\n\n    for (int qi = 0; qi < K; qi++) {\n        int idx = order[qi];\n        auto [sp, tp] = pairs[idx];\n        int sCell = cellId(sp.x, sp.y);\n        int tCell = cellId(tp.x, tp.y);\n\n        const auto& sourceGoals = cellGoals[sCell];\n        const auto& targetGoals = cellGoals[tCell];\n\n        // Step 1: reach a pickup state for the source.\n        BfsRes srcRes = bfs_collect(curState, sourceGoals);\n        if (srcRes.goals.empty()) continue; // should not happen\n\n        // Try all minimal pickup states; choose the one whose drop path is shortest.\n        int bestP = srcRes.goals[0];\n        int bestQ = -1;\n        BfsRes bestTRes;\n        tuple<int, int, int> bestScore = {1e9, 1e9, 1e9}; // target dist, ref dist, start dist\n\n        const vector<int>* nextRefGoals = nullptr;\n        vector<int> emptyRef;\n        if (qi + 1 < K) {\n            int nextIdx = order[qi + 1];\n            auto [ns, nt] = pairs[nextIdx];\n            nextRefGoals = &cellGoals[cellId(ns.x, ns.y)];\n        } else {\n            nextRefGoals = &emptyRef;\n        }\n\n        for (int p : srcRes.goals) {\n            BfsRes tRes = bfs_collect(p, targetGoals);\n            if (tRes.goals.empty()) continue;\n\n            int q = chooseGoalByRef(tRes.goals, *nextRefGoals, p);\n\n            int refDist;\n            if (!nextRefGoals->empty()) {\n                refDist = 1e9;\n                for (int r : *nextRefGoals) {\n                    refDist = min(refDist, manhattan(rootX[q], rootY[q], rootX[r], rootY[r]));\n                }\n            } else {\n                refDist = manhattan(rootX[q], rootY[q], rootX[p], rootY[p]);\n            }\n            int startDist = manhattan(rootX[q], rootY[q], rootX[p], rootY[p]);\n            tuple<int, int, int> sc = {tRes.bestDist, refDist, startDist};\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestP = p;\n                bestQ = q;\n                bestTRes = std::move(tRes);\n            }\n        }\n\n        // Emit path to pickup.\n        {\n            vector<int> seq = buildPathStates(srcRes, curState, bestP);\n            if (seq.empty()) {\n                emitTurn('.', '.', 'P');\n            } else {\n                for (int i = 0; i < (int)seq.size(); i++) {\n                    char act = (i + 1 == (int)seq.size() ? 'P' : '.');\n                    int st = seq[i];\n                    int prev = (i == 0 ? curState : seq[i - 1]);\n                    // Determine the edge action by comparing with predecessor.\n                    // We stored only states, so recover action from res.prev.\n                    int v = st;\n                    char mv = srcRes.pmv[v];\n                    char rot = srcRes.prot[v];\n                    emitTurn(mv, rot, act);\n                }\n            }\n        }\n        curState = bestP;\n\n        // Emit path to target and release.\n        {\n            vector<int> seq = buildPathStates(bestTRes, curState, bestQ);\n            if (seq.empty()) {\n                emitTurn('.', '.', 'P');\n            } else {\n                for (int i = 0; i < (int)seq.size(); i++) {\n                    char act = (i + 1 == (int)seq.size() ? 'P' : '.');\n                    int st = seq[i];\n                    char mv = bestTRes.pmv[st];\n                    char rot = bestTRes.prot[st];\n                    emitTurn(mv, rot, act);\n                }\n            }\n        }\n        curState = bestQ;\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int MAXC = 100000;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Rect {\n    int sum;\n    ll area;\n    int x1, y1, x2, y2;\n};\n\nstruct Config {\n    int S;\n    int ox, oy;\n};\n\nstatic void build_axis(int S, int off, vector<int>& st, vector<int>& en) {\n    st.clear();\n    en.clear();\n    st.push_back(0);\n    en.push_back(off - 1);\n    for (int l = off; l <= MAXC; l += S) {\n        st.push_back(l);\n        en.push_back(min(MAXC, l + S - 1));\n    }\n}\n\nstatic int cell_idx(int v, int S, int off) {\n    if (v < off) return 0;\n    return 1 + (v - off) / S;\n}\n\nstatic Rect solve_cfg(int S, int ox, int oy,\n                      const vector<Point>& mackerels,\n                      const vector<Point>& sardines) {\n    vector<int> xs, xe, ys, ye;\n    build_axis(S, ox, xs, xe);\n    build_axis(S, oy, ys, ye);\n\n    int nx = (int)xs.size();\n    int ny = (int)ys.size();\n\n    vector<int> w(nx * ny, 0);\n\n    auto add_point = [&](const Point& p, int delta) {\n        int ix = cell_idx(p.x, S, ox);\n        int iy = cell_idx(p.y, S, oy);\n        w[ix * ny + iy] += delta;\n    };\n\n    for (const auto& p : mackerels) add_point(p, +1);\n    for (const auto& p : sardines) add_point(p, -1);\n\n    Rect best{INT_MIN, -1, 0, 0, 0, 0};\n    vector<int> col(ny, 0);\n\n    for (int top = 0; top < nx; ++top) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < nx; ++bot) {\n            const int* row = &w[bot * ny];\n            for (int c = 0; c < ny; ++c) col[c] += row[c];\n\n            int cur = 0;\n            int left = 0;\n            for (int c = 0; c < ny; ++c) {\n                if (cur < 0) {\n                    cur = col[c];\n                    left = c;\n                } else {\n                    cur += col[c];\n                }\n\n                ll area = 1LL * (xe[bot] - xs[top]) * (ye[c] - ys[left]);\n                if (cur > best.sum || (cur == best.sum && area > best.area)) {\n                    best = {cur, area, xs[top], ys[left], xe[bot], ye[c]};\n                }\n            }\n        }\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<Point> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) cin >> sardines[i].x >> sardines[i].y;\n\n    // Phase-shifted grids to reduce boundary bias.\n    vector<Config> cfgs = {\n        {500, 100, 100},\n        {500, 225, 225},\n        {500, 350, 350},\n        {500, 475, 475},\n        {500, 100, 225},\n        {500, 225, 350},\n        {500, 350, 475},\n        {500, 475, 100},\n    };\n\n    Rect ans{INT_MIN, -1, 0, 0, MAXC, MAXC};\n    for (const auto& cfg : cfgs) {\n        Rect r = solve_cfg(cfg.S, cfg.ox, cfg.oy, mackerels, sardines);\n        if (r.sum > ans.sum || (r.sum == ans.sum && r.area > ans.area)) {\n            ans = r;\n        }\n    }\n\n    // Fallback (should not be needed): full box is always valid.\n    if (ans.x2 <= ans.x1 || ans.y2 <= ans.y1) {\n        ans = {0, 1LL * MAXC * MAXC, 0, 0, MAXC, MAXC};\n    }\n\n    cout << 4 << '\\n';\n    cout << ans.x1 << ' ' << ans.y1 << '\\n';\n    cout << ans.x2 << ' ' << ans.y1 << '\\n';\n    cout << ans.x2 << ' ' << ans.y2 << '\\n';\n    cout << ans.x1 << ' ' << ans.y2 << '\\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, b;\n    char d;\n};\n\nstruct State {\n    ll W, H;\n    int prev_i, prev_idx;\n};\n\nstruct Cand {\n    vector<Op> ops;\n    ll estW = 0, estH = 0;\n    string sig;\n};\n\nstruct Family {\n    ll bestScore = (1LL << 62);\n    vector<pair<int, Cand>> layers; // layer id, candidate\n    int mode = 0;\n    int axis = 0; // 0=row, 1=col\n};\n\nstatic string serialize_ops(const vector<Op>& ops) {\n    string s;\n    s.reserve(ops.size() * 16);\n    for (auto &op : ops) {\n        s += to_string(op.p);\n        s.push_back(',');\n        s += to_string(op.r);\n        s.push_back(',');\n        s.push_back(op.d);\n        s.push_back(',');\n        s += to_string(op.b);\n        s.push_back(';');\n    }\n    return s;\n}\n\nstatic int choose_state_by_weight(const vector<State>& front, ll a, ll b) {\n    int idx = 0;\n    __int128 best = (__int128)a * front[0].W + (__int128)b * front[0].H;\n    for (int i = 1; i < (int)front.size(); ++i) {\n        __int128 cur = (__int128)a * front[i].W + (__int128)b * front[i].H;\n        if (cur < best || (cur == best && (front[i].W < front[idx].W ||\n                                          (front[i].W == front[idx].W && front[i].H < front[idx].H)))) {\n            best = cur;\n            idx = i;\n        }\n    }\n    return idx;\n}\n\nstatic Cand build_candidate_from_state(\n    const vector<vector<State>>& dp,\n    int idx,\n    const vector<int>& rot,\n    const vector<ll>& sh,   // DP height dimension, used to pick anchors\n    int axis,               // 0=row, 1=col\n    int N\n) {\n    vector<pair<int,int>> groups;\n    int cur_i = N, cur_idx = idx;\n    while (cur_i > 0) {\n        const State& s = dp[cur_i][cur_idx];\n        groups.push_back({s.prev_i, cur_i});\n        cur_idx = s.prev_idx;\n        cur_i = s.prev_i;\n    }\n    reverse(groups.begin(), groups.end());\n\n    vector<Op> ops;\n    ops.reserve(N);\n    int prev_anchor = -1;\n\n    for (int g = 0; g < (int)groups.size(); ++g) {\n        int l = groups[g].first;\n        int r = groups[g].second;\n\n        int anchor = l;\n        for (int i = l + 1; i < r; ++i) {\n            if (sh[i] > sh[anchor]) anchor = i;\n        }\n\n        if (axis == 0) { // row packing\n            if (g == 0) ops.push_back({l, rot[l], -1, 'U'});\n            else ops.push_back({l, rot[l], prev_anchor, 'L'});\n            for (int i = l + 1; i < r; ++i) {\n                ops.push_back({i, rot[i], i - 1, 'U'});\n            }\n        } else { // column packing\n            if (g == 0) ops.push_back({l, rot[l], -1, 'U'});\n            else ops.push_back({l, rot[l], prev_anchor, 'U'});\n            for (int i = l + 1; i < r; ++i) {\n                ops.push_back({i, rot[i], i - 1, 'L'});\n            }\n        }\n\n        prev_anchor = anchor;\n    }\n\n    Cand c;\n    c.ops = move(ops);\n    c.estW = dp[N][idx].W;\n    c.estH = dp[N][idx].H;\n    c.sig = serialize_ops(c.ops);\n    return c;\n}\n\nstatic Family build_family(\n    const vector<ll>& baseW,\n    const vector<ll>& baseH,\n    int mode,\n    int axis\n) {\n    int N = (int)baseW.size();\n    vector<ll> ow(N), oh(N);\n    vector<int> rot(N);\n\n    auto make_oriented = [&](int i, bool width_min) {\n        if (width_min) {\n            if (baseW[i] <= baseH[i]) {\n                ow[i] = baseW[i];\n                oh[i] = baseH[i];\n                rot[i] = 0;\n            } else {\n                ow[i] = baseH[i];\n                oh[i] = baseW[i];\n                rot[i] = 1;\n            }\n        } else {\n            if (baseW[i] >= baseH[i]) {\n                ow[i] = baseW[i];\n                oh[i] = baseH[i];\n                rot[i] = 0;\n            } else {\n                ow[i] = baseH[i];\n                oh[i] = baseW[i];\n                rot[i] = 1;\n            }\n        }\n    };\n\n    for (int i = 0; i < N; ++i) {\n        if (mode == 0) {\n            make_oriented(i, true);  // width-min\n        } else if (mode == 1) {\n            make_oriented(i, false); // height-min\n        } else if (mode == 2) {\n            if (i & 1) make_oriented(i, false);\n            else make_oriented(i, true);\n        } else {\n            if (i & 1) make_oriented(i, true);\n            else make_oriented(i, false);\n        }\n    }\n\n    vector<ll> sw(N), sh(N);\n    if (axis == 0) { // row packing\n        sw = ow;\n        sh = oh;\n    } else { // column packing = row packing on transposed sizes\n        sw = oh;\n        sh = ow;\n    }\n\n    vector<ll> pref(N + 1, 0);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + sw[i];\n\n    vector<vector<ll>> mx(N, vector<ll>(N, 0));\n    for (int l = 0; l < N; ++l) {\n        ll cur = 0;\n        for (int r = l; r < N; ++r) {\n            cur = max(cur, sh[r]);\n            mx[l][r] = cur;\n        }\n    }\n\n    vector<vector<State>> dp(N + 1);\n    dp[0].push_back({0, 0, -1, -1});\n\n    for (int i = 1; i <= N; ++i) {\n        vector<State> cand;\n        for (int j = 0; j < i; ++j) {\n            ll rowW = pref[i] - pref[j];\n            ll rowH = mx[j][i - 1];\n            const auto& vec = dp[j];\n            cand.reserve(cand.size() + vec.size());\n            for (int idx = 0; idx < (int)vec.size(); ++idx) {\n                const State& s = vec[idx];\n                cand.push_back({max(s.W, rowW), s.H + rowH, j, idx});\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const State& a, const State& b) {\n            if (a.W != b.W) return a.W < b.W;\n            return a.H < b.H;\n        });\n\n        vector<State> tmp;\n        tmp.reserve(cand.size());\n        for (auto &s : cand) {\n            if (tmp.empty() || s.W != tmp.back().W) {\n                tmp.push_back(s);\n            } else {\n                if (s.H < tmp.back().H) tmp.back() = s;\n            }\n        }\n\n        ll bestH = (1LL << 62);\n        dp[i].clear();\n        for (auto &s : tmp) {\n            if (s.H < bestH) {\n                dp[i].push_back(s);\n                bestH = s.H;\n            }\n        }\n    }\n\n    const auto& front = dp[N];\n    int m = (int)front.size();\n\n    int idx_best = 0;\n    ll bestSum = front[0].W + front[0].H;\n    for (int i = 1; i < m; ++i) {\n        ll cur = front[i].W + front[i].H;\n        if (cur < bestSum) {\n            bestSum = cur;\n            idx_best = i;\n        }\n    }\n\n    // Selected layers:\n    // 0: best by W+H\n    // 1: 2W+H\n    // 2: W+2H\n    // 3: 4W+H\n    // 4: W+4H\n    // 5: minimum W\n    // 6: minimum H\n    struct Req { int layer; int type; ll a, b; };\n    vector<Req> reqs = {\n        {0, 0, 1, 1},\n        {1, 1, 2, 1},\n        {2, 2, 1, 2},\n        {3, 3, 4, 1},\n        {4, 4, 1, 4},\n        {5, 5, 0, 0},\n        {6, 6, 0, 0},\n    };\n\n    unordered_set<string> localSeen;\n    Family fam;\n    fam.bestScore = bestSum;\n    fam.mode = mode;\n    fam.axis = axis;\n\n    auto build_and_add = [&](int idx, int layer) {\n        if (idx < 0 || idx >= m) return;\n        Cand c = build_candidate_from_state(dp, idx, rot, sh, axis, N);\n        if (localSeen.insert(c.sig).second) {\n            fam.layers.push_back({layer, move(c)});\n        }\n    };\n\n    build_and_add(idx_best, 0);\n    build_and_add(choose_state_by_weight(front, 2, 1), 1);\n    build_and_add(choose_state_by_weight(front, 1, 2), 2);\n    build_and_add(choose_state_by_weight(front, 4, 1), 3);\n    build_and_add(choose_state_by_weight(front, 1, 4), 4);\n    build_and_add(0, 5);\n    build_and_add(m - 1, 6);\n\n    return fam;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    ll sigma;\n    cin >> N >> T >> sigma;\n\n    vector<ll> w(N), h(N);\n    for (int i = 0; i < N; ++i) cin >> w[i] >> h[i];\n\n    vector<Family> families;\n    families.reserve(8);\n\n    for (int mode = 0; mode < 4; ++mode) {\n        for (int axis = 0; axis < 2; ++axis) {\n            families.push_back(build_family(w, h, mode, axis));\n        }\n    }\n\n    sort(families.begin(), families.end(), [](const Family& a, const Family& b) {\n        if (a.bestScore != b.bestScore) return a.bestScore < b.bestScore;\n        if (a.axis != b.axis) return a.axis < b.axis;\n        return a.mode < b.mode;\n    });\n\n    vector<Cand> all;\n    all.reserve(64);\n    unordered_set<string> globalSeen;\n    globalSeen.reserve(128);\n\n    // Layer order: best, 2W+H, W+2H, 4W+H, W+4H, minW, minH\n    for (int layer = 0; layer <= 6; ++layer) {\n        for (auto &fam : families) {\n            for (auto &pr : fam.layers) {\n                if (pr.first != layer) continue;\n                if (globalSeen.insert(pr.second.sig).second) {\n                    all.push_back(move(pr.second));\n                }\n            }\n        }\n    }\n\n    if (all.empty()) {\n        // Fallback: one row with original order\n        Cand c;\n        vector<Op> ops;\n        ops.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (i == 0) ops.push_back({i, 0, -1, 'U'});\n            else ops.push_back({i, 0, i - 1, 'U'});\n        }\n        c.ops = move(ops);\n        c.sig = serialize_ops(c.ops);\n        all.push_back(move(c));\n    }\n\n    int used = min<int>(T, (int)all.size());\n    for (int t = 0; t < used; ++t) {\n        const auto& c = all[t];\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm;\n    }\n\n    for (int t = used; t < T; ++t) {\n        const auto& c = all[0];\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm;\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Key4 {\n    int a, b, c, d;\n    bool operator<(const Key4& o) const {\n        if (a != o.a) return a < o.a;\n        if (b != o.b) return b < o.b;\n        if (c != o.c) return c < o.c;\n        return d < o.d;\n    }\n};\n\nstruct Result {\n    long long score = -1;\n    vector<int> parent;\n};\n\nstatic int morton_code(int x, int y) {\n    int z = 0;\n    for (int i = 0; i < 10; ++i) {\n        z |= ((x >> i) & 1) << (2 * i);\n        z |= ((y >> i) & 1) << (2 * i + 1);\n    }\n    return z;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    vector<pair<int,int>> edges(M);\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    vector<int> X(N), Y(N);\n    for (int i = 0; i < N; ++i) cin >> X[i] >> Y[i];\n\n    vector<int> deg(N);\n    for (int i = 0; i < N; ++i) deg[i] = (int)adj[i].size();\n\n    vector<int> mort(N);\n    for (int i = 0; i < N; ++i) mort[i] = morton_code(X[i], Y[i]);\n\n    vector<Key4> keyA(N), keyB(N), keyD(N);\n    for (int i = 0; i < N; ++i) {\n        keyA[i] = {A[i], -deg[i], mort[i], i}; // beauty asc, degree desc, spatial\n        keyB[i] = {A[i], mort[i], deg[i], i};   // beauty asc, spatial, degree asc\n        keyD[i] = {A[i], deg[i], mort[i], i};   // beauty asc, degree asc (for DFS child order desc)\n    }\n\n    auto make_order_asc = [&](const vector<Key4>& key) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int x, int y) {\n            return key[x] < key[y];\n        });\n        return ord;\n    };\n\n    auto eval_order = [&](const vector<int>& ord) -> Result {\n        vector<int> parent(N, -2), depth(N, -1);\n        vector<long long> pot(N);\n        for (int i = 0; i < N; ++i) {\n            pot[i] = 1LL * A[i] * 1000 + deg[i];\n        }\n\n        long long score = 0;\n        for (int v : ord) {\n            int best = -1;\n            int bestDepth = -1;\n            long long bestPot = -1;\n            for (int u : adj[v]) {\n                if (depth[u] == -1 || depth[u] >= H) continue;\n                if (depth[u] > bestDepth ||\n                    (depth[u] == bestDepth && (pot[u] > bestPot || (pot[u] == bestPot && u < best)))) {\n                    best = u;\n                    bestDepth = depth[u];\n                    bestPot = pot[u];\n                }\n            }\n            if (best == -1) {\n                parent[v] = -1;\n                depth[v] = 0;\n            } else {\n                parent[v] = best;\n                depth[v] = depth[best] + 1;\n            }\n            score += 1LL * (depth[v] + 1) * A[v];\n        }\n        return {score, move(parent)};\n    };\n\n    // Candidate 1: order by (A, -deg, morton)\n    auto ord1 = make_order_asc(keyA);\n    Result res1 = eval_order(ord1);\n\n    // Candidate 2: order by (A, morton, deg)\n    auto ord2 = make_order_asc(keyB);\n    Result res2 = eval_order(ord2);\n\n    // Candidate 3: connected best-first order from the minimum prio seed.\n    // prio = low beauty, high degree first\n    vector<long long> prio(N);\n    for (int i = 0; i < N; ++i) prio[i] = 1LL * A[i] * 1000 - 200LL * deg[i];\n\n    vector<int> ord3;\n    ord3.reserve(N);\n    vector<char> inq(N, 0), vis(N, 0);\n    using T = tuple<long long, int, int>; // prio, morton, id\n    priority_queue<T, vector<T>, greater<T>> pq;\n\n    int seed = 0;\n    for (int i = 1; i < N; ++i) {\n        if (make_tuple(prio[i], mort[i], i) < make_tuple(prio[seed], mort[seed], seed)) seed = i;\n    }\n    pq.emplace(prio[seed], mort[seed], seed);\n    inq[seed] = 1;\n\n    while (!pq.empty()) {\n        auto [p, m, v] = pq.top();\n        pq.pop();\n        if (vis[v]) continue;\n        vis[v] = 1;\n        ord3.push_back(v);\n        for (int to : adj[v]) {\n            if (!inq[to]) {\n                inq[to] = 1;\n                pq.emplace(prio[to], mort[to], to);\n            }\n        }\n    }\n    Result res3 = eval_order(ord3);\n\n    // Candidate 4: depth-limited DFS forest\n    vector<int> roots = ord1;\n    vector<vector<int>> adjChild = adj;\n    sort(roots.begin(), roots.end(), [&](int x, int y) { return keyA[x] < keyA[y]; });\n    for (int v = 0; v < N; ++v) {\n        sort(adjChild[v].begin(), adjChild[v].end(), [&](int x, int y) {\n            return keyD[y] < keyD[x]; // descending by (A, deg, morton, id)\n        });\n    }\n\n    vector<int> parent4(N, -2), depth4(N, -1);\n    vector<char> vis4(N, 0);\n    long long score4 = 0;\n\n    auto dfs = [&](auto&& self, int u, int p, int d) -> void {\n        vis4[u] = 1;\n        parent4[u] = p;\n        depth4[u] = d;\n        score4 += 1LL * (d + 1) * A[u];\n        if (d == H) return;\n        for (int to : adjChild[u]) {\n            if (!vis4[to]) self(self, to, u, d + 1);\n        }\n    };\n\n    for (int r : roots) {\n        if (!vis4[r]) dfs(dfs, r, -1, 0);\n    }\n    Result res4{score4, move(parent4)};\n\n    Result best = res1;\n    if (res2.score > best.score) best = move(res2);\n    if (res3.score > best.score) best = move(res3);\n    if (res4.score > best.score) best = move(res4);\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << best.parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cand {\n    char dir;   // L/R/U/D\n    int idx;    // row or column index\n    int len;    // number of shifts on one side\n    uint64_t mask; // Oni covered by this strip\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    vector<vector<int>> oniId(N, vector<int>(N, -1));\n    vector<pair<int,int>> oniPos;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'x') {\n                oniId[i][j] = (int)oniPos.size();\n                oniPos.push_back({i, j});\n            }\n        }\n    }\n    int M = (int)oniPos.size(); // should be 40\n\n    vector<int> rowFirstF(N, N), rowLastF(N, -1);\n    vector<int> colFirstF(N, N), colLastF(N, -1);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'o') {\n                rowFirstF[i] = min(rowFirstF[i], j);\n                rowLastF[i] = max(rowLastF[i], j);\n                colFirstF[j] = min(colFirstF[j], i);\n                colLastF[j] = max(colLastF[j], i);\n            }\n        }\n    }\n\n    vector<Cand> cands;\n    auto addCand = [&](char dir, int idx, int len, uint64_t mask) {\n        if (len > 0 && mask) cands.push_back({dir, idx, len, mask});\n    };\n\n    // Row-based strips\n    for (int i = 0; i < N; ++i) {\n        // Left prefixes: lengths 1..first Fukunokami position\n        uint64_t mask = 0;\n        for (int len = 1; len <= rowFirstF[i]; ++len) {\n            int b = oniId[i][len - 1];\n            if (b != -1) {\n                mask |= (1ULL << b);\n                addCand('L', i, len, mask);\n            }\n        }\n        // Right prefixes (suffixes): lengths 1..distance to last Fukunokami from right\n        mask = 0;\n        int rmax = (rowLastF[i] == -1 ? N : N - 1 - rowLastF[i]);\n        for (int len = 1; len <= rmax; ++len) {\n            int col = N - len;\n            int b = oniId[i][col];\n            if (b != -1) {\n                mask |= (1ULL << b);\n                addCand('R', i, len, mask);\n            }\n        }\n    }\n\n    // Column-based strips\n    for (int j = 0; j < N; ++j) {\n        // Upward prefixes\n        uint64_t mask = 0;\n        for (int len = 1; len <= colFirstF[j]; ++len) {\n            int b = oniId[len - 1][j];\n            if (b != -1) {\n                mask |= (1ULL << b);\n                addCand('U', j, len, mask);\n            }\n        }\n        // Downward prefixes (suffixes)\n        mask = 0;\n        int bmax = (colLastF[j] == -1 ? N : N - 1 - colLastF[j]);\n        for (int len = 1; len <= bmax; ++len) {\n            int row = N - len;\n            int b = oniId[row][j];\n            if (b != -1) {\n                mask |= (1ULL << b);\n                addCand('D', j, len, mask);\n            }\n        }\n    }\n\n    // Deduplicate identical coverage masks, keeping the shortest strip.\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.len != b.len) return a.len < b.len;\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.idx < b.idx;\n    });\n    vector<Cand> uniq;\n    for (auto &c : cands) {\n        if (uniq.empty() || uniq.back().mask != c.mask) uniq.push_back(c);\n    }\n    cands.swap(uniq);\n\n    uint64_t fullMask = (M == 64 ? ~0ULL : ((1ULL << M) - 1ULL));\n\n    auto cleanup = [&](vector<int> sel) -> vector<int> {\n        vector<int> cnt(M, 0);\n        for (int id : sel) {\n            uint64_t m = cands[id].mask;\n            while (m) {\n                int b = __builtin_ctzll(m);\n                cnt[b]++;\n                m &= (m - 1);\n            }\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            sort(sel.begin(), sel.end(), [&](int a, int b) {\n                if (cands[a].len != cands[b].len) return cands[a].len > cands[b].len;\n                return a < b;\n            });\n\n            vector<int> nxt;\n            nxt.reserve(sel.size());\n            for (int id : sel) {\n                bool removable = true;\n                uint64_t m = cands[id].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    if (cnt[b] <= 1) {\n                        removable = false;\n                        break;\n                    }\n                    m &= (m - 1);\n                }\n\n                if (removable) {\n                    uint64_t m2 = cands[id].mask;\n                    while (m2) {\n                        int b = __builtin_ctzll(m2);\n                        cnt[b]--;\n                        m2 &= (m2 - 1);\n                    }\n                    changed = true;\n                } else {\n                    nxt.push_back(id);\n                }\n            }\n            sel.swap(nxt);\n        }\n        return sel;\n    };\n\n    auto runGreedyLinear = [&](int K) -> pair<vector<int>, int> {\n        uint64_t uncovered = fullMask;\n        vector<char> used(cands.size(), false);\n        vector<int> sel;\n\n        while (uncovered) {\n            int best = -1;\n            long long bestScore = LLONG_MIN;\n            int bestNew = -1;\n            int bestLen = INT_MAX;\n\n            for (int id = 0; id < (int)cands.size(); ++id) {\n                if (used[id]) continue;\n                uint64_t nm = cands[id].mask & uncovered;\n                if (!nm) continue;\n                int newCnt = __builtin_popcountll(nm);\n                long long score = 1LL * K * newCnt - cands[id].len;\n\n                if (best == -1 ||\n                    score > bestScore ||\n                    (score == bestScore && (newCnt > bestNew ||\n                                            (newCnt == bestNew && cands[id].len < bestLen)))) {\n                    best = id;\n                    bestScore = score;\n                    bestNew = newCnt;\n                    bestLen = cands[id].len;\n                }\n            }\n\n            if (best == -1) break; // should not happen\n            used[best] = true;\n            sel.push_back(best);\n            uncovered &= ~cands[best].mask;\n        }\n\n        sel = cleanup(sel);\n\n        // Safety fallback: if anything remains uncovered, add minimal-length strips for them.\n        uint64_t cover = 0;\n        for (int id : sel) cover |= cands[id].mask;\n        if (cover != fullMask) {\n            uint64_t rem = fullMask & ~cover;\n            while (rem) {\n                int b = __builtin_ctzll(rem);\n                int choose = -1;\n                int chooseLen = INT_MAX;\n                for (int id = 0; id < (int)cands.size(); ++id) {\n                    if ((cands[id].mask >> b) & 1ULL) {\n                        if (cands[id].len < chooseLen) {\n                            choose = id;\n                            chooseLen = cands[id].len;\n                        }\n                    }\n                }\n                if (choose == -1) break; // should not happen\n                sel.push_back(choose);\n                cover |= cands[choose].mask;\n                rem = fullMask & ~cover;\n            }\n            sel = cleanup(sel);\n        }\n\n        int cost = 0;\n        for (int id : sel) cost += 2 * cands[id].len;\n        return {sel, cost};\n    };\n\n    auto runGreedyRatio = [&]() -> pair<vector<int>, int> {\n        uint64_t uncovered = fullMask;\n        vector<char> used(cands.size(), false);\n        vector<int> sel;\n\n        while (uncovered) {\n            int best = -1;\n            int bestNew = -1;\n            int bestLen = INT_MAX;\n\n            for (int id = 0; id < (int)cands.size(); ++id) {\n                if (used[id]) continue;\n                uint64_t nm = cands[id].mask & uncovered;\n                if (!nm) continue;\n                int newCnt = __builtin_popcountll(nm);\n\n                if (best == -1 ||\n                    1LL * newCnt * bestLen > 1LL * bestNew * cands[id].len ||\n                    (1LL * newCnt * bestLen == 1LL * bestNew * cands[id].len &&\n                     (newCnt > bestNew ||\n                      (newCnt == bestNew && cands[id].len < bestLen)))) {\n                    best = id;\n                    bestNew = newCnt;\n                    bestLen = cands[id].len;\n                }\n            }\n\n            if (best == -1) break;\n            used[best] = true;\n            sel.push_back(best);\n            uncovered &= ~cands[best].mask;\n        }\n\n        sel = cleanup(sel);\n\n        uint64_t cover = 0;\n        for (int id : sel) cover |= cands[id].mask;\n        if (cover != fullMask) {\n            uint64_t rem = fullMask & ~cover;\n            while (rem) {\n                int b = __builtin_ctzll(rem);\n                int choose = -1;\n                int chooseLen = INT_MAX;\n                for (int id = 0; id < (int)cands.size(); ++id) {\n                    if ((cands[id].mask >> b) & 1ULL) {\n                        if (cands[id].len < chooseLen) {\n                            choose = id;\n                            chooseLen = cands[id].len;\n                        }\n                    }\n                }\n                if (choose == -1) break;\n                sel.push_back(choose);\n                cover |= cands[choose].mask;\n                rem = fullMask & ~cover;\n            }\n            sel = cleanup(sel);\n        }\n\n        int cost = 0;\n        for (int id : sel) cost += 2 * cands[id].len;\n        return {sel, cost};\n    };\n\n    vector<int> Ks = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 30, 50};\n\n    vector<int> bestSel;\n    int bestCost = INT_MAX;\n\n    for (int K : Ks) {\n        auto [sel, cost] = runGreedyLinear(K);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestSel = sel;\n        }\n    }\n\n    {\n        auto [sel, cost] = runGreedyRatio();\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestSel = sel;\n        }\n    }\n\n    // Output the selected strips.\n    for (int id : bestSel) {\n        const auto &c = cands[id];\n        char d1, d2;\n        if (c.dir == 'L') d1 = 'L', d2 = 'R';\n        else if (c.dir == 'R') d1 = 'R', d2 = 'L';\n        else if (c.dir == 'U') d1 = 'U', d2 = 'D';\n        else d1 = 'D', d2 = 'U';\n\n        for (int t = 0; t < c.len; ++t) {\n            cout << d1 << ' ' << c.idx << '\\n';\n        }\n        for (int t = 0; t < c.len; ++t) {\n            cout << d2 << ' ' << c.idx << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr int MAXP = 2;\n\nstruct XorShift64 {\n    uint64_t x;\n    explicit XorShift64(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        return (int)(next() % (uint64_t)mod);\n    }\n};\n\nstruct Result {\n    array<array<int, MAXP>, MAXN> succ{};\n    array<int, MAXN> cnt{};\n    array<array<int, MAXP>, MAXN> use{};\n    long long err = (1LL << 60);\n};\n\nint N, L;\narray<int, MAXN> T{};\narray<int, MAXN> quota{};\n\nstatic inline long long sqll(long long x) { return x * x; }\n\nlong long calcScore(\n    int mode,\n    int y,\n    int x,\n    int p,\n    long long rem,\n    int assigned,\n    int q,\n    const array<array<int, MAXP>, MAXN>& succ,\n    XorShift64& rng\n) {\n    long long score = 0;\n    switch (mode) {\n        case 0:\n            score = rem * 1000LL;\n            break;\n        case 1:\n            score = rem * 1000LL - 1500LL * assigned;\n            break;\n        case 2:\n            score = rem * 1000LL - 700LL * 1LL * assigned * assigned;\n            break;\n        case 3:\n            score = rem * 1000LL / (assigned + 1);\n            break;\n        default: {\n            long long d = max(0, assigned - q);\n            score = rem * 1000LL - 2500LL * d * d;\n            break;\n        }\n    }\n\n    // Small penalties to avoid over-concentrating on a single node.\n    if (y == x) {\n        if (mode == 0) score -= 0;\n        else if (mode == 1) score -= 500;\n        else if (mode == 2) score -= 1000;\n        else if (mode == 3) score -= 300;\n        else score -= 700;\n    }\n    if (succ[x][1 - p] == y) {\n        if (mode == 0) score -= 0;\n        else if (mode == 1) score -= 1500;\n        else if (mode == 2) score -= 2500;\n        else if (mode == 3) score -= 1000;\n        else score -= 3000;\n    }\n\n    // Tiny noise for diversification.\n    score += (long long)(rng.next() & 1023ULL) - 511LL;\n    return score;\n}\n\nResult buildCandidate(int mode, uint64_t seed) {\n    Result res;\n    for (int i = 0; i < N; ++i) {\n        res.succ[i][0] = res.succ[i][1] = -1;\n        res.cnt[i] = 0;\n        res.use[i][0] = res.use[i][1] = 0;\n    }\n\n    array<int, MAXN> assigned_to{};\n    assigned_to.fill(0);\n\n    XorShift64 rng(seed);\n    int x = 0;\n\n    for (int step = 0; step < L; ++step) {\n        res.cnt[x]++;\n\n        if (step == L - 1) break;\n\n        int p = res.cnt[x] & 1;\n        int &s = res.succ[x][p];\n        if (s == -1) {\n            // Prefer nodes with positive remaining target.\n            bool hasPositive = false;\n            for (int y = 0; y < N; ++y) {\n                if (T[y] - res.cnt[y] > 0) {\n                    hasPositive = true;\n                    break;\n                }\n            }\n\n            int bestY = 0;\n            long long bestScore = (1LL << 60) * -1;\n            bool initialized = false;\n\n            for (int y = 0; y < N; ++y) {\n                long long rem = (long long)T[y] - res.cnt[y];\n                if (hasPositive && rem <= 0) continue;\n\n                long long sc = calcScore(mode, y, x, p, rem, assigned_to[y], quota[y], res.succ, rng);\n                if (!initialized || sc > bestScore) {\n                    initialized = true;\n                    bestScore = sc;\n                    bestY = y;\n                }\n            }\n\n            // Fallback, should not happen because sum of remaining targets is positive.\n            if (!initialized) bestY = 0;\n\n            s = bestY;\n            assigned_to[bestY]++;\n        }\n\n        res.use[x][p]++;\n        x = s;\n    }\n\n    long long err = 0;\n    for (int i = 0; i < N; ++i) {\n        err += llabs((long long)res.cnt[i] - (long long)T[i]);\n    }\n    res.err = err;\n\n    // Fill any never-used edges safely.\n    for (int i = 0; i < N; ++i) {\n        if (res.succ[i][0] == -1 && res.succ[i][1] == -1) {\n            res.succ[i][0] = res.succ[i][1] = 0;\n        } else if (res.succ[i][0] == -1) {\n            res.succ[i][0] = res.succ[i][1];\n        } else if (res.succ[i][1] == -1) {\n            res.succ[i][1] = res.succ[i][0];\n        }\n    }\n\n    return res;\n}\n\nResult simulateFixed(const array<array<int, MAXP>, MAXN>& succ) {\n    Result res;\n    for (int i = 0; i < N; ++i) {\n        res.succ[i][0] = succ[i][0];\n        res.succ[i][1] = succ[i][1];\n        res.cnt[i] = 0;\n        res.use[i][0] = res.use[i][1] = 0;\n    }\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        res.cnt[x]++;\n        if (step == L - 1) break;\n        int p = res.cnt[x] & 1;\n        res.use[x][p]++;\n        x = res.succ[x][p];\n    }\n\n    long long err = 0;\n    for (int i = 0; i < N; ++i) {\n        err += llabs((long long)res.cnt[i] - (long long)T[i]);\n    }\n    res.err = err;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    // Precompute a small quota used by one of the candidate modes.\n    for (int i = 0; i < N; ++i) {\n        quota[i] = max(1, (T[i] + 2499) / 2500);\n    }\n\n    // Seed derived from the input.\n    uint64_t baseSeed = 1469598103934665603ULL;\n    for (int i = 0; i < N; ++i) {\n        baseSeed ^= (uint64_t)(T[i] + 1);\n        baseSeed *= 1099511628211ULL;\n    }\n\n    auto start = chrono::steady_clock::now();\n    const double GENERATE_LIMIT = 1.55;\n    const double LOCAL_LIMIT = 1.92;\n\n    Result best;\n    best.err = (1LL << 60);\n\n    int iter = 0;\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > GENERATE_LIMIT) break;\n\n        int mode = iter % 5;\n        uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(iter + 1));\n        Result cand = buildCandidate(mode, seed);\n        if (cand.err < best.err) {\n            best = std::move(cand);\n            if (best.err == 0) break;\n        }\n        ++iter;\n    }\n\n    // Small local improvement: change a heavily used edge from an overrepresented\n    // employee to an underrepresented one, and keep only if the score improves.\n    XorShift64 rng(baseSeed ^ 0x123456789abcdefULL);\n    for (int it = 0; it < 20; ++it) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > LOCAL_LIMIT) break;\n        if (best.err == 0) break;\n\n        vector<int> over, under;\n        over.reserve(N);\n        under.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (best.cnt[i] > T[i]) over.push_back(i);\n            else if (best.cnt[i] < T[i]) under.push_back(i);\n        }\n        if (over.empty() || under.empty()) break;\n\n        sort(over.begin(), over.end(), [&](int a, int b) {\n            return (best.cnt[a] - T[a]) > (best.cnt[b] - T[b]);\n        });\n        sort(under.begin(), under.end(), [&](int a, int b) {\n            return (T[a] - best.cnt[a]) > (T[b] - best.cnt[b]);\n        });\n\n        int ov = over[rng.nextInt(min<int>(3, over.size()))];\n        int un = under[rng.nextInt(min<int>(3, under.size()))];\n\n        int bestSrc = -1, bestPar = -1;\n        int bestUse = -1;\n        for (int i = 0; i < N; ++i) {\n            for (int p = 0; p < 2; ++p) {\n                if (best.succ[i][p] == ov) {\n                    if (best.use[i][p] > bestUse) {\n                        bestUse = best.use[i][p];\n                        bestSrc = i;\n                        bestPar = p;\n                    }\n                }\n            }\n        }\n        if (bestSrc == -1) continue;\n\n        int old = best.succ[bestSrc][bestPar];\n        if (old == un) continue;\n\n        best.succ[bestSrc][bestPar] = un;\n        Result cand = simulateFixed(best.succ);\n        if (cand.err < best.err) {\n            best = std::move(cand);\n        } else {\n            best.succ[bestSrc][bestPar] = old;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best.succ[i][0] << ' ' << best.succ[i][1] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ull = unsigned long long;\n\nstatic const int HN = 1 << 15; // enough for coordinates up to 20000\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\n\n// doubled estimated centers: ex = lx+rx, ey = ly+ry\nvector<int> exs, eys;\n\n// estimated squared distances between centers (doubled coordinates)\nvector<vector<int>> est2;\n\n// keys[orient][i]\nvector<vector<ull>> keys;\nvector<vector<int>> cityOrders; // sorted order for each orientation\n\nint bestOrient = 0;\nvector<int> bestGroupOrder;\n\n// assigned cities per original group index\nvector<vector<int>> groupCities;\nvector<vector<pair<int,int>>> groupEdges;\n\nint queries_used = 0;\n\null hilbertOrder(int x, int y) {\n    ull d = 0;\n    for (int s = HN / 2; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += (ull)s * (ull)s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = s - 1 - x;\n                y = s - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\ninline int d2_est(int a, int b) {\n    return est2[a][b];\n}\n\ndouble edge_len_est(int a, int b) {\n    return sqrt((double)d2_est(a, b)) * 0.5; // doubled coordinates => divide by 2\n}\n\ndouble prim_cost_range(const vector<int>& ord, int st, int len) {\n    if (len <= 1) return 0.0;\n    const int INF = 1e9;\n    vector<int> best(len, INF);\n    vector<char> used(len, 0);\n    best[0] = 0;\n    double cost = 0.0;\n    for (int it = 0; it < len; ++it) {\n        int v = -1;\n        for (int i = 0; i < len; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (best[v] != 0) cost += sqrt((double)best[v]) * 0.5;\n        for (int to = 0; to < len; ++to) if (!used[to]) {\n            int w = d2_est(ord[st + v], ord[st + to]);\n            if (w < best[to]) best[to] = w;\n        }\n    }\n    return cost;\n}\n\ndouble prim_cost_vec(const vector<int>& nodes) {\n    return prim_cost_range(nodes, 0, (int)nodes.size());\n}\n\nvector<pair<int,int>> prim_tree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    vector<pair<int,int>> edges;\n    if (k <= 1) return edges;\n    const int INF = 1e9;\n    vector<int> best(k, INF), parent(k, -1);\n    vector<char> used(k, 0);\n    best[0] = 0;\n    edges.reserve(k - 1);\n    for (int it = 0; it < k; ++it) {\n        int v = -1;\n        for (int i = 0; i < k; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (parent[v] != -1) {\n            int a = nodes[v], b = nodes[parent[v]];\n            if (a > b) swap(a, b);\n            edges.push_back({a, b});\n        }\n        for (int to = 0; to < k; ++to) if (!used[to]) {\n            int w = d2_est(nodes[v], nodes[to]);\n            if (w < best[to]) {\n                best[to] = w;\n                parent[to] = v;\n            }\n        }\n    }\n    return edges;\n}\n\nvector<pair<int,int>> query_tree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    cout << \"? \" << k;\n    for (int v : nodes) cout << ' ' << v;\n    cout << '\\n' << flush;\n    ++queries_used;\n\n    vector<pair<int,int>> edges;\n    edges.reserve(k - 1);\n    for (int i = 0; i < k - 1; ++i) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nint choose_rep(const vector<int>& nodes, const vector<pair<int,int>>& treeEdges) {\n    int k = (int)nodes.size();\n    if (k == 1) return nodes[0];\n\n    static int pos[800];\n    for (int i = 0; i < N; ++i) pos[i] = -1;\n    for (int i = 0; i < k; ++i) pos[nodes[i]] = i;\n\n    vector<int> deg(k, 0);\n    for (auto [a, b] : treeEdges) {\n        int ia = pos[a], ib = pos[b];\n        if (ia >= 0) deg[ia]++;\n        if (ib >= 0) deg[ib]++;\n    }\n\n    int bestIdx = 0;\n    int bestDeg = -1;\n    long long bestSum = (1LL << 62);\n\n    for (int i = 0; i < k; ++i) {\n        long long sum = 0;\n        for (int j = 0; j < k; ++j) if (i != j) {\n            sum += (long long)d2_est(nodes[i], nodes[j]);\n        }\n        int d = deg[i];\n        int id = nodes[i];\n        if (d > bestDeg ||\n            (d == bestDeg && (sum < bestSum ||\n             (sum == bestSum && (keys[bestOrient][id] < keys[bestOrient][nodes[bestIdx]] ||\n              (keys[bestOrient][id] == keys[bestOrient][nodes[bestIdx]] && id < nodes[bestIdx])))))) {\n            bestDeg = d;\n            bestSum = sum;\n            bestIdx = i;\n        }\n    }\n    return nodes[bestIdx];\n}\n\n// build a connected tree on nodes; returns representative city\nint solve(vector<int> nodes, vector<pair<int,int>>& out, bool already_sorted) {\n    int s = (int)nodes.size();\n    if (s == 1) return nodes[0];\n\n    if (!already_sorted) {\n        sort(nodes.begin(), nodes.end(), [&](int a, int b) {\n            if (keys[bestOrient][a] != keys[bestOrient][b]) return keys[bestOrient][a] < keys[bestOrient][b];\n            return a < b;\n        });\n    }\n\n    if (s == 2) {\n        int a = nodes[0], b = nodes[1];\n        if (a > b) swap(a, b);\n        out.push_back({a, b});\n        vector<pair<int,int>> e = {{a, b}};\n        return choose_rep(nodes, e);\n    }\n\n    if (s <= L) {\n        vector<pair<int,int>> tree;\n        if (queries_used < Q) tree = query_tree(nodes);\n        else tree = prim_tree(nodes);\n        out.insert(out.end(), tree.begin(), tree.end());\n        return choose_rep(nodes, tree);\n    }\n\n    if (queries_used >= Q) {\n        vector<pair<int,int>> tree = prim_tree(nodes);\n        out.insert(out.end(), tree.begin(), tree.end());\n        return choose_rep(nodes, tree);\n    }\n\n    vector<int> reps;\n    int q = s / L;\n    int r = s % L;\n\n    if (r == 1) {\n        // q >= 1 because s > L\n        for (int i = 0; i < q - 1; ++i) {\n            vector<int> ch(nodes.begin() + i * L, nodes.begin() + (i + 1) * L);\n            reps.push_back(solve(ch, out, true));\n        }\n        // split the remaining L+1 nodes into (L-1) and 2\n        vector<int> ch1(nodes.begin() + (q - 1) * L, nodes.begin() + (q - 1) * L + (L - 1));\n        vector<int> ch2(nodes.end() - 2, nodes.end());\n        reps.push_back(solve(ch1, out, true));\n        reps.push_back(solve(ch2, out, true));\n    } else {\n        for (int i = 0; i < q; ++i) {\n            vector<int> ch(nodes.begin() + i * L, nodes.begin() + (i + 1) * L);\n            reps.push_back(solve(ch, out, true));\n        }\n        if (r > 0) {\n            vector<int> ch(nodes.begin() + q * L, nodes.end());\n            reps.push_back(solve(ch, out, true));\n        }\n    }\n\n    if (reps.size() == 1) return reps[0];\n    return solve(reps, out, false);\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    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    exs.resize(N);\n    eys.resize(N);\n    for (int i = 0; i < N; ++i) {\n        exs[i] = lx[i] + rx[i];\n        eys[i] = ly[i] + ry[i];\n    }\n\n    // Precompute estimated distances\n    est2.assign(N, vector<int>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i; j < N; ++j) {\n            long long dx = (long long)exs[i] - exs[j];\n            long long dy = (long long)eys[i] - eys[j];\n            long long v = dx * dx + dy * dy;\n            est2[i][j] = est2[j][i] = (int)v;\n        }\n    }\n\n    // Precompute Hilbert keys for all 8 symmetries\n    keys.assign(8, vector<ull>(N, 0));\n    cityOrders.assign(8, {});\n    for (int o = 0; o < 8; ++o) {\n        for (int i = 0; i < N; ++i) {\n            int x = exs[i], y = eys[i];\n            if (o & 1) x = 20000 - x;\n            if (o & 2) y = 20000 - y;\n            if (o & 4) swap(x, y);\n            keys[o][i] = hilbertOrder(x, y);\n        }\n        cityOrders[o].resize(N);\n        iota(cityOrders[o].begin(), cityOrders[o].end(), 0);\n        sort(cityOrders[o].begin(), cityOrders[o].end(), [&](int a, int b) {\n            if (keys[o][a] != keys[o][b]) return keys[o][a] < keys[o][b];\n            return a < b;\n        });\n    }\n\n    // Candidate group orders\n    vector<int> ordDesc(M), ordAsc(M), ordOrig(M);\n    iota(ordOrig.begin(), ordOrig.end(), 0);\n    ordDesc = ordOrig;\n    ordAsc = ordOrig;\n\n    sort(ordDesc.begin(), ordDesc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n    sort(ordAsc.begin(), ordAsc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n\n    vector<vector<int>> candOrders = {ordDesc, ordAsc, ordOrig};\n\n    // Choose best orientation + group order by estimated MST cost of the segments\n    double bestScore = 1e100;\n    int bestOrdType = 0;\n    int bestOr = 0;\n\n    for (int ot = 0; ot < (int)candOrders.size(); ++ot) {\n        const auto& gOrd = candOrders[ot];\n        for (int o = 0; o < 8; ++o) {\n            double score = 0.0;\n            int p = 0;\n            for (int gi : gOrd) {\n                score += prim_cost_range(cityOrders[o], p, G[gi]);\n                p += G[gi];\n            }\n            if (score < bestScore) {\n                bestScore = score;\n                bestOrdType = ot;\n                bestOr = o;\n                bestGroupOrder = gOrd;\n            }\n        }\n    }\n\n    bestOrient = bestOr;\n\n    // Assign cities to groups using the chosen order and orientation\n    groupCities.assign(M, {});\n    int p = 0;\n    const auto& cityOrd = cityOrders[bestOrient];\n    for (int gi : bestGroupOrder) {\n        groupCities[gi].assign(cityOrd.begin() + p, cityOrd.begin() + p + G[gi]);\n        p += G[gi];\n    }\n\n    // Compute estimated costs of each group and process difficult groups first\n    vector<pair<double,int>> proc;\n    proc.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        double c = prim_cost_vec(groupCities[i]);\n        proc.push_back({c, i});\n    }\n    sort(proc.begin(), proc.end(), [&](const auto& a, const auto& b) {\n        if (fabs(a.first - b.first) > 1e-12) return a.first > b.first;\n        if (G[a.second] != G[b.second]) return G[a.second] > G[b.second];\n        return a.second < b.second;\n    });\n\n    groupEdges.assign(M, {});\n    for (auto [cost, idx] : proc) {\n        groupEdges[idx].clear();\n        solve(groupCities[idx], groupEdges[idx], true);\n\n        // Safety fallback if something went wrong\n        if ((int)groupEdges[idx].size() != (int)groupCities[idx].size() - 1) {\n            groupEdges[idx] = prim_tree(groupCities[idx]);\n        }\n    }\n\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < (int)groupCities[i].size(); ++j) {\n            if (j) cout << ' ';\n            cout << groupCities[i][j];\n        }\n        cout << '\\n';\n        for (auto [a, b] : groupEdges[i]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, M;\n    vector<pair<int,int>> pts;\n    vector<array<int,4>> mv, sl;\n\n    static constexpr char dirC[4] = {'U','D','L','R'};\n\n    void build_graph() {\n        int V = N * N;\n        mv.assign(V, array<int,4>{});\n        sl.assign(V, array<int,4>{});\n        for (int u = 0; u < V; ++u) {\n            mv[u].fill(-1);\n            sl[u].fill(-1);\n            int r = u / N, c = u % N;\n\n            // Move transitions\n            if (r > 0) mv[u][0] = (r - 1) * N + c;      // U\n            if (r + 1 < N) mv[u][1] = (r + 1) * N + c;  // D\n            if (c > 0) mv[u][2] = r * N + (c - 1);      // L\n            if (c + 1 < N) mv[u][3] = r * N + (c + 1);  // R\n\n            // Slide transitions to the border in that direction\n            sl[u][0] = 0 * N + c;           // U\n            sl[u][1] = (N - 1) * N + c;     // D\n            sl[u][2] = r * N + 0;           // L\n            sl[u][3] = r * N + (N - 1);     // R\n\n            // Ignore self-loop slides (they are never useful)\n            for (int d = 0; d < 4; ++d) {\n                if (sl[u][d] == u) sl[u][d] = -1;\n            }\n        }\n    }\n\n    vector<pair<char,char>> move_path(int s, int t) const {\n        vector<pair<char,char>> res;\n        int r = s / N, c = s % N;\n        int tr = t / N, tc = t % N;\n\n        while (r != tr) {\n            if (r < tr) {\n                res.push_back({'M', 'D'});\n                ++r;\n            } else {\n                res.push_back({'M', 'U'});\n                --r;\n            }\n        }\n        while (c != tc) {\n            if (c < tc) {\n                res.push_back({'M', 'R'});\n                ++c;\n            } else {\n                res.push_back({'M', 'L'});\n                --c;\n            }\n        }\n        return res;\n    }\n\n    vector<pair<char,char>> bfs_path(int s, int t) const {\n        int V = N * N;\n        vector<int> pre(V, -1);\n        vector<char> pact(V, 0), pdir(V, 0);\n        queue<int> q;\n\n        pre[s] = -2;\n        q.push(s);\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            if (u == t) break;\n\n            for (int d = 0; d < 4; ++d) {\n                int v = mv[u][d];\n                if (v != -1 && pre[v] == -1) {\n                    pre[v] = u;\n                    pact[v] = 'M';\n                    pdir[v] = dirC[d];\n                    q.push(v);\n                }\n                v = sl[u][d];\n                if (v != -1 && pre[v] == -1) {\n                    pre[v] = u;\n                    pact[v] = 'S';\n                    pdir[v] = dirC[d];\n                    q.push(v);\n                }\n            }\n        }\n\n        vector<pair<char,char>> path;\n        if (pre[t] == -1) return path; // should never happen\n\n        for (int v = t; v != s; v = pre[v]) {\n            path.push_back({pact[v], pdir[v]});\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    }\n\n    bool simulate(int s, const vector<pair<char,char>>& path, int t) const {\n        int r = s / N, c = s % N;\n        for (auto [a, d] : path) {\n            if (a == 'M') {\n                if (d == 'U') --r;\n                else if (d == 'D') ++r;\n                else if (d == 'L') --c;\n                else if (d == 'R') ++c;\n                else return false;\n            } else if (a == 'S') {\n                if (d == 'U') r = 0;\n                else if (d == 'D') r = N - 1;\n                else if (d == 'L') c = 0;\n                else if (d == 'R') c = N - 1;\n                else return false;\n            } else {\n                return false;\n            }\n            if (r < 0 || r >= N || c < 0 || c >= N) return false;\n        }\n        return r * N + c == t;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver sol;\n    cin >> sol.N >> sol.M;\n    sol.pts.resize(sol.M);\n    for (int i = 0; i < sol.M; ++i) {\n        cin >> sol.pts[i].first >> sol.pts[i].second;\n    }\n\n    sol.build_graph();\n\n    vector<pair<char,char>> ans;\n    ans.reserve(1600);\n\n    int cur = sol.pts[0].first * sol.N + sol.pts[0].second;\n\n    for (int k = 1; k < sol.M; ++k) {\n        int nxt = sol.pts[k].first * sol.N + sol.pts[k].second;\n\n        auto path = sol.bfs_path(cur, nxt);\n        auto fallback = sol.move_path(cur, nxt);\n\n        // Safety: if something goes wrong, use guaranteed-valid move-only path.\n        if (path.empty() || !sol.simulate(cur, path, nxt) || path.size() > fallback.size()) {\n            path = std::move(fallback);\n        }\n\n        ans.insert(ans.end(), path.begin(), path.end());\n        cur = nxt;\n    }\n\n    for (auto [a, d] : ans) {\n        cout << a << ' ' << d << '\\n';\n    }\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstruct Cand {\n    long long diff;     // |areaL * T - A * TL|\n    long long denom;    // TL * TR\n    long long balance;  // shape tie-break: smaller is better\n    long double val;    // diff / denom, used for random pool threshold\n    int orient;         // 0: vertical, 1: horizontal\n    int cut;            // selected cut coordinate\n    int lo, hi;         // allowed cut interval\n};\n\nstatic const int B = 10000;\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\n\nstatic inline long long absl(long long x) { return x < 0 ? -x : x; }\n\nbool candLess(const Cand& a, const Cand& b) {\n    __int128 lhs = (__int128)a.diff * b.denom;\n    __int128 rhs = (__int128)b.diff * a.denom;\n    if (lhs != rhs) return lhs < rhs;\n    if (a.balance != b.balance) return a.balance < b.balance;\n    int spanA = a.hi - a.lo, spanB = b.hi - b.lo;\n    if (spanA != spanB) return spanA > spanB; // more flexibility\n    if (a.orient != b.orient) return a.orient < b.orient;\n    return a.cut < b.cut;\n}\n\nvoid addCandidates(\n    const vector<int>& ids,\n    int lx, int ly, int rx, int ry,\n    int orient,\n    vector<Cand>& cands\n) {\n    int m = (int)ids.size();\n    if (m <= 1) return;\n\n    long long T = 0;\n    for (int id : ids) T += rs[id];\n    if (T <= 0) return;\n\n    long long A = 1LL * (rx - lx) * (ry - ly);\n\n    if (orient == 0) {\n        int W = rx - lx;\n        int H = ry - ly;\n        if (W < 2) return;\n\n        vector<int> ord = ids;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            return a < b;\n        });\n\n        long long pref = 0;\n        for (int i = 0; i + 1 < m; ++i) {\n            pref += rs[ord[i]];\n            if (xs[ord[i]] == xs[ord[i + 1]]) continue;\n\n            int lo = max(lx + 1, xs[ord[i]] + 1);\n            int hi = min(rx - 1, xs[ord[i + 1]]);\n            if (lo > hi) continue;\n\n            long long num = A * pref;\n            long long den = 1LL * H * T;\n            long long w = num / den;\n            if ((num % den) * 2 >= den) ++w;\n\n            long long cutll = lx + w;\n            cutll = max<long long>(lo, min<long long>(hi, cutll));\n            int cut = (int)cutll;\n\n            long long areaL = 1LL * (cut - lx) * H;\n            long long diff = absl(areaL * T - A * pref);\n            long long TL = pref, TR = T - pref;\n            long long denom = TL * TR;\n            if (denom <= 0) continue;\n\n            long long balance = absl(2LL * (cut - lx) - W);\n            long double val = (long double)diff / (long double)denom;\n            cands.push_back({diff, denom, balance, val, orient, cut, lo, hi});\n        }\n    } else {\n        int W = rx - lx;\n        int H = ry - ly;\n        if (H < 2) return;\n\n        vector<int> ord = ids;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            return a < b;\n        });\n\n        long long pref = 0;\n        for (int i = 0; i + 1 < m; ++i) {\n            pref += rs[ord[i]];\n            if (ys[ord[i]] == ys[ord[i + 1]]) continue;\n\n            int lo = max(ly + 1, ys[ord[i]] + 1);\n            int hi = min(ry - 1, ys[ord[i + 1]]);\n            if (lo > hi) continue;\n\n            long long num = A * pref;\n            long long den = 1LL * W * T;\n            long long h = num / den;\n            if ((num % den) * 2 >= den) ++h;\n\n            long long cutll = ly + h;\n            cutll = max<long long>(lo, min<long long>(hi, cutll));\n            int cut = (int)cutll;\n\n            long long areaL = 1LL * W * (cut - ly);\n            long long diff = absl(areaL * T - A * pref);\n            long long TL = pref, TR = T - pref;\n            long long denom = TL * TR;\n            if (denom <= 0) continue;\n\n            long long balance = absl(2LL * (cut - ly) - H);\n            long double val = (long double)diff / (long double)denom;\n            cands.push_back({diff, denom, balance, val, orient, cut, lo, hi});\n        }\n    }\n}\n\nCand chooseCandidate(\n    vector<Cand>& cands,\n    bool randomize,\n    mt19937_64& rng,\n    long double slack_ratio,\n    int best_prob\n) {\n    sort(cands.begin(), cands.end(), candLess);\n    Cand best = cands[0];\n\n    if (!randomize || cands.size() == 1) return best;\n\n    long double lim = best.val * (1.0L + slack_ratio) + 1e-18L;\n    vector<int> pool;\n    for (int i = 0; i < (int)cands.size(); ++i) {\n        if (cands[i].val <= lim) pool.push_back(i);\n        else break;\n    }\n\n    if ((int)pool.size() <= 1) return best;\n\n    // Usually keep the best; sometimes explore a nearby candidate.\n    if ((int)(rng() % 1000) < best_prob) return best;\n\n    int take = min<int>(5, (int)pool.size());\n    if (take <= 1) return best;\n\n    int idx = pool[1 + (int)(rng() % (take - 1))];\n    return cands[idx];\n}\n\nvoid build(\n    int lx, int ly, int rx, int ry,\n    const vector<int>& ids,\n    vector<Rect>& ans,\n    bool randomize,\n    mt19937_64& rng,\n    long double slack_ratio,\n    int best_prob,\n    int perturb_max\n) {\n    if (ids.size() == 1) {\n        ans[ids[0]] = {lx, ly, rx, ry};\n        return;\n    }\n\n    vector<Cand> cands;\n    cands.reserve(ids.size() * 2);\n\n    addCandidates(ids, lx, ly, rx, ry, 0, cands);\n    addCandidates(ids, lx, ly, rx, ry, 1, cands);\n\n    if (cands.empty()) {\n        // Robust fallback: split by the longer side using a simple median boundary.\n        // This should almost never be needed.\n        if (rx - lx >= ry - ly && rx - lx >= 2) {\n            vector<int> ord = ids;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                return a < b;\n            });\n            int m = (int)ord.size();\n            int mid = m / 2 - 1;\n            if (mid < 0) mid = 0;\n            while (mid + 1 < m && xs[ord[mid]] == xs[ord[mid + 1]]) ++mid;\n            if (mid + 1 >= m) mid = m / 2 - 1;\n            int cut = xs[ord[mid]] + 1;\n            cut = max(lx + 1, min(rx - 1, cut));\n\n            vector<int> left, right;\n            left.reserve(ids.size());\n            right.reserve(ids.size());\n            for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n            if (left.empty() || right.empty()) {\n                cut = lx + 1;\n                left.clear(); right.clear();\n                for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n            }\n            build(lx, ly, cut, ry, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            build(cut, ly, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            return;\n        } else {\n            vector<int> ord = ids;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                return a < b;\n            });\n            int m = (int)ord.size();\n            int mid = m / 2 - 1;\n            if (mid < 0) mid = 0;\n            while (mid + 1 < m && ys[ord[mid]] == ys[ord[mid + 1]]) ++mid;\n            if (mid + 1 >= m) mid = m / 2 - 1;\n            int cut = ys[ord[mid]] + 1;\n            cut = max(ly + 1, min(ry - 1, cut));\n\n            vector<int> left, right;\n            left.reserve(ids.size());\n            right.reserve(ids.size());\n            for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n            if (left.empty() || right.empty()) {\n                cut = ly + 1;\n                left.clear(); right.clear();\n                for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n            }\n            build(lx, ly, rx, cut, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            build(lx, cut, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            return;\n        }\n    }\n\n    Cand ch = chooseCandidate(cands, randomize, rng, slack_ratio, best_prob);\n    int cut = ch.cut;\n\n    if (randomize && perturb_max > 0 && ch.lo < ch.hi) {\n        int span = min(perturb_max, max(1, (ch.hi - ch.lo) / 4));\n        if (span > 0) {\n            int off = (int)(rng() % (2ULL * span + 1ULL)) - span;\n            cut = max(ch.lo, min(ch.hi, cut + off));\n        }\n    }\n\n    vector<int> left, right;\n    left.reserve(ids.size());\n    right.reserve(ids.size());\n\n    if (ch.orient == 0) {\n        for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n        if (left.empty() || right.empty()) {\n            // Extremely defensive fallback.\n            int med = lx + (rx - lx) / 2;\n            left.clear(); right.clear();\n            for (int id : ids) (xs[id] < med ? left : right).push_back(id);\n            cut = med;\n        }\n        build(lx, ly, cut, ry, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n        build(cut, ly, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n    } else {\n        for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n        if (left.empty() || right.empty()) {\n            int med = ly + (ry - ly) / 2;\n            left.clear(); right.clear();\n            for (int id : ids) (ys[id] < med ? left : right).push_back(id);\n            cut = med;\n        }\n        build(lx, ly, rx, cut, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n        build(lx, cut, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n    }\n}\n\nlong double evaluate(const vector<Rect>& ans) {\n    long double sum = 0.0L;\n    for (int i = 0; i < n; ++i) {\n        long long s = 1LL * (ans[i].x2 - ans[i].x1) * (ans[i].y2 - ans[i].y1);\n        long long r = rs[i];\n        long long mn = min(s, r), mx = max(s, r);\n        long double t = (long double)mn / (long double)mx;\n        long double p = 1.0L - (1.0L - t) * (1.0L - t);\n        sum += p;\n    }\n    return sum / n;\n}\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_ans(n);\n    long double best_score = -1.0L;\n\n    auto start = chrono::steady_clock::now();\n    uint64_t base_seed = chrono::steady_clock::now().time_since_epoch().count();\n\n    const int MAX_ATTEMPTS = 200;\n\n    for (int attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) {\n        if (attempt > 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > 4.7) break;\n        }\n\n        bool randomize = (attempt != 0);\n        long double slack_ratio = 0.0L;\n        int best_prob = 1000;   // probability (permille) of keeping the best candidate\n        int perturb_max = 0;\n\n        if (randomize) {\n            if (attempt < 10) {\n                slack_ratio = 0.02L;\n                best_prob = 950;\n                perturb_max = 3;\n            } else if (attempt < 30) {\n                slack_ratio = 0.05L;\n                best_prob = 850;\n                perturb_max = 10;\n            } else {\n                slack_ratio = 0.15L;\n                best_prob = 700;\n                perturb_max = 30;\n            }\n        }\n\n        vector<Rect> ans(n);\n        vector<int> ids(n);\n        iota(ids.begin(), ids.end(), 0);\n\n        mt19937_64 rng(base_seed + 1000003ULL * (uint64_t)attempt + 1234567ULL);\n\n        build(0, 0, B, B, ids, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n\n        long double score = evaluate(ans);\n        if (score > best_score) {\n            best_score = score;\n            best_ans = ans;\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        cout << best_ans[i].x1 << ' ' << best_ans[i].y1 << ' '\n             << best_ans[i].x2 << ' ' << best_ans[i].y2 << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 50;\nstatic constexpr int W = 50;\nstatic constexpr int N = H * W;\nstatic constexpr int WORDS = (N + 63) / 64;\n\nstruct State {\n    array<uint64_t, WORDS> vis{};\n    int pos = 0;\n    int score = 0;\n};\n\nstruct MoveCand {\n    int next = -1;\n    char mv = '?';\n    int val = 0;\n    int deg = 0;\n    int fut = 0;\n    int pot = 0;\n    int key = 0;\n};\n\nstruct Node {\n    State st;\n    int firstNext = -1;\n    char firstMv = 0;\n    int prio = 0;\n};\n\nstruct Mode {\n    int wVal, wDeg, wFut, wPot;\n    int noise;\n    int depth;\n    int width;\n};\n\nstruct Result {\n    string path;\n    int score = -1;\n};\n\nint si, sj;\nint tileId[H][W];\nint valGrid[H][W];\n\nint tileOf[N];\nint valueOf[N];\nint localPot[N];\n\nint adjCnt[N];\nint adjTo[N][4];\nchar adjMv[N][4];\n\ninline int idOf(int r, int c) { return r * W + c; }\n\ninline bool visited(const array<uint64_t, WORDS>& vis, int tid) {\n    return (vis[tid >> 6] >> (tid & 63)) & 1ULL;\n}\ninline void setVisited(array<uint64_t, WORDS>& vis, int tid) {\n    vis[tid >> 6] |= (1ULL << (tid & 63));\n}\n\ninline void applyMove(State& st, int nxt) {\n    st.pos = nxt;\n    st.score += valueOf[nxt];\n    setVisited(st.vis, tileOf[nxt]);\n}\n\nstatic inline bool betterCand(const MoveCand& a, const MoveCand& b) {\n    if (a.key != b.key) return a.key > b.key;\n    if (a.val != b.val) return a.val > b.val;\n    if (a.deg != b.deg) return a.deg > b.deg;\n    return a.next < b.next;\n}\n\nstatic inline bool betterNode(const Node& a, const Node& b) {\n    if (a.prio != b.prio) return a.prio > b.prio;\n    if (a.st.score != b.st.score) return a.st.score > b.st.score;\n    if (a.firstNext != b.firstNext) return a.firstNext < b.firstNext;\n    return a.firstMv < b.firstMv;\n}\n\nint makeCandidates(const State& st, const Mode& m, MoveCand out[4]) {\n    int cnt = 0;\n    int curTid = tileOf[st.pos];\n\n    for (int k = 0; k < adjCnt[st.pos]; ++k) {\n        int nxt = adjTo[st.pos][k];\n        int tid = tileOf[nxt];\n        if (visited(st.vis, tid)) continue;\n\n        int seenT[4];\n        int seenV[4];\n        int seenCnt = 0;\n\n        for (int e = 0; e < adjCnt[nxt]; ++e) {\n            int nb = adjTo[nxt][e];\n            int tid2 = tileOf[nb];\n            if (tid2 == tid || visited(st.vis, tid2)) continue;\n\n            int idx = -1;\n            for (int i = 0; i < seenCnt; ++i) {\n                if (seenT[i] == tid2) {\n                    idx = i;\n                    break;\n                }\n            }\n            int v = valueOf[nb];\n            if (idx == -1) {\n                seenT[seenCnt] = tid2;\n                seenV[seenCnt] = v;\n                ++seenCnt;\n            } else {\n                seenV[idx] = max(seenV[idx], v);\n            }\n        }\n\n        sort(seenV, seenV + seenCnt, greater<int>());\n\n        int fut = 0;\n        for (int i = 0; i < min(3, seenCnt); ++i) fut += seenV[i];\n\n        int deg = seenCnt;\n        int pot = localPot[nxt];\n\n        int key = m.wVal * valueOf[nxt]\n                + m.wDeg * deg\n                + m.wFut * fut\n                + m.wPot * pot;\n\n        out[cnt++] = {nxt, adjMv[st.pos][k], valueOf[nxt], deg, fut, pot, key};\n    }\n\n    sort(out, out + cnt, betterCand);\n    return cnt;\n}\n\nint heuristicState(const State& st, const Mode& m) {\n    MoveCand c[4];\n    int cnt = makeCandidates(st, m, c);\n    if (cnt == 0) return 0;\n\n    int h = c[0].key;\n    if (cnt >= 2) h += c[1].key / 2;\n    if (cnt >= 3) h += c[2].key / 4;\n    return h / 2;\n}\n\nbool pickNextMoveLocalBeam(const State& root, const Mode& m, mt19937_64& rng,\n                           chrono::steady_clock::time_point deadline,\n                           int& outNext, char& outMv) {\n    vector<Node> beam;\n    beam.reserve(m.width * 2 + 8);\n\n    Node start;\n    start.st = root;\n    start.firstNext = -1;\n    start.firstMv = 0;\n    start.prio = root.score + heuristicState(root, m);\n    beam.push_back(start);\n\n    bool bestValid = false;\n    Node best;\n\n    for (int depth = 0; depth < m.depth; ++depth) {\n        if (chrono::steady_clock::now() >= deadline) break;\n\n        vector<Node> nxt;\n        nxt.reserve(beam.size() * 4 + 8);\n\n        for (const Node& node : beam) {\n            MoveCand cand[4];\n            int cnt = makeCandidates(node.st, m, cand);\n            if (cnt == 0) {\n                if (node.firstNext != -1) {\n                    if (!bestValid || betterNode(node, best)) {\n                        best = node;\n                        bestValid = true;\n                    }\n                }\n                continue;\n            }\n\n            for (int i = 0; i < cnt; ++i) {\n                Node ch;\n                ch.st = node.st;\n                applyMove(ch.st, cand[i].next);\n                ch.firstNext = (node.firstNext == -1 ? cand[i].next : node.firstNext);\n                ch.firstMv = (node.firstMv ? node.firstMv : cand[i].mv);\n\n                int jitter = m.noise ? (int)(rng() % (uint64_t)m.noise) : 0;\n                ch.prio = ch.st.score + heuristicState(ch.st, m) + jitter;\n                nxt.push_back(ch);\n\n                if (!bestValid || betterNode(ch, best)) {\n                    best = ch;\n                    bestValid = true;\n                }\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        if ((int)nxt.size() > m.width) {\n            nth_element(nxt.begin(), nxt.begin() + m.width, nxt.end(), betterNode);\n            nxt.resize(m.width);\n        }\n\n        beam.swap(nxt);\n    }\n\n    if (!bestValid) {\n        MoveCand cand[4];\n        int cnt = makeCandidates(root, m, cand);\n        if (cnt == 0) return false;\n        outNext = cand[0].next;\n        outMv = cand[0].mv;\n        return true;\n    }\n\n    outNext = best.firstNext;\n    outMv = best.firstMv;\n    return true;\n}\n\nResult runAttempt(const Mode& m, mt19937_64& rng, chrono::steady_clock::time_point deadline) {\n    State st;\n    int start = idOf(si, sj);\n    st.pos = start;\n    st.score = valueOf[start];\n    setVisited(st.vis, tileOf[start]);\n\n    string path;\n    path.reserve(2600);\n\n    while (chrono::steady_clock::now() < deadline && (int)path.size() < 2600) {\n        int nxt;\n        char mv;\n        if (!pickNextMoveLocalBeam(st, m, rng, deadline, nxt, mv)) break;\n        applyMove(st, nxt);\n        path.push_back(mv);\n    }\n\n    return {path, st.score};\n}\n\npair<bool,int> simulatePath(const string& path) {\n    State st;\n    int start = idOf(si, sj);\n    st.pos = start;\n    st.score = valueOf[start];\n    setVisited(st.vis, tileOf[start]);\n\n    for (char ch : path) {\n        int nxt = -1;\n        for (int k = 0; k < adjCnt[st.pos]; ++k) {\n            if (adjMv[st.pos][k] == ch) {\n                nxt = adjTo[st.pos][k];\n                break;\n            }\n        }\n        if (nxt == -1) return {false, -1};\n        int tid = tileOf[nxt];\n        if (visited(st.vis, tid)) return {false, -1};\n        applyMove(st, nxt);\n    }\n    return {true, st.score};\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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> tileId[i][j];\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> valGrid[i][j];\n    }\n\n    uint64_t baseSeed = 0x123456789abcdefULL;\n    auto mix = [&](uint64_t x) {\n        baseSeed = splitmix64(baseSeed ^ x);\n    };\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            tileOf[id] = tileId[i][j];\n            valueOf[id] = valGrid[i][j];\n            mix((uint64_t)tileId[i][j] << 16 ^ (uint64_t)valGrid[i][j] ^ (uint64_t)(i * 50 + j));\n        }\n    }\n    mix((uint64_t)si << 32 | (uint64_t)sj);\n\n    // adjacency\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            adjCnt[id] = 0;\n            if (i > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i - 1, j);\n                adjMv[id][adjCnt[id]++] = 'U';\n            }\n            if (i + 1 < H) {\n                adjTo[id][adjCnt[id]] = idOf(i + 1, j);\n                adjMv[id][adjCnt[id]++] = 'D';\n            }\n            if (j > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i, j - 1);\n                adjMv[id][adjCnt[id]++] = 'L';\n            }\n            if (j + 1 < W) {\n                adjTo[id][adjCnt[id]] = idOf(i, j + 1);\n                adjMv[id][adjCnt[id]++] = 'R';\n            }\n        }\n    }\n\n    // 5x5 local average potential, centered by global average 50\n    static int ps[H + 1][W + 1];\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            ps[i + 1][j + 1] = ps[i + 1][j] + ps[i][j + 1] - ps[i][j] + valGrid[i][j];\n        }\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int r1 = max(0, i - 2), r2 = min(H - 1, i + 2);\n            int c1 = max(0, j - 2), c2 = min(W - 1, j + 2);\n            int sum = ps[r2 + 1][c2 + 1] - ps[r1][c2 + 1] - ps[r2 + 1][c1] + ps[r1][c1];\n            int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n            localPot[idOf(i, j)] = sum / area - 50;\n        }\n    }\n\n    chrono::steady_clock::time_point startTime = chrono::steady_clock::now();\n    chrono::steady_clock::time_point deadline = startTime + chrono::milliseconds(1850);\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[idOf(si, sj)];\n\n    auto consider = [&](const Result& r) {\n        auto [ok, sc] = simulatePath(r.path);\n        if (!ok) return;\n        if (sc > best.score || (sc == best.score && r.path.size() > best.path.size())) {\n            best = r;\n            best.score = sc;\n        }\n    };\n\n    vector<Mode> modes = {\n        {12, 18, 4, 10, 5, 4,  8},\n        { 8, 30, 5,  8, 6, 5, 12},\n        {14, 10, 3, 12, 5, 4, 10},\n        {16,  8, 2,  6, 4, 3,  8},\n        {10, 20, 4, 14, 7, 6, 14},\n    };\n\n    int rep = 0;\n    while (chrono::steady_clock::now() < deadline) {\n        const Mode& m = modes[rep % modes.size()];\n        uint64_t seed = splitmix64(baseSeed ^ (uint64_t)rep * 0x9e3779b97f4a7c15ULL);\n        mt19937_64 rng(seed);\n        Result r = runAttempt(m, rng, deadline);\n        consider(r);\n        ++rep;\n    }\n\n    auto [ok, sc] = simulatePath(best.path);\n    if (!ok) best.path.clear();\n\n    cout << best.path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr double INIT_W = 5000.0;\nstatic constexpr double MIN_W = 1000.0;\nstatic constexpr double MAX_W = 9000.0;\n\nstatic constexpr double SEG_BLEND = 6.0;        // how much we trust row/col segment mean\nstatic constexpr double SPLIT_GAIN_ABS = 1.5e6; // absolute gain needed to accept split\nstatic constexpr double SPLIT_GAIN_REL = 0.05;   // relative gain needed to accept split\nstatic constexpr double UPDATE_BASE = 0.40;      // update step\nstatic constexpr double UPDATE_DECAY = 0.08;     // update decay by visit count\nstatic constexpr double EXPLORE_BASE = 0.90;     // tiny optimistic bonus for unobserved edges\n\nmt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\ndouble estH[N][N - 1], estV[N - 1][N];\nint cntH[N][N - 1], cntV[N - 1][N];\n\nstruct LineModel {\n    bool split = false;\n    int pos = -1;        // split point [1..28]\n    double mean = INIT_W;\n    double left = INIT_W;\n    double right = INIT_W;\n};\n\nLineModel rowModel[N], colModel[N];\n\ninline double clampW(double x) {\n    return max(MIN_W, min(MAX_W, x));\n}\n\ninline bool tieBetter(double cand, double best) {\n    constexpr double EPS = 1e-9;\n    if (cand + EPS < best) return true;\n    if (fabs(cand - best) <= EPS) return (rng() & 1);\n    return false;\n}\n\ninline double rowSegMean(const LineModel &m, int j) {\n    if (!m.split) return m.mean;\n    return (j < m.pos ? m.left : m.right);\n}\n\ninline double colSegMean(const LineModel &m, int i) {\n    if (!m.split) return m.mean;\n    return (i < m.pos ? m.left : m.right);\n}\n\ndouble computeGlobalMean() {\n    double sw = 0.0, sv = 0.0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            if (cntH[i][j] > 0) {\n                double w = sqrt((double)cntH[i][j]);\n                sw += w;\n                sv += w * estH[i][j];\n            }\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (cntV[i][j] > 0) {\n                double w = sqrt((double)cntV[i][j]);\n                sw += w;\n                sv += w * estV[i][j];\n            }\n        }\n    }\n    if (sw <= 0.0) return INIT_W;\n    return sv / sw;\n}\n\nLineModel fitRow(int i, double globalMean) {\n    double w[29] = {}, v[29] = {};\n    double pw[30] = {}, ps[30] = {}, pq[30] = {};\n    int po[30] = {};\n    double totW = 0.0, totS = 0.0, totQ = 0.0;\n    int obs = 0;\n\n    for (int j = 0; j < 29; ++j) {\n        if (cntH[i][j] > 0) {\n            double ww = sqrt((double)cntH[i][j]);\n            w[j] = ww;\n            v[j] = estH[i][j];\n            totW += ww;\n            totS += ww * v[j];\n            totQ += ww * v[j] * v[j];\n            ++obs;\n        } else {\n            w[j] = 0.0;\n            v[j] = globalMean;\n        }\n        pw[j + 1] = pw[j] + w[j];\n        ps[j + 1] = ps[j] + w[j] * v[j];\n        pq[j + 1] = pq[j] + w[j] * v[j] * v[j];\n        po[j + 1] = po[j] + (cntH[i][j] > 0);\n    }\n\n    LineModel m;\n    if (totW <= 0.0) {\n        m.mean = globalMean;\n        return m;\n    }\n\n    double mean = totS / totW;\n    double best1 = max(0.0, totQ - totS * totS / totW);\n\n    double best2 = 1e100;\n    int bestPos = -1;\n    double bestL = mean, bestR = mean;\n\n    for (int x = 1; x < 29; ++x) {\n        double wL = pw[x], wR = totW - wL;\n        int oL = po[x], oR = obs - oL;\n        if (wL < 1.5 || wR < 1.5) continue;\n        if (oL < 2 || oR < 2) continue;\n\n        double sL = ps[x], sR = totS - sL;\n        double qL = pq[x], qR = totQ - qL;\n        double sse = max(0.0, qL - sL * sL / wL) + max(0.0, qR - sR * sR / wR);\n\n        if (sse < best2) {\n            best2 = sse;\n            bestPos = x;\n            bestL = sL / wL;\n            bestR = sR / wR;\n        }\n    }\n\n    if (bestPos != -1) {\n        double gain = best1 - best2;\n        if (gain > SPLIT_GAIN_ABS && gain > SPLIT_GAIN_REL * best1) {\n            m.split = true;\n            m.pos = bestPos;\n            m.mean = mean;\n            m.left = bestL;\n            m.right = bestR;\n            return m;\n        }\n    }\n\n    m.mean = mean;\n    return m;\n}\n\nLineModel fitCol(int j, double globalMean) {\n    double w[29] = {}, v[29] = {};\n    double pw[30] = {}, ps[30] = {}, pq[30] = {};\n    int po[30] = {};\n    double totW = 0.0, totS = 0.0, totQ = 0.0;\n    int obs = 0;\n\n    for (int i = 0; i < 29; ++i) {\n        if (cntV[i][j] > 0) {\n            double ww = sqrt((double)cntV[i][j]);\n            w[i] = ww;\n            v[i] = estV[i][j];\n            totW += ww;\n            totS += ww * v[i];\n            totQ += ww * v[i] * v[i];\n            ++obs;\n        } else {\n            w[i] = 0.0;\n            v[i] = globalMean;\n        }\n        pw[i + 1] = pw[i] + w[i];\n        ps[i + 1] = ps[i] + w[i] * v[i];\n        pq[i + 1] = pq[i] + w[i] * v[i] * v[i];\n        po[i + 1] = po[i] + (cntV[i][j] > 0);\n    }\n\n    LineModel m;\n    if (totW <= 0.0) {\n        m.mean = globalMean;\n        return m;\n    }\n\n    double mean = totS / totW;\n    double best1 = max(0.0, totQ - totS * totS / totW);\n\n    double best2 = 1e100;\n    int bestPos = -1;\n    double bestL = mean, bestR = mean;\n\n    for (int x = 1; x < 29; ++x) {\n        double wL = pw[x], wR = totW - wL;\n        int oL = po[x], oR = obs - oL;\n        if (wL < 1.5 || wR < 1.5) continue;\n        if (oL < 2 || oR < 2) continue;\n\n        double sL = ps[x], sR = totS - sL;\n        double qL = pq[x], qR = totQ - qL;\n        double sse = max(0.0, qL - sL * sL / wL) + max(0.0, qR - sR * sR / wR);\n\n        if (sse < best2) {\n            best2 = sse;\n            bestPos = x;\n            bestL = sL / wL;\n            bestR = sR / wR;\n        }\n    }\n\n    if (bestPos != -1) {\n        double gain = best1 - best2;\n        if (gain > SPLIT_GAIN_ABS && gain > SPLIT_GAIN_REL * best1) {\n            m.split = true;\n            m.pos = bestPos;\n            m.mean = mean;\n            m.left = bestL;\n            m.right = bestR;\n            return m;\n        }\n    }\n\n    m.mean = mean;\n    return m;\n}\n\ninline double costH(int i, int j, double explore) {\n    double seg = rowSegMean(rowModel[i], j);\n    double base = estH[i][j];\n    int c = cntH[i][j];\n    if (c == 0) base = seg;\n    else base = (base * c + seg * SEG_BLEND) / (c + SEG_BLEND);\n    base -= explore / sqrt((double)c + 1.0);\n    return base;\n}\n\ninline double costV(int i, int j, double explore) {\n    double seg = colSegMean(colModel[j], i);\n    double base = estV[i][j];\n    int c = cntV[i][j];\n    if (c == 0) base = seg;\n    else base = (base * c + seg * SEG_BLEND) / (c + SEG_BLEND);\n    base -= explore / sqrt((double)c + 1.0);\n    return base;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            estH[i][j] = INIT_W;\n            cntH[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            estV[i][j] = INIT_W;\n            cntV[i][j] = 0;\n        }\n    }\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        double globalMean = computeGlobalMean();\n        for (int i = 0; i < N; ++i) rowModel[i] = fitRow(i, globalMean);\n        for (int j = 0; j < N; ++j) colModel[j] = fitCol(j, globalMean);\n\n        // Fill only unobserved edges with the current row/column model.\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N - 1; ++j) {\n                if (cntH[i][j] == 0) estH[i][j] = rowSegMean(rowModel[i], j);\n            }\n        }\n        for (int i = 0; i < N - 1; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (cntV[i][j] == 0) estV[i][j] = colSegMean(colModel[j], i);\n            }\n        }\n\n        int dy = abs(ti - si);\n        int dx = abs(tj - sj);\n        int sv = (ti >= si ? 1 : -1);\n        int sh = (tj >= sj ? 1 : -1);\n\n        double explore = EXPLORE_BASE * (1000.0 - q) / 1000.0;\n\n        static double dp[30][30];\n        static char par[30][30];\n\n        for (int i = 0; i <= dy; ++i) {\n            for (int j = 0; j <= dx; ++j) {\n                dp[i][j] = 1e100;\n                par[i][j] = 0;\n            }\n        }\n        dp[0][0] = 0.0;\n\n        for (int i = 0; i <= dy; ++i) {\n            for (int j = 0; j <= dx; ++j) {\n                if (i == 0 && j == 0) continue;\n\n                double best = 1e100;\n                char bestPar = 0;\n\n                if (i > 0) {\n                    int px = si + sv * (i - 1);\n                    int py = sj + sh * j;\n                    int ex = (sv == 1 ? px : px - 1);\n                    int ey = py;\n                    double cand = dp[i - 1][j] + costV(ex, ey, explore);\n                    if (tieBetter(cand, best)) {\n                        best = cand;\n                        bestPar = (sv == 1 ? 'D' : 'U');\n                    }\n                }\n\n                if (j > 0) {\n                    int px = si + sv * i;\n                    int py = sj + sh * (j - 1);\n                    int ex = px;\n                    int ey = (sh == 1 ? py : py - 1);\n                    double cand = dp[i][j - 1] + costH(ex, ey, explore);\n                    if (tieBetter(cand, best)) {\n                        best = cand;\n                        bestPar = (sh == 1 ? 'R' : 'L');\n                    }\n                }\n\n                dp[i][j] = best;\n                par[i][j] = bestPar;\n            }\n        }\n\n        string path;\n        path.reserve(dx + dy);\n        for (int i = dy, j = dx; i > 0 || j > 0; ) {\n            char c = par[i][j];\n            path.push_back(c);\n            if (c == 'D' || c == 'U') --i;\n            else --j;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << '\\n' << flush;\n\n        long long obs;\n        if (!(cin >> obs)) return 0;\n\n        // Predict length with the current raw estimates.\n        double pred = 0.0;\n        int x = si, y = sj;\n        for (char c : path) {\n            if (c == 'D') {\n                pred += estV[x][y];\n                ++x;\n            } else if (c == 'U') {\n                pred += estV[x - 1][y];\n                --x;\n            } else if (c == 'R') {\n                pred += estH[x][y];\n                ++y;\n            } else { // 'L'\n                pred += estH[x][y - 1];\n                --y;\n            }\n        }\n\n        double delta = ((double)obs - pred) / (double)path.size();\n\n        // Update traversed edges.\n        x = si;\n        y = sj;\n        for (char c : path) {\n            if (c == 'D') {\n                int ex = x, ey = y;\n                double eta = UPDATE_BASE / (1.0 + UPDATE_DECAY * cntV[ex][ey]);\n                estV[ex][ey] = clampW(estV[ex][ey] + eta * delta);\n                ++cntV[ex][ey];\n                ++x;\n            } else if (c == 'U') {\n                int ex = x - 1, ey = y;\n                double eta = UPDATE_BASE / (1.0 + UPDATE_DECAY * cntV[ex][ey]);\n                estV[ex][ey] = clampW(estV[ex][ey] + eta * delta);\n                ++cntV[ex][ey];\n                --x;\n            } else if (c == 'R') {\n                int ex = x, ey = y;\n                double eta = UPDATE_BASE / (1.0 + UPDATE_DECAY * cntH[ex][ey]);\n                estH[ex][ey] = clampW(estH[ex][ey] + eta * delta);\n                ++cntH[ex][ey];\n                ++y;\n            } else { // 'L'\n                int ex = x, ey = y - 1;\n                double eta = UPDATE_BASE / (1.0 + UPDATE_DECAY * cntH[ex][ey]);\n                estH[ex][ey] = clampW(estH[ex][ey] + eta * delta);\n                ++cntH[ex][ey];\n                --y;\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int CELLS = N * N;\nstatic constexpr int SIG = 8;\nstatic constexpr int DOT = 8;\nstatic constexpr int PLACES_PER_WORD = 2 * N * N; // 800\nstatic constexpr int MAXM = 800;\n\nstruct Word {\n    int len;\n    array<uint8_t, 12> ch{};\n};\n\nstruct Place {\n    int sid;\n    uint8_t len, ori, line, st;\n};\n\nstruct Inc {\n    int pid;\n    uint8_t ch;\n};\n\nusing Board = array<uint8_t, CELLS>;\n\nstatic inline int cid(int r, int c) { return r * N + c; }\n\nstatic inline uint8_t rndLetter(mt19937_64 &rng) {\n    return uint8_t(rng() & 7ULL);\n}\n\nstatic void randomBoard(Board &b, mt19937_64 &rng) {\n    for (int i = 0; i < CELLS; ++i) b[i] = rndLetter(rng);\n}\n\nstatic void perturbBoard(Board &b, mt19937_64 &rng, int cnt) {\n    for (int i = 0; i < cnt; ++i) {\n        int pos = int(rng() % CELLS);\n        uint8_t nw = rndLetter(rng);\n        if (nw == b[pos]) nw = uint8_t((nw + 1) & 7);\n        b[pos] = nw;\n    }\n}\n\nstatic void overlaySeed(Board &b, const Word &w, int line, int st, bool horiz) {\n    if (horiz) {\n        int c = st;\n        for (int t = 0; t < w.len; ++t) {\n            b[cid(line, c)] = w.ch[t];\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = st;\n        for (int t = 0; t < w.len; ++t) {\n            b[cid(r, line)] = w.ch[t];\n            if (++r == N) r = 0;\n        }\n    }\n}\n\nstatic void recomputeCounts(const Board &b,\n                            const vector<Word> &words,\n                            const vector<Place> &places,\n                            vector<int> &placeCnt,\n                            vector<int> &fullCnt) {\n    fill(placeCnt.begin(), placeCnt.end(), 0);\n    fill(fullCnt.begin(), fullCnt.end(), 0);\n\n    for (int p = 0; p < (int)places.size(); ++p) {\n        const auto &pl = places[p];\n        const auto &w = words[pl.sid];\n        int cnt = 0;\n\n        if (pl.ori == 0) {\n            int base = pl.line * N;\n            int c = pl.st;\n            for (int t = 0; t < pl.len; ++t) {\n                if (b[base + c] == w.ch[t]) ++cnt;\n                if (++c == N) c = 0;\n            }\n        } else {\n            int c = pl.line;\n            int r = pl.st;\n            for (int t = 0; t < pl.len; ++t) {\n                if (b[r * N + c] == w.ch[t]) ++cnt;\n                if (++r == N) r = 0;\n            }\n        }\n\n        placeCnt[p] = cnt;\n        if (cnt == pl.len) ++fullCnt[pl.sid];\n    }\n}\n\nstatic int satisfiedCount(const vector<int> &fullCnt) {\n    int c = 0;\n    for (int x : fullCnt) if (x > 0) ++c;\n    return c;\n}\n\nstatic bool softUpdate(Board &b,\n                       int round,\n                       const vector<Word> &words,\n                       const vector<Place> &places,\n                       const array<vector<Inc>, CELLS> &cellInc,\n                       mt19937_64 &rng) {\n    int P = (int)places.size();\n    vector<uint8_t> mc(P);\n    vector<int> bestCnt(words.size(), 0);\n\n    for (int p = 0; p < P; ++p) {\n        const auto &pl = places[p];\n        const auto &w = words[pl.sid];\n        int cnt = 0;\n\n        if (pl.ori == 0) {\n            int base = pl.line * N;\n            int c = pl.st;\n            for (int t = 0; t < pl.len; ++t) {\n                if (b[base + c] == w.ch[t]) ++cnt;\n                if (++c == N) c = 0;\n            }\n        } else {\n            int c = pl.line;\n            int r = pl.st;\n            for (int t = 0; t < pl.len; ++t) {\n                if (b[r * N + c] == w.ch[t]) ++cnt;\n                if (++r == N) r = 0;\n            }\n        }\n\n        mc[p] = (uint8_t)cnt;\n        if (cnt > bestCnt[pl.sid]) bestCnt[pl.sid] = cnt;\n    }\n\n    static long long votes[CELLS][SIG];\n    memset(votes, 0, sizeof(votes));\n\n    vector<int> cut(words.size(), 0);\n    for (int sid = 0; sid < (int)words.size(); ++sid) {\n        if (bestCnt[sid] == 0) {\n            cut[sid] = 1; // skip this string entirely\n        } else {\n            cut[sid] = min(bestCnt[sid], 1 + round); // 1,2,3 matches in successive rounds\n        }\n    }\n\n    for (int p = 0; p < P; ++p) {\n        const auto &pl = places[p];\n        int sid = pl.sid;\n        int cnt = mc[p];\n        if (cnt < cut[sid]) continue;\n\n        const auto &w = words[sid];\n        long long wt = (1LL << cnt) * 1LL * w.len * w.len;\n\n        if (pl.ori == 0) {\n            int base = pl.line * N;\n            int c = pl.st;\n            for (int t = 0; t < pl.len; ++t) {\n                votes[base + c][w.ch[t]] += wt;\n                if (++c == N) c = 0;\n            }\n        } else {\n            int c = pl.line;\n            int r = pl.st;\n            for (int t = 0; t < pl.len; ++t) {\n                votes[r * N + c][w.ch[t]] += wt;\n                if (++r == N) r = 0;\n            }\n        }\n    }\n\n    bool changed = false;\n    Board nb = b;\n    for (int cell = 0; cell < CELLS; ++cell) {\n        uint8_t old = b[cell];\n        long long bestV = votes[cell][old] + 1000; // inertia\n        uint8_t bestC = old;\n\n        for (int c = 0; c < SIG; ++c) {\n            if (c == old) continue;\n            long long v = votes[cell][c];\n            if (v > bestV) {\n                bestV = v;\n                bestC = (uint8_t)c;\n            }\n        }\n\n        nb[cell] = bestC;\n        if (bestC != old) changed = true;\n    }\n\n    b = nb;\n    return changed;\n}\n\nstatic void applyChange(Board &b,\n                        int idx,\n                        uint8_t nw,\n                        const vector<Place> &places,\n                        vector<int> &placeCnt,\n                        vector<int> &fullCnt,\n                        const array<vector<Inc>, CELLS> &cellInc) {\n    uint8_t old = b[idx];\n    if (old == nw) return;\n\n    for (const auto &inc : cellInc[idx]) {\n        int p = inc.pid;\n        int sid = places[p].sid;\n        int len = places[p].len;\n        uint8_t exp = inc.ch;\n\n        int delta = int(nw == exp) - int(old == exp);\n        if (delta == 0) continue;\n\n        bool oldFull = (placeCnt[p] == len);\n        bool newFull = (placeCnt[p] + delta == len);\n\n        if (oldFull != newFull) {\n            fullCnt[sid] += newFull ? 1 : -1;\n        }\n        placeCnt[p] += delta;\n    }\n\n    b[idx] = nw;\n}\n\nstatic void greedyImproveLetters(Board &b,\n                                 vector<int> &placeCnt,\n                                 vector<int> &fullCnt,\n                                 const vector<Place> &places,\n                                 const array<vector<Inc>, CELLS> &cellInc,\n                                 mt19937_64 &rng) {\n    vector<int> order(CELLS);\n    iota(order.begin(), order.end(), 0);\n\n    static int dFull[SIG][MAXM];\n\n    for (int pass = 0; pass < 3; ++pass) {\n        shuffle(order.begin(), order.end(), rng);\n        bool any = false;\n\n        for (int idx : order) {\n            uint8_t old = b[idx];\n            memset(dFull, 0, sizeof(dFull));\n            bool touched = false;\n\n            for (const auto &inc : cellInc[idx]) {\n                int p = inc.pid;\n                int sid = places[p].sid;\n                int len = places[p].len;\n                uint8_t exp = inc.ch;\n\n                if (old == exp) {\n                    if (placeCnt[p] == len) {\n                        touched = true;\n                        for (int c = 0; c < SIG; ++c) {\n                            if (c != old) dFull[c][sid]--;\n                        }\n                    }\n                } else {\n                    if (placeCnt[p] == len - 1) {\n                        touched = true;\n                        dFull[exp][sid]++;\n                    }\n                }\n            }\n\n            if (!touched) continue;\n\n            int bestCand = old;\n            int bestDelta = 0;\n\n            for (int cand = 0; cand < SIG; ++cand) {\n                int delta = 0;\n                for (int sid = 0; sid < (int)fullCnt.size(); ++sid) {\n                    int after = fullCnt[sid] + dFull[cand][sid];\n                    if (fullCnt[sid] == 0) {\n                        if (after > 0) ++delta;\n                    } else {\n                        if (after == 0) --delta;\n                    }\n                }\n                if (delta > bestDelta) {\n                    bestDelta = delta;\n                    bestCand = cand;\n                }\n            }\n\n            if (bestDelta > 0 && bestCand != old) {\n                applyChange(b, idx, (uint8_t)bestCand, places, placeCnt, fullCnt, cellInc);\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n}\n\nstatic int pruneDots(Board &b,\n                     vector<int> &placeCnt,\n                     vector<int> &fullCnt,\n                     const vector<Place> &places,\n                     const array<vector<Inc>, CELLS> &cellInc,\n                     mt19937_64 &rng) {\n    vector<int> order(CELLS);\n    iota(order.begin(), order.end(), 0);\n\n    int dots = 0;\n    static int lost[MAXM];\n\n    while (true) {\n        shuffle(order.begin(), order.end(), rng);\n        bool any = false;\n\n        for (int idx : order) {\n            if (b[idx] == DOT) continue;\n\n            uint8_t old = b[idx];\n            memset(lost, 0, sizeof(lost));\n            bool hasFullAffected = false;\n\n            for (const auto &inc : cellInc[idx]) {\n                int p = inc.pid;\n                int sid = places[p].sid;\n                int len = places[p].len;\n                uint8_t exp = inc.ch;\n\n                if (old == exp && placeCnt[p] == len) {\n                    hasFullAffected = true;\n                    lost[sid]--;\n                }\n            }\n\n            bool ok = true;\n            if (hasFullAffected) {\n                for (int sid = 0; sid < (int)fullCnt.size(); ++sid) {\n                    if (fullCnt[sid] + lost[sid] == 0) {\n                        ok = false;\n                        break;\n                    }\n                }\n            }\n\n            if (ok) {\n                // Apply dot\n                for (const auto &inc : cellInc[idx]) {\n                    int p = inc.pid;\n                    int sid = places[p].sid;\n                    int len = places[p].len;\n                    uint8_t exp = inc.ch;\n\n                    if (old == exp) {\n                        if (placeCnt[p] == len) fullCnt[sid]--;\n                        placeCnt[p]--;\n                    }\n                }\n                b[idx] = DOT;\n                ++dots;\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    return dots;\n}\n\nstatic void outputBoard(const Board &b) {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            uint8_t x = b[cid(r, c)];\n            cout << (x == DOT ? '.' : char('A' + x));\n        }\n        cout << '\\n';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Ninput, M;\n    cin >> Ninput >> M;\n\n    vector<Word> words(M);\n    for (int i = 0; i < M; ++i) {\n        string s;\n        cin >> s;\n        words[i].len = (int)s.size();\n        for (int j = 0; j < words[i].len; ++j) {\n            words[i].ch[j] = uint8_t(s[j] - 'A');\n        }\n    }\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (words[a].len != words[b].len) return words[a].len > words[b].len;\n        return a < b;\n    });\n\n    vector<Place> places;\n    places.reserve((size_t)M * PLACES_PER_WORD);\n\n    array<vector<Inc>, CELLS> cellInc;\n    int totalLen = 0;\n    for (auto &w : words) totalLen += w.len;\n    int reservePerCell = max(1, 2 * totalLen + 16);\n    for (auto &v : cellInc) v.reserve(reservePerCell);\n\n    for (int sid = 0; sid < M; ++sid) {\n        int len = words[sid].len;\n        for (int ori = 0; ori < 2; ++ori) {\n            for (int line = 0; line < N; ++line) {\n                for (int st = 0; st < N; ++st) {\n                    int pid = (int)places.size();\n                    places.push_back(Place{sid, (uint8_t)len, (uint8_t)ori, (uint8_t)line, (uint8_t)st});\n\n                    if (ori == 0) {\n                        int c = st;\n                        for (int t = 0; t < len; ++t) {\n                            cellInc[cid(line, c)].push_back(Inc{pid, words[sid].ch[t]});\n                            if (++c == N) c = 0;\n                        }\n                    } else {\n                        int r = st;\n                        for (int t = 0; t < len; ++t) {\n                            cellInc[cid(r, line)].push_back(Inc{pid, words[sid].ch[t]});\n                            if (++r == N) r = 0;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    Board bestLetters{};\n    int bestC = -1;\n\n    Board bestFull{};\n    int bestDots = -1;\n    bool haveBestFull = false;\n\n    const int MAX_RESTARTS = 6;\n    for (int restart = 0; restart < MAX_RESTARTS; ++restart) {\n        if (elapsed() > 2.85) break;\n\n        Board b{};\n        if (restart < 2 || bestC < 0) {\n            randomBoard(b, rng);\n            int seedCnt = min(12, M);\n            for (int k = 0; k < seedCnt; ++k) {\n                int sid = order[k];\n                bool horiz = ((k + restart) & 1) == 0;\n                int line = (k * 3 + restart) % N;\n                int st = int(rng() % N);\n                overlaySeed(b, words[sid], line, st, horiz);\n            }\n        } else {\n            b = bestLetters;\n            int mut = 4;\n            if (bestC < M / 2) mut = 20;\n            else if (bestC < M) mut = 10;\n            perturbBoard(b, rng, mut);\n\n            int seedCnt = (bestC < M / 2 ? 10 : (bestC < M ? 6 : 0));\n            for (int k = 0; k < seedCnt; ++k) {\n                int sid = order[(k + restart) % M];\n                bool horiz = ((k + restart) & 1) == 0;\n                int line = (k * 5 + restart * 3) % N;\n                int st = int(rng() % N);\n                overlaySeed(b, words[sid], line, st, horiz);\n            }\n        }\n\n        for (int round = 0; round < 3; ++round) {\n            if (elapsed() > 2.90) break;\n            softUpdate(b, round, words, places, cellInc, rng);\n        }\n\n        vector<int> placeCnt(places.size());\n        vector<int> fullCnt(M);\n        recomputeCounts(b, words, places, placeCnt, fullCnt);\n        greedyImproveLetters(b, placeCnt, fullCnt, places, cellInc, rng);\n        recomputeCounts(b, words, places, placeCnt, fullCnt);\n\n        int c = satisfiedCount(fullCnt);\n        if (c > bestC) {\n            bestC = c;\n            bestLetters = b;\n        }\n\n        if (c == M) {\n            // Try a few dot-pruning orders and keep the one with the most dots.\n            Board localBest = b;\n            int localBestDots = -1;\n\n            int attempts = 2;\n            for (int att = 0; att < attempts; ++att) {\n                if (elapsed() > 2.95) break;\n                Board tb = b;\n                vector<int> pc = placeCnt;\n                vector<int> fc = fullCnt;\n                int dots = pruneDots(tb, pc, fc, places, cellInc, rng);\n                if (dots > localBestDots) {\n                    localBestDots = dots;\n                    localBest = tb;\n                }\n            }\n\n            if (localBestDots > bestDots) {\n                bestDots = localBestDots;\n                bestFull = localBest;\n                haveBestFull = true;\n            }\n        }\n    }\n\n    // If we found a fully satisfied board but didn't prune it yet due time,\n    // do one final pruning attempt.\n    if (bestC == M && !haveBestFull) {\n        vector<int> placeCnt(places.size());\n        vector<int> fullCnt(M);\n        recomputeCounts(bestLetters, words, places, placeCnt, fullCnt);\n\n        Board tb = bestLetters;\n        int dots = pruneDots(tb, placeCnt, fullCnt, places, cellInc, rng);\n        bestFull = tb;\n        bestDots = dots;\n        haveBestFull = true;\n    }\n\n    if (haveBestFull) {\n        outputBoard(bestFull);\n    } else {\n        outputBoard(bestLetters);\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INF = (1LL << 60);\n\nstruct HSeg { int row, l, r; };\nstruct VSeg { int col, u, d; };\nstruct Plan { string route; ll cost; };\nstruct SimResult { bool ok; ll cost; };\n\nstatic const int di[4] = {-1, 1, 0, 0};\nstatic const int dj[4] = {0, 0, -1, 1};\nstatic const char dc[4] = {'U', 'D', 'L', 'R'};\nstatic const int invd[4] = {1, 0, 3, 2};\n\nstruct Solver {\n    using Graph = vector<vector<pair<int,int>>>;\n\n    int N, si, sj, M, start;\n    vector<string> grid;\n    vector<int> wt, rowOf, colOf;\n    vector<char> road;\n    vector<int> hOf, vOf;\n    vector<vector<int>> hCells, vCells;\n    vector<HSeg> hsegs;\n    vector<VSeg> vsegs;\n    Graph adjCell, radjCell;\n\n    void read_input() {\n        cin >> N >> si >> sj;\n        grid.resize(N);\n        for (int i = 0; i < N; ++i) cin >> grid[i];\n        M = N * N;\n        start = si * N + sj;\n\n        wt.assign(M, 0);\n        rowOf.assign(M, 0);\n        colOf.assign(M, 0);\n        road.assign(M, 0);\n        hOf.assign(M, -1);\n        vOf.assign(M, -1);\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int idx = i * N + j;\n                rowOf[idx] = i;\n                colOf[idx] = j;\n                if (grid[i][j] != '#') {\n                    road[idx] = 1;\n                    wt[idx] = grid[i][j] - '0';\n                }\n            }\n        }\n\n        // Build original cell graph\n        adjCell.assign(M, {});\n        radjCell.assign(M, {});\n        for (int idx = 0; idx < M; ++idx) {\n            if (!road[idx]) continue;\n            int i = rowOf[idx], j = colOf[idx];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int to = ni * N + nj;\n                if (!road[to]) continue;\n                adjCell[idx].push_back({to, wt[to]});\n                radjCell[to].push_back({idx, wt[to]});\n            }\n        }\n\n        // Horizontal segments on even rows\n        for (int i = 0; i < N; i += 2) {\n            int j = 0;\n            while (j < N) {\n                while (j < N && !road[i * N + j]) ++j;\n                if (j >= N) break;\n                int l = j;\n                vector<int> cells;\n                while (j < N && road[i * N + j]) {\n                    int idx = i * N + j;\n                    cells.push_back(idx);\n                    ++j;\n                }\n                int r = j - 1;\n                int id = (int)hsegs.size();\n                hsegs.push_back({i, l, r});\n                hCells.push_back(cells);\n                for (int x : cells) hOf[x] = id;\n            }\n        }\n\n        // Vertical segments on even cols\n        for (int j = 0; j < N; j += 2) {\n            int i = 0;\n            while (i < N) {\n                while (i < N && !road[i * N + j]) ++i;\n                if (i >= N) break;\n                int u = i;\n                vector<int> cells;\n                while (i < N && road[i * N + j]) {\n                    int idx = i * N + j;\n                    cells.push_back(idx);\n                    ++i;\n                }\n                int d = i - 1;\n                int id = (int)vsegs.size();\n                vsegs.push_back({j, u, d});\n                vCells.push_back(cells);\n                for (int x : cells) vOf[x] = id;\n            }\n        }\n    }\n\n    void dijkstra(int src, const Graph& graph, vector<ll>& dist, vector<int>& par, vector<int>* parEdge = nullptr) const {\n        int V = (int)graph.size();\n        dist.assign(V, INF);\n        par.assign(V, -1);\n        if (parEdge) parEdge->assign(V, -1);\n\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[src] = 0;\n        par[src] = src;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, w] : graph[u]) {\n                ll nd = d + w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    par[v] = u;\n                    if (parEdge) (*parEdge)[v] = w; // not used for this graph variant\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n\n    void dijkstraNode(int src, const Graph& graph, vector<ll>& dist, vector<int>& parV, vector<int>& parE) const {\n        int V = (int)graph.size();\n        dist.assign(V, INF);\n        parV.assign(V, -1);\n        parE.assign(V, -1);\n\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[src] = 0;\n        parV[src] = src;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, eid] : graph[u]) {\n                const auto& e = nodeEdges[eid];\n                ll nd = d + e.cost;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parV[v] = u;\n                    parE[v] = eid;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n\n    struct NodeEdge {\n        int u, v;\n        int cost;\n        string moves; // from u -> v\n    };\n    vector<NodeEdge> nodeEdges;\n\n    Plan buildGreedy() const {\n        int totalSeg = (int)hsegs.size() + (int)vsegs.size();\n\n        vector<char> coveredH(hsegs.size(), 0), coveredV(vsegs.size(), 0);\n        vector<int> seenH(hsegs.size(), 0), seenV(vsegs.size(), 0);\n        int stamp = 0, coveredCnt = 0;\n\n        auto coverCell = [&](int idx) {\n            int add = 0;\n            int h = hOf[idx];\n            if (h != -1 && !coveredH[h]) {\n                coveredH[h] = 1;\n                ++add;\n            }\n            int v = vOf[idx];\n            if (v != -1 && !coveredV[v]) {\n                coveredV[v] = 1;\n                ++add;\n            }\n            coveredCnt += add;\n        };\n\n        coverCell(start);\n\n        vector<ll> retDist;\n        vector<int> dummyPar;\n        dijkstra(start, radjCell, retDist, dummyPar);\n\n        vector<int> candidates;\n        vector<char> isCand(M, 0);\n        auto addCand = [&](int idx) {\n            if (idx < 0 || idx >= M) return;\n            if (!road[idx]) return;\n            if (!isCand[idx]) {\n                isCand[idx] = 1;\n                candidates.push_back(idx);\n            }\n        };\n\n        for (int idx = 0; idx < M; ++idx) {\n            if (!road[idx]) continue;\n            if (hOf[idx] != -1 && vOf[idx] != -1) addCand(idx); // intersections\n        }\n        for (const auto& s : hsegs) addCand(s.row * N + (s.l + s.r) / 2);\n        for (const auto& s : vsegs) addCand(((s.u + s.d) / 2) * N + s.col);\n\n        int current = start;\n        string ans;\n        ans.reserve(30000);\n        ll totalCost = 0;\n\n        auto appendPath = [&](const vector<int>& path) {\n            int prev = current;\n            for (int idx : path) {\n                int pi = rowOf[prev], pj2 = colOf[prev];\n                int i = rowOf[idx], j = colOf[idx];\n                if (i == pi - 1 && j == pj2) ans.push_back('U');\n                else if (i == pi + 1 && j == pj2) ans.push_back('D');\n                else if (i == pi && j == pj2 - 1) ans.push_back('L');\n                else if (i == pi && j == pj2 + 1) ans.push_back('R');\n                else {\n                    // Should not happen\n                }\n                totalCost += wt[idx];\n                prev = idx;\n                // mark coverage\n                int h = hOf[idx];\n                if (h != -1 && !coveredH[h]) {\n                    coveredH[h] = 1;\n                    ++coveredCnt;\n                }\n                int v = vOf[idx];\n                if (v != -1 && !coveredV[v]) {\n                    coveredV[v] = 1;\n                    ++coveredCnt;\n                }\n            }\n            current = prev;\n        };\n\n        while (coveredCnt < totalSeg) {\n            vector<ll> dist;\n            vector<int> par;\n            dijkstra(current, adjCell, dist, par);\n\n            int rem = totalSeg - coveredCnt;\n            long double bonus, retCoef;\n            if (rem * 3 > totalSeg * 2) {\n                bonus = 20.0L;\n                retCoef = 0.05L;\n            } else if (rem * 3 > totalSeg) {\n                bonus = 17.0L;\n                retCoef = 0.10L;\n            } else {\n                bonus = 14.0L;\n                retCoef = 0.20L;\n            }\n\n            long double bestScore = -1e100L;\n            int bestCand = -1;\n            int bestGain = -1;\n            ll bestDist = INF, bestRet = INF;\n            vector<int> bestPath;\n\n            vector<int> tmp;\n            tmp.reserve(256);\n\n            for (int cand : candidates) {\n                if (dist[cand] >= INF / 2) continue;\n                tmp.clear();\n                int x = cand;\n                bool ok = true;\n                while (x != current) {\n                    if (x < 0 || x >= M || par[x] == -1) { ok = false; break; }\n                    tmp.push_back(x);\n                    x = par[x];\n                }\n                if (!ok || tmp.empty()) continue;\n\n                int gain = 0;\n                ++stamp;\n                for (int idx : tmp) {\n                    int h = hOf[idx];\n                    if (h != -1 && !coveredH[h] && seenH[h] != stamp) {\n                        seenH[h] = stamp;\n                        ++gain;\n                    }\n                    int v = vOf[idx];\n                    if (v != -1 && !coveredV[v] && seenV[v] != stamp) {\n                        seenV[v] = stamp;\n                        ++gain;\n                    }\n                }\n                if (gain == 0) continue;\n\n                long double score = bonus * gain - (long double)dist[cand] - retCoef * (long double)retDist[cand];\n                if (score > bestScore + 1e-12L ||\n                    (fabsl(score - bestScore) <= 1e-12L &&\n                     (gain > bestGain ||\n                      (gain == bestGain && (dist[cand] < bestDist ||\n                                            (dist[cand] == bestDist && retDist[cand] < bestRet)))))) {\n                    bestScore = score;\n                    bestCand = cand;\n                    bestGain = gain;\n                    bestDist = dist[cand];\n                    bestRet = retDist[cand];\n                    bestPath = tmp;\n                    reverse(bestPath.begin(), bestPath.end());\n                }\n            }\n\n            if (bestCand == -1) {\n                // Safety fallback\n                bool found = false;\n                for (int cand : candidates) {\n                    if (dist[cand] >= INF / 2) continue;\n                    int h = hOf[cand], v = vOf[cand];\n                    if ((h != -1 && !coveredH[h]) || (v != -1 && !coveredV[v])) {\n                        tmp.clear();\n                        int x = cand;\n                        bool ok = true;\n                        while (x != current) {\n                            if (x < 0 || x >= M || par[x] == -1) { ok = false; break; }\n                            tmp.push_back(x);\n                            x = par[x];\n                        }\n                        if (!ok || tmp.empty()) continue;\n                        bestPath = tmp;\n                        reverse(bestPath.begin(), bestPath.end());\n                        found = true;\n                        break;\n                    }\n                }\n                if (!found) break;\n            }\n\n            appendPath(bestPath);\n        }\n\n        if (current != start) {\n            vector<ll> dist;\n            vector<int> par;\n            dijkstra(current, adjCell, dist, par);\n            vector<int> back;\n            int x = start;\n            while (x != current) {\n                if (x < 0 || x >= M || par[x] == -1) break;\n                back.push_back(x);\n                x = par[x];\n            }\n            if (!back.empty()) {\n                reverse(back.begin(), back.end());\n                appendPath(back);\n            }\n        }\n\n        return {ans, totalCost};\n    }\n\n    Plan buildPostman() {\n        // Build node set: all road cells with degree != 2, or turn cells, plus start.\n        vector<int> deg(M, 0);\n        for (int idx = 0; idx < M; ++idx) deg[idx] = (int)adjCell[idx].size();\n\n        vector<char> isNode(M, 0);\n        vector<int> nodeCells;\n        for (int idx = 0; idx < M; ++idx) {\n            if (!road[idx]) continue;\n            bool node = false;\n            if (idx == start) node = true;\n            else if (deg[idx] != 2) node = true;\n            else {\n                int a = adjCell[idx][0].first;\n                int b = adjCell[idx][1].first;\n                // Straight if same row or same col, otherwise a turn.\n                if (!(rowOf[a] == rowOf[b] || colOf[a] == colOf[b])) node = true;\n            }\n            if (node) {\n                isNode[idx] = 1;\n                nodeCells.push_back(idx);\n            }\n        }\n\n        vector<int> nodeId(M, -1);\n        for (int i = 0; i < (int)nodeCells.size(); ++i) nodeId[nodeCells[i]] = i;\n        int V = (int)nodeCells.size();\n\n        // Trace compressed edges\n        vector<array<char,4>> usedStep(M);\n        for (auto &a : usedStep) a.fill(0);\n\n        struct CEdge {\n            int u, v, cost;\n            string moves; // from u to v\n        };\n        vector<CEdge> edges;\n        vector<vector<pair<int,int>>> gnode(V); // to, edgeId\n\n        auto inside = [&](int i, int j) {\n            return 0 <= i && i < N && 0 <= j && j < N;\n        };\n        auto neighbor = [&](int idx, int d) {\n            int i = rowOf[idx] + di[d];\n            int j = colOf[idx] + dj[d];\n            if (!inside(i, j)) return -1;\n            return i * N + j;\n        };\n\n        for (int idx : nodeCells) {\n            for (int d = 0; d < 4; ++d) {\n                int nxt = neighbor(idx, d);\n                if (nxt < 0 || !road[nxt]) continue;\n                if (usedStep[idx][d]) continue;\n\n                int cur = idx;\n                int prev = idx;\n                int dir = d;\n                int nxtCell = nxt;\n                int cost = 0;\n                string mv;\n\n                while (true) {\n                    usedStep[cur][dir] = 1;\n                    usedStep[nxtCell][invd[dir]] = 1;\n\n                    mv.push_back(dc[dir]);\n                    cost += wt[nxtCell];\n\n                    prev = cur;\n                    cur = nxtCell;\n                    if (isNode[cur]) break;\n\n                    int nd = -1, nn = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int t = neighbor(cur, d2);\n                        if (t < 0 || !road[t] || t == prev) continue;\n                        nd = d2;\n                        nn = t;\n                        break;\n                    }\n                    if (nd == -1) break; // should not happen\n                    dir = nd;\n                    nxtCell = nn;\n                }\n\n                int a = nodeId[idx];\n                int b = nodeId[cur];\n                int eid = (int)edges.size();\n                edges.push_back({a, b, cost, mv});\n                if (a == b) {\n                    gnode[a].push_back({b, eid});\n                    gnode[a].push_back({b, eid});\n                } else {\n                    gnode[a].push_back({b, eid});\n                    gnode[b].push_back({a, eid});\n                }\n            }\n        }\n\n        // Build shortest path trees from each odd vertex\n        vector<int> odd;\n        for (int u = 0; u < V; ++u) {\n            if ((int)gnode[u].size() % 2 == 1) odd.push_back(u);\n        }\n\n        vector<vector<ll>> distOdd;\n        vector<vector<int>> parVOdd, parEOdd;\n        distOdd.resize(odd.size());\n        parVOdd.resize(odd.size());\n        parEOdd.resize(odd.size());\n\n        // Need Dijkstra on compressed graph; use local lambda\n        auto dijkstraOnNodeGraph = [&](int src, vector<ll>& dist, vector<int>& parV, vector<int>& parE) {\n            dist.assign(V, INF);\n            parV.assign(V, -1);\n            parE.assign(V, -1);\n            priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n            dist[src] = 0;\n            parV[src] = src;\n            pq.push({0, src});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                if (d != dist[u]) continue;\n                for (auto [v, eid] : gnode[u]) {\n                    ll nd = d + edges[eid].cost;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        parV[v] = u;\n                        parE[v] = eid;\n                        pq.push({nd, v});\n                    }\n                }\n            }\n        };\n\n        for (int i = 0; i < (int)odd.size(); ++i) {\n            dijkstraOnNodeGraph(odd[i], distOdd[i], parVOdd[i], parEOdd[i]);\n        }\n\n        auto makeDup = [&](int strategy) {\n            vector<int> dup(edges.size(), 0);\n            ll extra = 0;\n            int O = (int)odd.size();\n            if (O == 0) return pair<vector<int>, ll>{dup, 0};\n\n            if (strategy == 0) {\n                vector<char> used(O, 0);\n                int rem = O;\n                while (rem > 0) {\n                    ll best = INF;\n                    int bi = -1, bj = -1;\n                    for (int i = 0; i < O; ++i) if (!used[i]) {\n                        for (int j = i + 1; j < O; ++j) if (!used[j]) {\n                            ll d = distOdd[i][odd[j]];\n                            if (d < best) {\n                                best = d;\n                                bi = i;\n                                bj = j;\n                            }\n                        }\n                    }\n                    if (bi == -1) break;\n                    used[bi] = used[bj] = 1;\n                    rem -= 2;\n                    extra += best;\n                    int v = odd[bj];\n                    while (v != odd[bi]) {\n                        int eid = parEOdd[bi][v];\n                        dup[eid]++;\n                        v = parVOdd[bi][v];\n                    }\n                }\n            } else {\n                vector<int> order(O);\n                iota(order.begin(), order.end(), 0);\n                if (strategy == 2) {\n                    reverse(order.begin(), order.end());\n                } else if (strategy == 3) {\n                    mt19937 rng(712367);\n                    shuffle(order.begin(), order.end(), rng);\n                }\n\n                vector<char> used(O, 0);\n                for (int pos = 0; pos < O; ++pos) {\n                    int i = order[pos];\n                    if (used[i]) continue;\n                    used[i] = 1;\n                    int bj = -1;\n                    ll best = INF;\n                    for (int pos2 = pos + 1; pos2 < O; ++pos2) {\n                        int j = order[pos2];\n                        if (used[j]) continue;\n                        ll d = distOdd[i][odd[j]];\n                        if (d < best) {\n                            best = d;\n                            bj = j;\n                        }\n                    }\n                    if (bj == -1) continue;\n                    used[bj] = 1;\n                    extra += best;\n                    int v = odd[bj];\n                    while (v != odd[i]) {\n                        int eid = parEOdd[i][v];\n                        dup[eid]++;\n                        v = parVOdd[i][v];\n                    }\n                }\n            }\n            return pair<vector<int>, ll>{dup, extra};\n        };\n\n        vector<int> bestDup(edges.size(), 0);\n        ll bestExtra = INF;\n        for (int s = 0; s < 4; ++s) {\n            auto [dup, extra] = makeDup(s);\n            if (extra < bestExtra) {\n                bestExtra = extra;\n                bestDup.swap(dup);\n            }\n        }\n\n        // Build Eulerian multigraph with duplicated edges\n        struct UseEdge { int u, v, orig; };\n        vector<UseEdge> uses;\n        vector<vector<pair<int,int>>> multAdj(V); // to, useId\n\n        for (int eid = 0; eid < (int)edges.size(); ++eid) {\n            int cnt = 1 + bestDup[eid];\n            for (int k = 0; k < cnt; ++k) {\n                int uid = (int)uses.size();\n                uses.push_back({edges[eid].u, edges[eid].v, eid});\n                if (edges[eid].u == edges[eid].v) {\n                    multAdj[edges[eid].u].push_back({edges[eid].v, uid});\n                    multAdj[edges[eid].u].push_back({edges[eid].v, uid});\n                } else {\n                    multAdj[edges[eid].u].push_back({edges[eid].v, uid});\n                    multAdj[edges[eid].v].push_back({edges[eid].u, uid});\n                }\n            }\n        }\n\n        // Hierholzer\n        vector<int> it(V, 0);\n        vector<char> usedUse(uses.size(), 0);\n        vector<int> stV, stE;\n        vector<char> stRev;\n        vector<pair<int, char>> circuit;\n        stV.push_back(nodeId[start]); // start at the exact start cell\n\n        while (!stV.empty()) {\n            int v = stV.back();\n            auto &adj = multAdj[v];\n            while (it[v] < (int)adj.size() && usedUse[adj[it[v]].second]) ++it[v];\n            if (it[v] == (int)adj.size()) {\n                stV.pop_back();\n                if (!stE.empty()) {\n                    circuit.push_back({stE.back(), stRev.back()});\n                    stE.pop_back();\n                    stRev.pop_back();\n                }\n            } else {\n                auto [to, uid] = adj[it[v]++];\n                if (usedUse[uid]) continue;\n                usedUse[uid] = 1;\n                bool rev = (v != uses[uid].u);\n                stV.push_back(to);\n                stE.push_back(uid);\n                stRev.push_back((char)rev);\n            }\n        }\n\n        reverse(circuit.begin(), circuit.end());\n\n        string route;\n        route.reserve(30000);\n        for (auto [uid, rev] : circuit) {\n            const auto &e = edges[uses[uid].orig];\n            if (!rev) {\n                route += e.moves;\n            } else {\n                for (int i = (int)e.moves.size() - 1; i >= 0; --i) {\n                    char c = e.moves[i];\n                    if (c == 'U') route.push_back('D');\n                    else if (c == 'D') route.push_back('U');\n                    else if (c == 'L') route.push_back('R');\n                    else route.push_back('L');\n                }\n            }\n        }\n\n        return {route, 0};\n    }\n\n    SimResult simulate(const string& s) const {\n        int ci = si, cj = sj;\n        vector<char> covH(hsegs.size(), 0), covV(vsegs.size(), 0);\n        int cov = 0;\n\n        auto cover = [&](int idx) {\n            int h = hOf[idx];\n            if (h != -1 && !covH[h]) {\n                covH[h] = 1;\n                ++cov;\n            }\n            int v = vOf[idx];\n            if (v != -1 && !covV[v]) {\n                covV[v] = 1;\n                ++cov;\n            }\n        };\n\n        cover(start);\n        ll cost = 0;\n        for (char c : s) {\n            int d = -1;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            else return {false, 0};\n\n            int ni = ci + di[d];\n            int nj = cj + dj[d];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) return {false, 0};\n            int nxt = ni * N + nj;\n            if (!road[nxt]) return {false, 0};\n\n            ci = ni;\n            cj = nj;\n            cost += wt[nxt];\n            cover(nxt);\n        }\n\n        if (ci != si || cj != sj) return {false, 0};\n        if (cov != (int)hsegs.size() + (int)vsegs.size()) return {false, 0};\n        return {true, cost};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.read_input();\n\n    auto greedy = solver.buildGreedy();\n    auto postman = solver.buildPostman();\n\n    auto sg = solver.simulate(greedy.route);\n    auto sp = solver.simulate(postman.route);\n\n    string ans;\n    if (sg.ok && sp.ok) {\n        ans = (sg.cost <= sp.cost ? greedy.route : postman.route);\n    } else if (sg.ok) {\n        ans = greedy.route;\n    } else if (sp.ok) {\n        ans = postman.route;\n    } else {\n        // Extremely unlikely fallback\n        ans = greedy.route;\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskNode {\n    long long pr;\n    int id;\n};\n\nstruct TaskCmp {\n    bool operator()(const TaskNode& a, const TaskNode& b) const {\n        if (a.pr != b.pr) return a.pr < b.pr; // max-heap by priority\n        return a.id > b.id;                  // smaller id first on tie\n    }\n};\n\nstatic const double INIT_SKILL = 5.0;\n\nvector<int> hungarian_min_cost(const vector<vector<double>>& a) {\n    int n = (int)a.size();\n    const double INF = 1e100;\n    vector<double> u(n + 1, 0.0), v(n + 1, 0.0), minv(n + 1);\n    vector<int> p(n + 1, 0), way(n + 1, 0);\n\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        fill(minv.begin(), minv.end(), INF);\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            double delta = INF;\n            int j1 = 0;\n\n            for (int j = 1; j <= n; ++j) {\n                if (used[j]) continue;\n                double cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n\n            for (int j = 0; j <= n; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    vector<int> ans(n, -1);\n    for (int j = 1; j <= n; ++j) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<vector<int>> d(N, vector<int>(K));\n    vector<long long> sumd(N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            cin >> d[i][k];\n            sumd[i] += d[i][k];\n        }\n    }\n\n    vector<vector<int>> succ(N);\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Weighted criticality: own difficulty + longest downstream chain difficulty.\n    vector<long long> workRemain(N, 0), height(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        long long bestWork = 0;\n        long long bestH = 0;\n        for (int v : succ[i]) {\n            bestWork = max(bestWork, workRemain[v]);\n            bestH = max(bestH, height[v]);\n        }\n        workRemain[i] = sumd[i] + bestWork;\n        height[i] = 1 + bestH;\n    }\n\n    vector<long long> priority(N, 0);\n    for (int i = 0; i < N; ++i) {\n        priority[i] = workRemain[i] * 1000LL + height[i];\n    }\n\n    priority_queue<TaskNode, vector<TaskNode>, TaskCmp> pq;\n    for (int i = 0; i < N; ++i) {\n        if (indeg[i] == 0) pq.push({priority[i], i});\n    }\n\n    vector<int> busyTask(M, -1);\n    vector<int> startDay(M, -1);\n    vector<int> taskStatus(N, 0); // 0=not started, 1=started, 2=done\n    vector<vector<double>> skill(M, vector<double>(K, INIT_SKILL));\n    vector<int> obsCnt(M, 0);\n\n    auto predict_duration = [&](int mem, int task) -> double {\n        double w = 0.0;\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill[mem][k]) {\n                w += (double)d[task][k] - skill[mem][k];\n            }\n        }\n        return max(1.0, w);\n    };\n\n    auto update_skill = [&](int mem, int task, int dur) {\n        double w = 0.0;\n        vector<double> gap(K, 0.0);\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill[mem][k]) {\n                gap[k] = (double)d[task][k] - skill[mem][k];\n                w += gap[k];\n            }\n        }\n\n        double pred = max(1.0, w);\n        double err = (double)dur - pred;\n        err = max(-4.0, min(4.0, err));\n\n        double eta = 0.5 / sqrt((double)obsCnt[mem] + 1.0);\n\n        if (w > 1e-9) {\n            for (int k = 0; k < K; ++k) {\n                if (gap[k] <= 0.0) continue;\n                skill[mem][k] -= eta * err * (gap[k] / w);\n                if (skill[mem][k] < 0.0) skill[mem][k] = 0.0;\n                if (skill[mem][k] > 100.0) skill[mem][k] = 100.0;\n            }\n        } else if (err > 0.0) {\n            // If predicted exactly 1, but actual duration was longer, lower all skills slightly.\n            double dec = eta * err / max(1, K);\n            for (int k = 0; k < K; ++k) {\n                skill[mem][k] = max(0.0, skill[mem][k] - dec);\n            }\n        }\n\n        obsCnt[mem]++;\n    };\n\n    int day = 1;\n    while (true) {\n        vector<int> freeMembers;\n        freeMembers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (busyTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        int freeCount = (int)freeMembers.size();\n        int take = min(freeCount, (int)pq.size());\n\n        vector<int> selected;\n        selected.reserve(take);\n        for (int t = 0; t < take; ++t) {\n            selected.push_back(pq.top().id);\n            pq.pop();\n        }\n\n        vector<pair<int,int>> outPairs;\n\n        if (freeCount > 0 && !selected.empty()) {\n            int n = freeCount;\n            int L = (int)selected.size();\n\n            vector<vector<double>> cost(n, vector<double>(n, 0.0));\n            for (int r = 0; r < n; ++r) {\n                int mem = freeMembers[r];\n                for (int c = 0; c < L; ++c) {\n                    cost[r][c] = predict_duration(mem, selected[c]);\n                }\n                for (int c = L; c < n; ++c) {\n                    cost[r][c] = 0.0; // dummy task\n                }\n            }\n\n            vector<int> assign = hungarian_min_cost(cost);\n\n            for (int r = 0; r < n; ++r) {\n                int c = assign[r];\n                if (c >= 0 && c < L) {\n                    int mem = freeMembers[r];\n                    int task = selected[c];\n                    outPairs.push_back({mem, task});\n                    busyTask[mem] = task;\n                    startDay[mem] = day;\n                    taskStatus[task] = 1;\n                }\n            }\n        }\n\n        cout << outPairs.size();\n        for (auto &p : outPairs) {\n            cout << ' ' << (p.first + 1) << ' ' << (p.second + 1);\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        vector<int> finished(cnt);\n        for (int i = 0; i < cnt; ++i) cin >> finished[i];\n\n        for (int mem1 : finished) {\n            int mem = mem1 - 1;\n            int task = busyTask[mem];\n            if (task < 0) continue;\n\n            int dur = day - startDay[mem] + 1;\n            update_skill(mem, task, dur);\n\n            busyTask[mem] = -1;\n            startDay[mem] = -1;\n            taskStatus[task] = 2;\n\n            for (int v : succ[task]) {\n                if (--indeg[v] == 0) {\n                    pq.push({priority[v], v});\n                }\n            }\n        }\n\n        day++;\n    }\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Pt {\n    int x, y;\n};\n\nstruct Order {\n    Pt p, q;\n    ll op, oq, pq;\n};\n\nstruct Event {\n    int id;\n    int type; // 0: pickup, 1: delivery\n};\n\nstruct Candidate {\n    vector<pair<ll,int>> ranked; // ascending by selection score\n    vector<int> ids;             // selected ids, sorted by id\n};\n\nstruct InsertChoice {\n    ll delta;\n    int i, j;\n    bool same;\n};\n\nstruct RouteRes {\n    ll cost = (1LL<<60);\n    vector<Event> seq;\n};\n\nstatic constexpr int N = 1000;\nstatic constexpr Pt OFFICE{400, 400};\n\nvector<Order> ord(N);\n\nstatic inline ll absl(ll x) { return x >= 0 ? x : -x; }\nstatic inline ll md(const Pt& a, const Pt& b) {\n    return absl((ll)a.x - b.x) + absl((ll)a.y - b.y);\n}\nstatic inline Pt pointOf(const Event& e) {\n    return (e.type == 0 ? ord[e.id].p : ord[e.id].q);\n}\nstatic inline ll routeCost(const vector<Event>& seq) {\n    ll cost = 0;\n    Pt cur = OFFICE;\n    for (const auto& e : seq) {\n        Pt nxt = pointOf(e);\n        cost += md(cur, nxt);\n        cur = nxt;\n    }\n    cost += md(cur, OFFICE);\n    return cost;\n}\n\nstatic bool feasibleSeq(const vector<Event>& seq, const vector<int>& selIds) {\n    static int posP[N], posQ[N];\n    fill(posP, posP + N, -1);\n    fill(posQ, posQ + N, -1);\n    for (int i = 0; i < (int)seq.size(); ++i) {\n        if (seq[i].type == 0) posP[seq[i].id] = i;\n        else posQ[seq[i].id] = i;\n    }\n    for (int id : selIds) {\n        if (posP[id] > posQ[id]) return false;\n    }\n    return true;\n}\n\nstatic InsertChoice chooseInsert(const vector<Event>& seq, int id) {\n    vector<Pt> pts;\n    pts.reserve(seq.size() + 2);\n    pts.push_back(OFFICE);\n    for (const auto& e : seq) pts.push_back(pointOf(e));\n    pts.push_back(OFFICE);\n\n    Pt P = ord[id].p, Q = ord[id].q;\n    int m = (int)seq.size();\n\n    ll best = (1LL << 60);\n    int bi = 0, bj = 0;\n    bool same = true;\n\n    for (int i = 0; i <= m; ++i) {\n        ll dSame = md(pts[i], P) + md(P, Q) + md(Q, pts[i + 1]) - md(pts[i], pts[i + 1]);\n        if (dSame < best) {\n            best = dSame;\n            bi = i;\n            bj = i;\n            same = true;\n        }\n        for (int j = i + 1; j <= m; ++j) {\n            ll d = md(pts[i], P) + md(P, pts[i + 1]) - md(pts[i], pts[i + 1])\n                 + md(pts[j], Q) + md(Q, pts[j + 1]) - md(pts[j], pts[j + 1]);\n            if (d < best) {\n                best = d;\n                bi = i;\n                bj = j;\n                same = false;\n            }\n        }\n    }\n    return {best, bi, bj, same};\n}\n\nstatic void applyInsert(vector<Event>& seq, const InsertChoice& ch, int id) {\n    if (ch.same) {\n        seq.insert(seq.begin() + ch.i, Event{id, 0});\n        seq.insert(seq.begin() + ch.i + 1, Event{id, 1});\n    } else {\n        seq.insert(seq.begin() + ch.i, Event{id, 0});\n        seq.insert(seq.begin() + ch.j + 1, Event{id, 1});\n    }\n}\n\nstatic void adjacentImprove(vector<Event>& seq, ll& curCost, const vector<int>& selIds) {\n    for (int iter = 0; iter < 30; ++iter) {\n        bool improved = false;\n        for (int i = 0; i + 1 < (int)seq.size(); ++i) {\n            if (seq[i].id == seq[i + 1].id) continue;\n            vector<Event> cand = seq;\n            swap(cand[i], cand[i + 1]);\n            if (!feasibleSeq(cand, selIds)) continue;\n            ll cc = routeCost(cand);\n            if (cc < curCost) {\n                seq.swap(cand);\n                curCost = cc;\n                improved = true;\n                break;\n            }\n        }\n        if (!improved) break;\n    }\n}\n\nstatic void reinsertImprove(vector<Event>& seq, ll& curCost, const vector<int>& orderList) {\n    for (int pass = 0; pass < 2; ++pass) {\n        vector<int> ords = orderList;\n        if (pass == 1) reverse(ords.begin(), ords.end());\n\n        bool changed = false;\n        for (int id : ords) {\n            vector<Event> base = seq;\n            ll orig = curCost;\n\n            int p = -1, q = -1;\n            for (int i = 0; i < (int)seq.size(); ++i) {\n                if (seq[i].id == id) {\n                    if (seq[i].type == 0) p = i;\n                    else q = i;\n                }\n            }\n            if (p > q) swap(p, q);\n\n            seq.erase(seq.begin() + q);\n            seq.erase(seq.begin() + p);\n\n            ll reducedCost = routeCost(seq);\n            InsertChoice ch = chooseInsert(seq, id);\n            applyInsert(seq, ch, id);\n            ll candCost = reducedCost + ch.delta;\n\n            if (candCost < orig) {\n                curCost = candCost;\n                changed = true;\n            } else {\n                seq.swap(base);\n                curCost = orig;\n            }\n        }\n        if (!changed) break;\n    }\n}\n\nstatic Candidate makeCandidateFromScores(const vector<ll>& scores) {\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n\n    auto cmp = [&](int a, int b) {\n        if (scores[a] != scores[b]) return scores[a] < scores[b];\n        return a < b;\n    };\n\n    partial_sort(idx.begin(), idx.begin() + 50, idx.end(), cmp);\n\n    Candidate c;\n    c.ranked.reserve(50);\n    c.ids.reserve(50);\n    for (int k = 0; k < 50; ++k) {\n        int id = idx[k];\n        c.ranked.push_back({scores[id], id});\n        c.ids.push_back(id);\n    }\n    sort(c.ids.begin(), c.ids.end());\n    return c;\n}\n\nstatic RouteRes buildRoute(const Candidate& cand, int mode) {\n    vector<int> order;\n    order.reserve(50);\n\n    if (mode == 0) {\n        // Insert in descending order of the selection score.\n        for (auto it = cand.ranked.rbegin(); it != cand.ranked.rend(); ++it) {\n            order.push_back(it->second);\n        }\n    } else {\n        // Insert in descending order of (pair length + distance to office).\n        order = cand.ids;\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            ll ka = ord[a].pq + ord[a].op + ord[a].oq;\n            ll kb = ord[b].pq + ord[b].op + ord[b].oq;\n            if (ka != kb) return ka > kb;\n            return a < b;\n        });\n    }\n\n    vector<Event> seq;\n    seq.reserve(100);\n    ll curCost = 0;\n\n    for (int id : order) {\n        InsertChoice ch = chooseInsert(seq, id);\n        applyInsert(seq, ch, id);\n        curCost += ch.delta;\n    }\n\n    adjacentImprove(seq, curCost, cand.ids);\n    curCost = routeCost(seq);\n\n    return {curCost, std::move(seq)};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; ++i) {\n        cin >> ord[i].p.x >> ord[i].p.y >> ord[i].q.x >> ord[i].q.y;\n        ord[i].op = md(ord[i].p, OFFICE);\n        ord[i].oq = md(ord[i].q, OFFICE);\n        ord[i].pq = md(ord[i].p, ord[i].q);\n    }\n\n    vector<Candidate> candidates;\n    candidates.reserve(400);\n\n    auto addCandidateByFormula = [&](const Pt& anchor, int family, int lambda) {\n        vector<ll> scores(N);\n        for (int i = 0; i < N; ++i) {\n            ll dp = md(ord[i].p, anchor);\n            ll dq = md(ord[i].q, anchor);\n            ll base = (family == 0 ? dp + dq : max(dp, dq));\n            scores[i] = base + 1LL * lambda * ord[i].pq;\n        }\n        candidates.push_back(makeCandidateFromScores(scores));\n    };\n\n    // 9x9 grid anchors.\n    for (int x = 0; x <= 800; x += 100) {\n        for (int y = 0; y <= 800; y += 100) {\n            Pt a{x, y};\n            addCandidateByFormula(a, 0, 0);\n            addCandidateByFormula(a, 0, 2);\n            addCandidateByFormula(a, 1, 0);\n            addCandidateByFormula(a, 1, 2);\n        }\n    }\n\n    // Random midpoint anchors for diversity.\n    mt19937 rng(712367821);\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    for (int k = 0; k < 8; ++k) {\n        int id = perm[k];\n        Pt a{(ord[id].p.x + ord[id].q.x) / 2, (ord[id].p.y + ord[id].q.y) / 2};\n        addCandidateByFormula(a, 0, 0);\n        addCandidateByFormula(a, 0, 2);\n        addCandidateByFormula(a, 1, 0);\n        addCandidateByFormula(a, 1, 2);\n    }\n\n    // Global special candidates.\n    {\n        vector<ll> scores(N);\n        for (int i = 0; i < N; ++i) scores[i] = ord[i].pq;\n        candidates.push_back(makeCandidateFromScores(scores));\n    }\n    {\n        vector<ll> scores(N);\n        for (int i = 0; i < N; ++i) scores[i] = ord[i].pq + ord[i].op + ord[i].oq;\n        candidates.push_back(makeCandidateFromScores(scores));\n    }\n\n    int C = (int)candidates.size();\n    vector<RouteRes> best(C);\n\n    // Build mode 0 for all candidates.\n    for (int i = 0; i < C; ++i) {\n        best[i] = buildRoute(candidates[i], 0);\n    }\n\n    // Take top candidates and try mode 1 too.\n    vector<int> order(C);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return best[a].cost < best[b].cost;\n    });\n\n    int TRY = min(60, C);\n    for (int t = 0; t < TRY; ++t) {\n        int i = order[t];\n        RouteRes r = buildRoute(candidates[i], 1);\n        if (r.cost < best[i].cost) best[i] = std::move(r);\n    }\n\n    // Refine top few routes.\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        return best[a].cost < best[b].cost;\n    });\n\n    int REFINE = min(20, C);\n    for (int t = 0; t < REFINE; ++t) {\n        int i = order[t];\n        ll cur = best[i].cost;\n\n        vector<int> orderList = candidates[i].ids;\n        sort(orderList.begin(), orderList.end(), [&](int a, int b) {\n            ll ka = ord[a].pq + ord[a].op + ord[a].oq;\n            ll kb = ord[b].pq + ord[b].op + ord[b].oq;\n            if (ka != kb) return ka > kb;\n            return a < b;\n        });\n\n        reinsertImprove(best[i].seq, cur, orderList);\n        adjacentImprove(best[i].seq, cur, candidates[i].ids);\n        best[i].cost = routeCost(best[i].seq);\n    }\n\n    int bi = min_element(order.begin(), order.end(), [&](int a, int b) {\n        return best[a].cost < best[b].cost;\n    }) - order.begin();\n    int idx = order[bi];\n\n    vector<int> chosen = candidates[idx].ids;\n    vector<Pt> pts;\n    pts.reserve(best[idx].seq.size() + 2);\n    pts.push_back(OFFICE);\n    for (const auto& e : best[idx].seq) pts.push_back(pointOf(e));\n    pts.push_back(OFFICE);\n\n    cout << 50;\n    for (int id : chosen) cout << ' ' << (id + 1);\n    cout << '\\n';\n\n    cout << pts.size();\n    for (const auto& p : pts) cout << ' ' << p.x << ' ' << p.y;\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        iota(p.begin(), p.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        long long dx = (long long)x[edges[i].u] - x[edges[i].v];\n        long long dy = (long long)y[edges[i].u] - y[edges[i].v];\n        long long s = dx * dx + dy * dy;\n        long double r = sqrt((long double)s);\n        edges[i].d = (int)floor(r + 0.5L); // round to nearest integer\n    }\n\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (edges[a].d != edges[b].d) return edges[a].d < edges[b].d;\n        return a < b;\n    });\n\n    DSU dsu(N);\n    vector<char> take(M, 0);\n    for (int id : ord) {\n        if (dsu.unite(edges[id].u, edges[id].v)) {\n            take[id] = 1;\n        }\n    }\n\n    // Online phase: read each l_i and immediately answer.\n    for (int i = 0; i < M; ++i) {\n        int li;\n        cin >> li; // We don't use it; the tree is fixed beforehand.\n        cout << (take[i] ? 1 : 0) << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstatic const int HN = 30;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<Point> pets(N);\n    vector<int> ptype(N);\n    vector<vector<int>> petOcc(HN + 1, vector<int>(HN + 1, 0));\n\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> ptype[i];\n        petOcc[pets[i].x][pets[i].y]++;\n    }\n\n    int M;\n    cin >> M;\n    vector<Point> humans(M);\n    for (int i = 0; i < M; ++i) cin >> humans[i].x >> humans[i].y;\n\n    // Prefix sum of initial pet positions\n    vector<vector<int>> ps(HN + 1 + 1, vector<int>(HN + 1 + 1, 0)); // 32 x 32 enough\n    for (int i = 1; i <= HN; ++i) {\n        for (int j = 1; j <= HN; ++j) {\n            ps[i][j] = petOcc[i][j] + ps[i - 1][j] + ps[i][j - 1] - ps[i - 1][j - 1];\n        }\n    }\n\n    auto rectSum = [&](int r1, int c1, int r2, int c2) -> int {\n        if (r1 > r2 || c1 > c2) return 0;\n        return ps[r2][c2] - ps[r1 - 1][c2] - ps[r2][c1 - 1] + ps[r1 - 1][c1 - 1];\n    };\n\n    auto clampv = [](int v, int l, int r) {\n        return max(l, min(r, v));\n    };\n\n    auto distRect = [&](Point p, int r1, int r2, int c1, int c2) -> int {\n        int dx = 0, dy = 0;\n        if (p.x < r1) dx = r1 - p.x;\n        else if (p.x > r2) dx = p.x - r2;\n        if (p.y < c1) dy = c1 - p.y;\n        else if (p.y > c2) dy = p.y - c2;\n        return dx + dy;\n    };\n\n    struct BestRect {\n        int r1 = -1, r2 = -1, c1 = -1, c2 = -1;\n        long long score = LLONG_MIN;\n        int area = 0;\n    } best;\n\n    // Search an empty rectangle Q.\n    // Final safe area is the inner rectangle Q shrunk by 2 cells on each side.\n    for (int r1 = 1; r1 <= HN; ++r1) {\n        for (int r2 = r1 + 4; r2 <= HN; ++r2) { // height >= 5\n            for (int c1 = 1; c1 <= HN; ++c1) {\n                for (int c2 = c1 + 4; c2 <= HN; ++c2) { // width >= 5\n                    if (rectSum(r1, c1, r2, c2) != 0) continue;\n\n                    int h = r2 - r1 + 1;\n                    int w = c2 - c1 + 1;\n                    int innerH = h - 4;\n                    int innerW = w - 4;\n                    if (innerH <= 0 || innerW <= 0) continue;\n\n                    long long area = 1LL * innerH * innerW;\n                    long long perim = 2LL * (h + w);\n\n                    long long pen = 0;\n                    for (auto &p : pets) {\n                        int d = distRect(p, r1, r2, c1, c2);\n                        pen += 1000LL / (d + 1);\n                    }\n\n                    long long score = area * 100000LL - perim * 1000LL - pen;\n\n                    if (score > best.score) {\n                        best.score = score;\n                        best.r1 = r1; best.r2 = r2;\n                        best.c1 = c1; best.c2 = c2;\n                        best.area = (int)area;\n                    }\n                }\n            }\n        }\n    }\n\n    // If no usable rectangle is found, fall back to doing nothing.\n    if (best.r1 == -1 || best.area <= 0) {\n        for (int turn = 0; turn < 300; ++turn) {\n            cout << string(M, '.') << '\\n' << flush;\n            for (int i = 0; i < N; ++i) {\n                string s;\n                cin >> s;\n            }\n        }\n        return 0;\n    }\n\n    int r1 = best.r1, r2 = best.r2, c1 = best.c1, c2 = best.c2;\n    int x1 = r1 + 2, x2 = r2 - 2;\n    int y1 = c1 + 2, y2 = c2 - 2;\n    int H = x2 - x1 + 1; // inner height\n    int W = y2 - y1 + 1; // inner width\n\n    // Roles:\n    // 0: TOP    - start at (x1, y1), wall up, move right\n    // 1: LEFT   - start at (x1, y1), wall left, move down\n    // 2: BOTTOM - start at (x2, y1), wall down, move right\n    // 3: RIGHT  - start at (x1, y2), wall right, move down\n    enum Role { IDLE = 0, TOP = 1, LEFT = 2, BOTTOM = 3, RIGHT = 4 };\n\n    vector<int> role(M, IDLE);\n    vector<Point> target(M);\n\n    Point topStart{ x1, y1 };\n    Point leftStart{ x1, y1 };\n    Point bottomStart{ x2, y1 };\n    Point rightStart{ x1, y2 };\n\n    Point centerTarget{ clampv((x1 + x2) / 2, x1, x2), clampv((y1 + y2) / 2, y1, y2) };\n\n    // Choose 4 distinct humans for the 4 builder roles.\n    long long bestEval = LLONG_MAX;\n    array<int, 4> bestPick{-1, -1, -1, -1};\n\n    auto dman = [&](int i, Point t) -> int {\n        return abs(humans[i].x - t.x) + abs(humans[i].y - t.y);\n    };\n\n    vector<Point> roleTargets = { topStart, leftStart, bottomStart, rightStart };\n\n    for (int a = 0; a < M; ++a) for (int b = 0; b < M; ++b) if (b != a)\n    for (int c = 0; c < M; ++c) if (c != a && c != b)\n    for (int d = 0; d < M; ++d) if (d != a && d != b && d != c) {\n        array<int, 4> pick{a, b, c, d};\n\n        long long mx = 0, sum = 0;\n        bool used[20] = {};\n        for (int id : pick) used[id] = true;\n\n        mx = max<long long>(mx, dman(a, roleTargets[0]));\n        mx = max<long long>(mx, dman(b, roleTargets[1]));\n        mx = max<long long>(mx, dman(c, roleTargets[2]));\n        mx = max<long long>(mx, dman(d, roleTargets[3]));\n        sum += dman(a, roleTargets[0]);\n        sum += dman(b, roleTargets[1]);\n        sum += dman(c, roleTargets[2]);\n        sum += dman(d, roleTargets[3]);\n\n        for (int i = 0; i < M; ++i) if (!used[i]) {\n            Point t{ clampv(humans[i].x, x1, x2), clampv(humans[i].y, y1, y2) };\n            int dd = dman(i, t);\n            mx = max<long long>(mx, dd);\n            sum += dd;\n        }\n\n        long long eval = mx * 100000LL + sum;\n        if (eval < bestEval) {\n            bestEval = eval;\n            bestPick = pick;\n        }\n    }\n\n    // Assign roles\n    vector<Point> idleTarget(M);\n    for (int i = 0; i < M; ++i) idleTarget[i] = { clampv(humans[i].x, x1, x2), clampv(humans[i].y, y1, y2) };\n\n    role[bestPick[0]] = TOP;\n    role[bestPick[1]] = LEFT;\n    role[bestPick[2]] = BOTTOM;\n    role[bestPick[3]] = RIGHT;\n\n    target[bestPick[0]] = topStart;\n    target[bestPick[1]] = leftStart;\n    target[bestPick[2]] = bottomStart;\n    target[bestPick[3]] = rightStart;\n\n    for (int i = 0; i < M; ++i) {\n        if (role[i] == IDLE) target[i] = idleTarget[i];\n    }\n\n    // Movement phase duration\n    int moveTurns = 0;\n    for (int i = 0; i < M; ++i) {\n        moveTurns = max(moveTurns, abs(humans[i].x - target[i].x) + abs(humans[i].y - target[i].y));\n    }\n\n    // Builder state\n    struct BuilderState {\n        int idx = 0;\n        bool needWall = true;\n        bool done = false;\n    };\n    vector<BuilderState> bs(M);\n\n    auto inBoard = [](int x, int y) {\n        return 1 <= x && x <= HN && 1 <= y && y <= HN;\n    };\n\n    vector<vector<int>> humanOcc(HN + 1, vector<int>(HN + 1, 0));\n    for (auto &h : humans) humanOcc[h.x][h.y]++;\n\n    auto rebuildHumanOcc = [&]() {\n        for (int i = 1; i <= HN; ++i) fill(humanOcc[i].begin(), humanOcc[i].end(), 0);\n        for (auto &h : humans) humanOcc[h.x][h.y]++;\n    };\n\n    auto safeToWall = [&](int x, int y) -> bool {\n        if (!inBoard(x, y)) return false;\n        if (petOcc[x][y] > 0) return false;\n        if (humanOcc[x][y] > 0) return false;\n        static int dx[4] = {-1, 1, 0, 0};\n        static int dy[4] = {0, 0, -1, 1};\n        for (int dir = 0; dir < 4; ++dir) {\n            int nx = x + dx[dir], ny = y + dy[dir];\n            if (inBoard(nx, ny) && petOcc[nx][ny] > 0) return false;\n        }\n        return true;\n    };\n\n    auto petInsideTarget = [&]() -> bool {\n        for (auto &p : pets) {\n            if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) return true;\n        }\n        return false;\n    };\n\n    auto wallChar = [&](int r) -> char {\n        if (r == TOP) return 'u';\n        if (r == BOTTOM) return 'd';\n        if (r == LEFT) return 'l';\n        return 'r';\n    };\n\n    auto moveChar = [&](int r) -> char {\n        if (r == TOP || r == BOTTOM) return 'R';\n        return 'D';\n    };\n\n    auto wallTarget = [&](int r, const Point &p) -> Point {\n        if (r == TOP) return { p.x - 1, p.y };\n        if (r == BOTTOM) return { p.x + 1, p.y };\n        if (r == LEFT) return { p.x, p.y - 1 };\n        return { p.x, p.y + 1 };\n    };\n\n    auto sideLen = [&](int r) -> int {\n        if (r == TOP || r == BOTTOM) return W;\n        if (r == LEFT || r == RIGHT) return H;\n        return 0;\n    };\n\n    // To reduce risk of pets wandering into the target area while we wait,\n    // we allow a short waiting period after humans reach their targets.\n    const int WAIT_LIMIT = 20;\n\n    for (int turn = 0; turn < 300; ++turn) {\n        string out(M, '.');\n        vector<Point> nextPos = humans;\n\n        if (turn < moveTurns) {\n            // Move each human toward its assigned target.\n            for (int i = 0; i < M; ++i) {\n                if (humans[i].x < target[i].x) {\n                    out[i] = 'D';\n                    nextPos[i].x++;\n                } else if (humans[i].x > target[i].x) {\n                    out[i] = 'U';\n                    nextPos[i].x--;\n                } else if (humans[i].y < target[i].y) {\n                    out[i] = 'R';\n                    nextPos[i].y++;\n                } else if (humans[i].y > target[i].y) {\n                    out[i] = 'L';\n                    nextPos[i].y--;\n                } else {\n                    out[i] = '.';\n                }\n            }\n        } else {\n            bool forced = (turn >= moveTurns + WAIT_LIMIT);\n            bool canBuild = forced || !petInsideTarget();\n\n            if (canBuild) {\n                for (int i = 0; i < M; ++i) {\n                    if (role[i] == IDLE) continue;\n                    if (bs[i].done) continue;\n\n                    int len = sideLen(role[i]);\n                    if (len <= 0) {\n                        bs[i].done = true;\n                        continue;\n                    }\n\n                    if (bs[i].needWall) {\n                        Point wt = wallTarget(role[i], humans[i]);\n                        if (safeToWall(wt.x, wt.y)) {\n                            out[i] = wallChar(role[i]);\n                            // Wall built (or already impassable) if target is safe.\n                            // Mark it in our local map.\n                            // (If the cell was already impassable, this is harmless.)\n                            // We only need the wall map implicitly for safety checks.\n                            // No separate wall grid is necessary for the logic.\n                            // The target is inside the board by construction.\n                            // If the current cell is the last one, finish after walling.\n                            if (bs[i].idx == len - 1) {\n                                bs[i].done = true;\n                            } else {\n                                bs[i].needWall = false;\n                            }\n                        } else {\n                            out[i] = '.';\n                        }\n                    } else {\n                        if (bs[i].idx + 1 < len) {\n                            out[i] = moveChar(role[i]);\n                            if (role[i] == TOP || role[i] == BOTTOM) nextPos[i].y++;\n                            else nextPos[i].x++;\n                            bs[i].idx++;\n                            bs[i].needWall = true;\n                        } else {\n                            bs[i].done = true;\n                            out[i] = '.';\n                        }\n                    }\n                }\n            } else {\n                // Wait a bit for pets to leave the target area.\n                // All humans do nothing.\n            }\n        }\n\n        cout << out << '\\n' << flush;\n\n        // Apply human moves\n        humans = nextPos;\n        rebuildHumanOcc();\n\n        // Read pet movement strings and update pet positions.\n        vector<string> mv(N);\n        for (int i = 0; i < N; ++i) cin >> mv[i];\n\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].x, y = pets[i].y;\n            for (char ch : mv[i]) {\n                if (ch == 'U') --x;\n                else if (ch == 'D') ++x;\n                else if (ch == 'L') --y;\n                else if (ch == 'R') ++y;\n            }\n            pets[i] = {x, y};\n        }\n\n        // Rebuild pet occupancy\n        for (int i = 1; i <= HN; ++i) fill(petOcc[i].begin(), petOcc[i].end(), 0);\n        for (auto &p : pets) petOcc[p.x][p.y]++;\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int H = 20;\nstatic const int W = 20;\nstatic const int N = H * W;\nstatic const long long INF = (1LL << 60);\n\nint si, sj, ti, tj;\ndouble p;\ndouble qprob;\n\nvector<string> hwall(20), vwall(19);\n\nint startPos, goalPos;\n\nint moveTo[4][N];\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\ninline int id(int i, int j) { return i * W + j; }\ninline pair<int,int> coord(int x) { return {x / W, x % W}; }\n\nbool open_move(int pos, int dir) {\n    int i = pos / W, j = pos % W;\n    if (dir == 0) return (i > 0 && vwall[i - 1][j] == '0');\n    if (dir == 1) return (i + 1 < H && vwall[i][j] == '0');\n    if (dir == 2) return (j > 0 && hwall[i][j - 1] == '0');\n    if (dir == 3) return (j + 1 < W && hwall[i][j] == '0');\n    return false;\n}\n\nint next_pos(int pos, int dir) {\n    return moveTo[dir][pos];\n}\n\nstring trim200(string s) {\n    if ((int)s.size() > 200) s.resize(200);\n    return s;\n}\n\nstring build_shortest_path_bfs() {\n    vector<int> dist(N, -1), par(N, -1);\n    vector<char> parCh(N, '?');\n    queue<int> q;\n    dist[startPos] = 0;\n    q.push(startPos);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == goalPos) break;\n        for (int d = 0; d < 4; ++d) {\n            int nv = next_pos(v, d);\n            if (nv == v) continue;\n            if (dist[nv] != -1) continue;\n            dist[nv] = dist[v] + 1;\n            par[nv] = v;\n            parCh[nv] = dch[d];\n            q.push(nv);\n        }\n    }\n\n    if (dist[goalPos] == -1) return \"\";\n    string s;\n    for (int cur = goalPos; cur != startPos; cur = par[cur]) {\n        s.push_back(parCh[cur]);\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstring build_direct_Lshape(bool row_then_col) {\n    string s;\n    if (row_then_col) {\n        // R ... then D ...\n        if (sj > tj || si > ti) return \"\";\n        for (int j = sj; j < tj; ++j) {\n            if (hwall[si][j] == '1') return \"\";\n        }\n        for (int i = si; i < ti; ++i) {\n            if (vwall[i][tj] == '1') return \"\";\n        }\n        s.append(tj - sj, 'R');\n        s.append(ti - si, 'D');\n    } else {\n        // D ... then R ...\n        if (si > ti || sj > tj) return \"\";\n        for (int i = si; i < ti; ++i) {\n            if (vwall[i][sj] == '1') return \"\";\n        }\n        for (int j = sj; j < tj; ++j) {\n            if (hwall[ti][j] == '1') return \"\";\n        }\n        s.append(ti - si, 'D');\n        s.append(tj - sj, 'R');\n    }\n    return s;\n}\n\nstring build_weighted_path(int allowedMask, int turnPenalty) {\n    int S = N * 5;\n    vector<long long> dist(S, INF);\n    vector<int> par(S, -1);\n    vector<char> parCh(S, '?');\n\n    auto sid = [&](int pos, int prev) { return pos * 5 + prev; };\n\n    int st = sid(startPos, 4);\n    dist[st] = 0;\n\n    using P = pair<long long, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.push({0, st});\n\n    while (!pq.empty()) {\n        auto [cd, cur] = pq.top();\n        pq.pop();\n        if (cd != dist[cur]) continue;\n\n        int pos = cur / 5;\n        int prev = cur % 5;\n\n        for (int nd = 0; nd < 4; ++nd) {\n            if (!(allowedMask & (1 << nd))) continue;\n            int np = next_pos(pos, nd);\n            if (np == pos) continue; // only real moves\n            long long ndist = cd + 1;\n            if (prev != 4 && prev != nd) ndist += turnPenalty;\n\n            int ns = sid(np, nd);\n            if (ndist < dist[ns]) {\n                dist[ns] = ndist;\n                par[ns] = cur;\n                parCh[ns] = dch[nd];\n                pq.push({ndist, ns});\n            }\n        }\n    }\n\n    int best = -1;\n    long long bestd = INF;\n    for (int prev = 0; prev < 4; ++prev) {\n        int gs = sid(goalPos, prev);\n        if (dist[gs] < bestd) {\n            bestd = dist[gs];\n            best = gs;\n        }\n    }\n\n    if (best == -1 || bestd == INF) return \"\";\n\n    string s;\n    for (int cur = best; cur != st; cur = par[cur]) {\n        if (cur < 0 || par[cur] == -1) return \"\";\n        s.push_back(parCh[cur]);\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nvector<string> make_variants(const string& base) {\n    vector<string> res;\n    auto add = [&](string s) {\n        if ((int)s.size() > 200) s.resize(200);\n        if (!s.empty()) res.push_back(std::move(s));\n    };\n\n    if (base.empty()) return res;\n\n    string s = trim200(base);\n    add(s);\n\n    if ((int)base.size() < 200) {\n        int rem = 200 - (int)base.size();\n\n        vector<int> lens = {rem / 3, (2 * rem) / 3, rem};\n        sort(lens.begin(), lens.end());\n        lens.erase(unique(lens.begin(), lens.end()), lens.end());\n\n        // suffix padding with each direction\n        for (int k : lens) {\n            if (k <= 0) continue;\n            for (char c : string(\"UDLR\")) {\n                add(base + string(k, c));\n            }\n        }\n\n        // prefix padding with the first direction\n        add(string(rem, base.front()) + base);\n    }\n\n    sort(res.begin(), res.end());\n    res.erase(unique(res.begin(), res.end()), res.end());\n    return res;\n}\n\ndouble evaluate(const string& s) {\n    vector<double> cur(N, 0.0), nxt(N, 0.0);\n    cur[startPos] = 1.0;\n\n    double ans = 0.0;\n\n    for (int t = 0; t < (int)s.size(); ++t) {\n        fill(nxt.begin(), nxt.end(), 0.0);\n        double arrival = 0.0;\n\n        int dir = -1;\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 if (s[t] == 'R') dir = 3;\n        else return 0.0;\n\n        for (int pos = 0; pos < N; ++pos) {\n            double pr = cur[pos];\n            if (pr == 0.0) continue;\n\n            double stay = pr * p;\n            double mv = pr * qprob;\n\n            nxt[pos] += stay;\n\n            int np = moveTo[dir][pos];\n            if (np == goalPos) arrival += mv;\n            else nxt[np] += mv;\n        }\n\n        ans += arrival * (401.0 - (t + 1));\n        cur.swap(nxt);\n    }\n\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj >> ti >> tj >> p;\n    qprob = 1.0 - p;\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    startPos = id(si, sj);\n    goalPos = id(ti, tj);\n\n    // Precompute transitions with walls: blocked move => stay.\n    for (int pos = 0; pos < N; ++pos) {\n        for (int d = 0; d < 4; ++d) {\n            if (open_move(pos, d)) {\n                auto [i, j] = coord(pos);\n                int ni = i + (d == 1) - (d == 0);\n                int nj = j + (d == 3) - (d == 2);\n                moveTo[d][pos] = id(ni, nj);\n            } else {\n                moveTo[d][pos] = pos;\n            }\n        }\n    }\n\n    vector<string> bases;\n\n    // 1) Plain shortest path.\n    {\n        string s = build_shortest_path_bfs();\n        if (!s.empty()) bases.push_back(s);\n    }\n\n    // 2) Direct L-shapes if they exist.\n    {\n        string s1 = build_direct_Lshape(true);\n        if (!s1.empty()) bases.push_back(s1);\n        string s2 = build_direct_Lshape(false);\n        if (!s2.empty()) bases.push_back(s2);\n    }\n\n    // 3) Weighted shortest paths (unrestricted).\n    for (int w : {0, 1, 4, 16, 64, 256}) {\n        string s = build_weighted_path((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3), w);\n        if (!s.empty()) bases.push_back(s);\n    }\n\n    // 4) Weighted monotone-ish paths using only D / R.\n    for (int w : {0, 4, 16, 64}) {\n        string s = build_weighted_path((1 << 1) | (1 << 3), w);\n        if (!s.empty()) bases.push_back(s);\n    }\n\n    // Evaluate all variants exactly.\n    unordered_set<string> seen;\n    string bestAns;\n    double bestScore = -1.0;\n\n    for (const string& base : bases) {\n        for (const string& cand : make_variants(base)) {\n            if (!seen.insert(cand).second) continue;\n            double sc = evaluate(cand);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestAns = cand;\n            }\n        }\n    }\n\n    if (bestAns.empty()) {\n        // Fallback: shortest path truncated to 200.\n        string s = build_shortest_path_bfs();\n        if ((int)s.size() > 200) s.resize(200);\n        bestAns = s;\n    }\n\n    cout << bestAns << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int S = N * N;\nstatic constexpr int ST = S * 4;\n\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\n// base to-table from the statement\nint baseTo[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1},\n};\n\nint nxtDir[8][4][4]; // nxtDir[t][rot][entry_dir] -> exit_dir, or -1\n\nusing RotArr = array<uint8_t, S>;\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 Key {\n    uint64_t a, b;\n    bool operator==(const Key& other) const { return a == other.a && b == other.b; }\n};\nstruct KeyHash {\n    size_t operator()(const Key& k) const {\n        uint64_t x = k.a ^ (k.b + 0x9e3779b97f4a7c15ULL + (k.a << 6) + (k.a >> 2));\n        return (size_t)splitmix64(x);\n    }\n};\n\nint booth_min_rotation(const vector<int>& s) {\n    int n = (int)s.size();\n    if (n == 0) return 0;\n    vector<int> ss(2 * n);\n    for (int i = 0; i < 2 * n; ++i) ss[i] = s[i % n];\n\n    int i = 0, j = 1, k = 0;\n    while (i < n && j < n && k < n) {\n        int a = ss[i + k], b = ss[j + k];\n        if (a == b) {\n            ++k;\n            continue;\n        }\n        if (a > b) {\n            i += k + 1;\n            if (i <= j) i = j + 1;\n        } else {\n            j += k + 1;\n            if (j <= i) j = i + 1;\n        }\n        k = 0;\n    }\n    return min(i, j);\n}\n\nvector<int> canonical_cycle(const vector<int>& cyc) {\n    int n = (int)cyc.size();\n    vector<int> a = cyc;\n    int s1 = booth_min_rotation(a);\n    vector<int> c1(n);\n    for (int i = 0; i < n; ++i) c1[i] = a[(s1 + i) % n];\n\n    vector<int> b(n);\n    for (int i = 0; i < n; ++i) b[i] = cyc[n - 1 - i];\n    int s2 = booth_min_rotation(b);\n    vector<int> c2(n);\n    for (int i = 0; i < n; ++i) c2[i] = b[(s2 + i) % n];\n\n    if (lexicographical_compare(c2.begin(), c2.end(), c1.begin(), c1.end()))\n        return c2;\n    return c1;\n}\n\nKey hash_cycle(const vector<int>& cyc) {\n    vector<int> can = canonical_cycle(cyc);\n    uint64_t h1 = 1469598103934665603ULL;\n    uint64_t h2 = 0xcbf29ce484222325ULL;\n    for (int x : can) {\n        uint64_t y = splitmix64((uint64_t)x + 1);\n        h1 ^= y;\n        h1 *= 1099511628211ULL;\n        h2 += y + 0x9e3779b97f4a7c15ULL + (h2 << 6) + (h2 >> 2);\n    }\n    return Key{h1, h2};\n}\n\nstruct EvalResult {\n    long long score = 0;\n    vector<int> hotCells; // cell indices appearing in the two best unique cycles\n};\n\nEvalResult evaluate(const RotArr& rot, const array<int, S>& tile) {\n    static int succ[ST];\n    static uint8_t vis[ST];\n    static int pos[ST];\n    memset(vis, 0, sizeof(vis));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = (i * N + j) * 4;\n            int t = tile[i * N + j];\n            int r = rot[i * N + j];\n            for (int d = 0; d < 4; ++d) {\n                int d2 = nxtDir[t][r][d];\n                if (d2 < 0) {\n                    succ[idx + d] = -1;\n                    continue;\n                }\n                int ni = i + di[d2];\n                int nj = j + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    succ[idx + d] = -1;\n                    continue;\n                }\n                int nd = (d2 + 2) & 3;\n                succ[idx + d] = (ni * N + nj) * 4 + nd;\n            }\n        }\n    }\n\n    vector<vector<int>> uniq_cycles;\n    vector<int> uniq_len;\n    unordered_set<Key, KeyHash> seen;\n    seen.reserve(1024);\n\n    vector<int> st;\n    st.reserve(ST);\n\n    for (int s = 0; s < ST; ++s) {\n        if (vis[s]) continue;\n        int cur = s;\n        st.clear();\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;\n            pos[cur] = (int)st.size();\n            st.push_back(cur);\n            cur = succ[cur];\n        }\n        if (cur != -1 && vis[cur] == 1) {\n            vector<int> cyc(st.begin() + pos[cur], st.end());\n            Key k = hash_cycle(cyc);\n            if (seen.insert(k).second) {\n                uniq_len.push_back((int)cyc.size());\n                uniq_cycles.push_back(move(cyc));\n            }\n        }\n        for (int v : st) vis[v] = 2;\n    }\n\n    vector<int> ord(uniq_cycles.size());\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (uniq_len[a] != uniq_len[b]) return uniq_len[a] > uniq_len[b];\n        return a < b;\n    });\n\n    EvalResult res;\n    if ((int)ord.size() >= 2) {\n        res.score = 1LL * uniq_len[ord[0]] * uniq_len[ord[1]];\n    } else {\n        res.score = 0;\n    }\n\n    vector<char> mark(S, 0);\n    for (int t = 0; t < (int)ord.size() && t < 2; ++t) {\n        for (int stid : uniq_cycles[ord[t]]) {\n            mark[stid / 4] = 1;\n        }\n    }\n    for (int i = 0; i < S; ++i) if (mark[i]) res.hotCells.push_back(i);\n\n    return res;\n}\n\nint formula_value(int cid, int i, int j, uint64_t seed) {\n    switch (cid) {\n        case 0:  return 0;\n        case 1:  return i + j;\n        case 2:  return i - j + 30;\n        case 3:  return 2 * i + j;\n        case 4:  return i + 2 * j;\n        case 5:  return (i / 2) + (j / 2);\n        case 6:  return (i / 2) - (j / 2) + 30;\n        case 7:  return min(min(i, 29 - i), min(j, 29 - j));\n        case 8:  return (i & 1) * 2 + (j & 1);\n        case 9:  return (i % 3) * 3 + (j % 3);\n        case 10: return (int)(splitmix64(seed + (uint64_t)i * 10007ULL + (uint64_t)j * 10009ULL) & 1023ULL);\n        case 11: return (int)(splitmix64(seed + (uint64_t)i * 20011ULL + (uint64_t)j * 20021ULL) & 1023ULL);\n        case 12: return i ^ j;\n        case 13: return 3 * i + 5 * j;\n        case 14: return (i / 3) * 7 + (j / 3);\n        default: return i + j;\n    }\n}\n\nRotArr make_candidate(const array<int, S>& tile, int cid) {\n    RotArr rot{};\n    uint64_t seed = 0x123456789abcdef0ULL ^ (uint64_t)cid * 0x9e3779b97f4a7c15ULL;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int t = tile[i * N + j];\n            int f = formula_value(cid, i, j, seed);\n            int r;\n            if (t >= 6) {\n                r = (f + t + cid) & 1; // straight tiles: 0/1 enough\n            } else {\n                r = (f + t + cid) & 3;\n            }\n            rot[i * N + j] = (uint8_t)r;\n        }\n    }\n    return rot;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    array<int, S> tile{};\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) tile[i * N + j] = s[j] - '0';\n    }\n\n    // Precompute rotated transition tables.\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            for (int d = 0; d < 4; ++d) {\n                int bd = (d + r) & 3; // world dir -> base dir\n                int be = baseTo[t][bd];\n                if (be < 0) nxtDir[t][r][d] = -1;\n                else nxtDir[t][r][d] = (be - r + 4) & 3;\n            }\n        }\n    }\n\n    vector<int> candidate_ids = {0, 1, 2, 3, 4, 5, 7, 8, 9, 12, 13, 14, 10, 11};\n\n    RotArr best_rot{};\n    EvalResult best_eval;\n    best_eval.score = -1;\n\n    for (int cid : candidate_ids) {\n        RotArr cur = make_candidate(tile, cid);\n        EvalResult ev = evaluate(cur, tile);\n        if (ev.score > best_eval.score) {\n            best_eval = ev;\n            best_rot = cur;\n        }\n    }\n\n    // Hill-climbing around the best candidate.\n    RotArr cur = best_rot;\n    EvalResult cur_eval = best_eval;\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85;\n\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int noImprove = 0;\n    while (elapsed() < TIME_LIMIT) {\n        int cell;\n        if (!cur_eval.hotCells.empty() && (rng() % 100) < 70) {\n            cell = cur_eval.hotCells[rng() % cur_eval.hotCells.size()];\n        } else {\n            cell = rng() % S;\n        }\n\n        int oldr = cur[cell];\n        int nr = (int)(rng() & 3);\n        if (nr == oldr) nr = (nr + 1) & 3;\n\n        cur[cell] = (uint8_t)nr;\n        EvalResult ev = evaluate(cur, tile);\n\n        bool accept = false;\n        if (ev.score > cur_eval.score) accept = true;\n        else if (ev.score == cur_eval.score && (rng() % 5 == 0)) accept = true;\n\n        if (accept) {\n            cur_eval = move(ev);\n            noImprove = 0;\n            if (cur_eval.score > best_eval.score) {\n                best_eval = cur_eval;\n                best_rot = cur;\n            }\n        } else {\n            cur[cell] = (uint8_t)oldr;\n            ++noImprove;\n        }\n\n        if (noImprove >= 200) {\n            // Small random shake to escape plateaus.\n            for (int k = 0; k < 3; ++k) {\n                int c = rng() % S;\n                cur[c] = (uint8_t)(rng() & 3);\n            }\n            cur_eval = evaluate(cur, tile);\n            if (cur_eval.score > best_eval.score) {\n                best_eval = cur_eval;\n                best_rot = cur;\n            }\n            noImprove = 0;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << int(best_rot[i * N + j]);\n        }\n    }\n    cout << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100;\n\nint N, T, cells, fullV;\n\nint adjPos[MAXC][4];\nint oppDir[4] = {1, 0, 3, 2};\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\nuint64_t zob[MAXC][16];\n\nstruct EvalRes {\n    int exact = 0;   // largest tree component size\n    int near = 0;    // smoother proxy: component size - 2 * cycle_rank\n    int largest = 0; // largest connected component size\n    int cycles = 0;  // total cycle rank\n};\n\nstruct State {\n    array<uint8_t, MAXC> bd{};\n    int blank = -1;\n    int lastDir = -1;   // last move direction of blank, -1 for root\n    uint64_t hash = 0;\n    EvalRes ev;\n};\n\ninline int parseHex(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + (c - 'a');\n}\n\ninline uint64_t stateKey(uint64_t h, int lastDir) {\n    // lastDir in [-1,3]\n    return h ^ (uint64_t)(lastDir + 2) * 0x9e3779b97f4a7c15ULL;\n}\n\nEvalRes evaluate(const array<uint8_t, MAXC>& bd) {\n    int id[MAXC];\n    int V = 0;\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] != 0) id[i] = V++;\n        else id[i] = -1;\n    }\n\n    int deg[MAXC];\n    int adj[MAXC][4];\n    memset(deg, 0, sizeof(deg));\n\n    int E = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int m = bd[idx];\n            if (!m) continue;\n\n            if (j + 1 < N) {\n                int idx2 = idx + 1;\n                int m2 = bd[idx2];\n                if (m2 && (m & 4) && (m2 & 1)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n            if (i + 1 < N) {\n                int idx2 = idx + N;\n                int m2 = bd[idx2];\n                if (m2 && (m & 8) && (m2 & 2)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n        }\n    }\n\n    bool vis[MAXC];\n    memset(vis, 0, sizeof(vis));\n    int q[MAXC];\n\n    EvalRes res;\n    res.cycles = E - V; // will add +components below\n\n    for (int s = 0; s < V; ++s) {\n        if (vis[s]) continue;\n        ++res.cycles;\n\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n\n        int cnt = 0;\n        int sumdeg = 0;\n\n        while (head < tail) {\n            int x = q[head++];\n            ++cnt;\n            sumdeg += deg[x];\n            for (int k = 0; k < deg[x]; ++k) {\n                int y = adj[x][k];\n                if (!vis[y]) {\n                    vis[y] = true;\n                    q[tail++] = y;\n                }\n            }\n        }\n\n        int edges = sumdeg / 2;\n        int excess = edges - cnt + 1; // cycle rank of the component\n        res.largest = max(res.largest, cnt);\n        if (excess == 0) res.exact = max(res.exact, cnt);\n        res.near = max(res.near, cnt - 2 * excess);\n    }\n\n    if (V == 0) {\n        res.exact = res.near = res.largest = 0;\n        res.cycles = 0;\n    }\n    return res;\n}\n\ninline long long scoreKey(const EvalRes& e, bool exactMode) {\n    // Two different priorities:\n    //   exactMode  : exact tree size first\n    //   nearMode   : large almost-tree components first\n    if (exactMode) {\n        return 1LL * e.exact * 1'000'000LL + 1LL * e.near * 10'000LL + 1LL * e.largest * 100LL - e.cycles;\n    } else {\n        return 1LL * e.near * 1'000'000LL + 1LL * e.exact * 10'000LL + 1LL * e.largest * 100LL - e.cycles;\n    }\n}\n\ninline bool betterAnswer(const EvalRes& a, int lenA, const EvalRes& b, int lenB) {\n    if (a.exact != b.exact) return a.exact > b.exact;\n    if (a.exact == fullV) return lenA < lenB; // shorter full-tree solution is better\n    return lenA < lenB; // tie-break only\n}\n\nState applyMove(const State& s, int dir) {\n    State t = s;\n    int nb = adjPos[s.blank][dir];\n    uint8_t x = t.bd[s.blank];\n    uint8_t y = t.bd[nb];\n\n    // Update hash (swap positions s.blank and nb)\n    t.hash ^= zob[s.blank][x] ^ zob[s.blank][y] ^ zob[nb][y] ^ zob[nb][x];\n\n    swap(t.bd[s.blank], t.bd[nb]);\n    t.blank = nb;\n    t.lastDir = dir;\n    t.ev = evaluate(t.bd);\n    return t;\n}\n\nstruct SearchResult {\n    string path;\n    EvalRes ev;\n};\n\nSearchResult searchOnce(\n    const State& root,\n    int stepBase,\n    int warmMax,\n    int threshold,\n    int runType,\n    mt19937_64& rng\n) {\n    auto randInt = [&](int l, int r) -> int {\n        return l + int(rng() % uint64_t(r - l + 1));\n    };\n\n    State cur = root;\n    string curPath;\n    string bestPath = curPath;\n    EvalRes bestEv = cur.ev;\n\n    // Warm-up random walk to diversify.\n    int warm = 0;\n    if (warmMax > 0) warm = randInt(0, warmMax);\n    warm = min(warm, T);\n    int budget = min(stepBase, T - warm);\n\n    for (int i = 0; i < warm; ++i) {\n        vector<int> dirs;\n        for (int d = 0; d < 4; ++d) {\n            if (adjPos[cur.blank][d] == -1) continue;\n            if (cur.lastDir != -1 && d == oppDir[cur.lastDir]) continue;\n            dirs.push_back(d);\n        }\n        if (dirs.empty()) break;\n        int d = dirs[randInt(0, (int)dirs.size() - 1)];\n        cur = applyMove(cur, d);\n        curPath.push_back(dirChar[d]);\n        if (betterAnswer(cur.ev, (int)curPath.size(), bestEv, (int)bestPath.size())) {\n            bestEv = cur.ev;\n            bestPath = curPath;\n            if (bestEv.exact == fullV) return {bestPath, bestEv};\n        }\n    }\n\n    unordered_set<uint64_t> seen;\n    seen.reserve((size_t)budget * 3 + 16);\n    seen.insert(stateKey(cur.hash, cur.lastDir));\n\n    int stagnation = 0;\n    int step = 0;\n\n    while (step < budget) {\n        if ((step & 31) == 0 && chrono::duration<double>(chrono::steady_clock::now().time_since_epoch()).count() < 0) {\n            // dummy to keep compiler calm about chrono in loops\n        }\n\n        bool exactMode = (cur.ev.exact >= threshold);\n\n        struct Cand {\n            int dir = -1;\n            State st;\n            long long key = LLONG_MIN;\n        };\n\n        vector<Cand> cand;\n        cand.reserve(4);\n\n        auto genCandidates = [&](bool useSeen) {\n            cand.clear();\n            for (int d = 0; d < 4; ++d) {\n                if (adjPos[cur.blank][d] == -1) continue;\n                if (cur.lastDir != -1 && d == oppDir[cur.lastDir]) continue;\n\n                State nxt = applyMove(cur, d);\n                uint64_t sk = stateKey(nxt.hash, nxt.lastDir);\n                if (useSeen && seen.find(sk) != seen.end()) continue;\n\n                long long key = scoreKey(nxt.ev, exactMode);\n\n                // 2-ply lookahead\n                for (int d2 = 0; d2 < 4; ++d2) {\n                    if (adjPos[nxt.blank][d2] == -1) continue;\n                    if (d2 == oppDir[d]) continue;\n                    State g = applyMove(nxt, d2);\n                    long long k2 = scoreKey(g.ev, exactMode);\n                    if (k2 > key) key = k2;\n                }\n\n                cand.push_back({d, std::move(nxt), key});\n            }\n        };\n\n        genCandidates(true);\n        if (cand.empty()) {\n            genCandidates(false);\n            if (cand.empty()) break;\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            if (a.key != b.key) return a.key > b.key;\n            return a.dir < b.dir;\n        });\n\n        int m = (int)cand.size();\n        int pick = 0;\n\n        // Diversity policy depends on run type and stagnation.\n        if (runType == 0) {\n            // exact-focused\n            if (m > 1 && stagnation > 10) {\n                pick = randInt(0, min(1, m - 1));\n            } else if (m > 1 && randInt(0, 99) < 12) {\n                pick = randInt(0, min(1, m - 1));\n            } else {\n                pick = 0;\n            }\n        } else if (runType == 1) {\n            // near-focused / exploratory\n            if (m > 1 && stagnation > 12) {\n                pick = randInt(0, min(2, m - 1));\n            } else if (m > 1 && randInt(0, 99) < 25) {\n                pick = randInt(0, min(2, m - 1));\n            } else {\n                pick = 0;\n            }\n        } else {\n            // mixed\n            if (m > 1 && stagnation > 8) {\n                pick = randInt(0, min(2, m - 1));\n            } else if (m > 1 && randInt(0, 99) < 18) {\n                pick = randInt(0, min(2, m - 1));\n            } else {\n                pick = 0;\n            }\n        }\n\n        cur = std::move(cand[pick].st);\n        curPath.push_back(dirChar[cand[pick].dir]);\n        seen.insert(stateKey(cur.hash, cur.lastDir));\n\n        if (betterAnswer(cur.ev, (int)curPath.size(), bestEv, (int)bestPath.size())) {\n            bestEv = cur.ev;\n            bestPath = curPath;\n            stagnation = 0;\n            if (bestEv.exact == fullV) {\n                // Full tree found: later moves only make the score worse in this run.\n                break;\n            }\n        } else {\n            ++stagnation;\n        }\n\n        ++step;\n        if (stagnation > 60) break;\n    }\n\n    return {bestPath, bestEv};\n}\n\nuint64_t splitmixSeed(uint64_t& x) {\n    x += 0x9e3779b97f4a7c15ULL;\n    uint64_t z = x;\n    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n    z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n    return z ^ (z >> 31);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    cells = N * N;\n    fullV = cells - 1;\n\n    vector<string> s(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n\n    State root;\n    int blankPos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int v = parseHex(s[i][j]);\n            root.bd[idx] = (uint8_t)v;\n            if (v == 0) blankPos = idx;\n        }\n    }\n    root.blank = blankPos;\n    root.lastDir = -1;\n\n    // Precompute legal blank moves.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            adjPos[idx][0] = (i > 0 ? idx - N : -1); // U\n            adjPos[idx][1] = (i + 1 < N ? idx + N : -1); // D\n            adjPos[idx][2] = (j > 0 ? idx - 1 : -1); // L\n            adjPos[idx][3] = (j + 1 < N ? idx + 1 : -1); // R\n        }\n    }\n\n    // Initialize Zobrist table.\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    mt19937_64 zrng(seed ^ 0x123456789abcdef0ULL);\n    for (int i = 0; i < cells; ++i) {\n        for (int v = 0; v < 16; ++v) {\n            zob[i][v] = zrng();\n        }\n    }\n\n    // Root hash and evaluation.\n    root.hash = 0;\n    for (int i = 0; i < cells; ++i) root.hash ^= zob[i][root.bd[i]];\n    root.ev = evaluate(root.bd);\n\n    // If already full tree, answer is empty.\n    if (root.ev.exact == fullV) {\n        cout << '\\n';\n        return 0;\n    }\n\n    mt19937_64 rng(seed ^ 0xfedcba9876543210ULL);\n\n    string bestPath = \"\";\n    EvalRes bestEv = root.ev;\n\n    auto betterGlobal = [&](const EvalRes& a, const string& pa, const EvalRes& b, const string& pb) -> bool {\n        if (a.exact != b.exact) return a.exact > b.exact;\n        if (a.exact == fullV) return pa.size() < pb.size();\n        return pa.size() < pb.size();\n    };\n\n    auto start = chrono::steady_clock::now();\n    auto timeLimit = 2.85;\n\n    int runId = 0;\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > timeLimit) break;\n\n        int runType;\n        int stepBase, warmMax, threshold;\n\n        if (bestEv.exact == fullV) {\n            // We already have a full tree somewhere; now focus on finding a shorter full-tree path.\n            runType = 0;\n            stepBase = min(T, 220);\n            warmMax = 0;\n            threshold = 0;\n        } else {\n            runType = runId % 3;\n            if (runType == 0) {\n                // exact-focused\n                stepBase = min(T, 280);\n                warmMax = 5;\n                threshold = 0;\n            } else if (runType == 1) {\n                // near-focused / exploratory\n                stepBase = min(T, 450);\n                warmMax = min(20, T);\n                threshold = max(8, fullV * 2 / 3);\n            } else {\n                // mixed\n                stepBase = min(T, 350);\n                warmMax = min(10, T);\n                threshold = max(8, fullV * 3 / 5);\n            }\n        }\n\n        SearchResult res = searchOnce(root, stepBase, warmMax, threshold, runType, rng);\n\n        if (betterGlobal(res.ev, res.path, bestEv, bestPath)) {\n            bestEv = res.ev;\n            bestPath = res.path;\n        }\n\n        ++runId;\n    }\n\n    cout << bestPath << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int L = -9999;\nstatic constexpr int R = 9999;\nstatic constexpr int SZ = R - L + 1;   // 19999\nstatic constexpr int MAXS = 101;       // strips = cuts + 1, cuts <= 100\nstatic constexpr int INF_INT = 1e9;\n\nstruct AxisData {\n    vector<vector<int>> bounds; // bounds[s] = cut coordinates for s strips\n    vector<vector<int>> bin;    // bin[s][i] = strip index of point i\n};\n\nAxisData buildAxis(const vector<int>& vals, int N) {\n    vector<int> cnt(SZ, 0);\n    for (int v : vals) cnt[v - L]++;\n\n    vector<int> pref(SZ + 1, 0);\n    for (int i = 0; i < SZ; i++) pref[i + 1] = pref[i] + cnt[i];\n\n    vector<int> allowed;\n    vector<int> leftCnt;\n    allowed.reserve(SZ);\n    leftCnt.reserve(SZ);\n\n    for (int c = L; c <= R; c++) {\n        int idx = c - L;\n        if (cnt[idx] == 0) {\n            allowed.push_back(c);\n            leftCnt.push_back(pref[idx]); // number of points with coord < c\n        }\n    }\n\n    vector<vector<int>> bounds(MAXS + 1);\n    bounds[1] = {};\n\n    for (int s = 2; s <= MAXS; s++) {\n        vector<int> b;\n        b.reserve(s - 1);\n\n        int start = 0; // earliest allowed coordinate index for this boundary\n        for (int j = 1; j <= s - 1; j++) {\n            int target = (int)((1LL * j * N + s / 2) / s); // rounded quantile\n\n            auto it = lower_bound(leftCnt.begin() + start, leftCnt.end(), target);\n            int idx = (int)(it - leftCnt.begin());\n            if (idx >= (int)allowed.size()) idx = (int)allowed.size() - 1;\n\n            int chosen = idx;\n            if (idx > start) {\n                int prev = idx - 1;\n                long long dcur = llabs((long long)leftCnt[idx] - target);\n                long long dprev = llabs((long long)leftCnt[prev] - target);\n                if (dprev <= dcur) chosen = prev;\n            }\n\n            if (chosen < start) chosen = start; // safety\n            b.push_back(allowed[chosen]);\n            start = chosen + 1;\n            if (start >= (int)allowed.size()) start = (int)allowed.size() - 1;\n        }\n        bounds[s] = std::move(b);\n    }\n\n    vector<vector<int>> bin(MAXS + 1, vector<int>(N, 0));\n    for (int s = 1; s <= MAXS; s++) {\n        const auto& b = bounds[s];\n        for (int i = 0; i < N; i++) {\n            // boundaries are unused coordinates, so lower_bound is safe\n            bin[s][i] = (int)(lower_bound(b.begin(), b.end(), vals[i]) - b.begin());\n        }\n    }\n\n    return {std::move(bounds), std::move(bin)};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n\n    array<int, 11> a{};\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n    AxisData ax = buildAxis(xs, N);\n    AxisData ay = buildAxis(ys, N);\n\n    long long bestScore = -1;\n    int bestR = 1, bestC = 1;\n    int bestCuts = INF_INT;\n\n    static int cell[2601]; // max under r + c <= 102 is 51 * 51 = 2601\n\n    for (int r = 1; r <= MAXS; r++) {\n        for (int c = 1; c <= MAXS; c++) {\n            int cuts = (r - 1) + (c - 1);\n            if (cuts > K) continue;\n\n            int m = r * c;\n            fill(cell, cell + m, 0);\n\n            for (int i = 0; i < N; i++) {\n                int bx = ax.bin[r][i];\n                int by = ay.bin[c][i];\n                cell[bx * c + by]++;\n            }\n\n            int hist[11] = {};\n            for (int i = 0; i < m; i++) {\n                int v = cell[i];\n                if (1 <= v && v <= 10) hist[v]++;\n            }\n\n            long long score = 0;\n            for (int d = 1; d <= 10; d++) {\n                score += min(a[d], hist[d]);\n            }\n\n            if (score > bestScore || (score == bestScore && cuts < bestCuts)) {\n                bestScore = score;\n                bestCuts = cuts;\n                bestR = r;\n                bestC = c;\n            }\n        }\n    }\n\n    cout << bestCuts << '\\n';\n\n    for (int x : ax.bounds[bestR]) {\n        cout << x << ' ' << -1000000000 << ' ' << x << ' ' << 1000000000 << '\\n';\n    }\n    for (int y : ay.bounds[bestC]) {\n        cout << -1000000000 << ' ' << y << ' ' << 1000000000 << ' ' << y << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cand {\n    array<uint16_t, 4> c{};\n    array<uint16_t, 32> s{};\n    uint8_t slen = 0;\n    uint8_t cnt = 0;\n    bool used = false;\n    bool blockB = false;\n    bool blockS = false;\n    int perim = 0;\n    long long key = 0;\n};\n\nstruct Op {\n    array<int, 8> a{};\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    const int V = N * N;\n    const long long C = (N - 1) / 2;\n\n    auto pid = [&](int x, int y) { return x * N + y; };\n\n    vector<long long> wt(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long dx = x - C, dy = y - C;\n            wt[pid(x, y)] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    vector<char> occ(V, 0);\n    vector<int> initIds;\n    long long initSum = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        int p = pid(x, y);\n        if (!occ[p]) {\n            occ[p] = 1;\n            initIds.push_back(p);\n            initSum += wt[p];\n        }\n    }\n\n    const int H = N * (N - 1);\n    const int D = (N - 1) * (N - 1);\n    const int totalSeg = 2 * H + 2 * D;\n\n    auto hid = [&](int x, int y) { // (x,y) -> (x+1,y)\n        return y * (N - 1) + x;\n    };\n    auto vid = [&](int x, int y) { // (x,y) -> (x,y+1)\n        return H + x * (N - 1) + y;\n    };\n    auto pdiag = [&](int x, int y) { // (x,y) -> (x+1,y+1)\n        return 2 * H + y * (N - 1) + x;\n    };\n    auto ndiag = [&](int x, int y) { // (x,y+1) -> (x+1,y)\n        return 2 * H + D + y * (N - 1) + x;\n    };\n\n    vector<vector<int>> cornerInc(V), boundaryInc(V), segInc(totalSeg);\n    vector<Cand> cands;\n    cands.reserve(600000);\n\n    vector<char> segUsed(totalSeg, 0);\n    priority_queue<pair<long long, int>> pq;\n\n    auto buildCand = [&](const array<uint16_t, 4>& corners, int cnt,\n                         int perim, const uint16_t* bps, int bpn,\n                         const uint16_t* segs, int slen) {\n        if (cnt == 4) return; // already full, never usable\n\n        int cid = (int)cands.size();\n        cands.emplace_back();\n        Cand &cd = cands.back();\n        cd.c = corners;\n        cd.slen = (uint8_t)slen;\n        cd.cnt = (uint8_t)cnt;\n        cd.perim = perim;\n        cd.used = cd.blockB = cd.blockS = false;\n\n        for (int i = 0; i < slen; ++i) cd.s[i] = segs[i];\n\n        for (int i = 0; i < 4; ++i) cornerInc[corners[i]].push_back(cid);\n        for (int i = 0; i < bpn; ++i) boundaryInc[bps[i]].push_back(cid);\n        for (int i = 0; i < slen; ++i) segInc[segs[i]].push_back(cid);\n\n        if (cnt == 3) {\n            int miss = -1;\n            for (int i = 0; i < 4; ++i) {\n                if (!occ[corners[i]]) miss = i;\n            }\n            long long key = wt[corners[miss]] * 1000LL - (long long)perim * 10LL;\n            cd.key = key;\n            pq.push({key, cid});\n        }\n    };\n\n    // Parameters\n    const int AX_MAX = min(9, N - 1);\n    const int DIAG_SUM_MAX = min(12, N - 1);\n\n    // Axis-aligned rectangles\n    for (int w = 1; w <= AX_MAX; ++w) {\n        for (int h = 1; h <= AX_MAX; ++h) {\n            for (int x = 0; x + w < N; ++x) {\n                for (int y = 0; y + h < N; ++y) {\n                    array<uint16_t, 4> corners = {\n                        (uint16_t)pid(x, y),\n                        (uint16_t)pid(x + w, y),\n                        (uint16_t)pid(x + w, y + h),\n                        (uint16_t)pid(x, y + h)\n                    };\n\n                    int cnt = 0;\n                    for (int i = 0; i < 4; ++i) cnt += occ[corners[i]];\n                    if (cnt == 4) continue;\n\n                    uint16_t bps[64];\n                    int bpn = 0;\n                    bool dead = false;\n\n                    // bottom\n                    for (int xx = x + 1; xx < x + w; ++xx) {\n                        int p = pid(xx, y);\n                        if (occ[p]) { dead = true; break; }\n                        bps[bpn++] = (uint16_t)p;\n                    }\n                    if (dead) continue;\n\n                    // right\n                    for (int yy = y + 1; yy < y + h; ++yy) {\n                        int p = pid(x + w, yy);\n                        if (occ[p]) { dead = true; break; }\n                        bps[bpn++] = (uint16_t)p;\n                    }\n                    if (dead) continue;\n\n                    // top\n                    for (int xx = x + w - 1; xx > x; --xx) {\n                        int p = pid(xx, y + h);\n                        if (occ[p]) { dead = true; break; }\n                        bps[bpn++] = (uint16_t)p;\n                    }\n                    if (dead) continue;\n\n                    // left\n                    for (int yy = y + h - 1; yy > y; --yy) {\n                        int p = pid(x, yy);\n                        if (occ[p]) { dead = true; break; }\n                        bps[bpn++] = (uint16_t)p;\n                    }\n                    if (dead) continue;\n\n                    uint16_t segs[64];\n                    int slen = 0;\n                    for (int xx = x; xx < x + w; ++xx) segs[slen++] = (uint16_t)hid(xx, y);\n                    for (int yy = y; yy < y + h; ++yy) segs[slen++] = (uint16_t)vid(x + w, yy);\n                    for (int xx = x + w - 1; xx >= x; --xx) segs[slen++] = (uint16_t)hid(xx, y + h);\n                    for (int yy = y + h - 1; yy >= y; --yy) segs[slen++] = (uint16_t)vid(x, yy);\n\n                    buildCand(corners, cnt, 2 * (w + h), bps, bpn, segs, slen);\n                }\n            }\n        }\n    }\n\n    // 45-degree rectangles\n    // corners:\n    // p0=(x,y), p1=(x+a,y+a), p2=(x+a+b,y+a-b), p3=(x+b,y-b)\n    for (int a = 1; a <= DIAG_SUM_MAX - 1; ++a) {\n        for (int b = 1; a + b <= DIAG_SUM_MAX; ++b) {\n            for (int x = 0; x + a + b < N; ++x) {\n                for (int y = b; y + a < N; ++y) {\n                    array<uint16_t, 4> corners = {\n                        (uint16_t)pid(x, y),\n                        (uint16_t)pid(x + a, y + a),\n                        (uint16_t)pid(x + a + b, y + a - b),\n                        (uint16_t)pid(x + b, y - b)\n                    };\n\n                    int cnt = 0;\n                    for (int i = 0; i < 4; ++i) cnt += occ[corners[i]];\n                    if (cnt == 4) continue;\n\n                    uint16_t bps[64];\n                    int bpn = 0;\n                    bool dead = false;\n\n                    // p0 -> p1 (diag +)\n                    for (int t = 1; t < a; ++t) {\n                        int p = pid(x + t, y + t);\n                        if (occ[p]) { dead = true; break; }\n                        bps[bpn++] = (uint16_t)p;\n                    }\n                    if (dead) continue;\n\n                    // p1 -> p2 (diag -)\n                    for (int t = 1; t < b; ++t) {\n                        int p = pid(x + a + t, y + a - t);\n                        if (occ[p]) { dead = true; break; }\n                        bps[bpn++] = (uint16_t)p;\n                    }\n                    if (dead) continue;\n\n                    // p0 -> p3 (diag -)\n                    for (int t = 1; t < b; ++t) {\n                        int p = pid(x + t, y - t);\n                        if (occ[p]) { dead = true; break; }\n                        bps[bpn++] = (uint16_t)p;\n                    }\n                    if (dead) continue;\n\n                    // p3 -> p2 (diag +)\n                    for (int t = 1; t < a; ++t) {\n                        int p = pid(x + b + t, y - b + t);\n                        if (occ[p]) { dead = true; break; }\n                        bps[bpn++] = (uint16_t)p;\n                    }\n                    if (dead) continue;\n\n                    uint16_t segs[64];\n                    int slen = 0;\n\n                    // p0 -> p1\n                    for (int t = 0; t < a; ++t) segs[slen++] = (uint16_t)pdiag(x + t, y + t);\n\n                    // p1 -> p2\n                    for (int t = 0; t < b; ++t) segs[slen++] = (uint16_t)ndiag(x + a + t, y + a - t - 1);\n\n                    // p3 -> p2\n                    for (int t = 0; t < a; ++t) segs[slen++] = (uint16_t)pdiag(x + b + t, y - b + t);\n\n                    // p0 -> p3\n                    for (int t = 0; t < b; ++t) segs[slen++] = (uint16_t)ndiag(x + t, y - t - 1);\n\n                    buildCand(corners, cnt, 2 * (a + b), bps, bpn, segs, slen);\n                }\n            }\n        }\n    }\n\n    vector<Op> ops;\n    ops.reserve(200000);\n\n    long long curSum = initSum;\n\n    while (!pq.empty()) {\n        auto [key, cid] = pq.top();\n        pq.pop();\n\n        Cand &cd = cands[cid];\n        if (cd.used || cd.blockB || cd.blockS || cd.cnt != 3) continue;\n\n        int miss = -1;\n        for (int i = 0; i < 4; ++i) {\n            if (!occ[cd.c[i]]) {\n                miss = i;\n                break;\n            }\n        }\n        if (miss < 0) continue;\n\n        cd.used = true;\n        int newp = cd.c[miss];\n        if (occ[newp]) continue; // stale\n        occ[newp] = 1;\n        curSum += wt[newp];\n\n        // Output operation in cyclic order starting from the new dot\n        Op op;\n        for (int t = 0; t < 4; ++t) {\n            int p = cd.c[(miss + t) & 3];\n            op.a[2 * t] = p / N;\n            op.a[2 * t + 1] = p % N;\n        }\n        ops.push_back(op);\n\n        // Mark used segments and block all candidates using them\n        for (int i = 0; i < cd.slen; ++i) {\n            int sid = cd.s[i];\n            if (segUsed[sid]) continue;\n            segUsed[sid] = 1;\n            for (int nid : segInc[sid]) {\n                if (nid == cid) continue;\n                if (!cands[nid].used) cands[nid].blockS = true;\n            }\n        }\n\n        // Update candidates that have the new point as a corner\n        for (int nid : cornerInc[newp]) {\n            if (nid == cid) continue;\n            Cand &x = cands[nid];\n            if (x.used) continue;\n            ++x.cnt;\n            if (x.cnt == 3 && !x.blockB && !x.blockS) {\n                int miss2 = -1;\n                for (int i = 0; i < 4; ++i) {\n                    if (!occ[x.c[i]]) miss2 = i;\n                }\n                if (miss2 >= 0) {\n                    long long k = wt[x.c[miss2]] * 1000LL - (long long)x.perim * 10LL;\n                    x.key = k;\n                    pq.push({k, nid});\n                }\n            }\n        }\n\n        // Any candidate having this point on its boundary becomes invalid\n        for (int nid : boundaryInc[newp]) {\n            if (!cands[nid].used) cands[nid].blockB = true;\n        }\n    }\n\n    cout << ops.size() << '\\n';\n    for (auto &op : ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << op.a[i];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int COLORS = 3;\nstatic constexpr int THRESH = 5;\n\nstruct Board {\n    uint8_t a[N][N]{};\n};\n\nint F[100];\nint tot[4];\nint prefCnt[101][4];\nint remainAfter[101][4];\n\n// flavor rank by total count (0: largest, 1: second, 2: third)\nint rankOfFlavor[4];\n\n// bonus table by rank and direction index\n// direction order: F, B, L, R\ndouble bonusTable[3][4] = {\n    {0.30, 0.10, 0.20, 0.00}, // top-left-like\n    {0.30, 0.10, 0.00, 0.20}, // top-right-like\n    {0.10, 0.30, 0.00, 0.20}  // bottom-right-like\n};\n\ninline int dirIndex(char d) {\n    if (d == 'F') return 0;\n    if (d == 'B') return 1;\n    if (d == 'L') return 2;\n    return 3; // R\n}\n\ninline Board tilt(const Board& b, char d) {\n    Board r{};\n    if (d == 'L') {\n        for (int i = 0; i < N; i++) {\n            int w = 0;\n            for (int j = 0; j < N; j++) {\n                if (b.a[i][j]) r.a[i][w++] = b.a[i][j];\n            }\n        }\n    } else if (d == 'R') {\n        for (int i = 0; i < N; i++) {\n            int w = N - 1;\n            for (int j = N - 1; j >= 0; j--) {\n                if (b.a[i][j]) r.a[i][w--] = b.a[i][j];\n            }\n        }\n    } else if (d == 'F') {\n        for (int j = 0; j < N; j++) {\n            int w = 0;\n            for (int i = 0; i < N; i++) {\n                if (b.a[i][j]) r.a[w++][j] = b.a[i][j];\n            }\n        }\n    } else { // 'B'\n        for (int j = 0; j < N; j++) {\n            int w = N - 1;\n            for (int i = N - 1; i >= 0; i--) {\n                if (b.a[i][j]) r.a[w--][j] = b.a[i][j];\n            }\n        }\n    }\n    return r;\n}\n\ninline pair<int,int> kthEmpty(const Board& b, int p) {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0) {\n                --p;\n                if (p == 0) return {i, j};\n            }\n        }\n    }\n    return {-1, -1};\n}\n\nstruct Analysis {\n    long long sumSq = 0;\n    int mx[4]{};\n    int adj = 0;\n};\n\ninline Analysis analyze(const Board& b) {\n    Analysis res{};\n    bool vis[N][N]{};\n    int qx[N * N], qy[N * N];\n    static const int dr[4] = {1, -1, 0, 0};\n    static const int dc[4] = {0, 0, 1, -1};\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0 || vis[i][j]) continue;\n            uint8_t col = b.a[i][j];\n            int head = 0, tail = 0;\n            qx[tail] = i; qy[tail] = j; tail++;\n            vis[i][j] = true;\n            int sz = 0;\n\n            while (head < tail) {\n                int x = qx[head], y = qy[head];\n                head++;\n                sz++;\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + dr[k], ny = y + dc[k];\n                    if ((unsigned)nx < N && (unsigned)ny < N &&\n                        !vis[nx][ny] && b.a[nx][ny] == col) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx; qy[tail] = ny; tail++;\n                    }\n                }\n            }\n\n            res.sumSq += 1LL * sz * sz;\n            res.mx[col] = max(res.mx[col], sz);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0) continue;\n            if (i + 1 < N && b.a[i + 1][j] == b.a[i][j]) res.adj++;\n            if (j + 1 < N && b.a[i][j + 1] == b.a[i][j]) res.adj++;\n        }\n    }\n\n    return res;\n}\n\ninline long long exactScore(const Board& b) {\n    bool vis[N][N]{};\n    int qx[N * N], qy[N * N];\n    static const int dr[4] = {1, -1, 0, 0};\n    static const int dc[4] = {0, 0, 1, -1};\n\n    long long ans = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0 || vis[i][j]) continue;\n            uint8_t col = b.a[i][j];\n            int head = 0, tail = 0;\n            qx[tail] = i; qy[tail] = j; tail++;\n            vis[i][j] = true;\n            int sz = 0;\n\n            while (head < tail) {\n                int x = qx[head], y = qy[head];\n                head++;\n                sz++;\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + dr[k], ny = y + dc[k];\n                    if ((unsigned)nx < N && (unsigned)ny < N &&\n                        !vis[nx][ny] && b.a[nx][ny] == col) {\n                        vis[nx][ny] = true;\n                        qx[tail] = nx; qy[tail] = ny; tail++;\n                    }\n                }\n            }\n\n            ans += 1LL * sz * sz;\n        }\n    }\n    return ans;\n}\n\ndouble expectimax(const Board& b, int next_idx) {\n    // next_idx: index of the next candy to be inserted (0-based)\n    // if next_idx == 99, this is the last candy; insert it and finish.\n    if (next_idx == 99) {\n        Board t = b;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (t.a[i][j] == 0) {\n                    t.a[i][j] = F[next_idx];\n                    return (double)exactScore(t);\n                }\n            }\n        }\n        return (double)exactScore(t);\n    }\n\n    pair<int,int> empties[N * N];\n    int ec = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b.a[i][j] == 0) empties[ec++] = {i, j};\n        }\n    }\n\n    static const char dirs[4] = {'F', 'B', 'L', 'R'};\n    double sum = 0.0;\n\n    for (int e = 0; e < ec; e++) {\n        Board t = b;\n        auto [r, c] = empties[e];\n        t.a[r][c] = F[next_idx];\n\n        double best = -1e100;\n        for (char d : dirs) {\n            Board u = tilt(t, d);\n            double val = expectimax(u, next_idx + 1);\n            if (val > best) best = val;\n        }\n        sum += best;\n    }\n\n    return sum / ec;\n}\n\ndouble heuristic(const Board& b, int next_idx) {\n    Analysis an = analyze(b);\n    double score = (double)an.sumSq;\n\n    for (int c = 1; c <= 3; c++) {\n        score += 2.0 * (double)an.mx[c] * (double)remainAfter[next_idx][c];\n    }\n\n    score += 0.02 * (double)an.adj;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 100; i++) {\n        cin >> F[i];\n        tot[F[i]]++;\n    }\n\n    // prefix counts\n    for (int i = 0; i < 100; i++) {\n        for (int c = 1; c <= 3; c++) prefCnt[i + 1][c] = prefCnt[i][c];\n        prefCnt[i + 1][F[i]]++;\n    }\n    for (int i = 0; i <= 100; i++) {\n        for (int c = 1; c <= 3; c++) {\n            remainAfter[i][c] = tot[c] - prefCnt[i][c];\n        }\n    }\n\n    // flavor ranking by total counts\n    vector<pair<int,int>> ord;\n    for (int c = 1; c <= 3; c++) ord.push_back({tot[c], c});\n    sort(ord.begin(), ord.end(), [](auto& x, auto& y){\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n    for (int r = 0; r < 3; r++) {\n        rankOfFlavor[ord[r].second] = r;\n    }\n\n    Board board{};\n\n    static const char dirs[4] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < 100; t++) {\n        int p;\n        cin >> p;\n\n        Board cur = board;\n        auto [r, c] = kthEmpty(cur, p);\n        cur.a[r][c] = F[t];\n\n        if (t == 99) {\n            // Nothing happens on the last tilt.\n            board = cur;\n            break;\n        }\n\n        int next_idx = t + 1;\n        int remaining_after = 99 - t; // candies still to come after this tilt\n\n        double bestScore = -1e100;\n        Board bestBoard = cur;\n        char bestDir = 'F';\n\n        int rank = rankOfFlavor[F[t]];\n\n        for (char d : dirs) {\n            Board cand = tilt(cur, d);\n            double sc;\n            if (remaining_after <= THRESH) {\n                sc = expectimax(cand, next_idx);\n            } else {\n                sc = heuristic(cand, next_idx);\n            }\n            sc += bonusTable[rank][dirIndex(d)];\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestBoard = cand;\n                bestDir = d;\n            }\n        }\n\n        board = bestBoard;\n        cout << bestDir << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 100;\nstatic constexpr int T = N * (N - 1) / 2;\nstatic constexpr long double NEG_INF = -1e100L;\n\nstruct Codeword {\n    int a, b, c, d;                 // construction blocks: U^a I^b U^c I^d\n    array<int, 4> cnt;              // sorted-degree segment lengths: [d, b, a, c]\n    array<int, 4> lev;              // original degree levels: [0, c, a+c-1, a+b+c-1]\n    array<int, N> prof;             // raw sorted-degree profile (for selection)\n};\n\nstatic inline int dist_prof(const Codeword& x, const Codeword& y) {\n    int s = 0;\n    for (int i = 0; i < N; ++i) s += abs(x.prof[i] - y.prof[i]);\n    return s;\n}\n\nstatic string build_graph(const Codeword& cw) {\n    array<int, N> blk{};\n    int p = 0;\n    for (int i = 0; i < cw.a; ++i) blk[p++] = 0;\n    for (int i = 0; i < cw.b; ++i) blk[p++] = 1;\n    for (int i = 0; i < cw.c; ++i) blk[p++] = 2;\n    for (int i = 0; i < cw.d; ++i) blk[p++] = 3;\n\n    string s;\n    s.reserve(T);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            int x = blk[i], y = blk[j];\n            bool e = false;\n            // U^a I^b U^c I^d\n            // Edges exist iff:\n            // - inside block 0 (first U block), or\n            // - at least one endpoint is in block 2 (second U block), and the other is not block 3\n            if (x != 3 && y != 3) {\n                if (x == 2 || y == 2) e = true;\n                else if (x == 0 && y == 0) e = true;\n            }\n            s.push_back(e ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nstatic vector<vector<long double>> make_binom(int n, long double q) {\n    vector<vector<long double>> d(n + 1, vector<long double>(n + 1, 0.0L));\n    d[0][0] = 1.0L;\n    for (int i = 1; i <= n; ++i) {\n        d[i][0] = d[i - 1][0] * (1.0L - q);\n        for (int k = 1; k < i; ++k) {\n            d[i][k] = d[i - 1][k] * (1.0L - q) + d[i - 1][k - 1] * q;\n        }\n        d[i][i] = d[i - 1][i - 1] * q;\n    }\n    return d;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    long double eps;\n    cin >> M >> eps;\n\n    // Normalize epsilon to exactly two decimal digits.\n    int ieps = (int)llround((double)(eps * 100.0L));\n    eps = (long double)ieps / 100.0L;\n\n    // Build candidate pool:\n    // a = 25+x, b = 25+y, c = 25+z, d = 25-x-y-z\n    // with x,y,z in [-4,4], and keep block sizes reasonably balanced.\n    vector<Codeword> pool;\n    int centerIdx = -1;\n\n    for (int x = -4; x <= 4; ++x) {\n        for (int y = -4; y <= 4; ++y) {\n            for (int z = -4; z <= 4; ++z) {\n                Codeword cw;\n                cw.a = 25 + x;\n                cw.b = 25 + y;\n                cw.c = 25 + z;\n                cw.d = 25 - x - y - z;\n\n                // Keep all blocks reasonably balanced.\n                if (cw.a < 20 || cw.a > 30) continue;\n                if (cw.b < 20 || cw.b > 30) continue;\n                if (cw.c < 20 || cw.c > 30) continue;\n                if (cw.d < 20 || cw.d > 30) continue;\n\n                cw.cnt = {cw.d, cw.b, cw.a, cw.c};\n                cw.lev = {0, cw.c, cw.a + cw.c - 1, cw.a + cw.b + cw.c - 1};\n\n                int p = 0;\n                cw.prof.fill(0);\n                for (int i = 0; i < cw.cnt[0]; ++i) cw.prof[p++] = cw.lev[0];\n                for (int i = 0; i < cw.cnt[1]; ++i) cw.prof[p++] = cw.lev[1];\n                for (int i = 0; i < cw.cnt[2]; ++i) cw.prof[p++] = cw.lev[2];\n                for (int i = 0; i < cw.cnt[3]; ++i) cw.prof[p++] = cw.lev[3];\n\n                if (x == 0 && y == 0 && z == 0) centerIdx = (int)pool.size();\n                pool.push_back(cw);\n            }\n        }\n    }\n\n    if (centerIdx < 0) centerIdx = 0;\n\n    // Farthest-point selection on expected sorted degree profiles.\n    int P = (int)pool.size();\n    vector<int> order;\n    order.reserve(P);\n    vector<char> used(P, 0);\n    vector<int> best(P, INT_MAX);\n\n    order.push_back(centerIdx);\n    used[centerIdx] = 1;\n    for (int i = 0; i < P; ++i) best[i] = dist_prof(pool[i], pool[centerIdx]);\n    best[centerIdx] = -1;\n\n    for (int step = 1; step < P; ++step) {\n        int u = -1, val = -1;\n        for (int i = 0; i < P; ++i) {\n            if (used[i]) continue;\n            if (u == -1 || best[i] > val || (best[i] == val && i < u)) {\n                u = i;\n                val = best[i];\n            }\n        }\n        order.push_back(u);\n        used[u] = 1;\n        for (int i = 0; i < P; ++i) {\n            if (used[i]) continue;\n            int d = dist_prof(pool[i], pool[u]);\n            if (d < best[i]) best[i] = d;\n        }\n    }\n\n    vector<Codeword> chosen;\n    chosen.reserve(M);\n    for (int i = 0; i < M; ++i) chosen.push_back(pool[order[i]]);\n\n    // Precompute exact degree distributions for each possible original degree r.\n    // A vertex with original degree r has:\n    //   Bin(r, 1-eps) + Bin(N-1-r, eps)\n    auto bt = make_binom(N - 1, 1.0L - eps);\n    auto bf = make_binom(N - 1, eps);\n\n    vector<array<long double, N>> logP(N);\n    for (int r = 0; r < N; ++r) {\n        vector<long double> pmf(N, 0.0L);\n        int n1 = r;\n        int n0 = N - 1 - r;\n        for (int a = 0; a <= n1; ++a) {\n            long double pa = bt[n1][a];\n            if (pa == 0.0L) continue;\n            for (int b = 0; b <= n0; ++b) {\n                pmf[a + b] += pa * bf[n0][b];\n            }\n        }\n        for (int d = 0; d < N; ++d) {\n            logP[r][d] = (pmf[d] > 0.0L ? logl(pmf[d]) : NEG_INF);\n        }\n    }\n\n    // Output graphs.\n    cout << N << '\\n';\n    vector<string> graph_strings;\n    graph_strings.reserve(M);\n    for (const auto& cw : chosen) {\n        graph_strings.push_back(build_graph(cw));\n    }\n    for (const auto& g : graph_strings) {\n        cout << g << '\\n';\n    }\n    cout.flush();\n\n    // Answer queries.\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n\n        array<int, N> deg{};\n        int idx = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j, ++idx) {\n                if (H[idx] == '1') {\n                    ++deg[i];\n                    ++deg[j];\n                }\n            }\n        }\n\n        vector<int> ds(deg.begin(), deg.end());\n        sort(ds.begin(), ds.end());\n\n        int bestId = 0;\n        long double bestScore = NEG_INF;\n\n        for (int id = 0; id < M; ++id) {\n            const auto& cw = chosen[id];\n            long double sc = 0.0L;\n            int pos = 0;\n            for (int seg = 0; seg < 4; ++seg) {\n                int lv = cw.lev[seg];\n                int ct = cw.cnt[seg];\n                for (int k = 0; k < ct; ++k) {\n                    sc += logP[lv][ds[pos++]];\n                }\n            }\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestId = id;\n            }\n        }\n\n        cout << bestId << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ld = long double;\n\nstruct Edge {\n    int u, v;\n    ll w;\n    int cell = 0;\n    double bc = 0.0;\n    ld imp = 0.0L;\n};\n\nstruct Adj {\n    int to, id;\n};\n\nstatic constexpr int MAXD = 31;\nstatic constexpr int GRID = 20;\nstatic constexpr int CELLS = GRID * GRID;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<int> deg(N, 0);\n    ld totalW = 0.0L;\n\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        deg[u]++;\n        deg[v]++;\n        totalW += (ld)w;\n    }\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    vector<vector<Adj>> g(N);\n    for (int i = 0; i < N; ++i) g[i].reserve(deg[i]);\n    for (int i = 0; i < M; ++i) {\n        g[edges[i].u].push_back({edges[i].v, i});\n        g[edges[i].v].push_back({edges[i].u, i});\n    }\n\n    // Cell ID of each edge (midpoint-based coarse spatial feature).\n    for (int i = 0; i < M; ++i) {\n        int mx2 = xs[edges[i].u] + xs[edges[i].v]; // 0..2000\n        int my2 = ys[edges[i].u] + ys[edges[i].v];\n        int cx = min(GRID - 1, mx2 * GRID / 2001);\n        int cy = min(GRID - 1, my2 * GRID / 2001);\n        edges[i].cell = cx * GRID + cy;\n    }\n\n    // ---- Exact weighted edge betweenness (Brandes) ----\n    vector<double> bc(M, 0.0), sigma(N), delta(N);\n    vector<ll> dist(N);\n    vector<vector<int>> predV(N), predE(N);\n    for (int v = 0; v < N; ++v) {\n        predV[v].reserve(deg[v]);\n        predE[v].reserve(deg[v]);\n    }\n    vector<int> order;\n    order.reserve(N);\n\n    auto t0 = chrono::steady_clock::now();\n    auto elapsed = [&]() -> long double {\n        return chrono::duration<long double>(chrono::steady_clock::now() - t0).count();\n    };\n\n    const ll INF = (1LL << 62);\n\n    for (int s = 0; s < N; ++s) {\n        // Safety guard: if Brandes takes too long, stop early and continue with partial info.\n        if ((s & 31) == 0 && elapsed() > 4.0L) break;\n\n        fill(dist.begin(), dist.end(), INF);\n        fill(sigma.begin(), sigma.end(), 0.0);\n        fill(delta.begin(), delta.end(), 0.0);\n        for (int v = 0; v < N; ++v) {\n            predV[v].clear();\n            predE[v].clear();\n        }\n        order.clear();\n\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        sigma[s] = 1.0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n\n            order.push_back(v);\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                int eid = e.id;\n                ll nd = d + edges[eid].w;\n\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n                    sigma[to] = sigma[v];\n                    predV[to].clear();\n                    predE[to].clear();\n                    predV[to].push_back(v);\n                    predE[to].push_back(eid);\n                } else if (nd == dist[to]) {\n                    sigma[to] += sigma[v];\n                    predV[to].push_back(v);\n                    predE[to].push_back(eid);\n                }\n            }\n        }\n\n        for (int idx = (int)order.size() - 1; idx >= 0; --idx) {\n            int w = order[idx];\n            if (sigma[w] == 0.0) continue;\n            for (int k = 0; k < (int)predV[w].size(); ++k) {\n                int v = predV[w][k];\n                int eid = predE[w][k];\n                double c = (sigma[v] / sigma[w]) * (1.0 + delta[w]);\n                bc[eid] += c;\n                delta[v] += c;\n            }\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        if (!isfinite(bc[i]) || bc[i] < 0.0) bc[i] = 0.0;\n        bc[i] *= 0.5; // undirected graph\n        edges[i].bc = bc[i];\n    }\n\n    ld meanW = totalW / max(1, M);\n    for (int i = 0; i < M; ++i) {\n        ld b = max<ld>(0.0L, (ld)edges[i].bc);\n        // Compressed importance used for balancing and local search.\n        edges[i].imp = sqrtl(b + 1.0L) * (1.0L + 0.05L * (ld)edges[i].w / meanW);\n    }\n\n    vector<int> baseOrd(M);\n    iota(baseOrd.begin(), baseOrd.end(), 0);\n\n    // Fallback schedule.\n    vector<int> bestAns(M);\n    for (int i = 0; i < M; ++i) bestAns[i] = i % D + 1;\n    ld bestEval = numeric_limits<ld>::infinity();\n\n    uint64_t baseSeed = 0x123456789abcdefULL\n                      ^ (uint64_t)N * 1000003ULL\n                      ^ (uint64_t)M * 10007ULL\n                      ^ (uint64_t)D * 1000000007ULL\n                      ^ (uint64_t)K * 1000000009ULL;\n\n    vector<pair<ld, ld>> configs = {\n        {0.00L, 0.00L},\n        {0.03L, 0.01L},\n        {0.08L, 0.03L},\n    };\n\n    auto eval_solution = [&](const vector<array<ld, MAXD>> &sumV,\n                             const vector<array<ld, MAXD>> &cellSum,\n                             const vector<ld> &dayW) -> ld {\n        ld vTerm = 0.0L, dTerm = 0.0L, cTerm = 0.0L;\n        for (int v = 0; v < N; ++v) {\n            for (int d = 0; d < D; ++d) vTerm += sumV[v][d] * sumV[v][d];\n        }\n        for (int d = 0; d < D; ++d) dTerm += dayW[d] * dayW[d];\n        for (int c = 0; c < CELLS; ++c) {\n            for (int d = 0; d < D; ++d) cTerm += cellSum[c][d] * cellSum[c][d];\n        }\n        return vTerm + 0.05L * dTerm + 0.02L * cTerm;\n    };\n\n    for (int attempt = 0; attempt < (int)configs.size(); ++attempt) {\n        if (elapsed() > 5.85L) break;\n\n        ld lambda = configs[attempt].first;\n        ld mu = configs[attempt].second;\n\n        mt19937_64 rng(baseSeed + 1000003ULL * (attempt + 1));\n\n        vector<uint64_t> tieKey(M);\n        for (int i = 0; i < M; ++i) tieKey[i] = rng();\n\n        vector<int> ord = baseOrd;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].bc != edges[b].bc) return edges[a].bc > edges[b].bc;\n            if (tieKey[a] != tieKey[b]) return tieKey[a] < tieKey[b];\n            if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n            return a < b;\n        });\n\n        vector<int> perm(D);\n        iota(perm.begin(), perm.end(), 0);\n        shuffle(perm.begin(), perm.end(), rng);\n\n        vector<int> cap(D, M / D);\n        int rem = M % D;\n        for (int i = 0; i < rem; ++i) cap[perm[i]]++;\n\n        vector<array<ld, MAXD>> sumV(N), cellSum(CELLS);\n        for (int v = 0; v < N; ++v) sumV[v].fill(0.0L);\n        for (int c = 0; c < CELLS; ++c) cellSum[c].fill(0.0L);\n\n        vector<ld> dayW(D, 0.0L);\n        vector<int> dayCnt(D, 0);\n        vector<int> dayOf(M, -1), posInDay(M, -1);\n        vector<vector<int>> dayEdges(D);\n        for (int d = 0; d < D; ++d) dayEdges[d].reserve(cap[d]);\n\n        // Greedy assignment.\n        for (int idx = 0; idx < M; ++idx) {\n            int e = ord[idx];\n            int u = edges[e].u;\n            int v = edges[e].v;\n            int c = edges[e].cell;\n\n            int bestD = -1;\n            ld bestSc = numeric_limits<ld>::infinity();\n\n            for (int d = 0; d < D; ++d) {\n                if (dayCnt[d] >= cap[d]) continue;\n                ld sc = sumV[u][d] + sumV[v][d] + lambda * dayW[d] + mu * cellSum[c][d];\n                if (bestD == -1 || sc < bestSc) {\n                    bestSc = sc;\n                    bestD = d;\n                }\n            }\n\n            dayOf[e] = bestD;\n            posInDay[e] = (int)dayEdges[bestD].size();\n            dayEdges[bestD].push_back(e);\n            dayCnt[bestD]++;\n            dayW[bestD] += edges[e].imp;\n            sumV[u][bestD] += edges[e].imp;\n            sumV[v][bestD] += edges[e].imp;\n            cellSum[c][bestD] += edges[e].imp;\n        }\n\n        auto calcSwapDelta = [&](int e, int f, int a, int b) -> ld {\n            int u1 = edges[e].u, v1 = edges[e].v, c1 = edges[e].cell;\n            int u2 = edges[f].u, v2 = edges[f].v, c2 = edges[f].cell;\n            ld Ie = edges[e].imp, If = edges[f].imp;\n\n            ld delta = 0.0L;\n\n            int vs[4] = {u1, v1, u2, v2};\n            for (int i = 0; i < 4; ++i) {\n                bool seen = false;\n                for (int j = 0; j < i; ++j) {\n                    if (vs[j] == vs[i]) {\n                        seen = true;\n                        break;\n                    }\n                }\n                if (seen) continue;\n\n                bool ce = (vs[i] == u1 || vs[i] == v1);\n                bool cf = (vs[i] == u2 || vs[i] == v2);\n                ld oldA = sumV[vs[i]][a];\n                ld oldB = sumV[vs[i]][b];\n                ld newA = oldA - (ce ? Ie : 0.0L) + (cf ? If : 0.0L);\n                ld newB = oldB + (ce ? Ie : 0.0L) - (cf ? If : 0.0L);\n                delta += newA * newA + newB * newB - oldA * oldA - oldB * oldB;\n            }\n\n            ld oldWA = dayW[a], oldWB = dayW[b];\n            ld newWA = oldWA - Ie + If;\n            ld newWB = oldWB + Ie - If;\n            delta += lambda * (newWA * newWA + newWB * newWB - oldWA * oldWA - oldWB * oldWB);\n\n            if (c1 == c2) {\n                ld oldA = cellSum[c1][a], oldB = cellSum[c1][b];\n                ld newA = oldA - Ie + If;\n                ld newB = oldB + Ie - If;\n                delta += mu * (newA * newA + newB * newB - oldA * oldA - oldB * oldB);\n            } else {\n                ld oldA = cellSum[c1][a], oldB = cellSum[c1][b];\n                ld newA = oldA - Ie;\n                ld newB = oldB + Ie;\n                delta += mu * (newA * newA + newB * newB - oldA * oldA - oldB * oldB);\n\n                oldA = cellSum[c2][a];\n                oldB = cellSum[c2][b];\n                newA = oldA + If;\n                newB = oldB - If;\n                delta += mu * (newA * newA + newB * newB - oldA * oldA - oldB * oldB);\n            }\n\n            return delta;\n        };\n\n        auto applySwap = [&](int e, int f, int a, int b) {\n            int u1 = edges[e].u, v1 = edges[e].v, c1 = edges[e].cell;\n            int u2 = edges[f].u, v2 = edges[f].v, c2 = edges[f].cell;\n            ld Ie = edges[e].imp, If = edges[f].imp;\n\n            int vs[4] = {u1, v1, u2, v2};\n            for (int i = 0; i < 4; ++i) {\n                bool seen = false;\n                for (int j = 0; j < i; ++j) {\n                    if (vs[j] == vs[i]) {\n                        seen = true;\n                        break;\n                    }\n                }\n                if (seen) continue;\n\n                bool ce = (vs[i] == u1 || vs[i] == v1);\n                bool cf = (vs[i] == u2 || vs[i] == v2);\n                ld oldA = sumV[vs[i]][a];\n                ld oldB = sumV[vs[i]][b];\n                ld newA = oldA - (ce ? Ie : 0.0L) + (cf ? If : 0.0L);\n                ld newB = oldB + (ce ? Ie : 0.0L) - (cf ? If : 0.0L);\n                sumV[vs[i]][a] = newA;\n                sumV[vs[i]][b] = newB;\n            }\n\n            dayW[a] = dayW[a] - Ie + If;\n            dayW[b] = dayW[b] + Ie - If;\n\n            if (c1 == c2) {\n                ld oldA = cellSum[c1][a], oldB = cellSum[c1][b];\n                cellSum[c1][a] = oldA - Ie + If;\n                cellSum[c1][b] = oldB + Ie - If;\n            } else {\n                ld oldA = cellSum[c1][a], oldB = cellSum[c1][b];\n                cellSum[c1][a] = oldA - Ie;\n                cellSum[c1][b] = oldB + Ie;\n\n                oldA = cellSum[c2][a];\n                oldB = cellSum[c2][b];\n                cellSum[c2][a] = oldA + If;\n                cellSum[c2][b] = oldB - If;\n            }\n\n            int pa = posInDay[e];\n            int pb = posInDay[f];\n            dayEdges[a][pa] = f;\n            dayEdges[b][pb] = e;\n            posInDay[f] = pa;\n            posInDay[e] = pb;\n            dayOf[f] = a;\n            dayOf[e] = b;\n        };\n\n        // Local search: repeated greedy best-swap on important edges.\n        bool timeUp = false;\n        for (int rep = 0; rep < 2; ++rep) {\n            bool improved = false;\n\n            for (int idx = 0; idx < M; ++idx) {\n                if ((idx & 63) == 0 && elapsed() > 5.85L) {\n                    timeUp = true;\n                    break;\n                }\n\n                int e = ord[idx];\n                int a = dayOf[e];\n                int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n\n                vector<pair<ld,int>> cand;\n                cand.reserve(D - 1);\n                for (int d = 0; d < D; ++d) {\n                    if (d == a) continue;\n                    ld sc = sumV[u][d] + sumV[v][d] + lambda * dayW[d] + mu * cellSum[c][d];\n                    cand.push_back({sc, d});\n                }\n                sort(cand.begin(), cand.end());\n\n                int lim = min(2, (int)cand.size());\n                ld bestDelta = 0.0L;\n                int bestF = -1, bestB = -1;\n\n                for (int t = 0; t < lim; ++t) {\n                    int b = cand[t].second;\n                    for (int f : dayEdges[b]) {\n                        if (f == e) continue;\n                        ld delta = calcSwapDelta(e, f, a, b);\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestF = f;\n                            bestB = b;\n                        }\n                    }\n                }\n\n                if (bestF != -1) {\n                    applySwap(e, bestF, a, bestB);\n                    improved = true;\n                }\n            }\n\n            if (timeUp || !improved) break;\n        }\n\n        ld eval = eval_solution(sumV, cellSum, dayW);\n\n        if (eval < bestEval) {\n            bestEval = eval;\n            for (int i = 0; i < M; ++i) bestAns[i] = dayOf[i] + 1;\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << bestAns[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXD = 14;\nstatic constexpr int MAXM = 1 << MAXD;\nstatic constexpr int W_PREV = 1000; // dominates future heuristic\n\nusing Mat = array<array<unsigned char, MAXD>, MAXD>;\n\nstruct Rod {\n    int x, y, l, r; // z interval [l, r]\n    int len() const { return r - l + 1; }\n};\n\nstruct ObjSol {\n    vector<Rod> rods;\n    array<int, MAXD + 1> cnt{};\n};\n\nstruct LayerResult {\n    int score;\n    Mat mat{};\n};\n\nstatic int dp[MAXM], ndp[MAXM];\nstatic int parMask[15][MAXM];\nstatic signed char parChoice[15][MAXM];\n\nstatic LayerResult solve_orientation(const vector<int>& items,\n                                     const vector<int>& choices,\n                                     const Mat& prev,\n                                     const array<unsigned char, MAXD>& nextX,\n                                     const array<unsigned char, MAXD>& nextY,\n                                     bool x_to_y) {\n    int n = (int)items.size();\n    int m = (int)choices.size();\n    int M = 1 << m;\n    const int NEG = -1e9;\n\n    for (int mask = 0; mask < M; ++mask) dp[mask] = NEG;\n    dp[0] = 0;\n\n    for (int i = 0; i < n; ++i) {\n        for (int mask = 0; mask < M; ++mask) {\n            ndp[mask] = NEG;\n            parMask[i + 1][mask] = -1;\n            parChoice[i + 1][mask] = -1;\n        }\n\n        for (int mask = 0; mask < M; ++mask) {\n            if (dp[mask] == NEG) continue;\n            for (int j = 0; j < m; ++j) {\n                int x = x_to_y ? items[i] : choices[j];\n                int y = x_to_y ? choices[j] : items[i];\n                int w = (prev[x][y] ? W_PREV : 0) + ((nextX[x] && nextY[y]) ? 1 : 0);\n\n                int nmask = mask | (1 << j);\n                int val = dp[mask] + w;\n                if (val > ndp[nmask] ||\n                    (val == ndp[nmask] &&\n                     (parChoice[i + 1][nmask] == -1 || j < parChoice[i + 1][nmask]))) {\n                    ndp[nmask] = val;\n                    parMask[i + 1][nmask] = mask;\n                    parChoice[i + 1][nmask] = (signed char)j;\n                }\n            }\n        }\n        for (int mask = 0; mask < M; ++mask) dp[mask] = ndp[mask];\n    }\n\n    int full = M - 1;\n    int bestScore = dp[full];\n    vector<int> assign(n);\n    int mask = full;\n    for (int i = n; i >= 1; --i) {\n        int j = parChoice[i][mask];\n        assign[i - 1] = j;\n        mask = parMask[i][mask];\n    }\n\n    Mat mat{};\n    for (int i = 0; i < n; ++i) {\n        int x = x_to_y ? items[i] : choices[assign[i]];\n        int y = x_to_y ? choices[assign[i]] : items[i];\n        mat[x][y] = 1;\n    }\n    return {bestScore, mat};\n}\n\nstatic LayerResult choose_layer(const vector<int>& xs, const vector<int>& ys,\n                                const Mat& prev,\n                                const array<unsigned char, MAXD>& nextX,\n                                const array<unsigned char, MAXD>& nextY) {\n    int a = (int)xs.size();\n    int b = (int)ys.size();\n\n    if (a > b) {\n        return solve_orientation(xs, ys, prev, nextX, nextY, true);\n    } else if (b > a) {\n        return solve_orientation(ys, xs, prev, nextX, nextY, false);\n    } else {\n        auto r1 = solve_orientation(xs, ys, prev, nextX, nextY, true);\n        auto r2 = solve_orientation(ys, xs, prev, nextX, nextY, false);\n        if (r2.score > r1.score) return r2;\n        return r1; // tie -> x_to_y\n    }\n}\n\nstatic ObjSol solve_object(const vector<string>& f, const vector<string>& r, int dir) {\n    int D = (int)f.size();\n    vector<Mat> layers(D);\n    Mat prev{};\n\n    for (int step = 0; step < D; ++step) {\n        int z = (dir == 1 ? step : D - 1 - step);\n\n        vector<int> xs, ys;\n        xs.reserve(D);\n        ys.reserve(D);\n        for (int x = 0; x < D; ++x) if (f[z][x] == '1') xs.push_back(x);\n        for (int y = 0; y < D; ++y) if (r[z][y] == '1') ys.push_back(y);\n\n        array<unsigned char, MAXD> nextX{};\n        array<unsigned char, MAXD> nextY{};\n        if (step + 1 < D) {\n            int zn = (dir == 1 ? z + 1 : z - 1);\n            for (int x = 0; x < D; ++x) if (f[zn][x] == '1') nextX[x] = 1;\n            for (int y = 0; y < D; ++y) if (r[zn][y] == '1') nextY[y] = 1;\n        }\n\n        LayerResult lr = choose_layer(xs, ys, prev, nextX, nextY);\n        layers[z] = lr.mat;\n        prev = lr.mat;\n    }\n\n    ObjSol sol;\n    sol.cnt.fill(0);\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            int s = -1;\n            for (int z = 0; z < D; ++z) {\n                if (layers[z][x][y]) {\n                    if (s == -1) s = z;\n                } else if (s != -1) {\n                    Rod rd{x, y, s, z - 1};\n                    sol.cnt[rd.len()]++;\n                    sol.rods.push_back(rd);\n                    s = -1;\n                }\n            }\n            if (s != -1) {\n                Rod rd{x, y, s, D - 1};\n                sol.cnt[rd.len()]++;\n                sol.rods.push_back(rd);\n            }\n        }\n    }\n\n    return sol;\n}\n\nstatic long double eval_combo(const array<int, MAXD + 1>& c1,\n                              const array<int, MAXD + 1>& c2,\n                              int D) {\n    long double res = 0;\n    for (int L = 1; L <= D; ++L) {\n        int k = min(c1[L], c2[L]);\n        res += (long double)k / (long double)L;\n        res += (long double)(c1[L] - k + c2[L] - k) * (long double)L;\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; ++t) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int i = 0; i < D; ++i) cin >> f[t][i];\n        for (int i = 0; i < D; ++i) cin >> r[t][i];\n    }\n\n    // 2 directions per object: 0 = forward, 1 = backward\n    ObjSol sol[2][2];\n    for (int t = 0; t < 2; ++t) {\n        sol[t][0] = solve_object(f[t], r[t], +1);\n        sol[t][1] = solve_object(f[t], r[t], -1);\n    }\n\n    int bestA = 0, bestB = 0;\n    long double bestEval = numeric_limits<long double>::infinity();\n    for (int a = 0; a < 2; ++a) {\n        for (int b = 0; b < 2; ++b) {\n            long double e = eval_combo(sol[0][a].cnt, sol[1][b].cnt, D);\n            if (e < bestEval) {\n                bestEval = e;\n                bestA = a;\n                bestB = b;\n            }\n        }\n    }\n\n    const ObjSol& A = sol[0][bestA];\n    const ObjSol& B = sol[1][bestB];\n\n    array<vector<int>, MAXD + 1> idxA, idxB;\n    for (int i = 0; i < (int)A.rods.size(); ++i) idxA[A.rods[i].len()].push_back(i);\n    for (int i = 0; i < (int)B.rods.size(); ++i) idxB[B.rods[i].len()].push_back(i);\n\n    vector<int> idA(A.rods.size(), 0), idB(B.rods.size(), 0);\n    int n = 0;\n\n    for (int L = 1; L <= D; ++L) {\n        int k = min((int)idxA[L].size(), (int)idxB[L].size());\n        for (int i = 0; i < k; ++i) {\n            ++n;\n            idA[idxA[L][i]] = n;\n            idB[idxB[L][i]] = n;\n        }\n        for (int i = k; i < (int)idxA[L].size(); ++i) {\n            ++n;\n            idA[idxA[L][i]] = n;\n        }\n        for (int i = k; i < (int)idxB[L].size(); ++i) {\n            ++n;\n            idB[idxB[L][i]] = n;\n        }\n    }\n\n    vector<int> out1(D * D * D, 0), out2(D * D * D, 0);\n\n    auto fill_out = [&](vector<int>& out, const vector<Rod>& rods, const vector<int>& ids) {\n        for (int i = 0; i < (int)rods.size(); ++i) {\n            int id = ids[i];\n            const auto& rd = rods[i];\n            for (int z = rd.l; z <= rd.r; ++z) {\n                out[rd.x * D * D + rd.y * D + z] = id;\n            }\n        }\n    };\n\n    fill_out(out1, A.rods, idA);\n    fill_out(out2, B.rods, idB);\n\n    cout << 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    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\nusing ll = long long;\nstatic const ll INFLL = (1LL << 60);\nstatic const ll PENALTY = 100000000000000LL; // 1e14\nstatic const int MAXR = 5001;                // radii 0..5000\n\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n + 1);\n        sz.assign(n + 1, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct ConnResult {\n    ll cost = INFLL;\n    vector<char> used;\n};\n\nstruct EvalResult {\n    vector<int> sel;\n    vector<int> rad;\n    vector<char> used;\n    ll cov = INFLL, conn = INFLL, total = INFLL;\n    int uncovered = 0;\n};\n\nstruct SearchState {\n    vector<int> sel;\n    vector<char> inSel;\n    ll total = INFLL;\n    int uncovered = 0;\n};\n\nstatic int N, M, K;\nstatic vector<int> xs, ys;\nstatic vector<int> ax, ay;\nstatic vector<Edge> edges;\n\nstatic vector<vector<ll>> distGraph;\nstatic vector<vector<int>> nxtHop;\nstatic vector<vector<int>> edgeId;\nstatic vector<vector<int>> ceilDistSR; // station-resident ceil distances\nstatic vector<ll> densityScore;        // for candidate pool\nstatic vector<pair<ll,int>> singleRank; // (score, vertex), smaller is better\nstatic vector<int> addPool, swapPool;\n\nstatic auto startTime = chrono::steady_clock::now();\n\nstatic inline bool time_over() {\n    using namespace chrono;\n    return duration_cast<milliseconds>(steady_clock::now() - startTime).count() > 1800;\n}\n\nstatic int ceil_sqrt_ll(ll x) {\n    long double y = sqrt((long double)x);\n    int r = (int)y;\n    while ((ll)r * r < x) ++r;\n    while (r > 0 && (ll)(r - 1) * (r - 1) >= x) --r;\n    return r;\n}\n\nstatic vector<int> normalize_sel(vector<int> sel) {\n    if (find(sel.begin(), sel.end(), 1) == sel.end()) sel.push_back(1);\n    sort(sel.begin(), sel.end());\n    sel.erase(unique(sel.begin(), sel.end()), sel.end());\n    return sel;\n}\n\nstatic bool better(const SearchState& a, const SearchState& b) {\n    if (a.total != b.total) return a.total < b.total;\n    if (a.uncovered != b.uncovered) return a.uncovered < b.uncovered;\n    return a.sel.size() < b.sel.size();\n}\n\nstatic bool betterEval(const EvalResult& a, const EvalResult& b) {\n    if (a.total != b.total) return a.total < b.total;\n    if (a.uncovered != b.uncovered) return a.uncovered < b.uncovered;\n    return a.sel.size() < b.sel.size();\n}\n\nstatic SearchState make_state(const EvalResult& e) {\n    SearchState s;\n    s.sel = e.sel;\n    s.inSel.assign(N + 1, 0);\n    for (int v : s.sel) s.inSel[v] = 1;\n    s.total = e.total;\n    s.uncovered = e.uncovered;\n    return s;\n}\n\nstatic void add_path_edges(int a, int b, vector<char>& mark, vector<int>& cand) {\n    while (a != b) {\n        int c = nxtHop[a][b];\n        int id = edgeId[a][c];\n        if (!mark[id]) {\n            mark[id] = 1;\n            cand.push_back(id);\n        }\n        a = c;\n    }\n}\n\nstatic ConnResult reduce_candidate_edges(const vector<int>& candIds, const vector<char>& termMark, bool storeUsed) {\n    ConnResult res;\n    if (candIds.empty()) {\n        if (storeUsed) res.used.assign(M, 0);\n        res.cost = 0;\n        return res;\n    }\n\n    vector<int> ids = candIds;\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        if (edges[i].w != edges[j].w) return edges[i].w < edges[j].w;\n        return i < j;\n    });\n\n    DSU dsu(N);\n    vector<char> tree(M, 0);\n    ll cost = 0;\n\n    for (int id : ids) {\n        if (dsu.unite(edges[id].u, edges[id].v)) {\n            tree[id] = 1;\n            cost += edges[id].w;\n        }\n    }\n\n    // Connectivity check for terminals\n    int rootComp = -1;\n    for (int v = 1; v <= N; ++v) {\n        if (termMark[v]) {\n            rootComp = dsu.find(v);\n            break;\n        }\n    }\n    for (int v = 1; v <= N; ++v) {\n        if (termMark[v] && dsu.find(v) != rootComp) {\n            res.cost = INFLL;\n            if (storeUsed) res.used.assign(M, 0);\n            return res;\n        }\n    }\n\n    vector<vector<pair<int,int>>> adj(N + 1);\n    vector<int> deg(N + 1, 0);\n    for (int id = 0; id < M; ++id) {\n        if (!tree[id]) continue;\n        int u = edges[id].u, v = edges[id].v;\n        adj[u].push_back({v, id});\n        adj[v].push_back({u, id});\n        deg[u]++;\n        deg[v]++;\n    }\n\n    queue<int> q;\n    for (int v = 1; v <= N; ++v) {\n        if (!termMark[v] && deg[v] == 1) q.push(v);\n    }\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (termMark[v] || deg[v] != 1) continue;\n        int rem = -1, to = -1;\n        for (auto [nx, id] : adj[v]) {\n            if (tree[id]) {\n                rem = id;\n                to = nx;\n                break;\n            }\n        }\n        if (rem == -1) continue;\n        tree[rem] = 0;\n        cost -= edges[rem].w;\n        deg[v]--;\n        deg[to]--;\n        if (!termMark[to] && deg[to] == 1) q.push(to);\n    }\n\n    res.cost = cost;\n    if (storeUsed) res.used = move(tree);\n    return res;\n}\n\nstatic ConnResult build_conn_mst(const vector<int>& terminals, bool storeUsed) {\n    if (terminals.size() <= 1) {\n        ConnResult r;\n        r.cost = 0;\n        if (storeUsed) r.used.assign(M, 0);\n        return r;\n    }\n\n    int t = (int)terminals.size();\n    vector<ll> best(t, INFLL);\n    vector<int> par(t, -1);\n    vector<char> usedT(t, 0);\n    best[0] = 0;\n\n    vector<pair<int,int>> termEdges;\n    termEdges.reserve(t - 1);\n\n    for (int it = 0; it < t; ++it) {\n        int x = -1;\n        ll bd = INFLL;\n        for (int i = 0; i < t; ++i) {\n            if (!usedT[i] && best[i] < bd) {\n                bd = best[i];\n                x = i;\n            }\n        }\n        usedT[x] = 1;\n        if (par[x] != -1) termEdges.push_back({terminals[x], terminals[par[x]]});\n        for (int y = 0; y < t; ++y) {\n            if (usedT[y]) continue;\n            ll d = distGraph[terminals[x]][terminals[y]];\n            if (d < best[y]) {\n                best[y] = d;\n                par[y] = x;\n            }\n        }\n    }\n\n    vector<char> mark(M, 0);\n    vector<int> cand;\n    for (auto [u, v] : termEdges) add_path_edges(u, v, mark, cand);\n\n    vector<char> termMark(N + 1, 0);\n    for (int v : terminals) termMark[v] = 1;\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_greedy(const vector<int>& terminals, bool storeUsed) {\n    if (terminals.size() <= 1) {\n        ConnResult r;\n        r.cost = 0;\n        if (storeUsed) r.used.assign(M, 0);\n        return r;\n    }\n\n    vector<char> termMark(N + 1, 0);\n    for (int v : terminals) termMark[v] = 1;\n\n    vector<char> inTree(N + 1, 0), doneTerm(N + 1, 0);\n    vector<char> mark(M, 0);\n    vector<int> cand;\n\n    int root = terminals[0];\n    inTree[root] = 1;\n    doneTerm[root] = 1;\n    int done = 1;\n\n    while (done < (int)terminals.size()) {\n        ll bestD = INFLL;\n        int bestV = -1, bestT = -1;\n        for (int t : terminals) {\n            if (doneTerm[t]) continue;\n            for (int v = 1; v <= N; ++v) if (inTree[v]) {\n                ll d = distGraph[v][t];\n                if (d < bestD) {\n                    bestD = d;\n                    bestV = v;\n                    bestT = t;\n                }\n            }\n        }\n        int a = bestV, b = bestT;\n        while (a != b) {\n            int c = nxtHop[a][b];\n            int id = edgeId[a][c];\n            if (!mark[id]) {\n                mark[id] = 1;\n                cand.push_back(id);\n            }\n            inTree[a] = inTree[c] = 1;\n            a = c;\n        }\n        doneTerm[bestT] = 1;\n        done++;\n    }\n\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_star(const vector<int>& terminals, bool storeUsed) {\n    if (terminals.size() <= 1) {\n        ConnResult r;\n        r.cost = 0;\n        if (storeUsed) r.used.assign(M, 0);\n        return r;\n    }\n\n    vector<char> termMark(N + 1, 0);\n    for (int v : terminals) termMark[v] = 1;\n\n    vector<char> mark(M, 0);\n    vector<int> cand;\n    int root = terminals[0];\n    for (int i = 1; i < (int)terminals.size(); ++i) {\n        add_path_edges(root, terminals[i], mark, cand);\n    }\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_best(const vector<int>& terminals, bool storeUsed) {\n    if (terminals.size() <= 1) {\n        ConnResult r;\n        r.cost = 0;\n        if (storeUsed) r.used.assign(M, 0);\n        return r;\n    }\n\n    ConnResult best;\n    best.cost = INFLL;\n\n    auto tryCand = [&](ConnResult cand) {\n        if (cand.cost < best.cost) best = move(cand);\n    };\n\n    tryCand(build_conn_mst(terminals, storeUsed));\n    tryCand(build_conn_greedy(terminals, storeUsed));\n    tryCand(build_conn_star(terminals, storeUsed));\n\n    return best;\n}\n\nstatic EvalResult evaluate_set(vector<int> selIn, bool storeUsed, bool doImprove = true) {\n    EvalResult res;\n    selIn = normalize_sel(move(selIn));\n    res.sel = selIn;\n\n    int t = (int)selIn.size();\n    if (t == 1) {\n        int r = 0;\n        for (int k = 0; k < K; ++k) r = max(r, ceilDistSR[selIn[0]][k]);\n        res.rad = {r};\n        res.cov = 1LL * r * r;\n        res.conn = 0;\n        res.total = res.cov;\n        res.uncovered = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<const int*> dist(t);\n    for (int j = 0; j < t; ++j) dist[j] = ceilDistSR[selIn[j]].data();\n\n    vector<int> best1(K, INT_MAX), best2(K, INT_MAX);\n    vector<int> covered;\n    covered.reserve(K);\n    int uncovered = 0;\n\n    for (int k = 0; k < K; ++k) {\n        int b1 = INT_MAX, b2 = INT_MAX;\n        for (int j = 0; j < t; ++j) {\n            int d = dist[j][k];\n            if (d > 5000) continue;\n            if (d < b1) {\n                b2 = b1;\n                b1 = d;\n            } else if (d < b2) {\n                b2 = d;\n            }\n        }\n        if (b1 <= 5000) {\n            best1[k] = b1;\n            best2[k] = b2;\n            covered.push_back(k);\n        } else {\n            uncovered++;\n        }\n    }\n\n    sort(covered.begin(), covered.end(), [&](int a, int b) {\n        if (best1[a] != best1[b]) return best1[a] > best1[b];\n        int ga = (best2[a] >= INT_MAX / 2 ? INT_MAX : best2[a] - best1[a]);\n        int gb = (best2[b] >= INT_MAX / 2 ? INT_MAX : best2[b] - best1[b]);\n        if (ga != gb) return ga > gb;\n        return a < b;\n    });\n\n    vector<int> owner(K, -1), rad(t, 0), cnt(t, 0);\n    vector<int> freq(t * MAXR, 0);\n\n    // Greedy incremental assignment\n    for (int k : covered) {\n        int choose = -1;\n        ll bestInc = INFLL;\n        int bestD = INT_MAX;\n        int bestRad = INT_MAX;\n        for (int j = 0; j < t; ++j) {\n            int d = dist[j][k];\n            if (d > 5000) continue;\n            ll inc = 0;\n            if (d > rad[j]) {\n                inc = 1LL * d * d - 1LL * rad[j] * rad[j];\n            }\n            if (inc < bestInc ||\n                (inc == bestInc && (d < bestD || (d == bestD && rad[j] < bestRad)))) {\n                bestInc = inc;\n                choose = j;\n                bestD = d;\n                bestRad = rad[j];\n            }\n        }\n        if (choose == -1) {\n            // should not happen, but keep as uncovered\n            uncovered++;\n            continue;\n        }\n        owner[k] = choose;\n        int d = dist[choose][k];\n        cnt[choose]++;\n        freq[choose * MAXR + d]++;\n        if (d > rad[choose]) rad[choose] = d;\n    }\n\n    // Local improvement by moving residents\n    if (doImprove && t <= 25 && !covered.empty()) {\n        int passes = (t <= 10 ? 3 : 2);\n        vector<int> ord = covered;\n        for (int it = 0; it < passes; ++it) {\n            vector<int> curD(K, -1);\n            for (int k : covered) {\n                if (owner[k] >= 0) curD[k] = dist[owner[k]][k];\n            }\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                return curD[a] > curD[b];\n            });\n\n            bool changed = false;\n            for (int k : ord) {\n                int a = owner[k];\n                if (a < 0) continue;\n                int da = dist[a][k];\n                int oldRa = rad[a];\n\n                ll bestDelta = 0;\n                int bestB = -1;\n\n                for (int b = 0; b < t; ++b) {\n                    if (b == a) continue;\n                    int db = dist[b][k];\n                    if (db > 5000) continue;\n\n                    int newRa = oldRa;\n                    int idxA = a * MAXR + da;\n                    if (da == oldRa && freq[idxA] == 1) {\n                        if (cnt[a] == 1) newRa = 0;\n                        else {\n                            int x = oldRa - 1;\n                            while (x > 0 && freq[a * MAXR + x] == 0) --x;\n                            newRa = x;\n                        }\n                    }\n\n                    int oldRb = rad[b];\n                    int newRb = max(oldRb, db);\n                    ll delta = 1LL * newRa * newRa + 1LL * newRb * newRb\n                             - 1LL * oldRa * oldRa - 1LL * oldRb * oldRb;\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestB = b;\n                    }\n                }\n\n                if (bestB != -1) {\n                    int b = bestB;\n                    int db = dist[b][k];\n\n                    int idxA = a * MAXR + da;\n                    freq[idxA]--;\n                    cnt[a]--;\n                    if (cnt[a] == 0) {\n                        rad[a] = 0;\n                    } else if (da == rad[a] && freq[idxA] == 0) {\n                        while (rad[a] > 0 && freq[a * MAXR + rad[a]] == 0) --rad[a];\n                    }\n\n                    int idxB = b * MAXR + db;\n                    freq[idxB]++;\n                    cnt[b]++;\n                    if (db > rad[b]) rad[b] = db;\n\n                    owner[k] = b;\n                    changed = true;\n                }\n            }\n            if (!changed) break;\n        }\n    }\n\n    // Prune empty stations except root\n    vector<int> newSel, newRad;\n    for (int j = 0; j < t; ++j) {\n        if (selIn[j] == 1 || cnt[j] > 0) {\n            newSel.push_back(selIn[j]);\n            newRad.push_back(rad[j]);\n        }\n    }\n\n    ll cov = 0;\n    for (int r : newRad) cov += 1LL * r * r;\n\n    ConnResult cr = build_conn_best(newSel, storeUsed);\n\n    res.sel = move(newSel);\n    res.rad = move(newRad);\n    res.cov = cov;\n    res.conn = cr.cost;\n    res.total = cov + cr.cost + PENALTY * uncovered;\n    res.uncovered = uncovered;\n    if (storeUsed) res.used = move(cr.used);\n    return res;\n}\n\nstatic vector<int> make_kmeans_groups(int C, int startIdx) {\n    if (C <= 0) return {};\n    C = min(C, K);\n\n    vector<int> centersIdx;\n    centersIdx.reserve(C);\n    startIdx %= K;\n    if (startIdx < 0) startIdx += K;\n    centersIdx.push_back(startIdx);\n\n    vector<ll> mind2(K, INFLL);\n    auto dist2p = [&](int i, int j) -> ll {\n        ll dx = (ll)ax[i] - ax[j];\n        ll dy = (ll)ay[i] - ay[j];\n        return dx * dx + dy * dy;\n    };\n\n    for (int k = 0; k < K; ++k) mind2[k] = dist2p(k, startIdx);\n\n    for (int c = 1; c < C; ++c) {\n        int nxt = 0;\n        ll best = -1;\n        for (int k = 0; k < K; ++k) {\n            if (mind2[k] > best) {\n                best = mind2[k];\n                nxt = k;\n            }\n        }\n        centersIdx.push_back(nxt);\n        for (int k = 0; k < K; ++k) {\n            mind2[k] = min(mind2[k], dist2p(k, nxt));\n        }\n    }\n\n    vector<pair<double,double>> centers(C);\n    for (int i = 0; i < C; ++i) {\n        centers[i] = { (double)ax[centersIdx[i]], (double)ay[centersIdx[i]] };\n    }\n\n    vector<int> assign(K, 0);\n    for (int it = 0; it < 5; ++it) {\n        vector<vector<int>> groups(C);\n        for (int k = 0; k < K; ++k) {\n            int bestc = 0;\n            long double bestd = 1e100;\n            for (int c = 0; c < C; ++c) {\n                long double dx = (long double)ax[k] - centers[c].first;\n                long double dy = (long double)ay[k] - centers[c].second;\n                long double d = dx * dx + dy * dy;\n                if (d < bestd) {\n                    bestd = d;\n                    bestc = c;\n                }\n            }\n            assign[k] = bestc;\n            groups[bestc].push_back(k);\n        }\n\n        for (int c = 0; c < C; ++c) {\n            if (groups[c].empty()) continue;\n            long double sx = 0, sy = 0;\n            for (int k : groups[c]) {\n                sx += ax[k];\n                sy += ay[k];\n            }\n            centers[c] = { (double)(sx / groups[c].size()), (double)(sy / groups[c].size()) };\n        }\n    }\n\n    vector<vector<int>> groups(C);\n    for (int k = 0; k < K; ++k) {\n        int bestc = 0;\n        long double bestd = 1e100;\n        for (int c = 0; c < C; ++c) {\n            long double dx = (long double)ax[k] - centers[c].first;\n            long double dy = (long double)ay[k] - centers[c].second;\n            long double d = dx * dx + dy * dy;\n            if (d < bestd) {\n                bestd = d;\n                bestc = c;\n            }\n        }\n        groups[bestc].push_back(k);\n    }\n\n    vector<int> chosenStations;\n    chosenStations.reserve(C);\n    for (int c = 0; c < C; ++c) {\n        if (groups[c].empty()) continue;\n        int bestV = 1;\n        int bestMax = INT_MAX;\n        ll bestSum = INFLL;\n        for (int v = 1; v <= N; ++v) {\n            int mx = 0;\n            ll sum = 0;\n            for (int k : groups[c]) {\n                int d = ceilDistSR[v][k];\n                mx = max(mx, d);\n                sum += d;\n                if (mx > bestMax) break;\n            }\n            if (mx < bestMax || (mx == bestMax && sum < bestSum)) {\n                bestMax = mx;\n                bestSum = sum;\n                bestV = v;\n            }\n        }\n        chosenStations.push_back(bestV);\n    }\n\n    sort(chosenStations.begin(), chosenStations.end());\n    chosenStations.erase(unique(chosenStations.begin(), chosenStations.end()), chosenStations.end());\n    if (find(chosenStations.begin(), chosenStations.end(), 1) == chosenStations.end())\n        chosenStations.push_back(1);\n    sort(chosenStations.begin(), chosenStations.end());\n    return chosenStations;\n}\n\nstatic SearchState local_search(SearchState cur) {\n    int stagnation = 0;\n    while (!time_over() && stagnation < 3) {\n        bool improved = false;\n\n        // Add phase\n        {\n            EvalResult best;\n            best.total = cur.total;\n            best.uncovered = cur.uncovered;\n            best.sel = cur.sel;\n\n            for (int v : addPool) {\n                if (v <= 1 || cur.inSel[v]) continue;\n                vector<int> tmp = cur.sel;\n                tmp.push_back(v);\n                EvalResult cand = evaluate_set(move(tmp), false, true);\n                if (betterEval(cand, best)) best = move(cand);\n                if (time_over()) break;\n            }\n            if (betterEval(best, EvalResult{cur.sel, {}, {}, cur.total, 0, 0, cur.uncovered})) {\n                cur = make_state(best);\n                improved = true;\n                stagnation = 0;\n                continue;\n            }\n        }\n\n        // Remove phase\n        {\n            EvalResult best;\n            best.total = cur.total;\n            best.uncovered = cur.uncovered;\n            best.sel = cur.sel;\n\n            if ((int)cur.sel.size() > 1) {\n                for (int v : cur.sel) {\n                    if (v == 1) continue;\n                    vector<int> tmp;\n                    tmp.reserve(cur.sel.size() - 1);\n                    for (int x : cur.sel) if (x != v) tmp.push_back(x);\n                    EvalResult cand = evaluate_set(move(tmp), false, true);\n                    if (betterEval(cand, best)) best = move(cand);\n                    if (time_over()) break;\n                }\n            }\n            if (betterEval(best, EvalResult{cur.sel, {}, {}, cur.total, 0, 0, cur.uncovered})) {\n                cur = make_state(best);\n                improved = true;\n                stagnation = 0;\n                continue;\n            }\n        }\n\n        // Swap phase\n        {\n            EvalResult best;\n            best.total = cur.total;\n            best.uncovered = cur.uncovered;\n            best.sel = cur.sel;\n\n            for (int s : cur.sel) {\n                if (s == 1) continue;\n                for (int v : swapPool) {\n                    if (v <= 1 || cur.inSel[v]) continue;\n                    vector<int> tmp;\n                    tmp.reserve(cur.sel.size());\n                    for (int x : cur.sel) if (x != s) tmp.push_back(x);\n                    tmp.push_back(v);\n                    EvalResult cand = evaluate_set(move(tmp), false, true);\n                    if (betterEval(cand, best)) best = move(cand);\n                    if (time_over()) break;\n                }\n                if (time_over()) break;\n            }\n            if (betterEval(best, EvalResult{cur.sel, {}, {}, cur.total, 0, 0, cur.uncovered})) {\n                cur = make_state(best);\n                improved = true;\n                stagnation = 0;\n                continue;\n            }\n        }\n\n        if (!improved) ++stagnation;\n    }\n    return cur;\n}\n\nstatic SearchState repair_coverage(SearchState cur) {\n    while (!time_over() && cur.uncovered > 0) {\n        EvalResult best;\n        bool found = false;\n\n        for (int v = 1; v <= N; ++v) {\n            if (cur.inSel[v]) continue;\n            vector<int> tmp = cur.sel;\n            tmp.push_back(v);\n            EvalResult cand = evaluate_set(move(tmp), false, false); // faster repair\n            if (!found || cand.uncovered < best.uncovered ||\n                (cand.uncovered == best.uncovered && betterEval(cand, best))) {\n                best = move(cand);\n                found = true;\n            }\n            if (time_over()) break;\n        }\n\n        if (!found) break;\n        SearchState nxt = make_state(best);\n        if (nxt.uncovered >= cur.uncovered) break;\n        cur = move(nxt);\n    }\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    xs.resize(N + 1);\n    ys.resize(N + 1);\n    for (int i = 1; i <= N; ++i) cin >> xs[i] >> ys[i];\n\n    edges.resize(M);\n    edgeId.assign(N + 1, vector<int>(N + 1, -1));\n    distGraph.assign(N + 1, vector<ll>(N + 1, INFLL));\n    nxtHop.assign(N + 1, vector<int>(N + 1, -1));\n\n    for (int i = 1; i <= N; ++i) {\n        distGraph[i][i] = 0;\n        nxtHop[i][i] = i;\n    }\n\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n        edgeId[u][v] = edgeId[v][u] = j;\n        if (w < distGraph[u][v]) {\n            distGraph[u][v] = distGraph[v][u] = w;\n            nxtHop[u][v] = v;\n            nxtHop[v][u] = u;\n        }\n    }\n\n    ax.resize(K);\n    ay.resize(K);\n    for (int i = 0; i < K; ++i) cin >> ax[i] >> ay[i];\n\n    // Floyd-Warshall\n    for (int k = 1; k <= N; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            if (distGraph[i][k] >= INFLL / 4) continue;\n            for (int j = 1; j <= N; ++j) {\n                if (distGraph[k][j] >= INFLL / 4) continue;\n                ll nd = distGraph[i][k] + distGraph[k][j];\n                if (nd < distGraph[i][j]) {\n                    distGraph[i][j] = nd;\n                    nxtHop[i][j] = nxtHop[i][k];\n                }\n            }\n        }\n    }\n\n    // Precompute station-resident ceil distances\n    ceilDistSR.assign(N + 1, vector<int>(K, 0));\n    for (int s = 1; s <= N; ++s) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = (ll)xs[s] - ax[k];\n            ll dy = (ll)ys[s] - ay[k];\n            ll d2 = dx * dx + dy * dy;\n            ceilDistSR[s][k] = ceil_sqrt_ll(d2);\n        }\n    }\n\n    // Density score for candidate diversity\n    densityScore.assign(N + 1, 0);\n    for (int s = 1; s <= N; ++s) {\n        ll sc = 0;\n        for (int k = 0; k < K; ++k) {\n            int d = ceilDistSR[s][k];\n            if (d <= 5000) sc += 5000 - d;\n        }\n        densityScore[s] = sc;\n    }\n\n    // Rank vertices by single-station score and density\n    singleRank.clear();\n    singleRank.reserve(N - 1);\n\n    // Single-station evaluation: root + v\n    vector<EvalResult> singleEval(N + 1);\n    for (int v = 2; v <= N; ++v) {\n        EvalResult e = evaluate_set({1, v}, false, false);\n        singleEval[v] = e;\n        singleRank.push_back({e.total, v});\n    }\n    sort(singleRank.begin(), singleRank.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n\n    vector<pair<ll,int>> densityRank;\n    densityRank.reserve(N);\n    for (int v = 2; v <= N; ++v) densityRank.push_back({densityScore[v], v});\n    sort(densityRank.begin(), densityRank.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    auto makePool = [&](int aCnt, int bCnt) {\n        vector<int> pool;\n        vector<char> seen(N + 1, 0);\n        for (int i = 0; i < aCnt && i < (int)singleRank.size(); ++i) {\n            int v = singleRank[i].second;\n            if (!seen[v]) {\n                seen[v] = 1;\n                pool.push_back(v);\n            }\n        }\n        for (int i = 0; i < bCnt && i < (int)densityRank.size(); ++i) {\n            int v = densityRank[i].second;\n            if (!seen[v]) {\n                seen[v] = 1;\n                pool.push_back(v);\n            }\n        }\n        return pool;\n    };\n\n    addPool = makePool(40, 20);\n    swapPool = makePool(25, 15);\n\n    // Build seeds\n    vector<vector<int>> seeds;\n\n    // Best single\n    if (!singleRank.empty()) {\n        seeds.push_back(normalize_sel({1, singleRank[0].second}));\n    }\n\n    // Best pair among top 15 single candidates\n    {\n        int L = min(15, (int)singleRank.size());\n        ll bestT = INFLL;\n        vector<int> bestSel = {1};\n        for (int i = 0; i < L; ++i) {\n            for (int j = i + 1; j < L; ++j) {\n                vector<int> sel = {1, singleRank[i].second, singleRank[j].second};\n                EvalResult e = evaluate_set(sel, false, true);\n                if (e.total < bestT) {\n                    bestT = e.total;\n                    bestSel = e.sel;\n                }\n                if (time_over()) break;\n            }\n            if (time_over()) break;\n        }\n        seeds.push_back(normalize_sel(bestSel));\n    }\n\n    // Top 6 singles seed\n    {\n        vector<int> sel = {1};\n        int L = min(6, (int)singleRank.size());\n        for (int i = 0; i < L; ++i) sel.push_back(singleRank[i].second);\n        seeds.push_back(normalize_sel(sel));\n    }\n\n    // K-means seeds\n    seeds.push_back(normalize_sel(make_kmeans_groups(8, 0)));\n    seeds.push_back(normalize_sel(make_kmeans_groups(16, K / 2)));\n\n    // Remove duplicate seeds\n    {\n        vector<vector<int>> uniq;\n        for (auto& s : seeds) {\n            sort(s.begin(), s.end());\n            s.erase(unique(s.begin(), s.end()), s.end());\n            if (find(s.begin(), s.end(), 1) == s.end()) s.push_back(1);\n            sort(s.begin(), s.end());\n            bool dup = false;\n            for (auto& t : uniq) {\n                if (t == s) { dup = true; break; }\n            }\n            if (!dup) uniq.push_back(s);\n        }\n        seeds = move(uniq);\n    }\n\n    // Search\n    SearchState best;\n    best.total = INFLL;\n    best.uncovered = INT_MAX;\n\n    for (auto& seed : seeds) {\n        if (time_over()) break;\n        EvalResult e = evaluate_set(seed, false, true);\n        SearchState cur = make_state(e);\n        cur = local_search(cur);\n        if (better(cur, best)) best = cur;\n    }\n\n    // Coverage repair if needed\n    if (best.uncovered > 0 && !time_over()) {\n        best = repair_coverage(best);\n        if (!time_over()) best = local_search(best);\n    }\n\n    // Final exact evaluation with edges\n    EvalResult finalEval;\n    if (!best.sel.empty()) {\n        finalEval = evaluate_set(best.sel, true, true);\n    }\n\n    // Last resort fallback: all vertices selected\n    if (best.sel.empty() || finalEval.uncovered > 0) {\n        vector<int> allSel;\n        for (int v = 1; v <= N; ++v) allSel.push_back(v);\n        finalEval = evaluate_set(allSel, true, false);\n    }\n\n    // Output P\n    vector<int> P(N + 1, 0);\n    for (int i = 0; i < (int)finalEval.sel.size(); ++i) {\n        P[finalEval.sel[i]] = finalEval.rad[i];\n    }\n    for (int i = 1; i <= N; ++i) {\n        if (i > 1) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n\n    // Output B\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (finalEval.used.empty() ? 0 : (finalEval.used[j] ? 1 : 0));\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const int V = N * (N + 1) / 2;\n    const int INF = 1e9;\n    const int LIMIT = 10000;\n\n    auto ID = [&](int x, int y) -> int {\n        return x * (x + 1) / 2 + y;\n    };\n\n    vector<pair<int,int>> coord(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            coord[ID(x, y)] = {x, y};\n        }\n    }\n\n    vector<vector<int>> adj(V), children(V);\n    vector<int> needParents(V, 0);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = ID(x, y);\n\n            // Children first (helps path selection prefer lower routes)\n            if (x + 1 < N) {\n                int d1 = ID(x + 1, y);\n                int d2 = ID(x + 1, y + 1);\n                adj[u].push_back(d1);\n                adj[u].push_back(d2);\n                children[u].push_back(d1);\n                children[u].push_back(d2);\n            }\n\n            // Same row\n            if (y > 0) adj[u].push_back(ID(x, y - 1));\n            if (y < x) adj[u].push_back(ID(x, y + 1));\n\n            // Parents\n            if (x > 0) {\n                if (y > 0) adj[u].push_back(ID(x - 1, y - 1));\n                if (y < x) adj[u].push_back(ID(x - 1, y));\n            }\n\n            if (x == 0) needParents[u] = 0;\n            else needParents[u] = (y > 0 && y < x) ? 2 : 1;\n        }\n    }\n\n    vector<int> board(V), pos(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            int u = ID(x, y);\n            board[u] = v;\n            pos[v] = u;\n        }\n    }\n\n    vector<char> fixed(V, 0), avail(V, 0);\n    vector<int> parentCnt(V, 0);\n    vector<int> availList;\n    availList.reserve(V);\n\n    int top = ID(0, 0);\n    avail[top] = 1;\n    availList.push_back(top);\n\n    vector<Op> ops;\n    ops.reserve(LIMIT);\n\n    for (int num = 0; num < V; ++num) {\n        int s = pos[num];\n\n        // BFS over unfixed cells\n        vector<int> dist(V, -1);\n        vector<int> order;\n        order.reserve(V);\n        dist[s] = 0;\n        order.push_back(s);\n\n        for (size_t head = 0; head < order.size(); ++head) {\n            int u = order[head];\n            for (int v : adj[u]) {\n                if (fixed[v] || dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                order.push_back(v);\n            }\n        }\n\n        // On shortest-path DAG, minimize number of upward moves\n        vector<int> bestPen(V, INF), bestPar(V, -1);\n        bestPen[s] = 0;\n\n        auto better_parent = [&](int a, int b) -> bool {\n            if (b == -1) return true;\n            if (coord[a].first != coord[b].first) return coord[a].first > coord[b].first;\n            return coord[a].second > coord[b].second;\n        };\n\n        for (int u : order) {\n            if (bestPen[u] == INF) continue;\n            for (int v : adj[u]) {\n                if (fixed[v] || dist[v] != dist[u] + 1) continue;\n                int add = (coord[v].first < coord[u].first ? 1 : 0); // upward move\n                int cand = bestPen[u] + add;\n                if (cand < bestPen[v] || (cand == bestPen[v] && better_parent(u, bestPar[v]))) {\n                    bestPen[v] = cand;\n                    bestPar[v] = u;\n                }\n            }\n        }\n\n        // Choose nearest available reachable cell\n        int target = -1;\n        tuple<int,int,int,int> best = {INF, INF, INF, INF};\n        for (int id : availList) {\n            if (!avail[id] || dist[id] == -1 || bestPen[id] == INF) continue;\n            auto cand = make_tuple(dist[id], bestPen[id], coord[id].first, coord[id].second);\n            if (cand < best) {\n                best = cand;\n                target = id;\n            }\n        }\n\n        if (target == -1) {\n            break; // Should not happen, but keep output legal\n        }\n\n        // Reconstruct path from s to target\n        vector<int> path;\n        for (int v = target;; v = bestPar[v]) {\n            path.push_back(v);\n            if (v == s) break;\n        }\n        reverse(path.begin(), path.end());\n\n        int needSwaps = (int)path.size() - 1;\n        if ((int)ops.size() + needSwaps > LIMIT) {\n            break; // keep output legal\n        }\n\n        // Apply swaps along the path\n        for (int i = 0; i < needSwaps; ++i) {\n            int a = path[i];\n            int b = path[i + 1];\n            int va = board[a];\n            int vb = board[b];\n            swap(board[a], board[b]);\n            pos[va] = b;\n            pos[vb] = a;\n            ops.push_back({coord[a].first, coord[a].second, coord[b].first, coord[b].second});\n        }\n\n        // Fix target cell\n        fixed[target] = 1;\n        avail[target] = 0;\n\n        for (int c : children[target]) {\n            if (fixed[c]) continue;\n            ++parentCnt[c];\n            if (parentCnt[c] == needParents[c] && !avail[c]) {\n                avail[c] = 1;\n                availList.push_back(c);\n            }\n        }\n    }\n\n    cout << ops.size() << '\\n';\n    for (auto &op : ops) {\n        cout << op.x1 << ' ' << op.y1 << ' ' << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Node {\n    int r = -1, c = -1;\n    int parent = 0;\n    int disc = -1;                 // BFS discovery order in the rooted tree\n    vector<int> child;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    const int er = 0;\n    const int ec = (D - 1) / 2;\n\n    auto inside = [&](int r, int c) {\n        return 0 <= r && r < D && 0 <= c && c < D;\n    };\n    auto free_cell = [&](int r, int c) {\n        return inside(r, c) && !obstacle[r][c] && !(r == er && c == ec);\n    };\n\n    // Compress free cells (excluding the entrance) into nodes 1..M.\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<pair<int,int>> pos(1); // node 0 = dummy root (entrance)\n    int M = 0;\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (free_cell(r, c)) {\n                id[r][c] = ++M;\n                pos.push_back({r, c});\n            }\n        }\n    }\n\n    vector<Node> nodes(M + 1);\n    for (int i = 1; i <= M; ++i) {\n        nodes[i].r = pos[i].first;\n        nodes[i].c = pos[i].second;\n    }\n\n    // Build a rooted BFS spanning tree from the entrance.\n    // The order of discovery is used as a static key for storage decisions.\n    vector<vector<bool>> vis(D, vector<bool>(D, false));\n    queue<int> q; // node ids\n    int discCnt = 0;\n\n    const int dr[4] = {1, 0, 0, -1}; // down, left, right, up\n    const int dc[4] = {0, -1, 1, 0};\n\n    auto add_if_free = [&](int nr, int nc, int parentId) {\n        if (!free_cell(nr, nc) || vis[nr][nc]) return;\n        int v = id[nr][nc];\n        vis[nr][nc] = true;\n        nodes[v].parent = parentId;\n        nodes[v].disc = discCnt++;\n        nodes[parentId].child.push_back(v);\n        q.push(v);\n    };\n\n    // Start from the 3 cells adjacent to the entrance.\n    for (int k = 0; k < 4; ++k) {\n        int nr = er + dr[k], nc = ec + dc[k];\n        add_if_free(nr, nc, 0);\n    }\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        int r = nodes[u].r, c = nodes[u].c;\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            add_if_free(nr, nc, u);\n        }\n    }\n\n    // Sanity: all free cells should be visited.\n    // (Guaranteed by the statement.)\n    // cerr << \"M=\" << M << \" discCnt=\" << discCnt << \"\\n\";\n\n    vector<int> remChild(M + 1);\n    for (int i = 0; i <= M; ++i) remChild[i] = (int)nodes[i].child.size();\n\n    vector<bool> occupied(M + 1, false);\n    vector<int> assigned(M + 1, -1);\n\n    // Online storage:\n    // among current leaves of the rooted tree, choose the one whose BFS discovery\n    // index is closest to the arriving number.\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        vector<int> leaves;\n        leaves.reserve(M);\n        for (int i = 1; i <= M; ++i) {\n            if (!occupied[i] && remChild[i] == 0) leaves.push_back(i);\n        }\n\n        int chosen = leaves[0];\n        int bestDiff = abs(nodes[chosen].disc - t);\n        for (int u : leaves) {\n            int d = abs(nodes[u].disc - t);\n            if (d < bestDiff || (d == bestDiff && nodes[u].disc < nodes[chosen].disc)) {\n                bestDiff = d;\n                chosen = u;\n            }\n        }\n\n        occupied[chosen] = true;\n        assigned[chosen] = t;\n\n        int p = nodes[chosen].parent;\n        if (p != 0) --remChild[p];\n\n        cout << nodes[chosen].r << ' ' << nodes[chosen].c << '\\n' << flush;\n    }\n\n    // Final removal order:\n    // tree-topological greedy: always take the available node with smallest label.\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int v : nodes[0].child) {\n        pq.push({assigned[v], v});\n    }\n\n    vector<int> outOrder;\n    outOrder.reserve(M);\n\n    while (!pq.empty()) {\n        auto [val, u] = pq.top();\n        pq.pop();\n        outOrder.push_back(u);\n        for (int v : nodes[u].child) {\n            pq.push({assigned[v], v});\n        }\n    }\n\n    for (int u : outOrder) {\n        cout << nodes[u].r << ' ' << nodes[u].c << '\\n';\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXM = 100;\nstatic const int MAXV = MAXN * MAXN;\n\nint n, m, N;\nvector<int> initBoard, boardCur;\narray<array<int, 4>, MAXV> nb;\nint distToBorder[MAXV];\nint sameDegOrig[MAXV];\nbool origB[MAXM + 1];\nbool origAdj[MAXM + 1][MAXM + 1];\nbool frozenCell[MAXV];\n\nint curCnt[MAXM + 1];\nint curTouch0[MAXM + 1];\nint curAdj[MAXM + 1][MAXM + 1];\n\nint visStamp[MAXV];\nint stampNow = 1;\n\ninline int id(int i, int j) { return i * n + j; }\n\nvoid recomputeStats() {\n    memset(curCnt, 0, sizeof(curCnt));\n    memset(curTouch0, 0, sizeof(curTouch0));\n    memset(curAdj, 0, sizeof(curAdj));\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c == 0) continue;\n        curCnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c == 0) continue;\n\n        if (origB[c]) {\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[idx][d];\n                if (v == -1 || boardCur[v] == 0) curTouch0[c]++;\n            }\n        }\n\n        int r = idx / n, ccol = idx % n;\n        // Count only right/down to avoid double counting.\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = boardCur[right];\n            if (d > 0 && origB[c] && origB[d] && c < d) {\n                curAdj[c][d]++;\n                curAdj[d][c]++;\n            }\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = boardCur[down];\n            if (d > 0 && origB[c] && origB[d] && c < d) {\n                curAdj[c][d]++;\n                curAdj[d][c]++;\n            }\n        }\n    }\n}\n\nbool canRemove(int idx) {\n    int c = boardCur[idx];\n    if (c == 0) return false;\n    if (!origB[c]) return false;\n    if (frozenCell[idx]) return false;\n\n    int same = 0;\n    int loss0 = 0;\n    int loss[MAXM + 1];\n    memset(loss, 0, sizeof(loss));\n\n    bool frontier = false;\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            frontier = true;\n            loss0++;\n        } else {\n            int t = boardCur[v];\n            if (t == c) {\n                same++;\n            } else {\n                if (!origB[t]) return false; // would expose a non-B color to 0\n                loss[t]++;\n            }\n        }\n    }\n\n    if (!frontier) return false;\n    if (curCnt[c] <= 1) return false;\n\n    int newTouch0 = curTouch0[c] - loss0 + same;\n    if (newTouch0 <= 0) return false; // boundary-adjacent colors must keep touching 0\n\n    for (int t = 1; t <= m; ++t) {\n        if (loss[t] == 0) continue;\n        if (curAdj[c][t] <= loss[t]) return false; // original adjacency edge would disappear\n    }\n\n    if (same <= 1) return true;\n\n    // Connectivity check for color c after removing idx.\n    ++stampNow;\n    vector<int> q;\n    q.reserve(N);\n\n    int start = -1;\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v != -1 && boardCur[v] == c) {\n            start = v;\n            break;\n        }\n    }\n    if (start == -1) return false;\n\n    q.push_back(start);\n    visStamp[start] = stampNow;\n    int seen = 1;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[u][d];\n            if (v == -1 || v == idx) continue;\n            if (boardCur[v] == c && visStamp[v] != stampNow) {\n                visStamp[v] = stampNow;\n                q.push_back(v);\n                ++seen;\n            }\n        }\n    }\n\n    return seen == curCnt[c] - 1;\n}\n\nbool validate(const vector<int>& b) {\n    bool outAdj[MAXM + 1][MAXM + 1];\n    memset(outAdj, 0, sizeof(outAdj));\n    bool outTouch0[MAXM + 1];\n    memset(outTouch0, 0, sizeof(outTouch0));\n\n    vector<int> cnt(MAXM + 1, 0);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c > 0) cnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c == 0) continue;\n\n        int i = idx / n, j = idx % n;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1 || b[v] == 0) outTouch0[c] = true;\n            else {\n                int t = b[v];\n                if (t != c) {\n                    outAdj[c][t] = outAdj[t][c] = true;\n                }\n            }\n        }\n    }\n\n    for (int c = 1; c <= m; ++c) {\n        if (outTouch0[c] != origB[c]) return false;\n        for (int d = 1; d <= m; ++d) {\n            if (outAdj[c][d] != origAdj[c][d]) return false;\n        }\n    }\n\n    // Connectivity of each color 1..m\n    vector<int> seen(N, 0);\n    int stamp = 1;\n    vector<int> q;\n    q.reserve(N);\n\n    for (int c = 1; c <= m; ++c) {\n        int start = -1;\n        for (int idx = 0; idx < N; ++idx) {\n            if (b[idx] == c) { start = idx; break; }\n        }\n        if (start == -1) return false;\n\n        ++stamp;\n        q.clear();\n        q.push_back(start);\n        seen[start] = stamp;\n        int got = 1;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == c && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                    ++got;\n                }\n            }\n        }\n\n        if (got != cnt[c]) return false;\n    }\n\n    // 0-color connectivity through outside: all 0-cells must be reachable from a boundary 0-cell.\n    int zeroCnt = 0;\n    for (int idx = 0; idx < N; ++idx) if (b[idx] == 0) zeroCnt++;\n    if (zeroCnt > 0) {\n        ++stamp;\n        q.clear();\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    int idx = id(i, j);\n                    if (b[idx] == 0 && seen[idx] != stamp) {\n                        seen[idx] = stamp;\n                        q.push_back(idx);\n                    }\n                }\n            }\n        }\n        if (q.empty()) return false;\n\n        int got = 0;\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            ++got;\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == 0 && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                }\n            }\n        }\n        if (got != zeroCnt) return false;\n    }\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    N = n * n;\n\n    initBoard.assign(N, 0);\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c;\n            cin >> c;\n            initBoard[id(i, j)] = c;\n        }\n    }\n\n    // Precompute neighbors and distances.\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = id(i, j);\n            nb[idx][0] = (i == 0 ? -1 : id(i - 1, j));\n            nb[idx][1] = (i + 1 == n ? -1 : id(i + 1, j));\n            nb[idx][2] = (j == 0 ? -1 : id(i, j - 1));\n            nb[idx][3] = (j + 1 == n ? -1 : id(i, j + 1));\n            distToBorder[idx] = min(min(i, j), min(n - 1 - i, n - 1 - j));\n        }\n    }\n\n    // Original boundary-adjacent colors.\n    memset(origB, 0, sizeof(origB));\n    for (int i = 0; i < n; ++i) {\n        origB[initBoard[id(i, 0)]] = true;\n        origB[initBoard[id(i, n - 1)]] = true;\n    }\n    for (int j = 0; j < n; ++j) {\n        origB[initBoard[id(0, j)]] = true;\n        origB[initBoard[id(n - 1, j)]] = true;\n    }\n\n    // Original adjacency among colors.\n    memset(origAdj, 0, sizeof(origAdj));\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = initBoard[right];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = initBoard[down];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n    }\n\n    // Same-color degree in the original map.\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int s = 0;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v != -1 && initBoard[v] == c) s++;\n        }\n        sameDegOrig[idx] = s;\n    }\n\n    // Frozen cells: any cell adjacent to a non-boundary-adjacent different color can never be removed.\n    memset(frozenCell, 0, sizeof(frozenCell));\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        if (!origB[c]) continue;\n        bool frozen = false;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1) continue;\n            int t = initBoard[v];\n            if (t != c && !origB[t]) {\n                frozen = true;\n                break;\n            }\n        }\n        frozenCell[idx] = frozen;\n    }\n\n    // Candidate list.\n    vector<int> cand;\n    cand.reserve(N);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        if (origB[c] && !frozenCell[idx]) cand.push_back(idx);\n    }\n\n    sort(cand.begin(), cand.end(), [&](int a, int b) {\n        if (distToBorder[a] != distToBorder[b]) return distToBorder[a] < distToBorder[b];\n        if (sameDegOrig[a] != sameDegOrig[b]) return sameDegOrig[a] < sameDegOrig[b];\n        return a < b;\n    });\n    vector<int> candRev = cand;\n    reverse(candRev.begin(), candRev.end());\n\n    boardCur = initBoard;\n    recomputeStats();\n\n    // Greedy peeling with two scan orders.\n    for (int round = 0; round < 100; ++round) {\n        bool changed = false;\n        for (int phase = 0; phase < 2; ++phase) {\n            const vector<int>& ord = (phase == 0 ? cand : candRev);\n            for (int idx : ord) {\n                if (boardCur[idx] == 0) continue;\n                if (canRemove(idx)) {\n                    boardCur[idx] = 0;\n                    recomputeStats();\n                    changed = true;\n                }\n            }\n        }\n        if (!changed) break;\n    }\n\n    // Safety validation; if anything goes wrong, fall back to the original map.\n    vector<int> out = boardCur;\n    if (!validate(out)) out = initBoard;\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << out[id(i, j)];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ld = long double;\n\nstruct Bucket {\n    vector<int> items;\n    int l, r;      // inclusive rank interval among descending order\n    bool same;     // middle block of equal items; do not split further\n    ld value;      // estimated total weight of this rank interval\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    const ld MU = 100000.0L;\n    const ld CAP = MU * (ld)N / (ld)D;\n    const ld capProb = 1.0L - expl(-CAP / MU);\n\n    // Estimated weight of descending rank r (0-based), via truncated exponential quantile.\n    vector<ld> rankW(N);\n    for (int r = 0; r < N; ++r) {\n        ld p = ((ld)N - r - 0.5L) / (ld)N; // midpoint quantile in ascending cdf\n        p = max((ld)1e-18L, min((ld)1.0L - 1e-18L, p));\n        ld z = -log1pl(-p * capProb);\n        ld w = MU * z;\n        w = max((ld)1.0L, min(CAP, w));\n        rankW[r] = w;\n    }\n\n    vector<ld> pref(N + 1, 0.0L);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + rankW[i];\n\n    auto intervalValue = [&](int l, int r) -> ld {\n        return pref[r + 1] - pref[l];\n    };\n\n    mt19937_64 rng(\n        0x9e3779b97f4a7c15ULL ^\n        (uint64_t)N * 1000003ULL ^\n        (uint64_t)D * 10007ULL ^\n        (uint64_t)Q * 10000019ULL\n    );\n\n    auto randInt = [&](int l, int r) -> int {\n        uniform_int_distribution<int> dist(l, r);\n        return dist(rng);\n    };\n\n    int queries_left = Q;\n\n    vector<ld> score(N, 0.0L); // win = 1, tie = 0.5\n    vector<int> deg(N, 0);\n\n    auto ask = [&](int a, int b) -> int {\n        // singleton vs singleton\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n' << flush;\n        char c;\n        cin >> c;\n        --queries_left;\n        int res = (c == '>' ? 1 : (c == '<' ? -1 : 0));\n        ++deg[a];\n        ++deg[b];\n        if (res > 0) score[a] += 1.0L;\n        else if (res < 0) score[b] += 1.0L;\n        else {\n            score[a] += 0.5L;\n            score[b] += 0.5L;\n        }\n        return res;\n    };\n\n    // --- Query phase 1: best-first bucket splitting ---\n    vector<Bucket> buckets;\n    {\n        Bucket root;\n        root.items.resize(N);\n        iota(root.items.begin(), root.items.end(), 0);\n        root.l = 0;\n        root.r = N - 1;\n        root.same = false;\n        root.value = pref[N];\n        buckets.push_back(move(root));\n    }\n\n    while (true) {\n        int best = -1;\n        ld bestMetric = -1.0L;\n\n        for (int i = 0; i < (int)buckets.size(); ++i) {\n            const auto &bk = buckets[i];\n            int m = (int)bk.items.size();\n            if (bk.same || m <= 1) continue;\n            int cost = m - 1;\n            if (cost > queries_left) continue;\n\n            ld metric = bk.value / (ld)cost; // estimated weight per query\n            if (metric > bestMetric) {\n                bestMetric = metric;\n                best = i;\n            }\n        }\n\n        if (best == -1) break;\n\n        Bucket cur = move(buckets[best]);\n        buckets[best] = move(buckets.back());\n        buckets.pop_back();\n\n        int m = (int)cur.items.size();\n        int pivot = cur.items[randInt(0, m - 1)];\n\n        vector<int> greater, less, equal;\n        greater.reserve(m);\n        less.reserve(m);\n        equal.reserve(m);\n\n        for (int x : cur.items) {\n            if (x == pivot) continue;\n            int res = ask(pivot, x);\n            // res > 0 : pivot heavier => x is lighter\n            // res < 0 : x heavier\n            if (res > 0) less.push_back(x);\n            else if (res < 0) greater.push_back(x);\n            else equal.push_back(x);\n        }\n\n        int g = (int)greater.size();\n        int e = (int)equal.size();\n\n        if (g > 0) {\n            Bucket bk;\n            bk.items = move(greater);\n            bk.l = cur.l;\n            bk.r = cur.l + g - 1;\n            bk.same = false;\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n\n        Bucket mid;\n        mid.items.reserve(1 + e);\n        mid.items.push_back(pivot);\n        for (int x : equal) mid.items.push_back(x);\n        mid.l = cur.l + g;\n        mid.r = cur.l + g + e;\n        mid.same = (e > 0);\n        mid.value = intervalValue(mid.l, mid.r);\n        buckets.push_back(move(mid));\n\n        if (!less.empty()) {\n            Bucket bk;\n            bk.items = move(less);\n            bk.l = cur.l + g + e + 1;\n            bk.r = cur.r;\n            bk.same = false;\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n    }\n\n    // --- Query phase 2: use remaining queries to refine uncertain buckets ---\n    auto pick_bucket = [&]() -> int {\n        int best = -1;\n        ld bestValue = -1.0L;\n        for (int i = 0; i < (int)buckets.size(); ++i) {\n            const auto &bk = buckets[i];\n            if (bk.same) continue;\n            if ((int)bk.items.size() <= 1) continue;\n            if (bk.value > bestValue) {\n                bestValue = bk.value;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    while (queries_left > 0) {\n        int bi = pick_bucket();\n        int a, b;\n\n        if (bi != -1) {\n            const auto &v = buckets[bi].items;\n            int m = (int)v.size();\n\n            // Prefer low-degree items inside the most important unresolved bucket.\n            int pa = 0;\n            for (int i = 1; i < m; ++i) {\n                if (deg[v[i]] < deg[v[pa]]) pa = i;\n            }\n            a = v[pa];\n\n            if (m == 2) {\n                b = (v[0] == a ? v[1] : v[0]);\n            } else {\n                do {\n                    b = v[randInt(0, m - 1)];\n                } while (b == a);\n            }\n        } else {\n            // No unresolved bucket; just diversify globally.\n            int pa = 0;\n            for (int i = 1; i < N; ++i) {\n                if (deg[i] < deg[pa]) pa = i;\n            }\n            a = pa;\n            do {\n                b = randInt(0, N - 1);\n            } while (b == a);\n        }\n\n        ask(a, b);\n    }\n\n    // --- Estimate item weights ---\n    vector<ld> baseWeight(N, 0.0L);\n    vector<int> bucketSizeOfItem(N, 1);\n\n    for (const auto &bk : buckets) {\n        int sz = (int)bk.items.size();\n        ld base = intervalValue(bk.l, bk.r) / (ld)sz;\n        for (int x : bk.items) {\n            baseWeight[x] = base;\n            bucketSizeOfItem[x] = sz;\n        }\n    }\n\n    vector<ld> est(N, 0.0L);\n    for (int i = 0; i < N; ++i) {\n        ld p = (score[i] + 0.5L) / (deg[i] + 1.0L);\n        p = max((ld)1e-18L, min((ld)1.0L - 1e-18L, p));\n        ld z = -log1pl(-p * capProb);\n        ld winWeight = MU * z;\n        winWeight = max((ld)1.0L, min(CAP, winWeight));\n\n        int sz = bucketSizeOfItem[i];\n        ld gamma = 0.0L;\n        if (sz > 1) {\n            gamma = ((ld)deg[i] / ((ld)deg[i] + 12.0L)) * (1.0L - 1.0L / (ld)sz);\n        }\n\n        est[i] = baseWeight[i] * (1.0L - gamma) + winWeight * gamma;\n    }\n\n    // --- Sort by estimated weight ---\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    stable_sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (fabsl(est[a] - est[b]) > 1e-18L) return est[a] > est[b];\n        return a < b;\n    });\n\n    // --- Greedy LPT assignment ---\n    vector<vector<int>> bins(D);\n    vector<ld> load(D, 0.0L);\n    vector<int> where(N, -1), pos(N, -1);\n\n    for (int id : ord) {\n        int best = 0;\n        for (int d = 1; d < D; ++d) {\n            if (load[d] < load[best]) best = d;\n        }\n        where[id] = best;\n        pos[id] = (int)bins[best].size();\n        bins[best].push_back(id);\n        load[best] += est[id];\n    }\n\n    auto remove_from_bin = [&](int item, int b) {\n        int idx = pos[item];\n        int last = bins[b].back();\n        bins[b][idx] = last;\n        pos[last] = idx;\n        bins[b].pop_back();\n    };\n\n    auto add_to_bin = [&](int item, int b) {\n        where[item] = b;\n        pos[item] = (int)bins[b].size();\n        bins[b].push_back(item);\n    };\n\n    auto apply_move = [&](int item, int from, int to) {\n        remove_from_bin(item, from);\n        load[from] -= est[item];\n        add_to_bin(item, to);\n        load[to] += est[item];\n    };\n\n    auto apply_swap = [&](int x, int bx, int y, int by) {\n        int ix = pos[x];\n        int iy = pos[y];\n        bins[bx][ix] = y;\n        bins[by][iy] = x;\n        pos[y] = ix;\n        pos[x] = iy;\n        where[x] = by;\n        where[y] = bx;\n        load[bx] += est[y] - est[x];\n        load[by] += est[x] - est[y];\n    };\n\n    // --- Local search on estimated loads ---\n    for (int iter = 0; iter < 200; ++iter) {\n        ld bestDelta = 0.0L;\n        int bestType = 0; // 1: move, 2: swap\n        int ba = -1, bb = -1, bx = -1, by = -1;\n\n        for (int a = 0; a < D; ++a) {\n            for (int b = 0; b < D; ++b) {\n                if (load[a] <= load[b]) continue;\n                ld d = load[a] - load[b];\n\n                if ((int)bins[a].size() > 1) {\n                    for (int x : bins[a]) {\n                        ld w = est[x];\n                        ld delta = 2.0L * w * (w - d);\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestType = 1;\n                            ba = a; bb = b; bx = x;\n                        }\n                    }\n                }\n\n                for (int x : bins[a]) {\n                    for (int y : bins[b]) {\n                        ld diff = est[x] - est[y];\n                        ld delta = 2.0L * diff * (diff - d);\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestType = 2;\n                            ba = a; bb = b; bx = x; by = y;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (bestDelta >= -1e-12L) break;\n\n        if (bestType == 1) {\n            apply_move(bx, ba, bb);\n        } else if (bestType == 2) {\n            apply_swap(bx, ba, by, bb);\n        }\n    }\n\n    vector<int> ans(N, 0);\n    for (int d = 0; d < D; ++d) {\n        for (int x : bins[d]) ans[x] = d;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << ans[i];\n    }\n    cout << '\\n' << flush;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int M = 10;\nstatic constexpr int MAXV = 205;\n\nint n, m;\n\nstruct Board {\n    int st[M][MAXV];\n    int len[M];\n    int stack_id[MAXV];\n    int idx[MAXV];\n    char removed[MAXV];\n    int cur; // smallest not yet removed\n};\n\ninline void updatePos(Board &b, int s) {\n    for (int i = 0; i < b.len[s]; ++i) {\n        int v = b.st[s][i];\n        b.stack_id[v] = s;\n        b.idx[v] = i;\n    }\n}\n\ninline void removeTop(Board &b, int s, vector<pair<int,int>> *ops) {\n    int v = b.st[s][b.len[s] - 1];\n    if (ops) ops->push_back({v, 0});\n    b.removed[v] = 1;\n    b.len[s]--;\n    updatePos(b, s);\n    while (b.cur <= n && b.removed[b.cur]) ++b.cur;\n}\n\ninline void flush(Board &b, vector<pair<int,int>> *ops) {\n    while (true) {\n        while (b.cur <= n && b.removed[b.cur]) ++b.cur;\n        if (b.cur > n) break;\n        int s = b.stack_id[b.cur];\n        if (b.idx[b.cur] != b.len[s] - 1) break;\n        removeTop(b, s, ops);\n    }\n}\n\ninline void applyMove(Board &b, int dest, vector<pair<int,int>> *ops) {\n    int x = b.cur;\n    int s = b.stack_id[x];\n    int idx = b.idx[x];\n    int cut = idx + 1;               // move boxes above x\n    int k = b.len[s] - cut;          // number of moved boxes\n\n    int moved[MAXV];\n    for (int i = 0; i < k; ++i) moved[i] = b.st[s][cut + i];\n\n    if (ops) ops->push_back({moved[0], dest + 1});\n\n    // source becomes prefix [0..cut-1], destination appends moved segment\n    b.len[s] = cut;\n    for (int i = 0; i < k; ++i) b.st[dest][b.len[dest]++] = moved[i];\n\n    updatePos(b, dest);\n\n    // x is now the top of source stack, so it can be removed for free\n    removeTop(b, s, ops);\n\n    // more free removals may become possible\n    flush(b, ops);\n}\n\ninline ll scoreBoard(const Board &b) {\n    ll P = 0;        // bad pairs inside stacks\n    ll T = 0;        // weighted depth of small labels\n    ll topSum = 0;\n    int empties = 0;\n    int maxH = 0;\n\n    for (int s = 0; s < m; ++s) {\n        int h = b.len[s];\n        maxH = max(maxH, h);\n        if (h == 0) {\n            ++empties;\n            continue;\n        }\n        topSum += b.st[s][h - 1];\n        for (int i = 0; i < h; ++i) {\n            int a = b.st[s][i];\n            for (int j = i + 1; j < h; ++j) {\n                if (a < b.st[s][j]) ++P;\n            }\n            int depthFromTop = h - 1 - i;\n            T += 1LL * depthFromTop * (n - a + 1);\n        }\n    }\n\n    // Smaller is better.\n    // P dominates, but we also reward progress and easier future states.\n    return 20000LL * P\n         + T\n         + 10LL * topSum\n         - 5000LL * b.cur\n         - 1000LL * empties\n         + maxH;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    Board b{};\n    b.cur = 1;\n\n    for (int s = 0; s < m; ++s) {\n        int h = n / m;\n        b.len[s] = h;\n        for (int i = 0; i < h; ++i) {\n            cin >> b.st[s][i];\n            b.removed[b.st[s][i]] = 0;\n        }\n    }\n\n    for (int s = 0; s < m; ++s) updatePos(b, s);\n\n    vector<pair<int,int>> ops;\n    ops.reserve(5000);\n\n    // remove everything that is already removable\n    flush(b, &ops);\n\n    while (b.cur <= n) {\n        int s = b.stack_id[b.cur];\n\n        ll bestScore = (1LL << 62);\n        int bestDest = -1;\n\n        for (int d = 0; d < m; ++d) {\n            if (d == s) continue;\n            Board tmp = b;\n            applyMove(tmp, d, nullptr);\n            ll sc = scoreBoard(tmp);\n            if (sc < bestScore || (sc == bestScore && (bestDest == -1 || d < bestDest))) {\n                bestScore = sc;\n                bestDest = d;\n            }\n        }\n\n        applyMove(b, bestDest, &ops);\n\n        if ((int)ops.size() > 5000) {\n            // Should not happen with this strategy, but keep the output legal.\n            break;\n        }\n    }\n\n    for (auto [v, i] : ops) {\n        cout << v << ' ' << i << '\\n';\n    }\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to, dir;\n};\n\nstatic const int DR[4] = {-1, 1, 0, 0};\nstatic const int DC[4] = {0, 0, -1, 1};\nstatic const int REV[4] = {1, 0, 3, 2};\nstatic const char CH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Cand {\n    int id;\n    long double proxy;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> v[i];\n\n    int TOT = N * N;\n    auto id = [&](int r, int c) { return r * N + c; };\n    auto rc = [&](int x) { return pair<int,int>{x / N, x % N}; };\n\n    vector<int> d(TOT);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> d[id(i, j)];\n        }\n    }\n\n    vector<array<int,4>> nxt(TOT);\n    for (int i = 0; i < TOT; ++i) nxt[i].fill(-1);\n\n    vector<vector<Edge>> adj(TOT);\n    auto add_edge = [&](int u, int vtx, int dir_uv, int dir_vu) {\n        adj[u].push_back({vtx, dir_uv});\n        adj[vtx].push_back({u, dir_vu});\n        nxt[u][dir_uv] = vtx;\n        nxt[vtx][dir_vu] = u;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                int vtx = id(i + 1, j);\n                add_edge(u, vtx, 1, 0); // D / U\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                int vtx = id(i, j + 1);\n                add_edge(u, vtx, 3, 2); // R / L\n            }\n        }\n    }\n\n    vector<long long> cellScore(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        long long s = d[u];\n        for (auto e : adj[u]) s += d[e.to];\n        cellScore[u] = s;\n    }\n\n    vector<vector<Edge>> sortedNbr = adj;\n    for (int u = 0; u < TOT; ++u) {\n        sort(sortedNbr[u].begin(), sortedNbr[u].end(), [&](const Edge& a, const Edge& b) {\n            if (cellScore[a.to] != cellScore[b.to]) return cellScore[a.to] > cellScore[b.to];\n            if (d[a.to] != d[b.to]) return d[a.to] > d[b.to];\n            return a.to < b.to;\n        });\n    }\n\n    // BFS from origin for candidate selection and path reconstruction\n    vector<int> dist0(TOT, -1), par0(TOT, -1), pdir0(TOT, -1), order0;\n    queue<int> q;\n    dist0[0] = 0;\n    par0[0] = 0;\n    q.push(0);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        order0.push_back(u);\n        for (auto e : sortedNbr[u]) {\n            int vtx = e.to;\n            if (dist0[vtx] == -1) {\n                dist0[vtx] = dist0[u] + 1;\n                par0[vtx] = u;\n                pdir0[vtx] = e.dir;\n                q.push(vtx);\n            }\n        }\n    }\n\n    vector<vector<int>> pathFrom0(TOT);\n    for (int t = 0; t < TOT; ++t) {\n        vector<int> p;\n        int x = t;\n        while (x != 0) {\n            p.push_back(pdir0[x]);\n            x = par0[x];\n        }\n        reverse(p.begin(), p.end());\n        pathFrom0[t] = move(p);\n    }\n\n    vector<Cand> ranked;\n    ranked.reserve(TOT);\n    for (int u = 0; u < TOT; ++u) {\n        long double proxy = (long double)cellScore[u] / (dist0[u] + 1);\n        ranked.push_back({u, proxy});\n    }\n    sort(ranked.begin(), ranked.end(), [&](const Cand& a, const Cand& b) {\n        if (fabsl(a.proxy - b.proxy) > 1e-18L) return a.proxy > b.proxy;\n        if (cellScore[a.id] != cellScore[b.id]) return cellScore[a.id] > cellScore[b.id];\n        if (d[a.id] != d[b.id]) return d[a.id] > d[b.id];\n        return a.id < b.id;\n    });\n\n    auto add_unique = [&](vector<int>& vec, int x) {\n        for (int y : vec) if (y == x) return;\n        vec.push_back(x);\n    };\n\n    // Root candidates: origin + top few by proxy\n    vector<int> rootIds;\n    rootIds.push_back(0);\n    for (int i = 0; i < min(4, (int)ranked.size()); ++i) {\n        if (ranked[i].id != 0) add_unique(rootIds, ranked[i].id);\n    }\n\n    // Loop candidates: top few by proxy (excluding origin)\n    vector<int> loopIds;\n    for (int i = 0; i < (int)ranked.size() && (int)loopIds.size() < 5; ++i) {\n        if (ranked[i].id != 0) add_unique(loopIds, ranked[i].id);\n    }\n\n    // Prepare root-specific coverage vectors\n    struct RootData {\n        int root;\n        vector<int> cov;\n    };\n    vector<RootData> roots;\n\n    for (int root : rootIds) {\n        vector<int> par(TOT, -1), pdir(TOT, -1), order;\n        vector<vector<pair<int,int>>> children(TOT);\n        queue<int> qq;\n        par[root] = root;\n        qq.push(root);\n\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            order.push_back(u);\n            for (auto e : sortedNbr[u]) {\n                int vtx = e.to;\n                if (par[vtx] == -1) {\n                    par[vtx] = u;\n                    pdir[vtx] = e.dir;\n                    children[u].push_back({vtx, e.dir});\n                    qq.push(vtx);\n                }\n            }\n        }\n\n        vector<long long> sub(TOT);\n        for (int u = 0; u < TOT; ++u) sub[u] = d[u];\n        for (int i = (int)order.size() - 1; i >= 0; --i) {\n            int u = order[i];\n            if (u != root) sub[par[u]] += sub[u];\n        }\n\n        for (int u = 0; u < TOT; ++u) {\n            sort(children[u].begin(), children[u].end(), [&](const auto& A, const auto& B) {\n                if (sub[A.first] != sub[B.first]) return sub[A.first] < sub[B.first];\n                if (d[A.first] != d[B.first]) return d[A.first] < d[B.first];\n                return A.first < B.first;\n            });\n        }\n\n        vector<int> cov;\n        cov.reserve((int)pathFrom0[root].size() * 2 + 2 * (TOT - 1));\n        for (int dir : pathFrom0[root]) cov.push_back(dir);\n\n        auto dfs_emit = [&](auto&& self, int u) -> void {\n            for (auto [vtx, dir] : children[u]) {\n                cov.push_back(dir);\n                self(self, vtx);\n                cov.push_back(REV[dir]);\n            }\n        };\n        dfs_emit(dfs_emit, root);\n\n        for (auto it = pathFrom0[root].rbegin(); it != pathFrom0[root].rend(); ++it) {\n            cov.push_back(REV[*it]);\n        }\n\n        roots.push_back({root, move(cov)});\n    }\n\n    struct LoopData {\n        int id;\n        vector<int> rt; // roundtrip from origin to id and back\n    };\n    vector<LoopData> loops;\n    for (int lid : loopIds) {\n        vector<int> rt = pathFrom0[lid];\n        for (auto it = pathFrom0[lid].rbegin(); it != pathFrom0[lid].rend(); ++it) rt.push_back(REV[*it]);\n        if (!rt.empty()) loops.push_back({lid, move(rt)});\n    }\n\n    const int LIMIT = 100000;\n\n    auto better = [&]( __int128 s1, int l1, __int128 s2, int l2 ) -> bool {\n        return s1 * (__int128)l2 < s2 * (__int128)l1;\n    };\n\n    bool hasBest = false;\n    __int128 bestSum = 0;\n    int bestLen = 1;\n    string bestRoute;\n\n    auto evaluate = [&](const vector<int>& rt, const vector<int>& cov, int M) {\n        long long len = (long long)cov.size() + (long long)M * (long long)rt.size();\n        if (len > LIMIT) return;\n\n        vector<int> first(TOT, -1), last(TOT, -1);\n        vector<long long> part(TOT, 0);\n        string route;\n        route.reserve((size_t)len);\n\n        int cur = 0, t = 0;\n        auto apply = [&](int dir) {\n            route.push_back(CH[dir]);\n            cur = nxt[cur][dir];\n            ++t;\n            if (first[cur] == -1) {\n                first[cur] = last[cur] = t;\n            } else {\n                int gap = t - last[cur];\n                part[cur] += 1LL * gap * (gap - 1) / 2;\n                last[cur] = t;\n            }\n        };\n\n        for (int rep = 0; rep < M; ++rep) {\n            for (int dir : rt) apply(dir);\n        }\n        for (int dir : cov) apply(dir);\n\n        __int128 total = 0;\n        for (int c = 0; c < TOT; ++c) {\n            if (first[c] == -1) return; // should not happen\n            int gap = first[c] + t - last[c];\n            part[c] += 1LL * gap * (gap - 1) / 2;\n            total += (__int128)part[c] * (__int128)d[c];\n        }\n\n        if (!hasBest || better(total, t, bestSum, bestLen)) {\n            hasBest = true;\n            bestSum = total;\n            bestLen = t;\n            bestRoute = move(route);\n        }\n    };\n\n    auto start = chrono::steady_clock::now();\n\n    for (const auto& rootData : roots) {\n        const vector<int>& cov = rootData.cov;\n        int covLen = (int)cov.size();\n\n        for (const auto& loopData : loops) {\n            const vector<int>& rt = loopData.rt;\n            if (rt.empty()) continue;\n            int loopLen = (int)rt.size();\n            int maxM = (LIMIT - covLen) / loopLen;\n            if (maxM < 0) continue;\n\n            vector<int> Ms = {0, 1, maxM / 4, maxM / 2, maxM};\n            sort(Ms.begin(), Ms.end());\n            Ms.erase(unique(Ms.begin(), Ms.end()), Ms.end());\n\n            for (int M : Ms) {\n                if (M < 0) continue;\n                evaluate(rt, cov, M);\n                if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count() > 1850) {\n                    break;\n                }\n            }\n            if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count() > 1850) {\n                break;\n            }\n        }\n        if (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count() > 1850) {\n            break;\n        }\n    }\n\n    // Fallback: baseline DFS from origin if somehow no candidate chosen\n    if (!hasBest) {\n        // This should practically never happen.\n        bestRoute = \"\";\n        auto& cov = roots[0].cov;\n        bestRoute.reserve(cov.size());\n        for (int dir : cov) bestRoute.push_back(CH[dir]);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int NMAX = 15;\nstatic constexpr int CELLS = 225;\nstatic constexpr int INF = 1e9;\n\nint N, M, si, sj;\nvector<string> words;\nvector<string> sufStr[205];\nint sufLB[205][5];\n\nint distCell[CELLS][CELLS];\nint cellLetter[CELLS];\nint cellToLetterDist[CELLS][26];\nint letterDist[26][26];\nvector<int> cellsByLetter[26];\n\nstruct FastRng {\n    uint64_t x;\n    explicit FastRng(uint64_t seed = 88172645463393265ULL) : x(seed) {}\n    uint64_t next() {\n        uint64_t z = (x += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n};\n\nint overlapLen(const string& tail, const string& w) {\n    int mx = min<int>(4, tail.size());\n    for (int k = mx; k >= 0; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (tail[tail.size() - k + i] != w[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\narray<int, CELLS> applyAdd(const array<int, CELLS>& dp, const string& add) {\n    array<int, CELLS> cur = dp, nxt;\n    for (char ch : add) {\n        int c = ch - 'A';\n        nxt.fill(INF);\n        const auto& pos = cellsByLetter[c];\n        for (int q : pos) {\n            int best = INF;\n            for (int p = 0; p < CELLS; ++p) {\n                int v = cur[p] + distCell[p][q] + 1;\n                if (v < best) best = v;\n            }\n            nxt[q] = best;\n        }\n        cur = nxt;\n    }\n    return cur;\n}\n\nint bestCost(const array<int, CELLS>& dp) {\n    return *min_element(dp.begin(), dp.end());\n}\n\nvector<int> topCellsByDp(const array<int, CELLS>& dp, int K) {\n    vector<int> ord(CELLS);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (dp[a] != dp[b]) return dp[a] < dp[b];\n        return a < b;\n    });\n    if ((int)ord.size() > K) ord.resize(K);\n    return ord;\n}\n\nint approxCostForAdd(const array<int, CELLS>& dp, const vector<int>& topCells, int firstLetter, int lb) {\n    int best = INF;\n    for (int p : topCells) {\n        int v = dp[p] + cellToLetterDist[p][firstLetter] + lb;\n        if (v < best) best = v;\n    }\n    return best;\n}\n\nint futurePotential(const string& tail, const vector<char>& used, int skip) {\n    int pot = 0;\n    for (int i = 0; i < M; ++i) {\n        if (i == skip || used[i]) continue;\n        pot += overlapLen(tail, words[i]);\n    }\n    return pot;\n}\n\nstring tailAfterAdd(const string& tail, const string& add) {\n    string t = tail;\n    t += add;\n    if ((int)t.size() > 4) t.erase(0, (int)t.size() - 4);\n    return t;\n}\n\nstruct RunParam {\n    int topP;\n    int primaryLimit;\n    int secondaryLimit;\n    int tertiaryLimit;\n    bool useFutureTieBreak;\n    uint64_t seed;\n};\n\nstruct RunResult {\n    string s;\n    int cost;\n};\n\nRunResult buildRun(int startIdx, const RunParam& param) {\n    FastRng rng(param.seed);\n\n    vector<char> used(M, 0);\n    array<int, CELLS> dp;\n    dp.fill(INF);\n    dp[si * N + sj] = 0;\n\n    string built;\n    string tail;\n    built.reserve(1100);\n    tail.reserve(4);\n\n    // first word\n    used[startIdx] = 1;\n    const string& firstAdd = sufStr[startIdx][0];\n    dp = applyAdd(dp, firstAdd);\n    built += firstAdd;\n    tail = tailAfterAdd(\"\", firstAdd);\n\n    for (int step = 1; step < M; ++step) {\n        vector<int> topCells = topCellsByDp(dp, param.topP);\n\n        int bestOv = -1;\n        vector<pair<int,int>> group[5]; // (approx, idx)\n\n        for (int i = 0; i < M; ++i) {\n            if (used[i]) continue;\n            int ov = overlapLen(tail, words[i]);\n            bestOv = max(bestOv, ov);\n        }\n\n        auto pushGroup = [&](int idx, int ov) {\n            const string& add = sufStr[idx][ov];\n            int first = add[0] - 'A';\n            int approx = approxCostForAdd(dp, topCells, first, sufLB[idx][ov]);\n            approx += (int)(rng.next() % 3); // tiny noise for diversity\n            group[ov].push_back({approx, idx});\n        };\n\n        if (bestOv == 0) {\n            for (int i = 0; i < M; ++i) {\n                if (used[i]) continue;\n                pushGroup(i, 0);\n            }\n            sort(group[0].begin(), group[0].end());\n        } else {\n            for (int i = 0; i < M; ++i) {\n                if (used[i]) continue;\n                int ov = overlapLen(tail, words[i]);\n                if (ov == bestOv) pushGroup(i, ov);\n                else if (ov == bestOv - 1) pushGroup(i, ov);\n                else if (bestOv >= 2 && ov == bestOv - 2) pushGroup(i, ov);\n            }\n            sort(group[bestOv].begin(), group[bestOv].end());\n            sort(group[max(0, bestOv - 1)].begin(), group[max(0, bestOv - 1)].end());\n            if (bestOv >= 2) sort(group[bestOv - 2].begin(), group[bestOv - 2].end());\n        }\n\n        vector<int> candidates;\n        if (bestOv == 0) {\n            int lim = min(param.primaryLimit, (int)group[0].size());\n            for (int i = 0; i < lim; ++i) candidates.push_back(group[0][i].second);\n        } else {\n            int lim1 = min(param.primaryLimit, (int)group[bestOv].size());\n            for (int i = 0; i < lim1; ++i) candidates.push_back(group[bestOv][i].second);\n\n            int secOv = bestOv - 1;\n            if (secOv >= 0) {\n                int lim2 = min(param.secondaryLimit, (int)group[secOv].size());\n                for (int i = 0; i < lim2; ++i) candidates.push_back(group[secOv][i].second);\n            }\n            int terOv = bestOv - 2;\n            if (terOv >= 0 && param.tertiaryLimit > 0) {\n                int lim3 = min(param.tertiaryLimit, (int)group[terOv].size());\n                for (int i = 0; i < lim3; ++i) candidates.push_back(group[terOv][i].second);\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        struct BestCand {\n            int cost = INF;\n            int future = -1;\n            int approx = INF;\n            int idx = -1;\n            array<int, CELLS> ndp{};\n            string add;\n            string newTail;\n        } best;\n\n        for (int idx : candidates) {\n            int ov = overlapLen(tail, words[idx]);\n            const string& add = sufStr[idx][ov];\n            array<int, CELLS> ndp = applyAdd(dp, add);\n            int cst = bestCost(ndp);\n\n            string nt = tailAfterAdd(tail, add);\n            int fut = param.useFutureTieBreak ? futurePotential(nt, used, idx) : 0;\n\n            int approx = 0;\n            {\n                int first = add[0] - 'A';\n                approx = approxCostForAdd(dp, topCells, first, sufLB[idx][ov]);\n            }\n\n            bool better = false;\n            if (cst < best.cost) better = true;\n            else if (cst == best.cost && fut > best.future) better = true;\n            else if (cst == best.cost && fut == best.future && approx < best.approx) better = true;\n            else if (cst == best.cost && fut == best.future && approx == best.approx && idx < best.idx) better = true;\n\n            if (better) {\n                best.cost = cst;\n                best.future = fut;\n                best.approx = approx;\n                best.idx = idx;\n                best.ndp = ndp;\n                best.add = add;\n                best.newTail = nt;\n            }\n        }\n\n        if (best.idx == -1) {\n            // Fallback, should not happen.\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                int ov = overlapLen(tail, words[i]);\n                const string& add = sufStr[i][ov];\n                array<int, CELLS> ndp = applyAdd(dp, add);\n                int cst = bestCost(ndp);\n                if (cst < best.cost) {\n                    best.cost = cst;\n                    best.idx = i;\n                    best.ndp = ndp;\n                    best.add = add;\n                    best.newTail = tailAfterAdd(tail, add);\n                }\n            }\n        }\n\n        used[best.idx] = 1;\n        dp = best.ndp;\n        built += best.add;\n        tail = best.newTail;\n    }\n\n    return {built, bestCost(dp)};\n}\n\nstruct SolveResult {\n    long long cost;\n    vector<int> path;\n};\n\nSolveResult solveTyping(const string& s) {\n    int L = (int)s.size();\n    vector<array<int16_t, CELLS>> par(L);\n    array<int, CELLS> dp, ndp;\n    dp.fill(INF);\n    int start = si * N + sj;\n    dp[start] = 0;\n\n    for (int i = 0; i < L; ++i) {\n        int c = s[i] - 'A';\n        ndp.fill(INF);\n        par[i].fill(-1);\n\n        for (int q : cellsByLetter[c]) {\n            int best = INF;\n            int bestp = -1;\n            for (int p = 0; p < CELLS; ++p) {\n                if (dp[p] >= INF) continue;\n                int v = dp[p] + distCell[p][q] + 1;\n                if (v < best) {\n                    best = v;\n                    bestp = p;\n                }\n            }\n            ndp[q] = best;\n            par[i][q] = (int16_t)bestp;\n        }\n        dp = ndp;\n    }\n\n    int end = -1;\n    int best = INF;\n    for (int q : cellsByLetter[s.back() - 'A']) {\n        if (dp[q] < best) {\n            best = dp[q];\n            end = q;\n        }\n    }\n\n    vector<int> path(L);\n    int cur = end;\n    for (int i = L - 1; i >= 0; --i) {\n        path[i] = cur;\n        cur = par[i][cur];\n    }\n\n    return {best, path};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    cin >> si >> sj;\n    words.resize(M);\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    for (int i = 0; i < M; ++i) cin >> words[i];\n\n    // Precompute cell letters and positions.\n    for (int i = 0; i < 26; ++i) cellsByLetter[i].clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            int c = grid[i][j] - 'A';\n            cellLetter[id] = c;\n            cellsByLetter[c].push_back(id);\n        }\n    }\n\n    // Distances between cells.\n    for (int a = 0; a < CELLS; ++a) {\n        int x1 = a / N, y1 = a % N;\n        for (int b = 0; b < CELLS; ++b) {\n            int x2 = b / N, y2 = b % N;\n            distCell[a][b] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    // cell -> letter distance\n    for (int p = 0; p < CELLS; ++p) {\n        for (int c = 0; c < 26; ++c) {\n            int best = INF;\n            for (int q : cellsByLetter[c]) best = min(best, distCell[p][q]);\n            cellToLetterDist[p][c] = best;\n        }\n    }\n\n    // letter -> letter distance\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) {\n            int best = INF;\n            for (int p : cellsByLetter[a]) {\n                for (int q : cellsByLetter[b]) {\n                    best = min(best, distCell[p][q]);\n                }\n            }\n            letterDist[a][b] = best;\n        }\n    }\n\n    // Precompute suffixes and lower bounds.\n    for (int i = 0; i < M; ++i) {\n        for (int k = 0; k < 5; ++k) {\n            sufStr[i].push_back(words[i].substr(k));\n            const string& t = sufStr[i][k];\n            int lb = (int)t.size();\n            for (int j = 1; j < (int)t.size(); ++j) {\n                lb += letterDist[t[j - 1] - 'A'][t[j] - 'A'];\n            }\n            sufLB[i][k] = lb;\n        }\n    }\n\n    // Rank start words exactly.\n    array<int, CELLS> startDp;\n    startDp.fill(INF);\n    startDp[si * N + sj] = 0;\n\n    vector<pair<int,int>> startRank; // (cost, idx)\n    startRank.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        auto ndp = applyAdd(startDp, words[i]);\n        int cst = bestCost(ndp);\n        int pot = futurePotential(words[i].substr(max(0, (int)words[i].size() - 4)), vector<char>(M, 0), i);\n        // use pot as tie-break through pair ordering\n        startRank.push_back({cst * 1000 - pot, i});\n    }\n    sort(startRank.begin(), startRank.end());\n\n    vector<RunParam> params = {\n        {8, 18, 10, 5, true, 1},\n        {6, 15, 8, 0, false, 2},\n        {10, 20, 10, 5, true, 3},\n        {8, 25, 12, 5, true, 4},\n    };\n\n    RunResult bestRun;\n    bestRun.cost = INT_MAX;\n\n    int runs = min((int)params.size(), M);\n    for (int r = 0; r < runs; ++r) {\n        int startIdx = startRank[r].second;\n        auto res = buildRun(startIdx, params[r]);\n        if (res.cost < bestRun.cost || (res.cost == bestRun.cost && res.s.size() < bestRun.s.size())) {\n            bestRun = move(res);\n        }\n    }\n\n    auto finalRes = solveTyping(bestRun.s);\n    for (int idx : finalRes.path) {\n        cout << idx / N << ' ' << idx % N << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Block {\n    vector<pair<int,int>> cells;\n};\n\nint N, M;\ndouble eps;\n\nvector<vector<int>> revealed;   // -1 = not drilled, otherwise exact value\nvector<vector<bool>> is_pos;\n\nstatic inline double transformed_estimate(double avg_raw, int k, double eps) {\n    return (avg_raw - k * eps) / (1.0 - 2.0 * eps);\n}\n\nvoid drill_cell(int i, int j) {\n    if (revealed[i][j] != -1) return;\n    cout << \"q 1 \" << i << ' ' << j << '\\n' << flush;\n    int v;\n    cin >> v;\n    revealed[i][j] = v;\n    if (v > 0) is_pos[i][j] = true;\n}\n\ndouble query_block_estimate(const vector<pair<int,int>>& cells, int reps) {\n    int k = (int)cells.size();\n    long double sum_raw = 0;\n    for (int t = 0; t < reps; ++t) {\n        cout << \"q \" << k;\n        for (auto [i, j] : cells) {\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << '\\n' << flush;\n\n        int resp;\n        cin >> resp;\n        sum_raw += resp;\n    }\n    double avg_raw = (double)(sum_raw / reps);\n    return transformed_estimate(avg_raw, k, eps);\n}\n\nvector<pair<int,int>> build_segments(int n, int first_len) {\n    vector<pair<int,int>> segs;\n    int s = 0;\n    if (s < n) {\n        int e = min(n, s + first_len);\n        segs.push_back({s, e});\n        s = e;\n    }\n    while (s < n) {\n        int e = min(n, s + 4);\n        segs.push_back({s, e});\n        s = e;\n    }\n    return segs;\n}\n\nvector<Block> build_blocks(int n, int first_len) {\n    auto rows = build_segments(n, first_len);\n    auto cols = build_segments(n, first_len);\n    vector<Block> blocks;\n    for (auto [r1, r2] : rows) {\n        for (auto [c1, c2] : cols) {\n            Block b;\n            for (int i = r1; i < r2; ++i) {\n                for (int j = c1; j < c2; ++j) {\n                    b.cells.push_back({i, j});\n                }\n            }\n            blocks.push_back(move(b));\n        }\n    }\n    return blocks;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> eps;\n\n    // Read prior info about shapes (unused in this heuristic).\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        for (int t = 0; t < d; ++t) {\n            int i, j;\n            cin >> i >> j;\n        }\n    }\n\n    revealed.assign(N, vector<int>(N, -1));\n    is_pos.assign(N, vector<bool>(N, false));\n\n    vector<Block> blocks;\n    {\n        auto b0 = build_blocks(N, 4); // regular partition\n        auto b1 = build_blocks(N, 2); // shifted partition\n        blocks.insert(blocks.end(), b0.begin(), b0.end());\n        blocks.insert(blocks.end(), b1.begin(), b1.end());\n    }\n\n    // Process larger blocks first so overlap helps reduce later work.\n    sort(blocks.begin(), blocks.end(),\n         [](const Block& a, const Block& b) {\n             return a.cells.size() > b.cells.size();\n         });\n\n    const int DIRECT_DRILL_LIMIT = 8;   // small blocks are drilled directly\n    const int QUERY_REPS = 4;           // repeated noisy estimates\n    const double POS_THR = 0.20;        // estimated sum threshold to drill\n\n    for (const auto& block : blocks) {\n        vector<pair<int,int>> pending;\n        pending.reserve(block.cells.size());\n        for (auto [i, j] : block.cells) {\n            if (revealed[i][j] == -1) pending.push_back({i, j});\n        }\n        if (pending.empty()) continue;\n\n        if ((int)pending.size() <= DIRECT_DRILL_LIMIT) {\n            for (auto [i, j] : pending) {\n                drill_cell(i, j);\n            }\n            continue;\n        }\n\n        double est = query_block_estimate(pending, QUERY_REPS);\n        if (est >= POS_THR) {\n            for (auto [i, j] : pending) {\n                drill_cell(i, j);\n            }\n        }\n    }\n\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (is_pos[i][j]) ans.push_back({i, j});\n        }\n    }\n\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) {\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << '\\n' << flush;\n\n    int ok;\n    cin >> ok;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) cin >> a[d][k];\n    }\n\n    const int S = W; // 1000\n    const int H = W; // 1000\n    const long long INF = (1LL << 62);\n\n    auto sid = [&](int s, int h) -> size_t {\n        return (size_t)s * (H + 1) + h;\n    };\n    auto cid = [&](int i, int s, int h) -> size_t {\n        return ((size_t)i * (S + 1) + s) * (H + 1) + h;\n    };\n\n    // cost[k][h] = total shortage cost over all days if strip k has height h\n    vector<vector<long long>> cost(N, vector<long long>(H + 1, 0));\n    for (int k = 0; k < N; ++k) {\n        for (int h = 1; h <= H; ++h) {\n            long long area = 1LL * W * h;\n            long long shortage = 0;\n            for (int d = 0; d < D; ++d) {\n                if (a[d][k] > area) shortage += (long long)a[d][k] - area;\n            }\n            cost[k][h] = shortage * 100LL;\n        }\n    }\n\n    // DP layers\n    vector<long long> prev((S + 1) * (H + 1), INF), cur((S + 1) * (H + 1), INF);\n\n    // parent choice for reconstruction:\n    // parent[i][s][h] = previous height used before strip i-1, for state (i,s,h)\n    vector<uint16_t> parent((size_t)(N + 1) * (S + 1) * (H + 1), 0);\n\n    // First strip\n    int firstMax = S - (N - 1); // leave at least 1 for each remaining strip\n    for (int h = 1; h <= firstMax; ++h) {\n        prev[sid(h, h)] = cost[0][h];\n        parent[cid(1, h, h)] = 0;\n    }\n\n    // Transition\n    for (int i = 2; i <= N; ++i) {\n        fill(cur.begin(), cur.end(), INF);\n\n        int prevMinSum = i - 1;\n        int prevMaxSum = S - (N - (i - 1));\n        int curMaxSum = S - (N - i);\n\n        array<long long, 1001> prefVal;\n        array<uint16_t, 1001> prefArg;\n\n        for (int sp = prevMinSum; sp <= prevMaxSum; ++sp) {\n            long long best = INF;\n            uint16_t besth = 0;\n\n            prefVal[0] = INF;\n            prefArg[0] = 0;\n\n            for (int h = 1; h <= H; ++h) {\n                long long v = prev[sid(sp, h)];\n                if (v < best) {\n                    best = v;\n                    besth = (uint16_t)h;\n                }\n                prefVal[h] = best;\n                prefArg[h] = besth;\n            }\n\n            int maxh = min(H, curMaxSum - sp);\n            for (int h = 1; h <= maxh; ++h) {\n                if (prefVal[h] >= INF) continue;\n                int s = sp + h;\n                long long cand = prefVal[h] + cost[i - 1][h];\n                size_t idx = sid(s, h);\n                if (cand < cur[idx]) {\n                    cur[idx] = cand;\n                    parent[cid(i, s, h)] = prefArg[h];\n                }\n            }\n        }\n\n        swap(prev, cur);\n    }\n\n    // Find best final height\n    long long bestCost = INF;\n    int lastH = 1;\n    for (int h = 1; h <= H; ++h) {\n        long long v = prev[sid(S, h)];\n        if (v < bestCost) {\n            bestCost = v;\n            lastH = h;\n        }\n    }\n\n    // Reconstruct heights\n    vector<int> heights(N);\n    int s = S;\n    int h = lastH;\n    for (int i = N; i >= 1; --i) {\n        heights[i - 1] = h;\n        if (i > 1) {\n            uint16_t ph = parent[cid(i, s, h)];\n            s -= h;\n            h = (int)ph;\n        }\n    }\n\n    // Build fixed rectangles: N horizontal strips, same every day\n    vector<array<int,4>> rect(N);\n    int y = 0;\n    for (int k = 0; k < N; ++k) {\n        rect[k] = {0, y, W, y + heights[k]};\n        y += heights[k];\n    }\n\n    // Output the same layout for every day\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            auto [x0, y0, x1, y1] = rect[k];\n            cout << x0 << ' ' << y0 << ' ' << x1 << ' ' << y1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr ll MOD = 998244353LL;\nstatic constexpr int H = 9;\nstatic constexpr int W = 9;\nstatic constexpr int CELLS = 81;\nstatic constexpr int S = 3;\nstatic constexpr int POS = H - S + 1;   // 7\nstatic constexpr int TOP = 5;\n\nstruct Action {\n    int m = -1, p = -1, q = -1;\n    array<int, CELLS> add{};   // contribution on each cell (0 if unaffected)\n    array<int, 9> cells{};     // the 9 affected cells\n    array<int, 9> vals{};      // stamp values on those cells\n};\n\nstruct Result {\n    array<int, CELLS> cur{};\n    ll score = 0;\n    vector<int> seq;           // action ids, ACTIONS means no-op\n};\n\nint N, M, K;\nint ACTIONS;\n\nvector<array<array<int, S>, S>> stamps;\nvector<Action> acts;\narray<int, CELLS> initBoard{};\nll initScore = 0;\n\ninline ll calc_score(const array<int, CELLS>& b) {\n    ll s = 0;\n    for (int x : b) s += x;\n    return s;\n}\n\ninline void apply_action(array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    for (int t = 0; t < 9; ++t) {\n        int c = ac.cells[t];\n        ll x = (ll)board[c] + ac.vals[t];\n        if (x >= MOD) x -= MOD;\n        board[c] = (int)x;\n    }\n}\n\ninline void insertTop(array<pair<ll, int>, TOP>& top, int& topn, ll gain, int id) {\n    if (topn < TOP) {\n        int pos = topn++;\n        while (pos > 0 && top[pos - 1].first < gain) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {gain, id};\n    } else if (gain > top[TOP - 1].first) {\n        int pos = TOP - 1;\n        while (pos > 0 && top[pos - 1].first < gain) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {gain, id};\n    }\n}\n\nResult build_initial(int mode, mt19937_64& rng) {\n    Result res;\n    res.cur = initBoard;\n    res.score = initScore;\n    res.seq.assign(K, ACTIONS);\n\n    for (int step = 0; step < K; ++step) {\n        array<pair<ll, int>, TOP> top;\n        int topn = 0;\n\n        for (int id = 0; id < ACTIONS; ++id) {\n            ll gain = 0;\n            const auto& ac = acts[id];\n            for (int t = 0; t < 9; ++t) {\n                int c = ac.cells[t];\n                int w = ac.vals[t];\n                ll x = res.cur[c];\n                gain += (x >= MOD - w ? (ll)w - MOD : (ll)w);\n            }\n            insertTop(top, topn, gain, id);\n        }\n\n        ll chosenGain = 0;\n        int chosenId = ACTIONS;\n\n        if (mode == 0) {\n            // deterministic, use all K slots\n            chosenId = top[0].second;\n            chosenGain = top[0].first;\n        } else if (mode == 1) {\n            // randomized, use all K slots\n            int pick = ((rng() & 3) != 0 ? 0 : (int)(rng() % topn)); // 75% best\n            chosenId = top[pick].second;\n            chosenGain = top[pick].first;\n        } else if (mode == 2) {\n            // deterministic, stop when no positive gain\n            if (top[0].first <= 0) break;\n            chosenId = top[0].second;\n            chosenGain = top[0].first;\n        } else {\n            // randomized, stop when no positive gain\n            if (top[0].first <= 0) break;\n            int posn = 0;\n            while (posn < topn && top[posn].first > 0) ++posn;\n            int pick = ((rng() & 3) != 0 ? 0 : (int)(rng() % posn)); // 75% best among positive\n            chosenId = top[pick].second;\n            chosenGain = top[pick].first;\n        }\n\n        apply_action(res.cur, chosenId);\n        res.score += chosenGain;\n        res.seq[step] = chosenId;\n    }\n\n    res.score = calc_score(res.cur);\n    return res;\n}\n\nvoid refine(Result& res, int passes, mt19937_64& rng) {\n    vector<int> ord(K);\n    iota(ord.begin(), ord.end(), 0);\n\n    for (int pass = 0; pass < passes; ++pass) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool any = false;\n\n        for (int idx : ord) {\n            int old = res.seq[idx];\n            ll bestDelta = 0;\n            int bestId = old;\n\n            const int* oa = acts[old].add.data();\n\n            for (int id = 0; id <= ACTIONS; ++id) {\n                if (id == old) continue;\n                const int* na = acts[id].add.data();\n\n                ll delta = 0;\n                for (int c = 0; c < CELLS; ++c) {\n                    int a = oa[c], b = na[c];\n                    if (a == b) continue;\n\n                    ll x = (ll)res.cur[c] - a;\n                    if (x < 0) x += MOD;\n                    x += b;\n                    if (x >= MOD) x -= MOD;\n                    delta += x - res.cur[c];\n                }\n\n                if (delta > bestDelta) {\n                    bestDelta = delta;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != old && bestDelta > 0) {\n                const int* na = acts[bestId].add.data();\n                for (int c = 0; c < CELLS; ++c) {\n                    int a = oa[c], b = na[c];\n                    if (a == b) continue;\n\n                    ll x = (ll)res.cur[c] - a;\n                    if (x < 0) x += MOD;\n                    x += b;\n                    if (x >= MOD) x -= MOD;\n                    res.cur[c] = (int)x;\n                }\n                res.score += bestDelta;\n                res.seq[idx] = bestId;\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    res.score = calc_score(res.cur);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n\n    vector<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    stamps.assign(M, {});\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < S; ++i) {\n            for (int j = 0; j < S; ++j) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    ACTIONS = M * POS * POS;\n    acts.assign(ACTIONS + 1, Action{});\n\n    int id = 0;\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < POS; ++p) {\n            for (int q = 0; q < POS; ++q) {\n                Action ac;\n                ac.m = m;\n                ac.p = p;\n                ac.q = q;\n\n                int t = 0;\n                for (int di = 0; di < S; ++di) {\n                    for (int dj = 0; dj < S; ++dj) {\n                        int c = (p + di) * W + (q + dj);\n                        int w = stamps[m][di][dj];\n                        ac.cells[t] = c;\n                        ac.vals[t] = w;\n                        ac.add[c] = w;\n                        ++t;\n                    }\n                }\n                acts[id++] = ac;\n            }\n        }\n    }\n    acts[ACTIONS] = Action{}; // no-op\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            initBoard[i * W + j] = a[i][j];\n        }\n    }\n    initScore = calc_score(initBoard);\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> modes = {0, 1, 2, 3};\n    Result best;\n    best.score = -1;\n\n    for (int mode : modes) {\n        Result cur = build_initial(mode, rng);\n        refine(cur, 2, rng);\n        if (cur.score > best.score) best = std::move(cur);\n    }\n\n    // one more polish on the best candidate\n    refine(best, 1, rng);\n\n    vector<tuple<int, int, int>> ans;\n    ans.reserve(K);\n    for (int id : best.seq) {\n        if (id == ACTIONS) continue;\n        ans.emplace_back(acts[id].m, acts[id].p, acts[id].q);\n    }\n\n    cout << ans.size() << '\\n';\n    for (auto [m, p, q] : ans) {\n        cout << m << ' ' << p << ' ' << q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N; // always 5\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> A[i][j];\n    }\n\n    // Merge the 5 source rows by current front value.\n    struct Node {\n        int val, row, idx;\n        bool operator>(const Node& other) const {\n            if (val != other.val) return val > other.val;\n            if (row != other.row) return row > other.row;\n            return idx > other.idx;\n        }\n    };\n\n    priority_queue<Node, vector<Node>, greater<Node>> pq;\n    for (int i = 0; i < N; ++i) pq.push({A[i][0], i, 0});\n\n    vector<pair<int,int>> order; // (source row, container value)\n    order.reserve(N * N);\n    while (!pq.empty()) {\n        auto cur = pq.top(); pq.pop();\n        order.push_back({cur.row, cur.val});\n        if (cur.idx + 1 < N) {\n            pq.push({A[cur.row][cur.idx + 1], cur.row, cur.idx + 1});\n        }\n    }\n\n    string big;\n    int x = 0, y = 0; // large crane position\n\n    auto emit = [&](char c) {\n        big.push_back(c);\n    };\n\n    auto move_to = [&](int nx, int ny) {\n        while (y < ny) { emit('R'); ++y; }\n        while (y > ny) { emit('L'); --y; }\n        while (x < nx) { emit('D'); ++x; }\n        while (x > nx) { emit('U'); --x; }\n    };\n\n    for (auto [src_row, val] : order) {\n        // Go to source gate (src_row, 0)\n        move_to(src_row, 0);\n        emit('P');\n\n        // Deliver to correct dispatch gate row = val / N\n        int dst_row = val / N;\n        move_to(dst_row, N - 1);\n        emit('Q');\n    }\n\n    int T = (int)big.size();\n    vector<string> ans(N, string(T, '.'));\n\n    // Large crane\n    ans[0] = big;\n\n    // Small cranes: bomb on turn 1, then do nothing\n    for (int i = 1; i < N; ++i) {\n        ans[i][0] = 'B';\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct P {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> H[i][j];\n    }\n\n    auto gen_base_cycle = [&](int N) {\n        vector<P> seq;\n        seq.reserve(N * N);\n        seq.push_back({0, 0});\n        for (int y = 1; y < N; ++y) seq.push_back({0, y});\n\n        for (int x = 1; x <= N - 2; ++x) {\n            if (x % 2 == 1) {\n                for (int y = N - 1; y >= 1; --y) seq.push_back({x, y});\n            } else {\n                for (int y = 1; y <= N - 1; ++y) seq.push_back({x, y});\n            }\n        }\n\n        for (int y = N - 1; y >= 0; --y) seq.push_back({N - 1, y});\n        for (int x = N - 2; x >= 1; --x) seq.push_back({x, 0});\n        return seq;\n    };\n\n    auto transform = [&](const P& p, int t) -> P {\n        int x = p.x, y = p.y;\n        switch (t) {\n            case 0: return {x, y};\n            case 1: return {x, N - 1 - y};\n            case 2: return {N - 1 - x, y};\n            case 3: return {N - 1 - x, N - 1 - y};\n            case 4: return {y, x};\n            case 5: return {y, N - 1 - x};\n            case 6: return {N - 1 - y, x};\n            case 7: return {N - 1 - y, N - 1 - x};\n        }\n        return {x, y};\n    };\n\n    vector<P> base = gen_base_cycle(N);\n\n    ll bestCost = (1LL << 60);\n    vector<P> bestSeq;\n    int bestStart = 0;\n\n    auto eval_candidate = [&](vector<P> seq) {\n        int L = (int)seq.size();\n        vector<ll> pref(L + 1, 0);\n        for (int i = 0; i < L; ++i) {\n            pref[i + 1] = pref[i] + H[seq[i].x][seq[i].y];\n        }\n\n        ll mn = pref[0];\n        for (int i = 1; i < L; ++i) mn = min(mn, pref[i]);\n\n        for (int s = 0; s < L; ++s) {\n            if (pref[s] != mn) continue; // valid rotation start\n\n            ll cost = 100LL * (seq[s].x + seq[s].y); // empty move to the start cell\n            ll cur = 0;\n            for (int k = 0; k < L; ++k) {\n                const P& p = seq[(s + k) % L];\n                cur += H[p.x][p.y];\n                if (k + 1 < L) cost += 100 + cur; // move to next cell\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSeq = seq;\n                bestStart = s;\n            }\n        }\n    };\n\n    for (int t = 0; t < 8; ++t) {\n        vector<P> seq;\n        seq.reserve(base.size());\n        for (const auto& p : base) seq.push_back(transform(p, t));\n\n        eval_candidate(seq);\n        reverse(seq.begin(), seq.end());\n        eval_candidate(seq);\n    }\n\n    // Output operations\n    vector<string> ops;\n    ops.reserve(1000);\n\n    auto add_op = [&](const string& s) {\n        ops.push_back(s);\n    };\n\n    // Move empty from (0,0) to the chosen start cell\n    int cx = 0, cy = 0;\n    P startP = bestSeq[bestStart];\n    while (cx < startP.x) {\n        add_op(\"D\");\n        ++cx;\n    }\n    while (cx > startP.x) {\n        add_op(\"U\");\n        --cx;\n    }\n    while (cy < startP.y) {\n        add_op(\"R\");\n        ++cy;\n    }\n    while (cy > startP.y) {\n        add_op(\"L\");\n        --cy;\n    }\n\n    int L = (int)bestSeq.size();\n    for (int step = 0; step < L; ++step) {\n        int idx = (bestStart + step) % L;\n        P p = bestSeq[idx];\n        int h = H[p.x][p.y];\n        if (h > 0) {\n            add_op(\"+\" + to_string(h));\n        } else if (h < 0) {\n            add_op(\"-\" + to_string(-h));\n        }\n\n        if (step + 1 < L) {\n            P q = bestSeq[(bestStart + step + 1) % L];\n            if (q.x == p.x + 1 && q.y == p.y) add_op(\"D\");\n            else if (q.x == p.x - 1 && q.y == p.y) add_op(\"U\");\n            else if (q.x == p.x && q.y == p.y + 1) add_op(\"R\");\n            else if (q.x == p.x && q.y == p.y - 1) add_op(\"L\");\n            else {\n                // Should never happen for our Hamiltonian cycle.\n                // If it does, the output would be invalid, so keep a safe fallback.\n                // But in practice, this branch is unreachable.\n            }\n        }\n    }\n\n    for (const auto& s : ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXM = 15;\n\nstruct Seed {\n    array<int, MAXM> x{};\n    int sum = 0;\n};\n\nstruct Sol {\n    long long arrObj = -(1LL << 60);\n    long long coverage = 0;\n    vector<int> sel;   // original seed ids, size 36\n    vector<int> perm;  // local indices on grid positions 0..35\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    if (!(cin >> N >> M >> T)) return 0;\n\n    int S = 2 * N * (N - 1); // 60\n    int P = N * N;           // 36\n\n    vector<Seed> seeds(S);\n    for (int i = 0; i < S; i++) {\n        int s = 0;\n        for (int j = 0; j < M; j++) {\n            cin >> seeds[i].x[j];\n            s += seeds[i].x[j];\n        }\n        seeds[i].sum = s;\n    }\n\n    // Grid edges\n    vector<pair<int,int>> edges;\n    edges.reserve(S);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if (i + 1 < N) edges.push_back({id, (i + 1) * N + j});\n            if (j + 1 < N) edges.push_back({id, i * N + (j + 1)});\n        }\n    }\n\n    // Cell orders\n    vector<int> posDeg, posSnake;\n    {\n        vector<tuple<int,int,int>> cells;\n        cells.reserve(P);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int deg = (i > 0) + (i + 1 < N) + (j > 0) + (j + 1 < N);\n                int dist = abs(2 * i - (N - 1)) + abs(2 * j - (N - 1));\n                cells.emplace_back(-deg, dist, i * N + j);\n            }\n        }\n        sort(cells.begin(), cells.end());\n        for (auto &t : cells) posDeg.push_back(get<2>(t));\n\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; j++) posSnake.push_back(i * N + j);\n            } else {\n                for (int j = N - 1; j >= 0; j--) posSnake.push_back(i * N + j);\n            }\n        }\n    }\n\n    mt19937 rng(712367821);\n    uniform_real_distribution<double> ur(0.0, 1.0);\n\n    for (int turn = 0; turn < T; turn++) {\n        // Pair scores for all current seeds\n        vector<vector<int>> Wall(S, vector<int>(S, 0));\n        vector<long long> connAll(S, 0);\n        for (int i = 0; i < S; i++) {\n            for (int j = i + 1; j < S; j++) {\n                int w = 0;\n                for (int l = 0; l < M; l++) {\n                    w += max(seeds[i].x[l], seeds[j].x[l]);\n                }\n                Wall[i][j] = Wall[j][i] = w;\n                connAll[i] += w;\n                connAll[j] += w;\n            }\n        }\n\n        vector<long long> baseScore(S);\n        for (int i = 0; i < S; i++) {\n            baseScore[i] = connAll[i] + 20LL * seeds[i].sum;\n        }\n\n        // Candidate A: top by global compatibility\n        vector<int> candA(S);\n        iota(candA.begin(), candA.end(), 0);\n        sort(candA.begin(), candA.end(), [&](int a, int b) {\n            if (baseScore[a] != baseScore[b]) return baseScore[a] > baseScore[b];\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            return a < b;\n        });\n        candA.resize(P);\n\n        // Candidate D: top by sum\n        vector<int> candD(S);\n        iota(candD.begin(), candD.end(), 0);\n        sort(candD.begin(), candD.end(), [&](int a, int b) {\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            if (baseScore[a] != baseScore[b]) return baseScore[a] > baseScore[b];\n            return a < b;\n        });\n        candD.resize(P);\n\n        // Candidate B: greedy coverage + compatibility\n        vector<int> candB;\n        vector<char> usedB(S, 0);\n        array<int, MAXM> bestTrait{};\n        bestTrait.fill(0);\n        for (int cnt = 0; cnt < P; cnt++) {\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < S; i++) if (!usedB[i]) {\n                long long gain = 0;\n                for (int l = 0; l < M; l++) {\n                    if (seeds[i].x[l] > bestTrait[l]) gain += seeds[i].x[l] - bestTrait[l];\n                }\n                long long sc;\n                if (candB.empty()) {\n                    sc = baseScore[i];\n                } else {\n                    long long pairSum = 0;\n                    for (int j : candB) pairSum += Wall[i][j];\n                    long long pairAvg = pairSum / (long long)candB.size();\n                    sc = (long long)seeds[i].sum + gain + pairAvg / 4;\n                }\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            usedB[best] = 1;\n            candB.push_back(best);\n            for (int l = 0; l < M; l++) bestTrait[l] = max(bestTrait[l], seeds[best].x[l]);\n        }\n\n        // Candidate C: top 2 seeds per trait, then greedy fill by compatibility\n        vector<int> candC;\n        vector<char> usedC(S, 0);\n        for (int l = 0; l < M; l++) {\n            vector<int> ord(S);\n            iota(ord.begin(), ord.end(), 0);\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (seeds[a].x[l] != seeds[b].x[l]) return seeds[a].x[l] > seeds[b].x[l];\n                if (baseScore[a] != baseScore[b]) return baseScore[a] > baseScore[b];\n                return a < b;\n            });\n            int taken = 0;\n            for (int id : ord) {\n                if (!usedC[id]) {\n                    usedC[id] = 1;\n                    candC.push_back(id);\n                    if (++taken == 2) break;\n                }\n            }\n        }\n        while ((int)candC.size() < P) {\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < S; i++) if (!usedC[i]) {\n                long long pairSum = 0;\n                for (int j : candC) pairSum += Wall[i][j];\n                long long pairAvg = pairSum / max(1, (int)candC.size());\n                long long sc = baseScore[i] + pairAvg / 8;\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            usedC[best] = 1;\n            candC.push_back(best);\n        }\n\n        // Solve one candidate subset by arranging it on the grid\n        auto solveCandidate = [&](const vector<int>& sel) -> Sol {\n            int s = (int)sel.size(); // always 36\n\n            vector<vector<int>> W(s, vector<int>(s, 0));\n            vector<long long> conn(s, 0);\n            vector<int> sumLocal(s, 0);\n\n            for (int i = 0; i < s; i++) {\n                sumLocal[i] = seeds[sel[i]].sum;\n                for (int j = 0; j < s; j++) {\n                    W[i][j] = Wall[sel[i]][sel[j]];\n                    conn[i] += W[i][j];\n                }\n            }\n\n            long long coverage = 0;\n            for (int l = 0; l < M; l++) {\n                int mx = 0;\n                for (int i = 0; i < s; i++) mx = max(mx, seeds[sel[i]].x[l]);\n                coverage += mx;\n            }\n\n            auto makePerm = [&](const vector<int>& order, const vector<int>& cellOrder) {\n                vector<int> perm(P, -1);\n                for (int t = 0; t < P; t++) perm[cellOrder[t]] = order[t];\n                return perm;\n            };\n\n            auto eval = [&](const vector<int>& perm) -> long long {\n                long long res = 0;\n                for (auto [u, v] : edges) res += W[perm[u]][perm[v]];\n                return res;\n            };\n\n            auto localSearch = [&](vector<int> perm) -> pair<long long, vector<int>> {\n                long long cur = eval(perm);\n                long long best = cur;\n                vector<int> bestPerm = perm;\n\n                uniform_int_distribution<int> distPos(0, P - 1);\n                const int ITER = 4000;\n                for (int it = 0; it < ITER; it++) {\n                    int a = distPos(rng);\n                    int b = distPos(rng);\n                    if (a == b) continue;\n\n                    swap(perm[a], perm[b]);\n                    long long nv = eval(perm);\n\n                    double temp = 2000.0 * (1.0 - (double)it / (double)ITER) + 1.0;\n                    bool accept = (nv >= cur);\n                    if (!accept) {\n                        double prob = exp((double)(nv - cur) / temp);\n                        if (ur(rng) < prob) accept = true;\n                    }\n\n                    if (accept) {\n                        cur = nv;\n                        if (cur > best) {\n                            best = cur;\n                            bestPerm = perm;\n                        }\n                    } else {\n                        swap(perm[a], perm[b]);\n                    }\n                }\n                return {best, bestPerm};\n            };\n\n            // Start 1: connect order on degree-based positions\n            vector<int> order1(s);\n            iota(order1.begin(), order1.end(), 0);\n            sort(order1.begin(), order1.end(), [&](int a, int b) {\n                if (conn[a] != conn[b]) return conn[a] > conn[b];\n                if (sumLocal[a] != sumLocal[b]) return sumLocal[a] > sumLocal[b];\n                return sel[a] < sel[b];\n            });\n            vector<int> perm1 = makePerm(order1, posDeg);\n            auto [obj1, bestPerm1] = localSearch(perm1);\n\n            // Start 2: greedy chain on snake positions\n            vector<int> order2;\n            vector<char> used2(s, 0);\n            int start = (int)(max_element(conn.begin(), conn.end()) - conn.begin());\n            order2.push_back(start);\n            used2[start] = 1;\n            while ((int)order2.size() < s) {\n                int last = order2.back();\n                int best = -1;\n                long long bestSc = -(1LL << 60);\n                for (int i = 0; i < s; i++) if (!used2[i]) {\n                    long long sc = 1000LL * W[last][i] + conn[i];\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n                used2[best] = 1;\n                order2.push_back(best);\n            }\n            vector<int> perm2 = makePerm(order2, posSnake);\n            auto [obj2, bestPerm2] = localSearch(perm2);\n\n            // Start 3: random order on degree-based positions\n            vector<int> order3(s);\n            iota(order3.begin(), order3.end(), 0);\n            shuffle(order3.begin(), order3.end(), rng);\n            vector<int> perm3 = makePerm(order3, posDeg);\n            auto [obj3, bestPerm3] = localSearch(perm3);\n\n            Sol ret;\n            ret.arrObj = obj1;\n            ret.perm = bestPerm1;\n            if (obj2 > ret.arrObj) {\n                ret.arrObj = obj2;\n                ret.perm = bestPerm2;\n            }\n            if (obj3 > ret.arrObj) {\n                ret.arrObj = obj3;\n                ret.perm = bestPerm3;\n            }\n            ret.coverage = coverage;\n            ret.sel = sel;\n            return ret;\n        };\n\n        Sol solA = solveCandidate(candA);\n        Sol solB = solveCandidate(candB);\n        Sol solC = solveCandidate(candC);\n        Sol solD = solveCandidate(candD);\n\n        double remRatio = (T <= 1 ? 0.0 : (double)(T - 1 - turn) / (double)(T - 1));\n        double alpha = 6.0 * sqrt(max(0.0, remRatio));\n\n        auto fitness = [&](const Sol& s) -> double {\n            return (double)s.arrObj + alpha * (double)s.coverage;\n        };\n\n        Sol bestSol = solA;\n        double bestFit = fitness(solA);\n        auto consider = [&](const Sol& s) {\n            double f = fitness(s);\n            if (f > bestFit) {\n                bestFit = f;\n                bestSol = s;\n            }\n        };\n        consider(solB);\n        consider(solC);\n        consider(solD);\n\n        // Output the chosen grid\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int pos = i * N + j;\n                int localIdx = bestSol.perm[pos];\n                int seedId = bestSol.sel[localIdx];\n                cout << seedId << (j + 1 == N ? '\\n' : ' ');\n            }\n        }\n        cout.flush();\n\n        // Read the next generation\n        for (int i = 0; i < S; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct PairJob {\n    Point s, t;\n    int mx2, my2; // doubled midpoint coordinates: s+t\n};\n\nstruct Edge {\n    int to;\n    char mv, rot;\n};\n\nstruct BFSRes {\n    vector<int> dist, prev;\n    vector<char> pmv, prot;\n};\n\nstatic const int DX4[4] = {0, 1, 0, -1};   // R, D, L, U\nstatic const int DY4[4] = {1, 0, -1, 0};\nstatic const char MOVEC[5] = {'.', 'U', 'D', 'L', 'R'};\nstatic const int MDX[5] = {0, -1, 1, 0, 0};\nstatic const int MDY[5] = {0, 0, 0, -1, 1};\nstatic const char ROTC[3] = {'.', 'L', 'R'};\nstatic const int RDELTA[3] = {0, 3, 1};\n\nint N, M, V;\nvector<string> S, T;\n\ninline int cellId(int x, int y) { return x * N + y; }\ninline int stateId(int x, int y, int d) { return ((x * N + y) << 2) | d; }\ninline bool inside(int x, int y) { return 0 <= x && x < N && 0 <= y && y < N; }\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\ninline int manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nvector<vector<Edge>> adj;\nvector<int> rootX, rootY, dirD;\nvector<vector<int>> cellGoals;\nint SSTATE;\n\nBFSRes bfs(int start) {\n    BFSRes res;\n    res.dist.assign(SSTATE, -1);\n    res.prev.assign(SSTATE, -1);\n    res.pmv.assign(SSTATE, '.');\n    res.prot.assign(SSTATE, '.');\n\n    vector<int> q;\n    q.reserve(SSTATE);\n    q.push_back(start);\n    res.dist[start] = 0;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        for (const auto& e : adj[u]) {\n            if (res.dist[e.to] == -1) {\n                res.dist[e.to] = res.dist[u] + 1;\n                res.prev[e.to] = u;\n                res.pmv[e.to] = e.mv;\n                res.prot[e.to] = e.rot;\n                q.push_back(e.to);\n            }\n        }\n    }\n    return res;\n}\n\nvector<int> buildPath(const BFSRes& res, int start, int goal) {\n    vector<int> path;\n    if (start == goal) return path;\n    int v = goal;\n    while (v != start) {\n        if (v == -1) {\n            path.clear();\n            return path;\n        }\n        path.push_back(v);\n        v = res.prev[v];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid emitTurn(char mv, char rot, char act) {\n    char buf[4] = {mv, rot, '.', act};\n    cout.write(buf, 4);\n    cout.put('\\n');\n}\n\nvoid emitPath(const BFSRes& res, int start, int goal, char finalAct) {\n    vector<int> path = buildPath(res, start, goal);\n    if (path.empty()) {\n        emitTurn('.', '.', finalAct);\n        return;\n    }\n    for (int i = 0; i < (int)path.size(); ++i) {\n        int v = path[i];\n        char act = (i + 1 == (int)path.size() ? finalAct : '.');\n        emitTurn(res.pmv[v], res.prot[v], act);\n    }\n}\n\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    if (n == 0) return {};\n    const int INF = 1e9;\n\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, 0);\n        do {\n            used[j0] = 1;\n            int i0 = p[j0], j1 = 0;\n            int delta = INF;\n            for (int j = 1; j <= n; j++) if (!used[j]) {\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n\n    vector<int> ans(n);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> V;\n    S.resize(N);\n    T.resize(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<Point> src, tgt;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool a = (S[i][j] == '1');\n            bool b = (T[i][j] == '1');\n            if (a && !b) src.push_back({i, j});\n            if (b && !a) tgt.push_back({i, j});\n        }\n    }\n\n    int K = (int)src.size();\n    if ((int)tgt.size() != K) {\n        // Should not happen, but keep safe.\n        int mn = min((int)src.size(), (int)tgt.size());\n        src.resize(mn);\n        tgt.resize(mn);\n        K = mn;\n    }\n\n    // If nothing needs to move, output a valid tree and stop.\n    if (K == 0) {\n        cout << 2 << '\\n';\n        cout << 0 << ' ' << 1 << '\\n';\n        cout << 0 << ' ' << 0 << '\\n';\n        return 0;\n    }\n\n    // Minimum-cost matching between source-only and target-only cells.\n    vector<vector<int>> cost(K, vector<int>(K));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < K; j++) {\n            cost[i][j] = manhattan(src[i], tgt[j]);\n        }\n    }\n    vector<int> assign = hungarian(cost);\n\n    vector<PairJob> jobs(K);\n    for (int i = 0; i < K; i++) {\n        jobs[i].s = src[i];\n        jobs[i].t = tgt[assign[i]];\n        jobs[i].mx2 = jobs[i].s.x + jobs[i].t.x;\n        jobs[i].my2 = jobs[i].s.y + jobs[i].t.y;\n    }\n\n    auto edgeCost = [&](int a, int b) -> long long {\n        return manhattan(jobs[a].t, jobs[b].s);\n    };\n\n    auto chooseStartRoot = [&](int first, int second) -> pair<long long, Point> {\n        const Point& s = jobs[first].s;\n        const Point& t = jobs[first].t;\n        long long best = (1LL << 60);\n        Point bestP{0, 0};\n        int bestPref = 10;\n        int center = (N - 1) / 2;\n\n        for (int d = 0; d < 4; d++) {\n            int rx = s.x - DX4[d];\n            int ry = s.y - DY4[d];\n            if (!inside(rx, ry)) continue;\n            long long c = manhattan(rx, ry, t.x, t.y);\n            if (second != -1) c += manhattan(rx, ry, jobs[second].s.x, jobs[second].s.y);\n\n            int pref = (rx == s.x && ry == s.y - 1) ? 0 : 1; // prefer the initial right-facing pickup if possible\n            long long tie = abs(rx - center) + abs(ry - center);\n\n            if (c < best || (c == best && (pref < bestPref || (pref == bestPref && tie < abs(bestP.x - center) + abs(bestP.y - center))))) {\n                best = c;\n                bestP = {rx, ry};\n                bestPref = pref;\n            }\n        }\n        return {best, bestP};\n    };\n\n    auto evalOrder = [&](const vector<int>& ord) -> pair<long long, Point> {\n        long long score = 0;\n        auto [sc, root] = chooseStartRoot(ord[0], (int)ord.size() >= 2 ? ord[1] : -1);\n        score += sc;\n        for (int i = 0; i + 1 < (int)ord.size(); i++) score += edgeCost(ord[i], ord[i + 1]);\n        return {score, root};\n    };\n\n    auto buildGreedyOrder = [&](int startIdx) -> vector<int> {\n        vector<int> ord;\n        ord.reserve(K);\n        vector<char> used(K, 0);\n        ord.push_back(startIdx);\n        used[startIdx] = 1;\n        int cur = startIdx;\n\n        while ((int)ord.size() < K) {\n            int best = -1;\n            long long bestD = (1LL << 60);\n            long long bestTie1 = (1LL << 60);\n            long long bestTie2 = (1LL << 60);\n            for (int j = 0; j < K; j++) if (!used[j]) {\n                long long d = manhattan(jobs[cur].t, jobs[j].s);\n                long long tie1 = llabs((long long)jobs[j].mx2 - (N - 1)) + llabs((long long)jobs[j].my2 - (N - 1));\n                long long tie2 = manhattan(jobs[j].s, jobs[j].t);\n                if (d < bestD || (d == bestD && (tie1 < bestTie1 || (tie1 == bestTie1 && tie2 < bestTie2)))) {\n                    bestD = d;\n                    bestTie1 = tie1;\n                    bestTie2 = tie2;\n                    best = j;\n                }\n            }\n            used[best] = 1;\n            ord.push_back(best);\n            cur = best;\n        }\n        return ord;\n    };\n\n    auto refineOrder = [&](vector<int>& ord) {\n        int K2 = (int)ord.size();\n        if (K2 <= 2) return;\n\n        auto startCost = [&](int first, int second) -> long long {\n            auto [c, _] = chooseStartRoot(first, second);\n            return c;\n        };\n\n        for (int pass = 0; pass < 3; pass++) {\n            bool changed = false;\n            for (int i = 0; i + 1 < K2; i++) {\n                long long oldc = 0, newc = 0;\n\n                if (i == 0) {\n                    int a = ord[0], b = ord[1];\n                    oldc = startCost(a, K2 >= 2 ? b : -1);\n                    oldc += edgeCost(a, b);\n                    if (K2 >= 3) oldc += edgeCost(b, ord[2]);\n\n                    newc = startCost(b, a);\n                    newc += edgeCost(b, a);\n                    if (K2 >= 3) newc += edgeCost(a, ord[2]);\n                } else {\n                    int a = ord[i - 1], b = ord[i], c = ord[i + 1];\n                    oldc = edgeCost(a, b) + edgeCost(b, c);\n                    if (i + 2 < K2) oldc += edgeCost(c, ord[i + 2]);\n\n                    newc = edgeCost(a, c) + edgeCost(c, b);\n                    if (i + 2 < K2) newc += edgeCost(b, ord[i + 2]);\n                }\n\n                if (newc < oldc) {\n                    swap(ord[i], ord[i + 1]);\n                    changed = true;\n                }\n            }\n            if (!changed) break;\n        }\n    };\n\n    // Candidate starts: near midpoint, source, and target.\n    vector<int> idx(K);\n    iota(idx.begin(), idx.end(), 0);\n\n    auto scoreMid = [&](int i) {\n        return llabs((long long)jobs[i].mx2 - (N - 1)) + llabs((long long)jobs[i].my2 - (N - 1));\n    };\n    auto scoreSrc = [&](int i) {\n        int c = (N - 1) / 2;\n        return llabs((long long)jobs[i].s.x - c) + llabs((long long)jobs[i].s.y - c);\n    };\n    auto scoreTgt = [&](int i) {\n        int c = (N - 1) / 2;\n        return llabs((long long)jobs[i].t.x - c) + llabs((long long)jobs[i].t.y - c);\n    };\n\n    vector<int> cand;\n    {\n        vector<int> a = idx, b = idx, c = idx;\n        sort(a.begin(), a.end(), [&](int i, int j) { return scoreMid(i) < scoreMid(j); });\n        sort(b.begin(), b.end(), [&](int i, int j) { return scoreSrc(i) < scoreSrc(j); });\n        sort(c.begin(), c.end(), [&](int i, int j) { return scoreTgt(i) < scoreTgt(j); });\n\n        vector<char> used(K, 0);\n        auto addTop = [&](const vector<int>& v) {\n            for (int i = 0; i < (int)v.size() && i < 4; i++) {\n                if (!used[v[i]]) {\n                    used[v[i]] = 1;\n                    cand.push_back(v[i]);\n                }\n            }\n        };\n        addTop(a);\n        addTop(b);\n        addTop(c);\n    }\n\n    long long bestProxy = (1LL << 60);\n    vector<int> bestOrder;\n    Point startRoot{0, 0};\n\n    for (int st : cand) {\n        vector<int> ord = buildGreedyOrder(st);\n\n        // Try the greedy order and its reverse.\n        for (int rev = 0; rev < 2; rev++) {\n            vector<int> cur = ord;\n            if (rev) reverse(cur.begin(), cur.end());\n            refineOrder(cur);\n\n            auto [sc, root] = evalOrder(cur);\n            if (sc < bestProxy) {\n                bestProxy = sc;\n                bestOrder = std::move(cur);\n                startRoot = root;\n            }\n        }\n    }\n\n    // One-finger arm: root + one fingertip of length 1.\n    // Precompute state graph.\n    SSTATE = N * N * 4;\n    adj.assign(SSTATE, {});\n    rootX.assign(SSTATE, 0);\n    rootY.assign(SSTATE, 0);\n    dirD.assign(SSTATE, 0);\n    cellGoals.assign(N * N, {});\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            for (int d = 0; d < 4; d++) {\n                int id = stateId(x, y, d);\n                rootX[id] = x;\n                rootY[id] = y;\n                dirD[id] = d;\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            int cid = cellId(x, y);\n            for (int d = 0; d < 4; d++) {\n                int rx = x - DX4[d];\n                int ry = y - DY4[d];\n                if (inside(rx, ry)) {\n                    cellGoals[cid].push_back(stateId(rx, ry, d));\n                }\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            for (int d = 0; d < 4; d++) {\n                int id = stateId(x, y, d);\n                for (int m = 0; m < 5; m++) {\n                    for (int r = 0; r < 3; r++) {\n                        if (m == 0 && r == 0) continue;\n                        int nx = x + MDX[m];\n                        int ny = y + MDY[m];\n                        if (!inside(nx, ny)) continue;\n                        int nd = (d + RDELTA[r]) & 3;\n                        int to = stateId(nx, ny, nd);\n                        adj[id].push_back({to, MOVEC[m], ROTC[r]});\n                    }\n                }\n            }\n        }\n    }\n\n    // Output the arm.\n    cout << 2 << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n    cout << startRoot.x << ' ' << startRoot.y << '\\n';\n\n    int curState = stateId(startRoot.x, startRoot.y, 0); // initial direction: right\n\n    for (int idxOrd = 0; idxOrd < (int)bestOrder.size(); idxOrd++) {\n        int jid = bestOrder[idxOrd];\n        const auto& job = jobs[jid];\n        int sCell = cellId(job.s.x, job.s.y);\n        int tCell = cellId(job.t.x, job.t.y);\n\n        const auto& srcGoals = cellGoals[sCell];\n        const auto& tgtGoals = cellGoals[tCell];\n\n        vector<int> nextGoals;\n        if (idxOrd + 1 < (int)bestOrder.size()) {\n            int njid = bestOrder[idxOrd + 1];\n            nextGoals = cellGoals[cellId(jobs[njid].s.x, jobs[njid].s.y)];\n        }\n\n        BFSRes curBfs = bfs(curState);\n\n        int bestPIdx = -1, bestQ = -1;\n        long long bestScore = (1LL << 60);\n        vector<int> pStates;\n        vector<BFSRes> pBfsList;\n\n        for (int pi = 0; pi < (int)srcGoals.size(); pi++) {\n            int p = srcGoals[pi];\n            if (curBfs.dist[p] == -1) continue;\n\n            BFSRes pbfs = bfs(p);\n            pStates.push_back(p);\n            pBfsList.emplace_back(std::move(pbfs));\n            int storedIdx = (int)pStates.size() - 1;\n            const BFSRes& now = pBfsList.back();\n\n            for (int q : tgtGoals) {\n                if (now.dist[q] == -1) continue;\n\n                long long future = 0;\n                if (!nextGoals.empty()) {\n                    long long bestFuture = (1LL << 60);\n                    for (int r : nextGoals) {\n                        long long d = llabs((long long)rootX[q] - rootX[r]) + llabs((long long)rootY[q] - rootY[r]);\n                        bestFuture = min(bestFuture, d);\n                    }\n                    future = bestFuture;\n                }\n\n                long long sc = (long long)curBfs.dist[p] + now.dist[q] + future;\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestPIdx = storedIdx;\n                    bestQ = q;\n                }\n            }\n        }\n\n        if (bestPIdx == -1) {\n            // Extremely defensive fallback: should never happen.\n            bestPIdx = 0;\n            bestQ = tgtGoals[0];\n        }\n\n        int bestP = pStates[bestPIdx];\n        const BFSRes& bestPBfs = pBfsList[bestPIdx];\n\n        emitPath(curBfs, curState, bestP, 'P');     // pick\n        emitPath(bestPBfs, bestP, bestQ, 'P');      // drop\n        curState = bestQ;\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int MAXC = 100000;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Rect {\n    int sum;\n    ll area;\n    int x1, y1, x2, y2;\n};\n\nstruct Config {\n    int S;\n    int ox, oy;\n};\n\nstatic void build_axis(int S, int off, vector<int>& st, vector<int>& en) {\n    st.clear();\n    en.clear();\n    st.push_back(0);\n    en.push_back(off - 1);\n    for (int l = off; l <= MAXC; l += S) {\n        st.push_back(l);\n        en.push_back(min(MAXC, l + S - 1));\n    }\n}\n\nstatic int cell_idx(int v, int S, int off) {\n    if (v < off) return 0;\n    return 1 + (v - off) / S;\n}\n\nstatic Rect solve_cfg(int S, int ox, int oy,\n                      const vector<Point>& mackerels,\n                      const vector<Point>& sardines) {\n    vector<int> xs, xe, ys, ye;\n    build_axis(S, ox, xs, xe);\n    build_axis(S, oy, ys, ye);\n\n    int nx = (int)xs.size();\n    int ny = (int)ys.size();\n\n    vector<int> w(nx * ny, 0);\n\n    auto add_point = [&](const Point& p, int delta) {\n        int ix = cell_idx(p.x, S, ox);\n        int iy = cell_idx(p.y, S, oy);\n        w[ix * ny + iy] += delta;\n    };\n\n    for (const auto& p : mackerels) add_point(p, +1);\n    for (const auto& p : sardines) add_point(p, -1);\n\n    Rect best{INT_MIN, -1, 0, 0, 0, 0};\n    vector<int> col(ny, 0);\n\n    for (int top = 0; top < nx; ++top) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < nx; ++bot) {\n            const int* row = &w[bot * ny];\n            for (int c = 0; c < ny; ++c) col[c] += row[c];\n\n            int cur = 0;\n            int left = 0;\n            for (int c = 0; c < ny; ++c) {\n                if (cur < 0) {\n                    cur = col[c];\n                    left = c;\n                } else {\n                    cur += col[c];\n                }\n\n                ll area = 1LL * (xe[bot] - xs[top]) * (ye[c] - ys[left]);\n                if (cur > best.sum || (cur == best.sum && area > best.area)) {\n                    best = {cur, area, xs[top], ys[left], xe[bot], ye[c]};\n                }\n            }\n        }\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<Point> mackerels(N), sardines(N);\n    for (int i = 0; i < N; ++i) cin >> mackerels[i].x >> mackerels[i].y;\n    for (int i = 0; i < N; ++i) cin >> sardines[i].x >> sardines[i].y;\n\n    // Phase-shifted grids to reduce boundary bias.\n    vector<Config> cfgs = {\n        {500, 100, 100},\n        {500, 225, 225},\n        {500, 350, 350},\n        {500, 475, 475},\n        {500, 100, 225},\n        {500, 225, 350},\n        {500, 350, 475},\n        {500, 475, 100},\n    };\n\n    Rect ans{INT_MIN, -1, 0, 0, MAXC, MAXC};\n    for (const auto& cfg : cfgs) {\n        Rect r = solve_cfg(cfg.S, cfg.ox, cfg.oy, mackerels, sardines);\n        if (r.sum > ans.sum || (r.sum == ans.sum && r.area > ans.area)) {\n            ans = r;\n        }\n    }\n\n    // Fallback (should not be needed): full box is always valid.\n    if (ans.x2 <= ans.x1 || ans.y2 <= ans.y1) {\n        ans = {0, 1LL * MAXC * MAXC, 0, 0, MAXC, MAXC};\n    }\n\n    cout << 4 << '\\n';\n    cout << ans.x1 << ' ' << ans.y1 << '\\n';\n    cout << ans.x2 << ' ' << ans.y1 << '\\n';\n    cout << ans.x2 << ' ' << ans.y2 << '\\n';\n    cout << ans.x1 << ' ' << ans.y2 << '\\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, b;\n    char d;\n};\n\nstruct State {\n    ll W, H;\n    int prev_i, prev_idx;\n};\n\nstruct Cand {\n    vector<Op> ops;\n    ll estW = 0, estH = 0;\n    string sig;\n};\n\nstruct Family {\n    ll bestScore = (1LL << 62);\n    int mode = 0, axis = 0;\n    vector<Cand> cands;\n};\n\nstatic string serialize_ops(const vector<Op>& ops) {\n    string s;\n    s.reserve(ops.size() * 16);\n    for (auto &op : ops) {\n        s += to_string(op.p);\n        s.push_back(',');\n        s += to_string(op.r);\n        s.push_back(',');\n        s.push_back(op.d);\n        s.push_back(',');\n        s += to_string(op.b);\n        s.push_back(';');\n    }\n    return s;\n}\n\nstatic int choose_state_by_weight(const vector<State>& front, ll a, ll b) {\n    int idx = 0;\n    __int128 best = (__int128)a * front[0].W + (__int128)b * front[0].H;\n    for (int i = 1; i < (int)front.size(); ++i) {\n        __int128 cur = (__int128)a * front[i].W + (__int128)b * front[i].H;\n        if (cur < best || (cur == best && (front[i].W < front[idx].W ||\n                                          (front[i].W == front[idx].W && front[i].H < front[idx].H)))) {\n            best = cur;\n            idx = i;\n        }\n    }\n    return idx;\n}\n\nstatic Cand build_candidate_from_state(\n    const vector<vector<State>>& dp,\n    int idx,\n    const vector<int>& rot,\n    const vector<ll>& sh,\n    int axis,\n    int N\n) {\n    vector<pair<int,int>> groups;\n    int cur_i = N, cur_idx = idx;\n    while (cur_i > 0) {\n        const State& s = dp[cur_i][cur_idx];\n        groups.push_back({s.prev_i, cur_i});\n        cur_idx = s.prev_idx;\n        cur_i = s.prev_i;\n    }\n    reverse(groups.begin(), groups.end());\n\n    vector<Op> ops;\n    ops.reserve(N);\n    int prev_anchor = -1;\n\n    for (int g = 0; g < (int)groups.size(); ++g) {\n        int l = groups[g].first;\n        int r = groups[g].second;\n\n        int anchor = l;\n        for (int i = l + 1; i < r; ++i) {\n            if (sh[i] > sh[anchor]) anchor = i;\n        }\n\n        if (axis == 0) { // row packing\n            if (g == 0) ops.push_back({l, rot[l], -1, 'U'});\n            else ops.push_back({l, rot[l], prev_anchor, 'L'});\n            for (int i = l + 1; i < r; ++i) {\n                ops.push_back({i, rot[i], i - 1, 'U'});\n            }\n        } else { // column packing\n            if (g == 0) ops.push_back({l, rot[l], -1, 'U'});\n            else ops.push_back({l, rot[l], prev_anchor, 'U'});\n            for (int i = l + 1; i < r; ++i) {\n                ops.push_back({i, rot[i], i - 1, 'L'});\n            }\n        }\n\n        prev_anchor = anchor;\n    }\n\n    Cand c;\n    c.ops = move(ops);\n    c.estW = dp[N][idx].W;\n    c.estH = dp[N][idx].H;\n    c.sig = serialize_ops(c.ops);\n    return c;\n}\n\nstatic Family build_family(const vector<ll>& baseW, const vector<ll>& baseH, int mode, int axis) {\n    int N = (int)baseW.size();\n    vector<ll> ow(N), oh(N);\n    vector<int> rot(N);\n\n    auto make_oriented = [&](int i, bool width_min) {\n        if (width_min) {\n            if (baseW[i] <= baseH[i]) {\n                ow[i] = baseW[i];\n                oh[i] = baseH[i];\n                rot[i] = 0;\n            } else {\n                ow[i] = baseH[i];\n                oh[i] = baseW[i];\n                rot[i] = 1;\n            }\n        } else {\n            if (baseW[i] >= baseH[i]) {\n                ow[i] = baseW[i];\n                oh[i] = baseH[i];\n                rot[i] = 0;\n            } else {\n                ow[i] = baseH[i];\n                oh[i] = baseW[i];\n                rot[i] = 1;\n            }\n        }\n    };\n\n    for (int i = 0; i < N; ++i) {\n        if (mode == 0) {\n            make_oriented(i, true);   // width-min\n        } else if (mode == 1) {\n            make_oriented(i, false);  // height-min\n        } else if (mode == 2) {\n            if (i & 1) make_oriented(i, false);\n            else make_oriented(i, true);\n        } else {\n            if (i & 1) make_oriented(i, true);\n            else make_oriented(i, false);\n        }\n    }\n\n    vector<ll> sw(N), sh(N);\n    if (axis == 0) {\n        sw = ow;\n        sh = oh;\n    } else {\n        sw = oh;\n        sh = ow;\n    }\n\n    vector<ll> pref(N + 1, 0);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + sw[i];\n\n    vector<vector<ll>> mx(N, vector<ll>(N, 0));\n    for (int l = 0; l < N; ++l) {\n        ll cur = 0;\n        for (int r = l; r < N; ++r) {\n            cur = max(cur, sh[r]);\n            mx[l][r] = cur;\n        }\n    }\n\n    vector<vector<State>> dp(N + 1);\n    dp[0].push_back({0, 0, -1, -1});\n\n    for (int i = 1; i <= N; ++i) {\n        vector<State> cand;\n        for (int j = 0; j < i; ++j) {\n            ll rowW = pref[i] - pref[j];\n            ll rowH = mx[j][i - 1];\n            const auto& vec = dp[j];\n            cand.reserve(cand.size() + vec.size());\n            for (int idx = 0; idx < (int)vec.size(); ++idx) {\n                const State& s = vec[idx];\n                cand.push_back({max(s.W, rowW), s.H + rowH, j, idx});\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const State& a, const State& b) {\n            if (a.W != b.W) return a.W < b.W;\n            return a.H < b.H;\n        });\n\n        vector<State> tmp;\n        tmp.reserve(cand.size());\n        for (auto &s : cand) {\n            if (tmp.empty() || s.W != tmp.back().W) {\n                tmp.push_back(s);\n            } else {\n                if (s.H < tmp.back().H) tmp.back() = s;\n            }\n        }\n\n        ll bestH = (1LL << 62);\n        dp[i].clear();\n        for (auto &s : tmp) {\n            if (s.H < bestH) {\n                dp[i].push_back(s);\n                bestH = s.H;\n            }\n        }\n    }\n\n    const auto& front = dp[N];\n    int M = (int)front.size();\n\n    int idx_best = choose_state_by_weight(front, 1, 1);\n    ll bestScore = front[idx_best].W + front[idx_best].H;\n\n    set<int> idxs;\n    auto add_idx = [&](int idx) {\n        if (0 <= idx && idx < M) idxs.insert(idx);\n    };\n\n    // Core representative points.\n    add_idx(0);\n    add_idx(M - 1);\n    add_idx(idx_best);\n\n    // A broad set of slope-based samples on the Pareto frontier.\n    vector<pair<int,int>> weights = {\n        {2,1}, {1,2}, {3,1}, {1,3}, {4,1}, {1,4},\n        {5,2}, {2,5}, {7,3}, {3,7}, {11,4}, {4,11},\n        {13,5}, {5,13}\n    };\n    for (auto [a, b] : weights) {\n        int idx = choose_state_by_weight(front, a, b);\n        add_idx(idx);\n        add_idx(idx - 1);\n        add_idx(idx + 1);\n    }\n\n    // Evenly sampled frontier states.\n    int K = min(M, 16);\n    if (K >= 2) {\n        for (int k = 0; k < K; ++k) {\n            int idx = (int)((1LL * k * (M - 1)) / (K - 1));\n            add_idx(idx);\n        }\n    } else {\n        add_idx(0);\n    }\n\n    unordered_set<string> localSeen;\n    Family fam;\n    fam.bestScore = bestScore;\n    fam.mode = mode;\n    fam.axis = axis;\n    fam.cands.reserve(idxs.size());\n\n    for (int idx : idxs) {\n        Cand c = build_candidate_from_state(dp, idx, rot, sh, axis, N);\n        if (localSeen.insert(c.sig).second) {\n            fam.cands.push_back(move(c));\n        }\n    }\n\n    return fam;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    ll sigma;\n    cin >> N >> T >> sigma;\n\n    vector<ll> w(N), h(N);\n    for (int i = 0; i < N; ++i) cin >> w[i] >> h[i];\n\n    vector<Family> families;\n    families.reserve(8);\n    for (int mode = 0; mode < 4; ++mode) {\n        for (int axis = 0; axis < 2; ++axis) {\n            families.push_back(build_family(w, h, mode, axis));\n        }\n    }\n\n    sort(families.begin(), families.end(), [](const Family& a, const Family& b) {\n        if (a.bestScore != b.bestScore) return a.bestScore < b.bestScore;\n        if (a.axis != b.axis) return a.axis < b.axis;\n        return a.mode < b.mode;\n    });\n\n    // Collect candidates: first one best per family, then the rest globally.\n    vector<Cand> chosen;\n    chosen.reserve(min(T, 256));\n    unordered_set<string> used;\n    used.reserve(512);\n\n    for (auto &fam : families) {\n        if (fam.cands.empty()) continue;\n        int bestIdx = 0;\n        ll best = fam.cands[0].estW + fam.cands[0].estH;\n        for (int i = 1; i < (int)fam.cands.size(); ++i) {\n            ll cur = fam.cands[i].estW + fam.cands[i].estH;\n            if (cur < best) {\n                best = cur;\n                bestIdx = i;\n            }\n        }\n        if (used.insert(fam.cands[bestIdx].sig).second) {\n            chosen.push_back(fam.cands[bestIdx]);\n        }\n    }\n\n    vector<Cand> rest;\n    rest.reserve(512);\n    for (auto &fam : families) {\n        for (auto &c : fam.cands) {\n            if (!used.count(c.sig)) rest.push_back(c);\n        }\n    }\n\n    sort(rest.begin(), rest.end(), [](const Cand& a, const Cand& b) {\n        ll sa = a.estW + a.estH;\n        ll sb = b.estW + b.estH;\n        if (sa != sb) return sa < sb;\n        if (a.estW != b.estW) return a.estW < b.estW;\n        return a.estH < b.estH;\n    });\n\n    int need = max(0, T - (int)chosen.size());\n    for (int i = 0; i < need && i < (int)rest.size(); ++i) {\n        chosen.push_back(rest[i]);\n        used.insert(rest[i].sig);\n    }\n\n    if (chosen.empty()) {\n        // Fallback: a simple row packing.\n        Cand c;\n        vector<Op> ops;\n        ops.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (i == 0) ops.push_back({i, 0, -1, 'U'});\n            else ops.push_back({i, 0, i - 1, 'U'});\n        }\n        c.ops = move(ops);\n        c.sig = serialize_ops(c.ops);\n        chosen.push_back(move(c));\n    }\n\n    sort(chosen.begin(), chosen.end(), [](const Cand& a, const Cand& b) {\n        ll sa = a.estW + a.estH;\n        ll sb = b.estW + b.estH;\n        if (sa != sb) return sa < sb;\n        if (a.estW != b.estW) return a.estW < b.estW;\n        return a.estH < b.estH;\n    });\n\n    int usedCount = min(T, (int)chosen.size());\n    for (int t = 0; t < usedCount; ++t) {\n        const auto& c = chosen[t];\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm; // Read judge feedback, but we don't need it for this heuristic.\n    }\n\n    for (int t = usedCount; t < T; ++t) {\n        const auto& c = chosen[0];\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm;\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Key4 {\n    int a, b, c, d;\n    bool operator<(const Key4& o) const {\n        if (a != o.a) return a < o.a;\n        if (b != o.b) return b < o.b;\n        if (c != o.c) return c < o.c;\n        return d < o.d;\n    }\n};\n\nstruct Info {\n    vector<vector<int>> children;\n    vector<int> parent;\n    vector<int> roots;\n    vector<int> comp;\n    vector<int> depth;\n    vector<int> tin, tout;\n    vector<long long> subW;\n    vector<int> maxDown;\n    vector<vector<int>> compNodes;\n    long long score = 0;\n};\n\nstatic int N, M, H;\nstatic vector<int> A, degv, mort, neighSum;\nstatic vector<vector<int>> adj;\nstatic chrono::steady_clock::time_point start_time;\n\nstatic inline bool time_up() {\n    return chrono::duration_cast<chrono::milliseconds>(\n               chrono::steady_clock::now() - start_time)\n        .count() > 1850;\n}\n\nstatic int morton_code(int x, int y) {\n    int z = 0;\n    for (int i = 0; i < 10; ++i) {\n        z |= ((x >> i) & 1) << (2 * i);\n        z |= ((y >> i) & 1) << (2 * i + 1);\n    }\n    return z;\n}\n\nstatic Info compute_info(const vector<int>& parent) {\n    Info info;\n    info.parent = parent;\n    info.children.assign(N, {});\n    info.roots.clear();\n    for (int v = 0; v < N; ++v) {\n        if (parent[v] == -1) info.roots.push_back(v);\n        else info.children[parent[v]].push_back(v);\n    }\n\n    info.comp.assign(N, -1);\n    info.depth.assign(N, -1);\n    info.tin.assign(N, -1);\n    info.tout.assign(N, -1);\n    info.subW.assign(N, 0);\n    info.maxDown.assign(N, 0);\n    info.compNodes.clear();\n    info.score = 0;\n\n    int timer = 0;\n    int cid = 0;\n\n    auto dfs = [&](auto&& self, int v, int d) -> void {\n        info.comp[v] = cid;\n        info.depth[v] = d;\n        info.tin[v] = timer++;\n        info.subW[v] = A[v];\n        info.maxDown[v] = 0;\n        info.score += 1LL * (d + 1) * A[v];\n        info.compNodes.back().push_back(v);\n\n        for (int ch : info.children[v]) {\n            self(self, ch, d + 1);\n            info.subW[v] += info.subW[ch];\n            info.maxDown[v] = max(info.maxDown[v], info.maxDown[ch] + 1);\n        }\n        info.tout[v] = timer;\n    };\n\n    for (int r : info.roots) {\n        info.compNodes.push_back({});\n        dfs(dfs, r, 0);\n        ++cid;\n    }\n\n    return info;\n}\n\nstatic vector<int> build_greedy(const vector<int>& order, const vector<Key4>& pref) {\n    vector<int> parent(N, -2), depth(N, -1);\n    for (int v : order) {\n        int best = -1;\n        for (int u : adj[v]) {\n            if (depth[u] == -1 || depth[u] >= H) continue;\n            if (best == -1 || depth[u] > depth[best] ||\n                (depth[u] == depth[best] && pref[u] < pref[best])) {\n                best = u;\n            }\n        }\n        if (best == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = best;\n            depth[v] = depth[best] + 1;\n        }\n    }\n    return parent;\n}\n\nstatic vector<int> build_connected_order(const vector<long long>& prio) {\n    vector<int> ord;\n    ord.reserve(N);\n\n    int seed = 0;\n    for (int i = 1; i < N; ++i) {\n        if (make_tuple(prio[i], mort[i], i) < make_tuple(prio[seed], mort[seed], seed)) seed = i;\n    }\n\n    using T = tuple<long long, int, int>; // prio, mort, id\n    priority_queue<T, vector<T>, greater<T>> pq;\n    vector<char> inq(N, 0), vis(N, 0);\n\n    pq.emplace(prio[seed], mort[seed], seed);\n    inq[seed] = 1;\n\n    while (!pq.empty()) {\n        auto [p, m, v] = pq.top();\n        pq.pop();\n        if (vis[v]) continue;\n        vis[v] = 1;\n        ord.push_back(v);\n        for (int to : adj[v]) {\n            if (!inq[to]) {\n                inq[to] = 1;\n                pq.emplace(prio[to], mort[to], to);\n            }\n        }\n    }\n    return ord;\n}\n\nstatic vector<int> build_dfs_forest() {\n    vector<Key4> rootKey(N), childKey(N);\n    for (int v = 0; v < N; ++v) {\n        rootKey[v] = {A[v], -degv[v], neighSum[v], mort[v]};\n        childKey[v] = {-A[v], -neighSum[v], -degv[v], mort[v]};\n    }\n\n    vector<int> roots(N);\n    iota(roots.begin(), roots.end(), 0);\n    sort(roots.begin(), roots.end(), [&](int x, int y) { return rootKey[x] < rootKey[y]; });\n\n    vector<vector<int>> ordAdj = adj;\n    for (int v = 0; v < N; ++v) {\n        sort(ordAdj[v].begin(), ordAdj[v].end(), [&](int x, int y) {\n            return childKey[x] < childKey[y];\n        });\n    }\n\n    vector<int> parent(N, -2), depth(N, -1);\n    vector<char> vis(N, 0);\n\n    auto dfs = [&](auto&& self, int v, int d) -> void {\n        vis[v] = 1;\n        depth[v] = d;\n        if (d == H) return;\n        for (int to : ordAdj[v]) {\n            if (!vis[to]) {\n                parent[to] = v;\n                self(self, to, d + 1);\n            }\n        }\n    };\n\n    for (int r : roots) {\n        if (vis[r]) continue;\n        parent[r] = -1;\n        dfs(dfs, r, 0);\n    }\n\n    return parent;\n}\n\nstatic vector<int> optimize_roots(const vector<int>& parentIn) {\n    vector<int> parent = parentIn;\n    Info info = compute_info(parent);\n\n    vector<int> newParent = parent;\n\n    auto bfs = [&](int s) {\n        vector<int> dist(N, -1);\n        queue<int> q;\n        q.push(s);\n        dist[s] = 0;\n        int far = s;\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            if (dist[v] > dist[far]) far = v;\n            if (info.parent[v] != -1 && dist[info.parent[v]] == -1) {\n                dist[info.parent[v]] = dist[v] + 1;\n                q.push(info.parent[v]);\n            }\n            for (int ch : info.children[v]) {\n                if (dist[ch] == -1) {\n                    dist[ch] = dist[v] + 1;\n                    q.push(ch);\n                }\n            }\n        }\n        return pair<int, vector<int>>(far, move(dist));\n    };\n\n    for (int cid = 0; cid < (int)info.roots.size(); ++cid) {\n        if (time_up()) break;\n\n        int r = info.roots[cid];\n        const auto& nodes = info.compNodes[cid];\n        if ((int)nodes.size() == 1) continue;\n\n        long long totalW = info.subW[r];\n        long long baseDist = 0;\n        for (int v : nodes) baseDist += 1LL * info.depth[v] * A[v];\n\n        vector<long long> sumDist(N, LLONG_MIN / 4);\n        sumDist[r] = baseDist;\n\n        auto dfs2 = [&](auto&& self, int v) -> void {\n            for (int ch : info.children[v]) {\n                sumDist[ch] = sumDist[v] + totalW - 2LL * info.subW[ch];\n                self(self, ch);\n            }\n        };\n        dfs2(dfs2, r);\n\n        auto [x, distFromR] = bfs(r);\n        auto [y, distX] = bfs(x);\n        auto [dummy, distY] = bfs(y);\n\n        int best = r;\n        auto bestKey = make_tuple(sumDist[r], -max(distX[r], distY[r]), -A[r], -r);\n\n        for (int v : nodes) {\n            int ecc = max(distX[v], distY[v]);\n            if (ecc > H) continue;\n            auto key = make_tuple(sumDist[v], -ecc, -A[v], -v);\n            if (key > bestKey) {\n                bestKey = key;\n                best = v;\n            }\n        }\n\n        if (best == r) continue;\n\n        vector<int> vis(N, 0), parComp(N, -2), depComp(N, -1);\n        queue<int> q;\n        q.push(best);\n        vis[best] = 1;\n        parComp[best] = -1;\n        depComp[best] = 0;\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            auto relax = [&](int to) {\n                if (vis[to]) return;\n                vis[to] = 1;\n                parComp[to] = v;\n                depComp[to] = depComp[v] + 1;\n                q.push(to);\n            };\n\n            if (info.parent[v] != -1) relax(info.parent[v]);\n            for (int ch : info.children[v]) relax(ch);\n        }\n\n        for (int v : nodes) newParent[v] = parComp[v];\n    }\n\n    return newParent;\n}\n\nstatic void improve(vector<int>& parent, int maxIter) {\n    for (int iter = 0; iter < maxIter; ++iter) {\n        if (time_up()) break;\n\n        Info info = compute_info(parent);\n\n        long long bestGain = 0;\n        tuple<long long, int, int, int, long long, int, int, int> bestKey =\n            make_tuple(-1LL, -1, -1, -1, -1LL, -1, -1, -1);\n        int bestV = -1, bestU = -1;\n\n        for (int v = 0; v < N; ++v) {\n            if (info.maxDown[v] == H) continue; // cannot go deeper\n            int d = info.depth[v];\n            long long sw = info.subW[v];\n\n            for (int u : adj[v]) {\n                if (u == parent[v]) continue;\n\n                bool sameComp = (info.comp[u] == info.comp[v]);\n                if (sameComp) {\n                    // u must not be in subtree(v)\n                    if (info.tin[v] <= info.tin[u] && info.tin[u] < info.tout[v]) continue;\n                }\n\n                int nd = info.depth[u] + 1;\n                if (nd <= d) continue;\n                if (nd + info.maxDown[v] > H) continue;\n\n                long long gain = 1LL * (nd - d) * sw;\n                if (gain <= 0) continue;\n\n                int rootMove = (parent[v] == -1) ? 1 : 0;\n                int crossMove = sameComp ? 0 : 1;\n                int delta = nd - d;\n\n                auto key = make_tuple(gain, rootMove, crossMove, delta, sw, -A[u], -v, -u);\n                if (key > bestKey) {\n                    bestKey = key;\n                    bestGain = gain;\n                    bestV = v;\n                    bestU = u;\n                }\n            }\n        }\n\n        if (bestGain <= 0) break;\n        parent[bestV] = bestU;\n    }\n}\n\nstatic vector<int> process_candidate(vector<int> parent) {\n    for (int rep = 0; rep < 3; ++rep) {\n        if (time_up()) break;\n        parent = optimize_roots(parent);\n        improve(parent, 100);\n    }\n    parent = optimize_roots(parent);\n    improve(parent, 30);\n    parent = optimize_roots(parent);\n    return parent;\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 >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    adj.assign(N, {});\n    vector<pair<int, int>> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    vector<int> X(N), Y(N);\n    for (int i = 0; i < N; ++i) cin >> X[i] >> Y[i];\n\n    degv.resize(N);\n    mort.resize(N);\n    neighSum.assign(N, 0);\n    for (int i = 0; i < N; ++i) {\n        degv[i] = (int)adj[i].size();\n        mort[i] = morton_code(X[i], Y[i]);\n        long long s = 0;\n        for (int to : adj[i]) s += A[to];\n        neighSum[i] = (int)s;\n    }\n\n    vector<Key4> key1(N), key2(N), key3(N);\n    for (int i = 0; i < N; ++i) {\n        key1[i] = {A[i], -degv[i], neighSum[i], mort[i]};\n        key2[i] = {A[i], neighSum[i], -degv[i], mort[i]};\n        key3[i] = {A[i], -degv[i], mort[i], i};\n    }\n\n    vector<int> order1(N), order2(N), order3(N);\n    iota(order1.begin(), order1.end(), 0);\n    iota(order2.begin(), order2.end(), 0);\n    iota(order3.begin(), order3.end(), 0);\n    sort(order1.begin(), order1.end(), [&](int x, int y) { return key1[x] < key1[y]; });\n    sort(order2.begin(), order2.end(), [&](int x, int y) { return key2[x] < key2[y]; });\n\n    vector<long long> prio(N);\n    for (int i = 0; i < N; ++i) {\n        prio[i] = 1000000LL * A[i] - 1000LL * degv[i] - 10LL * neighSum[i] + mort[i];\n    }\n    order3 = build_connected_order(prio);\n\n    vector<int> cand1 = build_greedy(order1, key1);\n    vector<int> cand2 = build_greedy(order2, key2);\n    vector<int> cand3 = build_greedy(order3, key3);\n    vector<int> cand4 = build_dfs_forest();\n\n    vector<pair<long long, vector<int>>> cands;\n    cands.reserve(4);\n\n    vector<int> res1 = process_candidate(cand1);\n    cands.push_back({compute_info(res1).score, move(res1)});\n\n    if (!time_up()) {\n        vector<int> res2 = process_candidate(cand2);\n        cands.push_back({compute_info(res2).score, move(res2)});\n    }\n    if (!time_up()) {\n        vector<int> res3 = process_candidate(cand3);\n        cands.push_back({compute_info(res3).score, move(res3)});\n    }\n    if (!time_up()) {\n        vector<int> res4 = process_candidate(cand4);\n        cands.push_back({compute_info(res4).score, move(res4)});\n    }\n\n    auto best = *max_element(cands.begin(), cands.end(),\n                             [](const auto& x, const auto& y) { return x.first < y.first; });\n\n    const vector<int>& ans = best.second;\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << ans[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cand {\n    char dir;   // L/R/U/D\n    int idx;    // row or column index\n    int len;    // number of shifts on one side\n    uint64_t mask; // Oni covered by this strip\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    vector<vector<int>> oniId(N, vector<int>(N, -1));\n    vector<pair<int,int>> oniPos;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'x') {\n                oniId[i][j] = (int)oniPos.size();\n                oniPos.push_back({i, j});\n            }\n        }\n    }\n    int M = (int)oniPos.size(); // should be 40\n\n    vector<int> rowFirstF(N, N), rowLastF(N, -1);\n    vector<int> colFirstF(N, N), colLastF(N, -1);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'o') {\n                rowFirstF[i] = min(rowFirstF[i], j);\n                rowLastF[i] = max(rowLastF[i], j);\n                colFirstF[j] = min(colFirstF[j], i);\n                colLastF[j] = max(colLastF[j], i);\n            }\n        }\n    }\n\n    vector<Cand> cands;\n    auto addCand = [&](char dir, int idx, int len, uint64_t mask) {\n        if (len > 0 && mask) cands.push_back({dir, idx, len, mask});\n    };\n\n    // Row-based strips\n    for (int i = 0; i < N; ++i) {\n        // Left prefixes: lengths 1..first Fukunokami position\n        uint64_t mask = 0;\n        for (int len = 1; len <= rowFirstF[i]; ++len) {\n            int b = oniId[i][len - 1];\n            if (b != -1) {\n                mask |= (1ULL << b);\n                addCand('L', i, len, mask);\n            }\n        }\n        // Right prefixes (suffixes): lengths 1..distance to last Fukunokami from right\n        mask = 0;\n        int rmax = (rowLastF[i] == -1 ? N : N - 1 - rowLastF[i]);\n        for (int len = 1; len <= rmax; ++len) {\n            int col = N - len;\n            int b = oniId[i][col];\n            if (b != -1) {\n                mask |= (1ULL << b);\n                addCand('R', i, len, mask);\n            }\n        }\n    }\n\n    // Column-based strips\n    for (int j = 0; j < N; ++j) {\n        // Upward prefixes\n        uint64_t mask = 0;\n        for (int len = 1; len <= colFirstF[j]; ++len) {\n            int b = oniId[len - 1][j];\n            if (b != -1) {\n                mask |= (1ULL << b);\n                addCand('U', j, len, mask);\n            }\n        }\n        // Downward prefixes (suffixes)\n        mask = 0;\n        int bmax = (colLastF[j] == -1 ? N : N - 1 - colLastF[j]);\n        for (int len = 1; len <= bmax; ++len) {\n            int row = N - len;\n            int b = oniId[row][j];\n            if (b != -1) {\n                mask |= (1ULL << b);\n                addCand('D', j, len, mask);\n            }\n        }\n    }\n\n    // Deduplicate identical coverage masks, keeping the shortest strip.\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.len != b.len) return a.len < b.len;\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.idx < b.idx;\n    });\n    vector<Cand> uniq;\n    for (auto &c : cands) {\n        if (uniq.empty() || uniq.back().mask != c.mask) uniq.push_back(c);\n    }\n    cands.swap(uniq);\n\n    uint64_t fullMask = (M == 64 ? ~0ULL : ((1ULL << M) - 1ULL));\n\n    auto cleanup = [&](vector<int> sel) -> vector<int> {\n        vector<int> cnt(M, 0);\n        for (int id : sel) {\n            uint64_t m = cands[id].mask;\n            while (m) {\n                int b = __builtin_ctzll(m);\n                cnt[b]++;\n                m &= (m - 1);\n            }\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            sort(sel.begin(), sel.end(), [&](int a, int b) {\n                if (cands[a].len != cands[b].len) return cands[a].len > cands[b].len;\n                return a < b;\n            });\n\n            vector<int> nxt;\n            nxt.reserve(sel.size());\n            for (int id : sel) {\n                bool removable = true;\n                uint64_t m = cands[id].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    if (cnt[b] <= 1) {\n                        removable = false;\n                        break;\n                    }\n                    m &= (m - 1);\n                }\n\n                if (removable) {\n                    uint64_t m2 = cands[id].mask;\n                    while (m2) {\n                        int b = __builtin_ctzll(m2);\n                        cnt[b]--;\n                        m2 &= (m2 - 1);\n                    }\n                    changed = true;\n                } else {\n                    nxt.push_back(id);\n                }\n            }\n            sel.swap(nxt);\n        }\n        return sel;\n    };\n\n    auto runGreedyLinear = [&](int K) -> pair<vector<int>, int> {\n        uint64_t uncovered = fullMask;\n        vector<char> used(cands.size(), false);\n        vector<int> sel;\n\n        while (uncovered) {\n            int best = -1;\n            long long bestScore = LLONG_MIN;\n            int bestNew = -1;\n            int bestLen = INT_MAX;\n\n            for (int id = 0; id < (int)cands.size(); ++id) {\n                if (used[id]) continue;\n                uint64_t nm = cands[id].mask & uncovered;\n                if (!nm) continue;\n                int newCnt = __builtin_popcountll(nm);\n                long long score = 1LL * K * newCnt - cands[id].len;\n\n                if (best == -1 ||\n                    score > bestScore ||\n                    (score == bestScore && (newCnt > bestNew ||\n                                            (newCnt == bestNew && cands[id].len < bestLen)))) {\n                    best = id;\n                    bestScore = score;\n                    bestNew = newCnt;\n                    bestLen = cands[id].len;\n                }\n            }\n\n            if (best == -1) break; // should not happen\n            used[best] = true;\n            sel.push_back(best);\n            uncovered &= ~cands[best].mask;\n        }\n\n        sel = cleanup(sel);\n\n        // Safety fallback: if anything remains uncovered, add minimal-length strips for them.\n        uint64_t cover = 0;\n        for (int id : sel) cover |= cands[id].mask;\n        if (cover != fullMask) {\n            uint64_t rem = fullMask & ~cover;\n            while (rem) {\n                int b = __builtin_ctzll(rem);\n                int choose = -1;\n                int chooseLen = INT_MAX;\n                for (int id = 0; id < (int)cands.size(); ++id) {\n                    if ((cands[id].mask >> b) & 1ULL) {\n                        if (cands[id].len < chooseLen) {\n                            choose = id;\n                            chooseLen = cands[id].len;\n                        }\n                    }\n                }\n                if (choose == -1) break; // should not happen\n                sel.push_back(choose);\n                cover |= cands[choose].mask;\n                rem = fullMask & ~cover;\n            }\n            sel = cleanup(sel);\n        }\n\n        int cost = 0;\n        for (int id : sel) cost += 2 * cands[id].len;\n        return {sel, cost};\n    };\n\n    auto runGreedyRatio = [&]() -> pair<vector<int>, int> {\n        uint64_t uncovered = fullMask;\n        vector<char> used(cands.size(), false);\n        vector<int> sel;\n\n        while (uncovered) {\n            int best = -1;\n            int bestNew = -1;\n            int bestLen = INT_MAX;\n\n            for (int id = 0; id < (int)cands.size(); ++id) {\n                if (used[id]) continue;\n                uint64_t nm = cands[id].mask & uncovered;\n                if (!nm) continue;\n                int newCnt = __builtin_popcountll(nm);\n\n                if (best == -1 ||\n                    1LL * newCnt * bestLen > 1LL * bestNew * cands[id].len ||\n                    (1LL * newCnt * bestLen == 1LL * bestNew * cands[id].len &&\n                     (newCnt > bestNew ||\n                      (newCnt == bestNew && cands[id].len < bestLen)))) {\n                    best = id;\n                    bestNew = newCnt;\n                    bestLen = cands[id].len;\n                }\n            }\n\n            if (best == -1) break;\n            used[best] = true;\n            sel.push_back(best);\n            uncovered &= ~cands[best].mask;\n        }\n\n        sel = cleanup(sel);\n\n        uint64_t cover = 0;\n        for (int id : sel) cover |= cands[id].mask;\n        if (cover != fullMask) {\n            uint64_t rem = fullMask & ~cover;\n            while (rem) {\n                int b = __builtin_ctzll(rem);\n                int choose = -1;\n                int chooseLen = INT_MAX;\n                for (int id = 0; id < (int)cands.size(); ++id) {\n                    if ((cands[id].mask >> b) & 1ULL) {\n                        if (cands[id].len < chooseLen) {\n                            choose = id;\n                            chooseLen = cands[id].len;\n                        }\n                    }\n                }\n                if (choose == -1) break;\n                sel.push_back(choose);\n                cover |= cands[choose].mask;\n                rem = fullMask & ~cover;\n            }\n            sel = cleanup(sel);\n        }\n\n        int cost = 0;\n        for (int id : sel) cost += 2 * cands[id].len;\n        return {sel, cost};\n    };\n\n    vector<int> Ks = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 30, 50};\n\n    vector<int> bestSel;\n    int bestCost = INT_MAX;\n\n    for (int K : Ks) {\n        auto [sel, cost] = runGreedyLinear(K);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestSel = sel;\n        }\n    }\n\n    {\n        auto [sel, cost] = runGreedyRatio();\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestSel = sel;\n        }\n    }\n\n    // Output the selected strips.\n    for (int id : bestSel) {\n        const auto &c = cands[id];\n        char d1, d2;\n        if (c.dir == 'L') d1 = 'L', d2 = 'R';\n        else if (c.dir == 'R') d1 = 'R', d2 = 'L';\n        else if (c.dir == 'U') d1 = 'U', d2 = 'D';\n        else d1 = 'D', d2 = 'U';\n\n        for (int t = 0; t < c.len; ++t) {\n            cout << d1 << ' ' << c.idx << '\\n';\n        }\n        for (int t = 0; t < c.len; ++t) {\n            cout << d2 << ' ' << c.idx << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T{};\nint avgT = 0;\nint bestTargetNode = 0;\n\nstruct XorShift64 {\n    uint64_t x;\n    explicit XorShift64(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        return (int)(next() % (uint64_t)mod);\n    }\n};\n\nstruct Plan {\n    array<array<int, 2>, MAXN> to;\n};\n\nstruct Eval {\n    Plan plan;\n    array<int, MAXN> cnt{};\n    array<array<int, 2>, MAXN> use{};\n    long long err = (1LL << 60);\n    int last = 0;\n};\n\nstatic inline long long llabsll(long long x) { return x < 0 ? -x : x; }\n\nvoid finalizePlan(Plan &p) {\n    for (int i = 0; i < N; ++i) {\n        if (p.to[i][0] == -1 && p.to[i][1] == -1) {\n            int d = (T[i] >= avgT ? i : bestTargetNode);\n            p.to[i][0] = p.to[i][1] = d;\n        } else if (p.to[i][0] == -1) {\n            p.to[i][0] = p.to[i][1];\n        } else if (p.to[i][1] == -1) {\n            p.to[i][1] = p.to[i][0];\n        }\n    }\n}\n\nint chooseDest(\n    int src,\n    const array<long long, MAXN> &rem,\n    int exclude,\n    long long selfBias,\n    long long samePenalty,\n    XorShift64 &rng\n) {\n    int best = 0;\n    long long bestSc = -(1LL << 60);\n\n    for (int j = 0; j < N; ++j) {\n        long long sc = 0;\n        sc += rem[j] * 200LL;\n        sc += 3LL * T[j];\n        sc -= 4LL * llabsll((long long)T[src] - (long long)T[j]);\n\n        if (j == src) {\n            long long selfAdj = ((long long)T[src] - (long long)avgT) * selfBias / max(1, avgT);\n            sc += selfAdj;\n        }\n\n        if (j == exclude) sc -= samePenalty;\n\n        sc += (long long)(rng.next() & 31ULL) - 15LL;\n\n        if (sc > bestSc) {\n            bestSc = sc;\n            best = j;\n        }\n    }\n    return best;\n}\n\nEval simulate(const Plan &p) {\n    Eval e;\n    e.plan = p;\n    e.cnt.fill(0);\n    for (int i = 0; i < N; ++i) e.use[i][0] = e.use[i][1] = 0;\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        e.cnt[x]++;\n        if (step == L - 1) {\n            e.last = x;\n            break;\n        }\n        int par = e.cnt[x] & 1; // 1 = odd visit -> a_i, 0 = even visit -> b_i\n        e.use[x][par]++;\n        x = p.to[x][par];\n    }\n\n    e.last = x;\n    long long err = 0;\n    for (int i = 0; i < N; ++i) err += llabsll((long long)e.cnt[i] - (long long)T[i]);\n    e.err = err;\n    return e;\n}\n\nPlan buildOnline(uint64_t seed, long long selfBias, long long samePenalty) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    XorShift64 rng(seed);\n    array<int, MAXN> cnt{};\n    cnt.fill(0);\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        cnt[x]++;\n        if (step == L - 1) break;\n\n        int par = cnt[x] & 1;\n        if (p.to[x][0] == -1 && p.to[x][1] == -1) {\n            array<long long, MAXN> rem{};\n            for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (long long)cnt[i];\n\n            int oddDest = chooseDest(x, rem, -1, selfBias, samePenalty, rng);\n            rem[oddDest] -= 1; // tiny bias for the second choice\n            int evenDest = chooseDest(x, rem, oddDest, selfBias, samePenalty, rng);\n\n            p.to[x][1] = oddDest;\n            p.to[x][0] = evenDest;\n        } else if (p.to[x][par] == -1) {\n            array<long long, MAXN> rem{};\n            for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (long long)cnt[i];\n            int other = p.to[x][1 - par];\n            p.to[x][par] = chooseDest(x, rem, other, selfBias, samePenalty, rng);\n        }\n\n        x = p.to[x][par];\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nPlan buildTransportFromSupply(const array<int, MAXN> &supply, int orderType, uint64_t seed, long long selfBias, long long samePenalty) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    XorShift64 rng(seed);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n\n    auto cmpDescSupply = [&](int a, int b) {\n        if (supply[a] != supply[b]) return supply[a] > supply[b];\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    };\n    auto cmpAscSupply = [&](int a, int b) {\n        if (supply[a] != supply[b]) return supply[a] < supply[b];\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    };\n    auto cmpDescT = [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        if (supply[a] != supply[b]) return supply[a] > supply[b];\n        return a < b;\n    };\n\n    if (orderType == 0) {\n        sort(ord.begin(), ord.end(), cmpDescSupply);\n    } else if (orderType == 1) {\n        sort(ord.begin(), ord.end(), cmpAscSupply);\n    } else {\n        // random order\n        for (int i = N - 1; i > 0; --i) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    array<long long, MAXN> rem{};\n    for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (i == 0 ? 1LL : 0LL);\n\n    for (int idx = 0; idx < N; ++idx) {\n        int i = ord[idx];\n        long long wOdd = (supply[i] + 1LL) / 2LL;\n        long long wEven = supply[i] / 2LL;\n\n        int dOdd = chooseDest(i, rem, -1, selfBias, samePenalty, rng);\n        rem[dOdd] -= wOdd;\n\n        int dEven = chooseDest(i, rem, dOdd, selfBias, samePenalty, rng);\n        rem[dEven] -= wEven;\n\n        p.to[i][1] = dOdd;\n        p.to[i][0] = dEven;\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nPlan buildTemplate(int type) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    });\n\n    int h1 = ord[0];\n    int h2 = ord[1];\n\n    for (int pos = 0; pos < N; ++pos) {\n        int i = ord[pos];\n        int nxt = ord[(pos + 1) % N];\n        int prv = ord[(pos + N - 1) % N];\n        int nxt2 = ord[(pos + 2) % N];\n\n        if (type == 0) {\n            if (T[i] >= avgT) {\n                p.to[i][1] = i;\n                p.to[i][0] = nxt;\n            } else {\n                p.to[i][1] = nxt;\n                p.to[i][0] = i;\n            }\n        } else if (type == 1) {\n            if (pos < 15) {\n                p.to[i][1] = i;\n                p.to[i][0] = i;\n            } else if (pos < 45) {\n                p.to[i][1] = i;\n                p.to[i][0] = nxt;\n            } else if (pos < 75) {\n                p.to[i][1] = nxt;\n                p.to[i][0] = i;\n            } else {\n                p.to[i][1] = nxt;\n                p.to[i][0] = nxt2;\n            }\n        } else if (type == 2) {\n            if (i == h1) {\n                p.to[i][1] = h1;\n                p.to[i][0] = h2;\n            } else if (T[i] >= avgT) {\n                p.to[i][1] = i;\n                p.to[i][0] = h1;\n            } else {\n                p.to[i][1] = h1;\n                p.to[i][0] = i;\n            }\n        } else {\n            p.to[i][1] = nxt;\n            p.to[i][0] = prv;\n        }\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nvoid buildCandidates(vector<Eval> &pool, uint64_t baseSeed) {\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    });\n\n    vector<int> ends;\n    for (int i = 0; i < N && (int)ends.size() < 4; ++i) {\n        if (T[ord[i]] > 0) ends.push_back(ord[i]);\n    }\n    if (T[0] > 0 && find(ends.begin(), ends.end(), 0) == ends.end()) ends.push_back(0);\n\n    int randomPositive = -1;\n    {\n        vector<int> pos;\n        for (int i = 0; i < N; ++i) if (T[i] > 0) pos.push_back(i);\n        if (!pos.empty()) {\n            XorShift64 rng(baseSeed ^ 0x123456789abcdefULL);\n            randomPositive = pos[rng.nextInt((int)pos.size())];\n            if (find(ends.begin(), ends.end(), randomPositive) == ends.end()) ends.push_back(randomPositive);\n        }\n    }\n    if ((int)ends.size() > 5) ends.resize(5);\n\n    long long onlineBiases[4] = {700, 1600, 3000, -800};\n    long long transportBiases[2] = {800, 2000};\n\n    int cid = 0;\n    for (int k = 0; k < 4; ++k) {\n        uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(cid + 1));\n        Plan p = buildOnline(seed, onlineBiases[k], 600);\n        pool.push_back(simulate(p));\n        ++cid;\n    }\n\n    for (int e : ends) {\n        array<int, MAXN> supply{};\n        for (int i = 0; i < N; ++i) supply[i] = T[i];\n        if (supply[e] <= 0) continue;\n        supply[e]--;\n\n        for (int ordType = 0; ordType < 3; ++ordType) {\n            for (int b = 0; b < 2; ++b) {\n                uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(cid + 1)) ^ (uint64_t)(e + 1000 * ordType + 17 * b);\n                Plan p = buildTransportFromSupply(supply, ordType, seed, transportBiases[b], 500);\n                pool.push_back(simulate(p));\n                ++cid;\n            }\n        }\n    }\n\n    for (int tp = 0; tp < 4; ++tp) {\n        Plan p = buildTemplate(tp);\n        pool.push_back(simulate(p));\n    }\n}\n\nEval refineByTransport(Eval cur, uint64_t seed) {\n    for (int iter = 0; iter < 2; ++iter) {\n        array<int, MAXN> supply = cur.cnt;\n        supply[cur.last]--;\n        if (supply[cur.last] < 0) supply[cur.last] = 0;\n\n        Plan p = buildTransportFromSupply(supply, 0, seed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(iter + 1)), 1600, 500);\n        Eval e = simulate(p);\n        if (e.err < cur.err) cur = std::move(e);\n        else break;\n    }\n    return cur;\n}\n\nEval localSearch(Eval cur, uint64_t seed, chrono::steady_clock::time_point start) {\n    XorShift64 rng(seed);\n\n    auto nowSeconds = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    for (int round = 0; round < 2; ++round) {\n        if (nowSeconds() > 1.93) break;\n        if (cur.err == 0) break;\n\n        vector<int> over, under;\n        over.reserve(N);\n        under.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            int d = cur.cnt[i] - T[i];\n            if (d > 0) over.push_back(i);\n            else if (d < 0) under.push_back(i);\n        }\n        if (over.empty() || under.empty()) break;\n\n        sort(over.begin(), over.end(), [&](int a, int b) {\n            return (cur.cnt[a] - T[a]) > (cur.cnt[b] - T[b]);\n        });\n        sort(under.begin(), under.end(), [&](int a, int b) {\n            return (T[a] - cur.cnt[a]) > (T[b] - cur.cnt[b]);\n        });\n\n        vector<int> overTop, underTop;\n        for (int i = 0; i < (int)min<size_t>(4, over.size()); ++i) overTop.push_back(over[i]);\n        for (int i = 0; i < (int)min<size_t>(3, under.size()); ++i) underTop.push_back(under[i]);\n\n        struct Slot {\n            int src, p, dest, use;\n        };\n\n        vector<Slot> slots;\n        for (int o : overTop) {\n            for (int i = 0; i < N; ++i) {\n                for (int p = 0; p < 2; ++p) {\n                    if (cur.plan.to[i][p] == o && cur.use[i][p] > 0) {\n                        slots.push_back({i, p, o, cur.use[i][p]});\n                    }\n                }\n            }\n        }\n\n        sort(slots.begin(), slots.end(), [&](const Slot &a, const Slot &b) {\n            return a.use > b.use;\n        });\n\n        long long bestErr = cur.err;\n        Eval bestCand = cur;\n        bool improved = false;\n\n        auto testPlan = [&](const Plan &pp) {\n            if (nowSeconds() > 1.93) return;\n            Eval e = simulate(pp);\n            if (e.err < bestErr) {\n                bestErr = e.err;\n                bestCand = std::move(e);\n                improved = true;\n            }\n        };\n\n        // 1) Change heavily used slots that currently point to overcounted nodes.\n        int slotLimit = min<int>(12, slots.size());\n        for (int i = 0; i < slotLimit; ++i) {\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[slots[i].src][slots[i].p] == u) continue;\n                Plan np = cur.plan;\n                np.to[slots[i].src][slots[i].p] = u;\n                testPlan(np);\n            }\n        }\n\n        // 2) Change one parity edge of overcounted source nodes.\n        for (int s = 0; s < (int)overTop.size(); ++s) {\n            int src = overTop[s];\n            int p = (cur.use[src][0] >= cur.use[src][1] ? 0 : 1);\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[src][p] == u) continue;\n                Plan np = cur.plan;\n                np.to[src][p] = u;\n                testPlan(np);\n            }\n        }\n\n        // 3) Change both edges of a strongly overcounted source to a better undercounted target.\n        for (int s = 0; s < (int)min<size_t>(3, overTop.size()); ++s) {\n            int src = overTop[s];\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[src][0] == u && cur.plan.to[src][1] == u) continue;\n                Plan np = cur.plan;\n                np.to[src][0] = np.to[src][1] = u;\n                testPlan(np);\n            }\n        }\n\n        if (improved) cur = std::move(bestCand);\n        else break;\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    avgT = L / N;\n    bestTargetNode = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[bestTargetNode]) bestTargetNode = i;\n    }\n\n    uint64_t baseSeed = 1469598103934665603ULL;\n    for (int i = 0; i < N; ++i) {\n        baseSeed ^= (uint64_t)(T[i] + 1);\n        baseSeed *= 1099511628211ULL;\n    }\n\n    auto start = chrono::steady_clock::now();\n\n    vector<Eval> pool;\n    pool.reserve(64);\n\n    buildCandidates(pool, baseSeed);\n\n    if (pool.empty()) {\n        Plan p;\n        for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = bestTargetNode;\n        auto e = simulate(p);\n        pool.push_back(std::move(e));\n    }\n\n    sort(pool.begin(), pool.end(), [&](const Eval &a, const Eval &b) {\n        return a.err < b.err;\n    });\n\n    int topK = min<int>(3, pool.size());\n    Eval best = pool[0];\n\n    for (int i = 0; i < topK; ++i) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > 1.90) break;\n\n        Eval cur = pool[i];\n        cur = refineByTransport(cur, baseSeed ^ (0xabcdef0123456789ULL + (uint64_t)i * 1337ULL));\n        cur = localSearch(cur, baseSeed ^ (0x123456789abcdef0ULL + (uint64_t)i * 10007ULL), start);\n\n        if (cur.err < best.err) best = std::move(cur);\n    }\n\n    // Final safety fill.\n    finalizePlan(best.plan);\n\n    for (int i = 0; i < N; ++i) {\n        cout << best.plan.to[i][1] << ' ' << best.plan.to[i][0] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ull = unsigned long long;\n\nstatic const int MAXN = 800;\nstatic const ll INFLL = (1LL << 62);\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<int> exs, eys;\n\nstatic ll dist2Mat[MAXN][MAXN];\nstatic ull hilbertKey[8][MAXN];\n\nint bestHilbertOrient = 0;\n\nstruct CityCand {\n    vector<int> ord;\n    int kind;   // 0: simple sort, 1: hilbert, 2: mst preorder\n    int param;  // for hilbert: orientation\n};\n\nstruct PrimRes {\n    vector<int> parent;\n    vector<ll> best;\n};\n\null hilbertOrder(int x, int y) {\n    ull d = 0;\n    for (int s = 1 << 14; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += (ull)s * (ull)s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = s * 2 - 1 - x;\n                y = s * 2 - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\nPrimRes primParents(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    PrimRes res;\n    res.parent.assign(k, -1);\n    res.best.assign(k, INFLL);\n    if (k == 0) return res;\n    vector<char> used(k, 0);\n    res.best[0] = 0;\n\n    for (int it = 0; it < k; ++it) {\n        int v = -1;\n        for (int i = 0; i < k; ++i) {\n            if (!used[i] && (v == -1 || res.best[i] < res.best[v])) v = i;\n        }\n        used[v] = 1;\n        int a = nodes[v];\n        for (int to = 0; to < k; ++to) if (!used[to]) {\n            ll w = dist2Mat[a][nodes[to]];\n            if (w < res.best[to]) {\n                res.best[to] = w;\n                res.parent[to] = v;\n            }\n        }\n    }\n    return res;\n}\n\ndouble mstCostVec(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    if (k <= 1) return 0.0;\n    auto res = primParents(nodes);\n    double cost = 0.0;\n    for (int i = 1; i < k; ++i) cost += sqrt((double)res.best[i]);\n    return cost;\n}\n\ndouble mstCostRange(const vector<int>& ord, int l, int r) {\n    int k = r - l;\n    if (k <= 1) return 0.0;\n    vector<ll> best(k, INFLL);\n    vector<char> used(k, 0);\n    best[0] = 0;\n    double cost = 0.0;\n\n    for (int it = 0; it < k; ++it) {\n        int v = -1;\n        for (int i = 0; i < k; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (best[v] != 0) cost += sqrt((double)best[v]);\n\n        int a = ord[l + v];\n        for (int to = 0; to < k; ++to) if (!used[to]) {\n            ll w = dist2Mat[a][ord[l + to]];\n            if (w < best[to]) best[to] = w;\n        }\n    }\n    return cost;\n}\n\nvector<int> buildMSTPreorder(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    if (k <= 2) return nodes;\n\n    auto res = primParents(nodes);\n\n    vector<vector<pair<ll, int>>> adj(k);\n    for (int i = 1; i < k; ++i) {\n        int p = res.parent[i];\n        ll w = res.best[i];\n        adj[i].push_back({w, p});\n        adj[p].push_back({w, i});\n    }\n\n    int root = 0;\n    ll bestSum = INFLL;\n    for (int i = 0; i < k; ++i) {\n        ll sum = 0;\n        int a = nodes[i];\n        for (int j = 0; j < k; ++j) if (i != j) sum += dist2Mat[a][nodes[j]];\n        if (sum < bestSum || (sum == bestSum && nodes[i] < nodes[root])) {\n            bestSum = sum;\n            root = i;\n        }\n    }\n\n    for (int i = 0; i < k; ++i) {\n        sort(adj[i].begin(), adj[i].end(), [&](const auto& A, const auto& B) {\n            if (A.first != B.first) return A.first < B.first;\n            return A.second < B.second;\n        });\n    }\n\n    vector<int> order;\n    order.reserve(k);\n    vector<int> par(k, -1);\n    stack<int> st;\n    st.push(root);\n    par[root] = root;\n\n    while (!st.empty()) {\n        int v = st.top();\n        st.pop();\n        order.push_back(nodes[v]);\n        for (int i = (int)adj[v].size() - 1; i >= 0; --i) {\n            int to = adj[v][i].second;\n            if (to == par[v]) continue;\n            par[to] = v;\n            st.push(to);\n        }\n    }\n    return order;\n}\n\nvector<vector<int>> splitChunks(const vector<int>& ord) {\n    vector<vector<int>> chunks;\n    int n = (int)ord.size();\n    if (n == 1) {\n        chunks.push_back(ord);\n        return chunks;\n    }\n    int p = 0;\n    while (p < n) {\n        int rem = n - p;\n        int take;\n        if (rem <= L) {\n            take = rem;\n        } else {\n            take = L;\n            if (rem - take == 1) --take;\n        }\n        chunks.emplace_back(ord.begin() + p, ord.begin() + p + take);\n        p += take;\n    }\n    return chunks;\n}\n\ndouble estimateTreeCostFromOrder(const vector<int>& ord) {\n    auto chunks = splitChunks(ord);\n    double cost = 0.0;\n\n    for (auto& ch : chunks) cost += mstCostVec(ch);\n    if (chunks.size() <= 1) return cost;\n\n    int c = (int)chunks.size();\n    vector<vector<ll>> w(c, vector<ll>(c, INFLL));\n\n    for (int i = 0; i < c; ++i) {\n        for (int j = i + 1; j < c; ++j) {\n            ll best = INFLL;\n            for (int a : chunks[i]) {\n                for (int b : chunks[j]) {\n                    ll d = dist2Mat[a][b];\n                    if (d < best) best = d;\n                }\n            }\n            w[i][j] = w[j][i] = best;\n        }\n    }\n\n    vector<ll> best(c, INFLL);\n    vector<int> par(c, -1);\n    vector<char> used(c, 0);\n    best[0] = 0;\n\n    for (int it = 0; it < c; ++it) {\n        int v = -1;\n        for (int i = 0; i < c; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (par[v] != -1) cost += sqrt((double)best[v]);\n        for (int to = 0; to < c; ++to) if (!used[to]) {\n            if (w[v][to] < best[to]) {\n                best[to] = w[v][to];\n                par[to] = v;\n            }\n        }\n    }\n    return cost;\n}\n\nvector<pair<int,int>> query_tree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    cout << \"? \" << k;\n    for (int v : nodes) cout << ' ' << v;\n    cout << '\\n' << flush;\n\n    vector<pair<int,int>> edges;\n    edges.reserve(k - 1);\n    for (int i = 0; i < k - 1; ++i) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nvector<pair<int,int>> prim_tree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    vector<pair<int,int>> edges;\n    if (k <= 1) return edges;\n    auto res = primParents(nodes);\n    edges.reserve(k - 1);\n    for (int i = 1; i < k; ++i) {\n        int a = nodes[i];\n        int b = nodes[res.parent[i]];\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nvector<pair<int,int>> buildChunkMSTEdges(const vector<vector<int>>& chunks) {\n    vector<pair<int,int>> edges;\n    int c = (int)chunks.size();\n    if (c <= 1) return edges;\n\n    vector<vector<ll>> w(c, vector<ll>(c, INFLL));\n    vector<vector<pair<int,int>>> bp(c, vector<pair<int,int>>(c, {INT_MAX, INT_MAX}));\n\n    for (int i = 0; i < c; ++i) {\n        for (int j = i + 1; j < c; ++j) {\n            ll best = INFLL;\n            pair<int,int> bestP = {INT_MAX, INT_MAX};\n            for (int a : chunks[i]) {\n                for (int b : chunks[j]) {\n                    ll d = dist2Mat[a][b];\n                    pair<int,int> p = (a < b ? make_pair(a, b) : make_pair(b, a));\n                    if (d < best || (d == best && p < bestP)) {\n                        best = d;\n                        bestP = p;\n                    }\n                }\n            }\n            w[i][j] = w[j][i] = best;\n            bp[i][j] = bp[j][i] = bestP;\n        }\n    }\n\n    vector<ll> best(c, INFLL);\n    vector<int> par(c, -1);\n    vector<char> used(c, 0);\n    best[0] = 0;\n\n    for (int it = 0; it < c; ++it) {\n        int v = -1;\n        for (int i = 0; i < c; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (par[v] != -1) edges.push_back(bp[v][par[v]]);\n        for (int to = 0; to < c; ++to) if (!used[to]) {\n            if (w[v][to] < best[to]) {\n                best[to] = w[v][to];\n                par[to] = v;\n            }\n        }\n    }\n    return edges;\n}\n\nvector<pair<int,int>> buildGroupEdges(const vector<int>& order) {\n    vector<pair<int,int>> edges;\n    auto chunks = splitChunks(order);\n\n    // internal chunk trees\n    for (auto& ch : chunks) {\n        int s = (int)ch.size();\n        if (s <= 1) continue;\n        if (s == 2) {\n            int a = ch[0], b = ch[1];\n            if (a > b) swap(a, b);\n            edges.push_back({a, b});\n        } else {\n            if (Q > 0) {\n                if ((int)edges.size() < (int)order.size() - 1 && true) {\n                    if (true) {\n                        if (true) {\n                            if (true) {\n                                if (true) {\n                                    if (true) {\n                                        if (true) {\n                                            if (true) {\n                                                if (true) {\n                                                    if (true) {\n                                                        if (true) {\n                                                            if (true) {\n                                                                if (true) {\n                                                                    if (true) {\n                                                                        if (true) {\n                                                                            if (true) {\n                                                                                // no-op, keeps structure simple for compilers\n                                                                            }\n                                                                        }\n                                                                    }\n                                                                }\n                                                            }\n                                                        }\n                                                    }\n                                                }\n                                            }\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            if (Q > 0 && (int)ch.size() >= 3 && (int)ch.size() <= L && (int)edges.size() < 1000000) {\n                // query if available\n                if (true) {\n                    // handled by calling context via global query counter\n                }\n            }\n        }\n    }\n\n    // Build internal chunk trees in a second pass with queries when possible.\n    edges.clear();\n    for (auto& ch : chunks) {\n        int s = (int)ch.size();\n        if (s <= 1) continue;\n        if (s == 2) {\n            int a = ch[0], b = ch[1];\n            if (a > b) swap(a, b);\n            edges.push_back({a, b});\n        } else {\n            if (s >= 3 && s <= L && Q > 0) {\n                // query exact MST on this chunk\n                vector<pair<int,int>> got = query_tree(ch);\n                edges.insert(edges.end(), got.begin(), got.end());\n            } else {\n                vector<pair<int,int>> got = prim_tree(ch);\n                edges.insert(edges.end(), got.begin(), got.end());\n            }\n        }\n    }\n\n    if (chunks.size() > 1) {\n        auto cross = buildChunkMSTEdges(chunks);\n        edges.insert(edges.end(), cross.begin(), cross.end());\n    }\n\n    return edges;\n}\n\nint queries_used = 0;\n\n// Build a global approximate MST preorder on all cities.\nvector<int> buildGlobalMSTOrder() {\n    vector<int> nodes(N);\n    iota(nodes.begin(), nodes.end(), 0);\n    return buildMSTPreorder(nodes);\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    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    exs.resize(N);\n    eys.resize(N);\n    for (int i = 0; i < N; ++i) {\n        exs[i] = lx[i] + rx[i];\n        eys[i] = ly[i] + ry[i];\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = i; j < N; ++j) {\n            ll dx = (ll)exs[i] - exs[j];\n            ll dy = (ll)eys[i] - eys[j];\n            ll d = dx * dx + dy * dy;\n            dist2Mat[i][j] = dist2Mat[j][i] = d;\n        }\n    }\n\n    // Hilbert keys for 8 symmetries\n    for (int o = 0; o < 8; ++o) {\n        for (int i = 0; i < N; ++i) {\n            int x = exs[i];\n            int y = eys[i];\n            if (o & 1) x = 20000 - x;\n            if (o & 2) y = 20000 - y;\n            if (o & 4) swap(x, y);\n            hilbertKey[o][i] = hilbertOrder(x, y);\n        }\n    }\n\n    // candidate city orders\n    vector<CityCand> cityCands;\n\n    auto addSimpleOrder = [&](vector<int> ord, int param) {\n        cityCands.push_back({move(ord), 0, param});\n    };\n\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            if (eys[a] != eys[b]) return eys[a] < eys[b];\n            return a < b;\n        });\n        addSimpleOrder(ord, 0);\n        vector<int> rev = ord;\n        reverse(rev.begin(), rev.end());\n        addSimpleOrder(rev, 1);\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 (eys[a] != eys[b]) return eys[a] < eys[b];\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            return a < b;\n        });\n        addSimpleOrder(ord, 2);\n        vector<int> rev = ord;\n        reverse(rev.begin(), rev.end());\n        addSimpleOrder(rev, 3);\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            ll ka = (ll)exs[a] + eys[a];\n            ll kb = (ll)exs[b] + eys[b];\n            if (ka != kb) return ka < kb;\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            return a < b;\n        });\n        addSimpleOrder(ord, 4);\n        vector<int> rev = ord;\n        reverse(rev.begin(), rev.end());\n        addSimpleOrder(rev, 5);\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            ll ka = (ll)exs[a] - eys[a];\n            ll kb = (ll)exs[b] - eys[b];\n            if (ka != kb) return ka < kb;\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            return a < b;\n        });\n        addSimpleOrder(ord, 6);\n        vector<int> rev = ord;\n        reverse(rev.begin(), rev.end());\n        addSimpleOrder(rev, 7);\n    }\n\n    for (int o = 0; o < 8; ++o) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (hilbertKey[o][a] != hilbertKey[o][b]) return hilbertKey[o][a] < hilbertKey[o][b];\n            return a < b;\n        });\n        cityCands.push_back({move(ord), 1, o});\n    }\n\n    {\n        vector<int> globalMST = buildGlobalMSTOrder();\n        cityCands.push_back({globalMST, 2, 0});\n        vector<int> rev = globalMST;\n        reverse(rev.begin(), rev.end());\n        cityCands.push_back({move(rev), 2, 1});\n    }\n\n    // candidate group orders\n    vector<int> ordOrig(M);\n    iota(ordOrig.begin(), ordOrig.end(), 0);\n\n    vector<int> ordRev = ordOrig;\n    reverse(ordRev.begin(), ordRev.end());\n\n    vector<int> ordAsc = ordOrig;\n    sort(ordAsc.begin(), ordAsc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n\n    vector<int> ordDesc = ordOrig;\n    sort(ordDesc.begin(), ordDesc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n\n    vector<int> ordAlt;\n    {\n        int l = 0, r = M - 1;\n        while (l <= r) {\n            ordAlt.push_back(ordDesc[l]);\n            if (l != r) ordAlt.push_back(ordDesc[r]);\n            ++l;\n            --r;\n        }\n    }\n\n    vector<vector<int>> groupOrders = {ordOrig, ordRev, ordAsc, ordDesc, ordAlt};\n\n    // Choose the best global city order and the best Hilbert orientation.\n    double bestScore = 1e100;\n    int bestCityIdx = 0;\n    int bestGroupIdx = 0;\n    double bestHilbertScore = 1e100;\n    int bestHilbertIdx = 0;\n\n    for (int ci = 0; ci < (int)cityCands.size(); ++ci) {\n        for (int gi = 0; gi < (int)groupOrders.size(); ++gi) {\n            double score = 0.0;\n            int p = 0;\n            for (int gidx : groupOrders[gi]) {\n                score += mstCostRange(cityCands[ci].ord, p, p + G[gidx]);\n                p += G[gidx];\n            }\n            if (cityCands[ci].kind == 1 && score < bestHilbertScore) {\n                bestHilbertScore = score;\n                bestHilbertIdx = cityCands[ci].param;\n            }\n            if (score < bestScore) {\n                bestScore = score;\n                bestCityIdx = ci;\n                bestGroupIdx = gi;\n            }\n        }\n    }\n\n    bestHilbertOrient = bestHilbertIdx;\n\n    const vector<int>& bestCityOrder = cityCands[bestCityIdx].ord;\n    const vector<int>& bestGroupOrder = groupOrders[bestGroupIdx];\n\n    // Assign cities to groups.\n    vector<vector<int>> assigned(M);\n    int p = 0;\n    for (int gi : bestGroupOrder) {\n        assigned[gi].assign(bestCityOrder.begin() + p, bestCityOrder.begin() + p + G[gi]);\n        p += G[gi];\n    }\n\n    // For each group, choose a local order if beneficial and estimate cost.\n    struct GroupPlan {\n        int idx;\n        vector<int> ord;\n        double est;\n    };\n    vector<GroupPlan> plans;\n    plans.reserve(M);\n\n    for (int i = 0; i < M; ++i) {\n        vector<int> raw = assigned[i];\n        double est = 0.0;\n        vector<int> bestOrd = raw;\n\n        if ((int)raw.size() <= L) {\n            est = mstCostVec(raw);\n        } else {\n            vector<vector<int>> cands;\n            cands.push_back(raw);\n\n            vector<int> rev = raw;\n            reverse(rev.begin(), rev.end());\n            cands.push_back(rev);\n\n            vector<int> hilb = raw;\n            sort(hilb.begin(), hilb.end(), [&](int a, int b) {\n                if (hilbertKey[bestHilbertOrient][a] != hilbertKey[bestHilbertOrient][b]) {\n                    return hilbertKey[bestHilbertOrient][a] < hilbertKey[bestHilbertOrient][b];\n                }\n                return a < b;\n            });\n            cands.push_back(hilb);\n            vector<int> hilbRev = hilb;\n            reverse(hilbRev.begin(), hilbRev.end());\n            cands.push_back(hilbRev);\n\n            vector<int> mstOrd = buildMSTPreorder(raw);\n            cands.push_back(mstOrd);\n            vector<int> mstRev = mstOrd;\n            reverse(mstRev.begin(), mstRev.end());\n            cands.push_back(mstRev);\n\n            est = 1e100;\n            for (auto& cand : cands) {\n                double val = estimateTreeCostFromOrder(cand);\n                if (val < est) {\n                    est = val;\n                    bestOrd = cand;\n                }\n            }\n        }\n\n        plans.push_back({i, move(bestOrd), est});\n    }\n\n    // Build larger groups first.\n    sort(plans.begin(), plans.end(), [&](const GroupPlan& a, const GroupPlan& b) {\n        if (fabs(a.est - b.est) > 1e-12) return a.est > b.est;\n        return a.idx < b.idx;\n    });\n\n    vector<vector<int>> finalCities(M);\n    vector<vector<pair<int,int>>> finalEdges(M);\n\n    for (auto& plan : plans) {\n        int idx = plan.idx;\n        finalCities[idx] = plan.ord;\n\n        vector<pair<int,int>> edges;\n        if ((int)plan.ord.size() == 1) {\n            edges.clear();\n        } else {\n            auto chunks = splitChunks(plan.ord);\n            // internal trees\n            for (auto& ch : chunks) {\n                int s = (int)ch.size();\n                if (s <= 1) continue;\n                if (s == 2) {\n                    int a = ch[0], b = ch[1];\n                    if (a > b) swap(a, b);\n                    edges.push_back({a, b});\n                } else {\n                    if (queries_used < Q) {\n                        auto got = query_tree(ch);\n                        ++queries_used;\n                        edges.insert(edges.end(), got.begin(), got.end());\n                    } else {\n                        auto got = prim_tree(ch);\n                        edges.insert(edges.end(), got.begin(), got.end());\n                    }\n                }\n            }\n            if (chunks.size() > 1) {\n                auto cross = buildChunkMSTEdges(chunks);\n                edges.insert(edges.end(), cross.begin(), cross.end());\n            }\n        }\n\n        // Safety fallback\n        if ((int)edges.size() != G[idx] - 1) {\n            edges = prim_tree(finalCities[idx]);\n        }\n\n        finalEdges[idx] = move(edges);\n    }\n\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < (int)finalCities[i].size(); ++j) {\n            if (j) cout << ' ';\n            cout << finalCities[i][j];\n        }\n        cout << '\\n';\n        for (auto [a, b] : finalEdges[i]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 20;\nstatic constexpr int MAXV = MAXN * MAXN;\nstatic constexpr double UTIL_WEIGHT = 0.7;\n\nstruct BFSState {\n    array<int, MAXV> dist;\n    array<int, MAXV> pre;\n    array<char, MAXV> pact;\n    array<char, MAXV> pdir;\n};\n\nstruct Board {\n    int N;\n    array<array<int, MAXN>, MAXN> b{};\n};\n\nint N, M;\nvector<pair<int,int>> pts;\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\ninline bool inside(int r, int c) {\n    return 0 <= r && r < N && 0 <= c && c < N;\n}\n\nint slide_dest(const Board& bd, int r, int c, int d) {\n    while (true) {\n        int nr = r + dr[d], nc = c + dc[d];\n        if (!inside(nr, nc) || bd.b[nr][nc]) break;\n        r = nr;\n        c = nc;\n    }\n    return r * N + c;\n}\n\nBFSState bfs_all(const Board& bd, int s) {\n    BFSState st;\n    st.dist.fill(-1);\n    st.pre.fill(-1);\n    st.pact.fill(0);\n    st.pdir.fill(0);\n\n    queue<int> q;\n    st.dist[s] = 0;\n    st.pre[s] = -2;\n    q.push(s);\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        int r = u / N, c = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move\n            {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (inside(nr, nc) && !bd.b[nr][nc]) {\n                    int v = nr * N + nc;\n                    if (st.dist[v] == -1) {\n                        st.dist[v] = st.dist[u] + 1;\n                        st.pre[v] = u;\n                        st.pact[v] = 'M';\n                        st.pdir[v] = dch[d];\n                        q.push(v);\n                    }\n                }\n            }\n            // Slide\n            {\n                int v = slide_dest(bd, r, c, d);\n                if (v != u && st.dist[v] == -1) {\n                    st.dist[v] = st.dist[u] + 1;\n                    st.pre[v] = u;\n                    st.pact[v] = 'S';\n                    st.pdir[v] = dch[d];\n                    q.push(v);\n                }\n            }\n        }\n    }\n    return st;\n}\n\nvector<pair<char,char>> reconstruct_path(const BFSState& st, int s, int t) {\n    vector<pair<char,char>> path;\n    if (st.dist[t] == -1) return path;\n    for (int v = t; v != s; v = st.pre[v]) {\n        path.push_back({st.pact[v], st.pdir[v]});\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct Candidate {\n    double score = 1e100;\n    int pathLen = INT_MAX;\n    int cost = INT_MAX;\n    double util = -1e100;\n    vector<pair<int,int>> blocks;\n    vector<pair<char,char>> path;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    pts.resize(M);\n    for (int i = 0; i < M; ++i) cin >> pts[i].first >> pts[i].second;\n\n    Board bd;\n    bd.N = N;\n\n    int cur = pts[0].first * N + pts[0].second;\n\n    for (int k = 0; k < M - 1; ++k) {\n        int r = pts[k].first, c = pts[k].second;\n        int nxt = pts[k + 1].first * N + pts[k + 1].second;\n\n        // Compute lookahead utility for each possible new wall direction.\n        // Future targets are k+2 ... M-1.\n        double sideUtil[4] = {0, 0, 0, 0};\n\n        for (int j = k + 2; j < M; ++j) {\n            int tr = pts[j].first, tc = pts[j].second;\n            if (tr == r) {\n                if (tc < c) {\n                    // Right wall helps future targets on the left.\n                    sideUtil[3] += 1.0 + (N - 1 - c) / 10.0;\n                } else if (tc > c) {\n                    // Left wall helps future targets on the right.\n                    sideUtil[2] += 1.0 + c / 10.0;\n                }\n            }\n            if (tc == c) {\n                if (tr < r) {\n                    // Down wall helps future targets above.\n                    sideUtil[1] += 1.0 + (N - 1 - r) / 10.0;\n                } else if (tr > r) {\n                    // Up wall helps future targets below.\n                    sideUtil[0] += 1.0 + r / 10.0;\n                }\n            }\n        }\n\n        vector<int> candDirs;\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && bd.b[nr][nc] == 0) candDirs.push_back(d);\n        }\n\n        Candidate best;\n\n        int m = (int)candDirs.size();\n        for (int mask = 0; mask < (1 << m); ++mask) {\n            Board temp = bd;\n            vector<pair<int,int>> addBlocks;\n            addBlocks.reserve(4);\n\n            int cost = 0;\n            double util = 0.0;\n            bool ok = true;\n\n            for (int i = 0; i < m; ++i) {\n                if ((mask >> i) & 1) {\n                    int d = candDirs[i];\n                    int nr = r + dr[d], nc = c + dc[d];\n                    temp.b[nr][nc] = 1;\n                    addBlocks.push_back({nr, nc});\n                    ++cost;\n                    util += sideUtil[d];\n                }\n            }\n\n            // Exact reachability check on the modified board.\n            BFSState st = bfs_all(temp, cur);\n            if (st.dist[nxt] == -1) continue;\n\n            bool reachableAll = true;\n            for (int j = k + 1; j < M; ++j) {\n                int id = pts[j].first * N + pts[j].second;\n                if (st.dist[id] == -1) {\n                    reachableAll = false;\n                    break;\n                }\n            }\n            if (!reachableAll) continue;\n\n            vector<pair<char,char>> path = reconstruct_path(st, cur, nxt);\n            if (path.empty() && cur != nxt) continue;\n\n            int L = (int)path.size();\n            double score = (double)L + cost - UTIL_WEIGHT * util;\n\n            if (score + 1e-12 < best.score ||\n                (abs(score - best.score) <= 1e-12 &&\n                 (L < best.pathLen ||\n                  (L == best.pathLen && cost < best.cost)))) {\n                best.score = score;\n                best.pathLen = L;\n                best.cost = cost;\n                best.util = util;\n                best.blocks = std::move(addBlocks);\n                best.path = std::move(path);\n            }\n        }\n\n        if (best.blocks.empty() && best.path.empty()) {\n            // Extremely safe fallback: no new blocks, recompute on current board.\n            BFSState st = bfs_all(bd, cur);\n            best.path = reconstruct_path(st, cur, nxt);\n            best.blocks.clear();\n        }\n\n        // Apply chosen blocks.\n        for (auto [br, bc] : best.blocks) {\n            bd.b[br][bc] = 1;\n            cout << 'A' << ' ' << dch[(br == r - 1 ? 0 : br == r + 1 ? 1 : bc == c - 1 ? 2 : 3)] << '\\n';\n        }\n\n        // Emit the movement path.\n        for (auto [a, d] : best.path) {\n            cout << a << ' ' << d << '\\n';\n        }\n\n        cur = nxt;\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstruct Cand {\n    long long diff;     // |areaL * T - A * TL|\n    long long denom;    // TL * TR\n    long long balance;  // shape tie-break: smaller is better\n    long double val;    // diff / denom, used for random pool threshold\n    int orient;         // 0: vertical, 1: horizontal\n    int cut;            // selected cut coordinate\n    int lo, hi;         // allowed cut interval\n};\n\nstatic const int B = 10000;\n\nint n;\nvector<int> xs, ys;\nvector<long long> rs;\n\nstatic inline long long absl(long long x) { return x < 0 ? -x : x; }\n\nbool candLess(const Cand& a, const Cand& b) {\n    __int128 lhs = (__int128)a.diff * b.denom;\n    __int128 rhs = (__int128)b.diff * a.denom;\n    if (lhs != rhs) return lhs < rhs;\n    if (a.balance != b.balance) return a.balance < b.balance;\n    int spanA = a.hi - a.lo, spanB = b.hi - b.lo;\n    if (spanA != spanB) return spanA > spanB; // more flexibility\n    if (a.orient != b.orient) return a.orient < b.orient;\n    return a.cut < b.cut;\n}\n\nvoid addCandidates(\n    const vector<int>& ids,\n    int lx, int ly, int rx, int ry,\n    int orient,\n    vector<Cand>& cands\n) {\n    int m = (int)ids.size();\n    if (m <= 1) return;\n\n    long long T = 0;\n    for (int id : ids) T += rs[id];\n    if (T <= 0) return;\n\n    long long A = 1LL * (rx - lx) * (ry - ly);\n\n    if (orient == 0) {\n        int W = rx - lx;\n        int H = ry - ly;\n        if (W < 2) return;\n\n        vector<int> ord = ids;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            return a < b;\n        });\n\n        long long pref = 0;\n        for (int i = 0; i + 1 < m; ++i) {\n            pref += rs[ord[i]];\n            if (xs[ord[i]] == xs[ord[i + 1]]) continue;\n\n            int lo = max(lx + 1, xs[ord[i]] + 1);\n            int hi = min(rx - 1, xs[ord[i + 1]]);\n            if (lo > hi) continue;\n\n            long long num = A * pref;\n            long long den = 1LL * H * T;\n            long long w = num / den;\n            if ((num % den) * 2 >= den) ++w;\n\n            long long cutll = lx + w;\n            cutll = max<long long>(lo, min<long long>(hi, cutll));\n            int cut = (int)cutll;\n\n            long long areaL = 1LL * (cut - lx) * H;\n            long long diff = absl(areaL * T - A * pref);\n            long long TL = pref, TR = T - pref;\n            long long denom = TL * TR;\n            if (denom <= 0) continue;\n\n            long long balance = absl(2LL * (cut - lx) - W);\n            long double val = (long double)diff / (long double)denom;\n            cands.push_back({diff, denom, balance, val, orient, cut, lo, hi});\n        }\n    } else {\n        int W = rx - lx;\n        int H = ry - ly;\n        if (H < 2) return;\n\n        vector<int> ord = ids;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (ys[a] != ys[b]) return ys[a] < ys[b];\n            if (xs[a] != xs[b]) return xs[a] < xs[b];\n            return a < b;\n        });\n\n        long long pref = 0;\n        for (int i = 0; i + 1 < m; ++i) {\n            pref += rs[ord[i]];\n            if (ys[ord[i]] == ys[ord[i + 1]]) continue;\n\n            int lo = max(ly + 1, ys[ord[i]] + 1);\n            int hi = min(ry - 1, ys[ord[i + 1]]);\n            if (lo > hi) continue;\n\n            long long num = A * pref;\n            long long den = 1LL * W * T;\n            long long h = num / den;\n            if ((num % den) * 2 >= den) ++h;\n\n            long long cutll = ly + h;\n            cutll = max<long long>(lo, min<long long>(hi, cutll));\n            int cut = (int)cutll;\n\n            long long areaL = 1LL * W * (cut - ly);\n            long long diff = absl(areaL * T - A * pref);\n            long long TL = pref, TR = T - pref;\n            long long denom = TL * TR;\n            if (denom <= 0) continue;\n\n            long long balance = absl(2LL * (cut - ly) - H);\n            long double val = (long double)diff / (long double)denom;\n            cands.push_back({diff, denom, balance, val, orient, cut, lo, hi});\n        }\n    }\n}\n\nCand chooseCandidate(\n    vector<Cand>& cands,\n    bool randomize,\n    mt19937_64& rng,\n    long double slack_ratio,\n    int best_prob\n) {\n    sort(cands.begin(), cands.end(), candLess);\n    Cand best = cands[0];\n\n    if (!randomize || cands.size() == 1) return best;\n\n    long double lim = best.val * (1.0L + slack_ratio) + 1e-18L;\n    vector<int> pool;\n    for (int i = 0; i < (int)cands.size(); ++i) {\n        if (cands[i].val <= lim) pool.push_back(i);\n        else break;\n    }\n\n    if ((int)pool.size() <= 1) return best;\n\n    // Usually keep the best; sometimes explore a nearby candidate.\n    if ((int)(rng() % 1000) < best_prob) return best;\n\n    int take = min<int>(5, (int)pool.size());\n    if (take <= 1) return best;\n\n    int idx = pool[1 + (int)(rng() % (take - 1))];\n    return cands[idx];\n}\n\nvoid build(\n    int lx, int ly, int rx, int ry,\n    const vector<int>& ids,\n    vector<Rect>& ans,\n    bool randomize,\n    mt19937_64& rng,\n    long double slack_ratio,\n    int best_prob,\n    int perturb_max\n) {\n    if (ids.size() == 1) {\n        ans[ids[0]] = {lx, ly, rx, ry};\n        return;\n    }\n\n    vector<Cand> cands;\n    cands.reserve(ids.size() * 2);\n\n    addCandidates(ids, lx, ly, rx, ry, 0, cands);\n    addCandidates(ids, lx, ly, rx, ry, 1, cands);\n\n    if (cands.empty()) {\n        // Robust fallback: split by the longer side using a simple median boundary.\n        // This should almost never be needed.\n        if (rx - lx >= ry - ly && rx - lx >= 2) {\n            vector<int> ord = ids;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                return a < b;\n            });\n            int m = (int)ord.size();\n            int mid = m / 2 - 1;\n            if (mid < 0) mid = 0;\n            while (mid + 1 < m && xs[ord[mid]] == xs[ord[mid + 1]]) ++mid;\n            if (mid + 1 >= m) mid = m / 2 - 1;\n            int cut = xs[ord[mid]] + 1;\n            cut = max(lx + 1, min(rx - 1, cut));\n\n            vector<int> left, right;\n            left.reserve(ids.size());\n            right.reserve(ids.size());\n            for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n            if (left.empty() || right.empty()) {\n                cut = lx + 1;\n                left.clear(); right.clear();\n                for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n            }\n            build(lx, ly, cut, ry, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            build(cut, ly, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            return;\n        } else {\n            vector<int> ord = ids;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                return a < b;\n            });\n            int m = (int)ord.size();\n            int mid = m / 2 - 1;\n            if (mid < 0) mid = 0;\n            while (mid + 1 < m && ys[ord[mid]] == ys[ord[mid + 1]]) ++mid;\n            if (mid + 1 >= m) mid = m / 2 - 1;\n            int cut = ys[ord[mid]] + 1;\n            cut = max(ly + 1, min(ry - 1, cut));\n\n            vector<int> left, right;\n            left.reserve(ids.size());\n            right.reserve(ids.size());\n            for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n            if (left.empty() || right.empty()) {\n                cut = ly + 1;\n                left.clear(); right.clear();\n                for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n            }\n            build(lx, ly, rx, cut, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            build(lx, cut, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n            return;\n        }\n    }\n\n    Cand ch = chooseCandidate(cands, randomize, rng, slack_ratio, best_prob);\n    int cut = ch.cut;\n\n    if (randomize && perturb_max > 0 && ch.lo < ch.hi) {\n        int span = min(perturb_max, max(1, (ch.hi - ch.lo) / 4));\n        if (span > 0) {\n            int off = (int)(rng() % (2ULL * span + 1ULL)) - span;\n            cut = max(ch.lo, min(ch.hi, cut + off));\n        }\n    }\n\n    vector<int> left, right;\n    left.reserve(ids.size());\n    right.reserve(ids.size());\n\n    if (ch.orient == 0) {\n        for (int id : ids) (xs[id] < cut ? left : right).push_back(id);\n        if (left.empty() || right.empty()) {\n            // Extremely defensive fallback.\n            int med = lx + (rx - lx) / 2;\n            left.clear(); right.clear();\n            for (int id : ids) (xs[id] < med ? left : right).push_back(id);\n            cut = med;\n        }\n        build(lx, ly, cut, ry, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n        build(cut, ly, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n    } else {\n        for (int id : ids) (ys[id] < cut ? left : right).push_back(id);\n        if (left.empty() || right.empty()) {\n            int med = ly + (ry - ly) / 2;\n            left.clear(); right.clear();\n            for (int id : ids) (ys[id] < med ? left : right).push_back(id);\n            cut = med;\n        }\n        build(lx, ly, rx, cut, left, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n        build(lx, cut, rx, ry, right, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n    }\n}\n\nlong double evaluate(const vector<Rect>& ans) {\n    long double sum = 0.0L;\n    for (int i = 0; i < n; ++i) {\n        long long s = 1LL * (ans[i].x2 - ans[i].x1) * (ans[i].y2 - ans[i].y1);\n        long long r = rs[i];\n        long long mn = min(s, r), mx = max(s, r);\n        long double t = (long double)mn / (long double)mx;\n        long double p = 1.0L - (1.0L - t) * (1.0L - t);\n        sum += p;\n    }\n    return sum / n;\n}\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_ans(n);\n    long double best_score = -1.0L;\n\n    auto start = chrono::steady_clock::now();\n    uint64_t base_seed = chrono::steady_clock::now().time_since_epoch().count();\n\n    const int MAX_ATTEMPTS = 200;\n\n    for (int attempt = 0; attempt < MAX_ATTEMPTS; ++attempt) {\n        if (attempt > 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > 4.7) break;\n        }\n\n        bool randomize = (attempt != 0);\n        long double slack_ratio = 0.0L;\n        int best_prob = 1000;   // probability (permille) of keeping the best candidate\n        int perturb_max = 0;\n\n        if (randomize) {\n            if (attempt < 10) {\n                slack_ratio = 0.02L;\n                best_prob = 950;\n                perturb_max = 3;\n            } else if (attempt < 30) {\n                slack_ratio = 0.05L;\n                best_prob = 850;\n                perturb_max = 10;\n            } else {\n                slack_ratio = 0.15L;\n                best_prob = 700;\n                perturb_max = 30;\n            }\n        }\n\n        vector<Rect> ans(n);\n        vector<int> ids(n);\n        iota(ids.begin(), ids.end(), 0);\n\n        mt19937_64 rng(base_seed + 1000003ULL * (uint64_t)attempt + 1234567ULL);\n\n        build(0, 0, B, B, ids, ans, randomize, rng, slack_ratio, best_prob, perturb_max);\n\n        long double score = evaluate(ans);\n        if (score > best_score) {\n            best_score = score;\n            best_ans = ans;\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        cout << best_ans[i].x1 << ' ' << best_ans[i].y1 << ' '\n             << best_ans[i].x2 << ' ' << best_ans[i].y2 << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 50;\nstatic constexpr int W = 50;\nstatic constexpr int N = H * W;\nstatic constexpr int WORDS = (N + 63) / 64;\n\nstruct State {\n    array<uint64_t, WORDS> vis{};\n    int pos = 0;\n    int score = 0;\n    int parent = -1;\n    char mv = 0;\n    int prio = 0;\n};\n\nstruct Cand {\n    int next = -1;\n    char mv = '?';\n    int val = 0;\n    int r1 = 0;\n    int r2 = 0;\n    int fut = 0;\n    int dens = 0;\n    int key = 0;\n};\n\nstruct Mode {\n    int wR2, wR1, wF, wV, wD;\n    int prioMul;\n    int noise;      // percentage for randomized completion\n    int beamDepth;\n    int beamWidth;\n    int finishK;\n};\n\nstruct Result {\n    string path;\n    int score = -1;\n};\n\nint si, sj;\nint tileId[H][W];\nint valGrid[H][W];\n\nint tileOf[N];\nint valueOf[N];\nint densityScore[N];\n\nint adjCnt[N];\nint adjTo[N][4];\nchar adjMv[N][4];\n\ninline int idOf(int r, int c) { return r * W + c; }\n\ninline bool visited(const array<uint64_t, WORDS>& vis, int tid) {\n    return (vis[tid >> 6] >> (tid & 63)) & 1ULL;\n}\ninline void setVisited(array<uint64_t, WORDS>& vis, int tid) {\n    vis[tid >> 6] |= (1ULL << (tid & 63));\n}\n\nstatic inline bool candBetter(const Cand& a, const Cand& b) {\n    if (a.key != b.key) return a.key > b.key;\n    if (a.r2 != b.r2) return a.r2 > b.r2;\n    if (a.r1 != b.r1) return a.r1 > b.r1;\n    if (a.val != b.val) return a.val > b.val;\n    return a.next < b.next;\n}\n\nstatic inline bool nodeBetter(const State& a, const State& b) {\n    if (a.prio != b.prio) return a.prio > b.prio;\n    if (a.score != b.score) return a.score > b.score;\n    return a.pos < b.pos;\n}\n\ninline void applyMove(State& st, int nxt) {\n    st.pos = nxt;\n    st.score += valueOf[nxt];\n    setVisited(st.vis, tileOf[nxt]);\n}\n\nint makeCandidates(const State& st, const Mode& m, Cand out[4]) {\n    int cnt = 0;\n    int curTid = tileOf[st.pos];\n\n    for (int k = 0; k < adjCnt[st.pos]; ++k) {\n        int nxt = adjTo[st.pos][k];\n        int nxtTid = tileOf[nxt];\n        if (visited(st.vis, nxtTid)) continue;\n\n        int directTid[8], directVal[8], directCnt = 0;\n        int reachTid[20], reachVal[20], reachCnt = 0;\n\n        auto addTo = [&](int tid, int val, int tids[], int vals[], int& c) {\n            if (tid == curTid || tid == nxtTid || visited(st.vis, tid)) return;\n            for (int i = 0; i < c; ++i) {\n                if (tids[i] == tid) {\n                    vals[i] = max(vals[i], val);\n                    return;\n                }\n            }\n            tids[c] = tid;\n            vals[c] = val;\n            ++c;\n        };\n\n        for (int e = 0; e < adjCnt[nxt]; ++e) {\n            int x = adjTo[nxt][e];\n            int tx = tileOf[x];\n            addTo(tx, valueOf[x], directTid, directVal, directCnt);\n            addTo(tx, valueOf[x], reachTid, reachVal, reachCnt);\n\n            for (int ee = 0; ee < adjCnt[x]; ++ee) {\n                int y = adjTo[x][ee];\n                int ty = tileOf[y];\n                addTo(ty, valueOf[y], reachTid, reachVal, reachCnt);\n            }\n        }\n\n        sort(reachVal, reachVal + reachCnt, greater<int>());\n        int fut = 0;\n        for (int i = 0; i < min(4, reachCnt); ++i) fut += reachVal[i];\n\n        int dens = densityScore[nxt] / 20;\n        int key = m.wR2 * reachCnt\n                + m.wR1 * directCnt\n                + m.wF  * fut\n                + m.wV  * valueOf[nxt]\n                + m.wD  * dens;\n\n        out[cnt++] = {nxt, adjMv[st.pos][k], valueOf[nxt], directCnt, reachCnt, fut, dens, key};\n    }\n\n    if (cnt == 0) return 0;\n\n    // If there exists a move with positive immediate mobility, discard dead-end moves.\n    bool hasGood = false;\n    for (int i = 0; i < cnt; ++i) {\n        if (out[i].r1 > 0) {\n            hasGood = true;\n            break;\n        }\n    }\n    if (hasGood) {\n        int j = 0;\n        for (int i = 0; i < cnt; ++i) {\n            if (out[i].r1 > 0) out[j++] = out[i];\n        }\n        cnt = j;\n    }\n\n    sort(out, out + cnt, candBetter);\n    return cnt;\n}\n\nstring reconstructPath(const vector<State>& pool, int idx) {\n    string s;\n    while (idx != -1 && pool[idx].parent != -1) {\n        s.push_back(pool[idx].mv);\n        idx = pool[idx].parent;\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nResult completeFrom(State st, string path, const Mode& m, mt19937_64& rng,\n                    chrono::steady_clock::time_point deadline) {\n    while (chrono::steady_clock::now() < deadline) {\n        Cand cand[4];\n        int cnt = makeCandidates(st, m, cand);\n        if (cnt == 0) break;\n\n        int choose = 0;\n        if (m.noise > 0 && cnt > 1 && (int)(rng() % 100) < m.noise) {\n            int minKey = cand[cnt - 1].key;\n            int w[4];\n            int sum = 0;\n            for (int i = 0; i < cnt; ++i) {\n                w[i] = max(1, cand[i].key - minKey + 1);\n                sum += w[i];\n            }\n            uint64_t r = rng() % sum;\n            int acc = 0;\n            for (int i = 0; i < cnt; ++i) {\n                acc += w[i];\n                if (r < (uint64_t)acc) {\n                    choose = i;\n                    break;\n                }\n            }\n        }\n\n        applyMove(st, cand[choose].next);\n        path.push_back(cand[choose].mv);\n    }\n    return {path, st.score};\n}\n\nResult runAttempt(const Mode& m, uint64_t seed, chrono::steady_clock::time_point deadline) {\n    mt19937_64 rng(seed);\n\n    vector<State> pool;\n    pool.reserve(120000);\n\n    State root;\n    int start = idOf(si, sj);\n    root.pos = start;\n    root.score = valueOf[start];\n    setVisited(root.vis, tileOf[start]);\n    root.parent = -1;\n    root.mv = 0;\n    root.prio = root.score;\n    pool.push_back(root);\n\n    vector<int> beam = {0};\n    int bestTerminal = -1;\n\n    for (int depth = 0; depth < m.beamDepth; ++depth) {\n        if (chrono::steady_clock::now() >= deadline) break;\n\n        vector<int> nxt;\n        nxt.reserve(beam.size() * 4 + 8);\n\n        for (int idx : beam) {\n            Cand cand[4];\n            int cnt = makeCandidates(pool[idx], m, cand);\n            if (cnt == 0) {\n                if (bestTerminal == -1 || pool[idx].score > pool[bestTerminal].score) {\n                    bestTerminal = idx;\n                }\n                continue;\n            }\n\n            for (int i = 0; i < cnt; ++i) {\n                State ch = pool[idx];\n                applyMove(ch, cand[i].next);\n                ch.parent = idx;\n                ch.mv = cand[i].mv;\n                int jitter = m.noise ? (int)(rng() % (2ULL * m.noise + 1)) - m.noise : 0;\n                ch.prio = ch.score + m.prioMul * cand[i].key + jitter;\n                pool.push_back(ch);\n                nxt.push_back((int)pool.size() - 1);\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        if ((int)nxt.size() > m.beamWidth) {\n            nth_element(nxt.begin(), nxt.begin() + m.beamWidth, nxt.end(),\n                        [&](int a, int b) {\n                            if (pool[a].prio != pool[b].prio) return pool[a].prio > pool[b].prio;\n                            if (pool[a].score != pool[b].score) return pool[a].score > pool[b].score;\n                            return a < b;\n                        });\n            nxt.resize(m.beamWidth);\n        }\n\n        beam.swap(nxt);\n    }\n\n    vector<int> selected;\n    auto addUnique = [&](int x) {\n        if (x < 0) return;\n        for (int y : selected) if (y == x) return;\n        selected.push_back(x);\n    };\n\n    sort(beam.begin(), beam.end(), [&](int a, int b) {\n        if (pool[a].prio != pool[b].prio) return pool[a].prio > pool[b].prio;\n        if (pool[a].score != pool[b].score) return pool[a].score > pool[b].score;\n        return a < b;\n    });\n\n    for (int i = 0; i < (int)beam.size() && i < m.finishK; ++i) addUnique(beam[i]);\n    if (bestTerminal != -1) addUnique(bestTerminal);\n\n    if (!beam.empty()) {\n        int bestScoreIdx = beam[0];\n        for (int idx : beam) {\n            if (pool[idx].score > pool[bestScoreIdx].score) bestScoreIdx = idx;\n        }\n        addUnique(bestScoreIdx);\n    } else {\n        addUnique(0);\n    }\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[start];\n\n    for (int idx : selected) {\n        if (chrono::steady_clock::now() >= deadline) break;\n\n        string path = reconstructPath(pool, idx);\n        State st = pool[idx];\n        Result r = completeFrom(st, path, m, rng, deadline);\n\n        if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) {\n            best = std::move(r);\n        }\n    }\n\n    return best;\n}\n\npair<bool, int> simulatePath(const string& path) {\n    State st;\n    int start = idOf(si, sj);\n    st.pos = start;\n    st.score = valueOf[start];\n    setVisited(st.vis, tileOf[start]);\n\n    for (char ch : path) {\n        int nxt = -1;\n        for (int k = 0; k < adjCnt[st.pos]; ++k) {\n            if (adjMv[st.pos][k] == ch) {\n                nxt = adjTo[st.pos][k];\n                break;\n            }\n        }\n        if (nxt == -1) return {false, -1};\n        int tid = tileOf[nxt];\n        if (visited(st.vis, tid)) return {false, -1};\n        applyMove(st, nxt);\n    }\n    return {true, st.score};\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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> tileId[i][j];\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> valGrid[i][j];\n    }\n\n    uint64_t baseSeed = 0x123456789abcdefULL;\n    auto mix = [&](uint64_t x) {\n        baseSeed = splitmix64(baseSeed ^ x);\n    };\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            tileOf[id] = tileId[i][j];\n            valueOf[id] = valGrid[i][j];\n            mix((uint64_t)tileId[i][j] << 32 ^ (uint64_t)valGrid[i][j] ^ (uint64_t)(i * 50 + j));\n        }\n    }\n    mix((uint64_t)si << 32 | (uint64_t)sj);\n\n    // adjacency\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            adjCnt[id] = 0;\n            if (i > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i - 1, j);\n                adjMv[id][adjCnt[id]++] = 'U';\n            }\n            if (i + 1 < H) {\n                adjTo[id][adjCnt[id]] = idOf(i + 1, j);\n                adjMv[id][adjCnt[id]++] = 'D';\n            }\n            if (j > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i, j - 1);\n                adjMv[id][adjCnt[id]++] = 'L';\n            }\n            if (j + 1 < W) {\n                adjTo[id][adjCnt[id]] = idOf(i, j + 1);\n                adjMv[id][adjCnt[id]++] = 'R';\n            }\n        }\n    }\n\n    // Local density: weighted sum in Manhattan radius 3\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int sum = 0;\n            for (int dr = -3; dr <= 3; ++dr) {\n                for (int dc = -3; dc <= 3; ++dc) {\n                    int d = abs(dr) + abs(dc);\n                    if (d > 3) continue;\n                    int ni = i + dr, nj = j + dc;\n                    if (ni < 0 || ni >= H || nj < 0 || nj >= W) continue;\n                    int w = 4 - d; // 4,3,2,1\n                    sum += w * valGrid[ni][nj];\n                }\n            }\n            densityScore[idOf(i, j)] = sum;\n        }\n    }\n\n    chrono::steady_clock::time_point startTime = chrono::steady_clock::now();\n    chrono::steady_clock::time_point deadline = startTime + chrono::milliseconds(1850);\n\n    vector<Mode> modes = {\n        // Strong mobility-first\n        {100, 35, 1, 0, 1, 4, 4, 260, 64, 8},\n        // Balanced\n        {70,  25, 3, 1, 2, 4, 6, 220, 72, 8},\n        // Value-balanced\n        {45,  18, 5, 4, 2, 4, 8, 200, 84, 10},\n        // Dense-area explorer\n        {60,  20, 2, 1, 4, 4, 7, 220, 80, 8},\n        // More exploratory\n        {30,  12, 6, 6, 1, 5, 12, 180, 96, 12},\n    };\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[idOf(si, sj)];\n\n    int attempt = 0;\n    while (chrono::steady_clock::now() < deadline) {\n        const Mode& m = modes[attempt % (int)modes.size()];\n        uint64_t seed = splitmix64(baseSeed ^ (uint64_t)attempt * 0x9e3779b97f4a7c15ULL);\n        Result r = runAttempt(m, seed, deadline);\n\n        // Safety check\n        auto [ok, sc] = simulatePath(r.path);\n        if (ok) r.score = sc;\n        else r.path.clear(), r.score = valueOf[idOf(si, sj)];\n\n        if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) {\n            best = std::move(r);\n        }\n\n        ++attempt;\n    }\n\n    auto [ok, sc] = simulatePath(best.path);\n    if (!ok) {\n        best.path.clear();\n    }\n\n    cout << best.path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr double INIT_W = 5000.0;\nstatic constexpr double MIN_W = 1000.0;\nstatic constexpr double MAX_W = 9000.0;\n\nstatic constexpr double PRIOR_W = 0.20;      // prior strength for unobserved edges in row/col fit\nstatic constexpr double SEG_BLEND = 6.0;     // blend between direct estimate and segment mean\nstatic constexpr double SEG_COV_BETA = 0.40; // coverage effect on uncertainty\nstatic constexpr double UPDATE_LR = 0.28;    // residual update step\n\nstatic constexpr double INF = 1e100;\nstatic constexpr double EPS = 1e-9;\n\ndouble estH[N][N - 1], estV[N - 1][N];\nint cntH[N][N - 1], cntV[N - 1][N];\n\nstruct LineModel {\n    bool split = false;\n    int pos = -1;   // split point in [1..28]\n    double mean = INIT_W;\n    double left = INIT_W;\n    double right = INIT_W;\n};\n\nLineModel rowModel[N], colModel[N];\nint rowCov[N][2], colCov[N][2];\n\ndouble pcostH[N][N - 1], pcostV[N - 1][N];\ndouble puncH[N][N - 1], puncV[N - 1][N];\n\nstruct Candidate {\n    string path;\n    double cost = INF;\n    double unc = INF;\n};\n\ninline double clampW(double x) {\n    return max(MIN_W, min(MAX_W, x));\n}\n\ninline double rowSegMean(int r, int c) {\n    if (!rowModel[r].split) return rowModel[r].mean;\n    return (c < rowModel[r].pos ? rowModel[r].left : rowModel[r].right);\n}\n\ninline double colSegMean(int c, int r) {\n    if (!colModel[c].split) return colModel[c].mean;\n    return (r < colModel[c].pos ? colModel[c].left : colModel[c].right);\n}\n\ninline int rowSegOf(int r, int c) {\n    return (rowModel[r].split && c >= rowModel[r].pos) ? 1 : 0;\n}\n\ninline int colSegOf(int c, int r) {\n    return (colModel[c].split && r >= colModel[c].pos) ? 1 : 0;\n}\n\ninline double edgeUncH(int r, int c) {\n    int s = rowSegOf(r, c);\n    return 1.0 / (1.0 + cntH[r][c] + SEG_COV_BETA * rowCov[r][s]);\n}\n\ninline double edgeUncV(int r, int c) {\n    int s = colSegOf(c, r);\n    return 1.0 / (1.0 + cntV[r][c] + SEG_COV_BETA * colCov[c][s]);\n}\n\nLineModel fitRow(int r) {\n    double w[29], x[29];\n    double pw[30], ps[30], pq[30];\n    int po[30];\n\n    double totW = 0.0, totS = 0.0, totQ = 0.0;\n    int obs = 0;\n\n    pw[0] = ps[0] = pq[0] = 0.0;\n    po[0] = 0;\n\n    for (int c = 0; c < 29; ++c) {\n        bool seen = (cntH[r][c] > 0);\n        double ww = seen ? (sqrt((double)cntH[r][c]) + PRIOR_W) : PRIOR_W;\n        double val = seen ? estH[r][c] : INIT_W;\n\n        w[c] = ww;\n        x[c] = val;\n\n        totW += ww;\n        totS += ww * val;\n        totQ += ww * val * val;\n        obs += seen ? 1 : 0;\n\n        pw[c + 1] = pw[c] + ww;\n        ps[c + 1] = ps[c] + ww * val;\n        pq[c + 1] = pq[c] + ww * val * val;\n        po[c + 1] = po[c] + (seen ? 1 : 0);\n    }\n\n    LineModel m;\n    if (totW <= 0.0) {\n        m.mean = INIT_W;\n        return m;\n    }\n\n    m.mean = totS / totW;\n    m.left = m.right = m.mean;\n    m.split = false;\n    m.pos = -1;\n\n    if (obs < 5) return m;\n\n    double sse1 = max(0.0, totQ - totS * totS / totW);\n\n    double best2 = INF;\n    int bestPos = -1;\n    double bestL = m.mean, bestR = m.mean;\n\n    for (int cut = 1; cut < 29; ++cut) {\n        double wL = pw[cut], wR = totW - wL;\n        int oL = po[cut], oR = obs - oL;\n        if (oL < 2 || oR < 2) continue;\n        if (wL < 1.0 || wR < 1.0) continue;\n\n        double sL = ps[cut], sR = totS - sL;\n        double qL = pq[cut], qR = totQ - qL;\n        double sse2 = max(0.0, qL - sL * sL / wL) + max(0.0, qR - sR * sR / wR);\n\n        if (sse2 < best2) {\n            best2 = sse2;\n            bestPos = cut;\n            bestL = sL / wL;\n            bestR = sR / wR;\n        }\n    }\n\n    if (bestPos != -1) {\n        double gain = sse1 - best2;\n        if (gain > 1.8e5 && gain > 0.025 * sse1) {\n            m.split = true;\n            m.pos = bestPos;\n            m.left = bestL;\n            m.right = bestR;\n        }\n    }\n\n    return m;\n}\n\nLineModel fitCol(int c) {\n    double w[29], x[29];\n    double pw[30], ps[30], pq[30];\n    int po[30];\n\n    double totW = 0.0, totS = 0.0, totQ = 0.0;\n    int obs = 0;\n\n    pw[0] = ps[0] = pq[0] = 0.0;\n    po[0] = 0;\n\n    for (int r = 0; r < 29; ++r) {\n        bool seen = (cntV[r][c] > 0);\n        double ww = seen ? (sqrt((double)cntV[r][c]) + PRIOR_W) : PRIOR_W;\n        double val = seen ? estV[r][c] : INIT_W;\n\n        w[r] = ww;\n        x[r] = val;\n\n        totW += ww;\n        totS += ww * val;\n        totQ += ww * val * val;\n        obs += seen ? 1 : 0;\n\n        pw[r + 1] = pw[r] + ww;\n        ps[r + 1] = ps[r] + ww * val;\n        pq[r + 1] = pq[r] + ww * val * val;\n        po[r + 1] = po[r] + (seen ? 1 : 0);\n    }\n\n    LineModel m;\n    if (totW <= 0.0) {\n        m.mean = INIT_W;\n        return m;\n    }\n\n    m.mean = totS / totW;\n    m.left = m.right = m.mean;\n    m.split = false;\n    m.pos = -1;\n\n    if (obs < 5) return m;\n\n    double sse1 = max(0.0, totQ - totS * totS / totW);\n\n    double best2 = INF;\n    int bestPos = -1;\n    double bestL = m.mean, bestR = m.mean;\n\n    for (int cut = 1; cut < 29; ++cut) {\n        double wL = pw[cut], wR = totW - wL;\n        int oL = po[cut], oR = obs - oL;\n        if (oL < 2 || oR < 2) continue;\n        if (wL < 1.0 || wR < 1.0) continue;\n\n        double sL = ps[cut], sR = totS - sL;\n        double qL = pq[cut], qR = totQ - qL;\n        double sse2 = max(0.0, qL - sL * sL / wL) + max(0.0, qR - sR * sR / wR);\n\n        if (sse2 < best2) {\n            best2 = sse2;\n            bestPos = cut;\n            bestL = sL / wL;\n            bestR = sR / wR;\n        }\n    }\n\n    if (bestPos != -1) {\n        double gain = sse1 - best2;\n        if (gain > 1.8e5 && gain > 0.025 * sse1) {\n            m.split = true;\n            m.pos = bestPos;\n            m.left = bestL;\n            m.right = bestR;\n        }\n    }\n\n    return m;\n}\n\nvoid rebuildModelsAndCosts(int q) {\n    // Fit row/column segment models.\n    for (int i = 0; i < N; ++i) rowModel[i] = fitRow(i);\n    for (int j = 0; j < N; ++j) colModel[j] = fitCol(j);\n\n    // Coverage of each segment = number of distinct observed edges in that segment.\n    for (int i = 0; i < N; ++i) rowCov[i][0] = rowCov[i][1] = 0;\n    for (int j = 0; j < N; ++j) colCov[j][0] = colCov[j][1] = 0;\n\n    for (int i = 0; i < N; ++i) {\n        if (!rowModel[i].split) {\n            int cov = 0;\n            for (int j = 0; j < N - 1; ++j) if (cntH[i][j] > 0) ++cov;\n            rowCov[i][0] = cov;\n        } else {\n            for (int j = 0; j < N - 1; ++j) {\n                if (cntH[i][j] > 0) ++rowCov[i][j >= rowModel[i].pos ? 1 : 0];\n            }\n        }\n    }\n\n    for (int j = 0; j < N; ++j) {\n        if (!colModel[j].split) {\n            int cov = 0;\n            for (int i = 0; i < N - 1; ++i) if (cntV[i][j] > 0) ++cov;\n            colCov[j][0] = cov;\n        } else {\n            for (int i = 0; i < N - 1; ++i) {\n                if (cntV[i][j] > 0) ++colCov[j][i >= colModel[j].pos ? 1 : 0];\n            }\n        }\n    }\n\n    double risk = 90.0 + 60.0 * (double)q / 999.0;\n\n    // Fill unobserved edges with the current row/column segment mean,\n    // and build planning costs + uncertainty values.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            double seg = rowSegMean(i, j);\n            if (cntH[i][j] == 0) estH[i][j] = seg;\n\n            int s = rowSegOf(i, j);\n            double unc = 1.0 / (1.0 + cntH[i][j] + SEG_COV_BETA * rowCov[i][s]);\n            puncH[i][j] = unc;\n\n            double base = (cntH[i][j] > 0)\n                ? (estH[i][j] * cntH[i][j] + seg * SEG_BLEND) / (cntH[i][j] + SEG_BLEND)\n                : seg;\n            pcostH[i][j] = base + risk * unc;\n        }\n    }\n\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            double seg = colSegMean(j, i);\n            if (cntV[i][j] == 0) estV[i][j] = seg;\n\n            int s = colSegOf(j, i);\n            double unc = 1.0 / (1.0 + cntV[i][j] + SEG_COV_BETA * colCov[j][s]);\n            puncV[i][j] = unc;\n\n            double base = (cntV[i][j] > 0)\n                ? (estV[i][j] * cntV[i][j] + seg * SEG_BLEND) / (cntV[i][j] + SEG_BLEND)\n                : seg;\n            pcostV[i][j] = base + risk * unc;\n        }\n    }\n}\n\nCandidate solveMonotone(int si, int sj, int ti, int tj) {\n    int dy = abs(ti - si);\n    int dx = abs(tj - sj);\n    int sv = (ti >= si ? 1 : -1);\n    int sh = (tj >= sj ? 1 : -1);\n\n    static double dpC[N][N];\n    static double dpU[N][N];\n    static char par[N][N];\n\n    for (int i = 0; i <= dy; ++i) {\n        for (int j = 0; j <= dx; ++j) {\n            dpC[i][j] = INF;\n            dpU[i][j] = INF;\n            par[i][j] = 0;\n        }\n    }\n    dpC[0][0] = 0.0;\n    dpU[0][0] = 0.0;\n\n    auto better = [&](double c1, double u1, double c2, double u2) -> bool {\n        if (c1 + EPS < c2) return true;\n        if (c2 + EPS < c1) return false;\n        return u1 + EPS < u2;\n    };\n\n    for (int i = 0; i <= dy; ++i) {\n        for (int j = 0; j <= dx; ++j) {\n            if (i == 0 && j == 0) continue;\n\n            double bestC = INF, bestU = INF;\n            char bestP = 0;\n\n            if (i > 0) {\n                int px = si + sv * (i - 1);\n                int py = sj + sh * j;\n                int ex = (sv == 1 ? px : px - 1);\n                int ey = py;\n\n                double candC = dpC[i - 1][j] + pcostV[ex][ey];\n                double candU = dpU[i - 1][j] + puncV[ex][ey];\n                if (better(candC, candU, bestC, bestU)) {\n                    bestC = candC;\n                    bestU = candU;\n                    bestP = (sv == 1 ? 'D' : 'U');\n                }\n            }\n\n            if (j > 0) {\n                int px = si + sv * i;\n                int py = sj + sh * (j - 1);\n                int ex = px;\n                int ey = (sh == 1 ? py : py - 1);\n\n                double candC = dpC[i][j - 1] + pcostH[ex][ey];\n                double candU = dpU[i][j - 1] + puncH[ex][ey];\n                if (better(candC, candU, bestC, bestU)) {\n                    bestC = candC;\n                    bestU = candU;\n                    bestP = (sh == 1 ? 'R' : 'L');\n                }\n            }\n\n            dpC[i][j] = bestC;\n            dpU[i][j] = bestU;\n            par[i][j] = bestP;\n        }\n    }\n\n    string path;\n    path.reserve(dx + dy);\n\n    for (int i = dy, j = dx; i > 0 || j > 0; ) {\n        char c = par[i][j];\n        path.push_back(c);\n        if (c == 'D' || c == 'U') --i;\n        else --j;\n    }\n    reverse(path.begin(), path.end());\n\n    return {path, dpC[dy][dx], dpU[dy][dx]};\n}\n\nCandidate solveDijkstra(int si, int sj, int ti, int tj) {\n    const int S = si * N + sj;\n    const int T = ti * N + tj;\n\n    static double dist[N * N];\n    static double du[N * N];\n    static int par[N * N];\n    static char pmove[N * N];\n\n    for (int i = 0; i < N * N; ++i) {\n        dist[i] = INF;\n        du[i] = INF;\n        par[i] = -1;\n        pmove[i] = 0;\n    }\n\n    priority_queue<tuple<double, double, int>, vector<tuple<double, double, int>>, greater<tuple<double, double, int>>> pq;\n\n    dist[S] = 0.0;\n    du[S] = 0.0;\n    pq.emplace(0.0, 0.0, S);\n\n    while (!pq.empty()) {\n        auto [d, uUnc, u] = pq.top();\n        pq.pop();\n\n        if (d > dist[u] + EPS) continue;\n        if (fabs(d - dist[u]) <= EPS && uUnc > du[u] + EPS) continue;\n\n        if (u == T) break;\n\n        int x = u / N;\n        int y = u % N;\n\n        // Up\n        if (x > 0) {\n            int v = (x - 1) * N + y;\n            double nd = d + pcostV[x - 1][y];\n            double nu = uUnc + puncV[x - 1][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'U';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Down\n        if (x + 1 < N) {\n            int v = (x + 1) * N + y;\n            double nd = d + pcostV[x][y];\n            double nu = uUnc + puncV[x][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'D';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Left\n        if (y > 0) {\n            int v = x * N + (y - 1);\n            double nd = d + pcostH[x][y - 1];\n            double nu = uUnc + puncH[x][y - 1];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'L';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Right\n        if (y + 1 < N) {\n            int v = x * N + (y + 1);\n            double nd = d + pcostH[x][y];\n            double nu = uUnc + puncH[x][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'R';\n                pq.emplace(nd, nu, v);\n            }\n        }\n    }\n\n    string path;\n    for (int v = T; v != S; v = par[v]) {\n        path.push_back(pmove[v]);\n    }\n    reverse(path.begin(), path.end());\n\n    return {path, dist[T], du[T]};\n}\n\nstruct Step {\n    bool isH;\n    int a, b;\n    double est;\n    double w;\n};\n\ninline double edgeEstimateH(int r, int c) {\n    return estH[r][c];\n}\n\ninline double edgeEstimateV(int r, int c) {\n    return estV[r][c];\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            estH[i][j] = INIT_W;\n            cntH[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            estV[i][j] = INIT_W;\n            cntV[i][j] = 0;\n        }\n    }\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        rebuildModelsAndCosts(q);\n\n        Candidate mono = solveMonotone(si, sj, ti, tj);\n        Candidate dijk = solveDijkstra(si, sj, ti, tj);\n\n        Candidate chosen = mono;\n        double margin = 100.0 + 40.0 * (double)q / 999.0;\n        if (dijk.cost + margin < mono.cost || (fabs(dijk.cost - mono.cost) <= margin && dijk.unc + EPS < mono.unc)) {\n            chosen = dijk;\n        }\n\n        cout << chosen.path << '\\n' << flush;\n\n        long long obs;\n        if (!(cin >> obs)) return 0;\n\n        // Predict path length from direct edge estimates.\n        double pred = 0.0;\n        int x = si, y = sj;\n\n        vector<Step> steps;\n        steps.reserve(chosen.path.size());\n\n        for (char c : chosen.path) {\n            if (c == 'D') {\n                double est = edgeEstimateV(x, y);\n                double unc = puncV[x][y];\n                double w = unc * (0.5 + est / INIT_W);\n                pred += est;\n                steps.push_back({false, x, y, est, w});\n                ++x;\n            } else if (c == 'U') {\n                double est = edgeEstimateV(x - 1, y);\n                double unc = puncV[x - 1][y];\n                double w = unc * (0.5 + est / INIT_W);\n                pred += est;\n                steps.push_back({false, x - 1, y, est, w});\n                --x;\n            } else if (c == 'R') {\n                double est = edgeEstimateH(x, y);\n                double unc = puncH[x][y];\n                double w = unc * (0.5 + est / INIT_W);\n                pred += est;\n                steps.push_back({true, x, y, est, w});\n                ++y;\n            } else { // 'L'\n                double est = edgeEstimateH(x, y - 1);\n                double unc = puncH[x][y - 1];\n                double w = unc * (0.5 + est / INIT_W);\n                pred += est;\n                steps.push_back({true, x, y - 1, est, w});\n                --y;\n            }\n        }\n\n        double residual = (double)obs - pred;\n\n        double sumW = 0.0;\n        for (auto &st : steps) sumW += st.w;\n        if (sumW <= 0.0) sumW = 1.0;\n\n        // Confidence-weighted additive update.\n        for (auto &st : steps) {\n            double delta = UPDATE_LR * residual * (st.w / sumW);\n            if (st.isH) {\n                estH[st.a][st.b] = clampW(estH[st.a][st.b] + delta);\n                ++cntH[st.a][st.b];\n            } else {\n                estV[st.a][st.b] = clampW(estV[st.a][st.b] + delta);\n                ++cntV[st.a][st.b];\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int CELLS = N * N;\nstatic constexpr int SIG = 8;\nstatic constexpr int DOT = 8;\nstatic constexpr int MAXM = 800;\nstatic constexpr int MAXL = 12;\n\nusing u8 = uint8_t;\nusing Board = array<u8, CELLS>;\n\nstruct Word {\n    int len;\n    array<u8, MAXL> ch{};\n};\n\nstruct Place {\n    int sid;\n    u8 len, ori, line, st;\n};\n\nstruct Score3 {\n    int sat = -1;\n    int fulls = -1;\n    long long sup = -1;\n};\n\nstatic int Ninput, M;\nstatic vector<Word> words;\nstatic vector<Place> places;\nstatic vector<vector<int>> wordPlaces;\nstatic array<array<vector<int>, SIG>, CELLS> cellByChar;\nstatic array<array<int, SIG>, CELLS> cellSupport;\n\nstatic inline int cid(int r, int c) { return r * N + c; }\n\nstatic inline int countPlacement(const Board& b, int pid) {\n    const Place& p = places[pid];\n    const Word& w = words[p.sid];\n    int cnt = 0;\n    if (p.ori == 0) {\n        int c = p.st;\n        int base = p.line * N;\n        for (int t = 0; t < p.len; ++t) {\n            cnt += (b[base + c] == w.ch[t]);\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = p.st;\n        int c = p.line;\n        for (int t = 0; t < p.len; ++t) {\n            cnt += (b[r * N + c] == w.ch[t]);\n            if (++r == N) r = 0;\n        }\n    }\n    return cnt;\n}\n\nstatic inline void depositPlacementVotes(\n    const Place& p, const Word& w, long long wt, long long votes[CELLS][SIG]\n) {\n    if (p.ori == 0) {\n        int c = p.st;\n        int base = p.line * N;\n        for (int t = 0; t < p.len; ++t) {\n            votes[base + c][w.ch[t]] += wt;\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = p.st;\n        int c = p.line;\n        for (int t = 0; t < p.len; ++t) {\n            votes[r * N + c][w.ch[t]] += wt;\n            if (++r == N) r = 0;\n        }\n    }\n}\n\nstatic Board makeSupportBoard(mt19937_64& rng) {\n    Board b{};\n    for (int i = 0; i < CELLS; ++i) {\n        int best = -1;\n        u8 bc = 0;\n        for (int c = 0; c < SIG; ++c) {\n            int sc = cellSupport[i][c];\n            if (sc > best || (sc == best && (rng() & 1ULL))) {\n                best = sc;\n                bc = (u8)c;\n            }\n        }\n        b[i] = bc;\n    }\n    return b;\n}\n\nstatic void overlaySeed(Board& b, const Word& w, int line, int st, bool horiz) {\n    if (horiz) {\n        int c = st;\n        for (int t = 0; t < w.len; ++t) {\n            b[cid(line, c)] = w.ch[t];\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = st;\n        for (int t = 0; t < w.len; ++t) {\n            b[cid(r, line)] = w.ch[t];\n            if (++r == N) r = 0;\n        }\n    }\n}\n\nstatic void mutateBoard(Board& b, mt19937_64& rng, int cnt) {\n    for (int i = 0; i < cnt; ++i) {\n        int pos = int(rng() % CELLS);\n        u8 nw = u8(rng() % SIG);\n        if (nw == b[pos]) nw = u8((nw + 1) % SIG);\n        b[pos] = nw;\n    }\n}\n\nstatic Board makeSeedBoard(const Board& base, const vector<int>& byLen, mt19937_64& rng) {\n    Board b = base;\n    int k = min(12, M);\n    for (int i = 0; i < k; ++i) {\n        int sid = byLen[i];\n        bool horiz = (i % 2 == 0);\n        int line = (i * 3 + 7) % N;\n        int st = int(rng() % N);\n        overlaySeed(b, words[sid], line, st, horiz);\n    }\n    mutateBoard(b, rng, 4);\n    return b;\n}\n\nstatic Board makeNoisyBoard(const Board& base, const vector<int>& byLen, mt19937_64& rng) {\n    Board b = base;\n    int k = min(6, M);\n    for (int i = 0; i < k; ++i) {\n        int sid = byLen[i];\n        bool horiz = (i % 2 == 1);\n        int line = (i * 5 + 11) % N;\n        int st = int(rng() % N);\n        overlaySeed(b, words[sid], line, st, horiz);\n    }\n    mutateBoard(b, rng, 18);\n    return b;\n}\n\nstatic void recomputeCounts(const Board& b, vector<u8>& placeCnt, vector<int>& fullCnt) {\n    fill(placeCnt.begin(), placeCnt.end(), 0);\n    fill(fullCnt.begin(), fullCnt.end(), 0);\n\n    for (int sid = 0; sid < M; ++sid) {\n        const Word& w = words[sid];\n        for (int pid : wordPlaces[sid]) {\n            const Place& p = places[pid];\n            int cnt = 0;\n            if (p.ori == 0) {\n                int c = p.st;\n                int base = p.line * N;\n                for (int t = 0; t < p.len; ++t) {\n                    cnt += (b[base + c] == w.ch[t]);\n                    if (++c == N) c = 0;\n                }\n            } else {\n                int r = p.st;\n                int c = p.line;\n                for (int t = 0; t < p.len; ++t) {\n                    cnt += (b[r * N + c] == w.ch[t]);\n                    if (++r == N) r = 0;\n                }\n            }\n            placeCnt[pid] = (u8)cnt;\n            if (cnt == p.len) ++fullCnt[sid];\n        }\n    }\n}\n\nstatic Score3 boardScore(const Board& b, const vector<int>& fullCnt) {\n    Score3 sc;\n    sc.sat = 0;\n    sc.fulls = 0;\n    sc.sup = 0;\n    for (int sid = 0; sid < M; ++sid) {\n        if (fullCnt[sid] > 0) ++sc.sat;\n        sc.fulls += fullCnt[sid];\n    }\n    for (int i = 0; i < CELLS; ++i) sc.sup += cellSupport[i][b[i]];\n    return sc;\n}\n\nstatic void emRound(Board& b, int minLen, int cutoff) {\n    static vector<int> act;\n    static vector<u8> cnt;\n    static vector<u8> best;\n    act.clear();\n\n    for (int sid = 0; sid < M; ++sid) {\n        if (words[sid].len >= minLen) act.push_back(sid);\n    }\n    if (act.empty()) return;\n\n    cnt.assign(places.size(), 0);\n    best.assign(M, 0);\n\n    for (int sid : act) {\n        for (int pid : wordPlaces[sid]) {\n            int c = countPlacement(b, pid);\n            cnt[pid] = (u8)c;\n            if (c > best[sid]) best[sid] = (u8)c;\n        }\n    }\n\n    static long long votes[CELLS][SIG];\n    memset(votes, 0, sizeof(votes));\n\n    for (int sid : act) {\n        int mx = best[sid];\n        if (mx < 2) continue;\n        int thr = max(2, mx - cutoff);\n        const Word& w = words[sid];\n\n        for (int pid : wordPlaces[sid]) {\n            int c = cnt[pid];\n            if (c < thr) continue;\n\n            long long wt = 1LL << c;\n            if (c == mx) wt <<= 2;\n            if (c == w.len) wt <<= 3;\n            wt *= w.len;\n\n            depositPlacementVotes(places[pid], w, wt, votes);\n        }\n    }\n\n    for (int i = 0; i < CELLS; ++i) {\n        u8 old = b[i];\n        long long bestV = votes[i][old] + 100;\n        u8 bestC = old;\n        for (int c = 0; c < SIG; ++c) {\n            if (votes[i][c] > bestV) {\n                bestV = votes[i][c];\n                bestC = (u8)c;\n            }\n        }\n        b[i] = bestC;\n    }\n}\n\nstruct MoveScore {\n    int ds = 0;\n    int df = 0;\n    int dsup = 0;\n    u8 c = 0;\n};\n\nstatic MoveScore evalCellMove(\n    int idx, u8 old, u8 cand,\n    const vector<u8>& placeCnt,\n    const vector<int>& fullCnt\n) {\n    MoveScore ret;\n    ret.c = cand;\n\n    static int seen[MAXM];\n    static int lost[MAXM];\n    static int gain[MAXM];\n    static int stamp = 1;\n    ++stamp;\n\n    vector<int> touched;\n    touched.reserve(M);\n\n    if (cand == old) return ret;\n\n    for (int pid : cellByChar[idx][old]) {\n        if (placeCnt[pid] == places[pid].len) {\n            int sid = places[pid].sid;\n            if (seen[sid] != stamp) {\n                seen[sid] = stamp;\n                lost[sid] = gain[sid] = 0;\n                touched.push_back(sid);\n            }\n            ++lost[sid];\n            --ret.df;\n        }\n    }\n    for (int pid : cellByChar[idx][cand]) {\n        if (placeCnt[pid] + 1 == places[pid].len) {\n            int sid = places[pid].sid;\n            if (seen[sid] != stamp) {\n                seen[sid] = stamp;\n                lost[sid] = gain[sid] = 0;\n                touched.push_back(sid);\n            }\n            ++gain[sid];\n            ++ret.df;\n        }\n    }\n\n    for (int sid : touched) {\n        int now = fullCnt[sid];\n        int nxt = now - lost[sid] + gain[sid];\n        if (now == 0) {\n            if (gain[sid] > 0) ++ret.ds;\n        } else {\n            if (nxt == 0) --ret.ds;\n        }\n    }\n\n    ret.dsup = cellSupport[idx][cand] - cellSupport[idx][old];\n    return ret;\n}\n\nstatic void applyMove(\n    Board& b, int idx, u8 old, u8 cand,\n    vector<u8>& placeCnt, vector<int>& fullCnt\n) {\n    if (old == cand) return;\n\n    for (int pid : cellByChar[idx][old]) {\n        int sid = places[pid].sid;\n        if (placeCnt[pid] == places[pid].len) --fullCnt[sid];\n        --placeCnt[pid];\n    }\n    for (int pid : cellByChar[idx][cand]) {\n        int sid = places[pid].sid;\n        if (placeCnt[pid] + 1 == places[pid].len) ++fullCnt[sid];\n        ++placeCnt[pid];\n    }\n    b[idx] = cand;\n}\n\nstatic void greedyOptimize(Board& b, vector<u8>& placeCnt, vector<int>& fullCnt, mt19937_64& rng) {\n    vector<int> ord(CELLS);\n    iota(ord.begin(), ord.end(), 0);\n\n    for (int sweep = 0; sweep < 6; ++sweep) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool any = false;\n\n        for (int idx : ord) {\n            u8 old = b[idx];\n            MoveScore best{0, 0, 0, old};\n\n            for (int c = 0; c < SIG; ++c) {\n                if (c == old) continue;\n                MoveScore sc = evalCellMove(idx, old, (u8)c, placeCnt, fullCnt);\n                if (sc.ds > best.ds ||\n                    (sc.ds == best.ds && (sc.df > best.df ||\n                     (sc.df == best.df && sc.dsup > best.dsup)))) {\n                    best = sc;\n                }\n            }\n\n            if (best.c != old && (best.ds > 0 || best.df > 0 || best.dsup > 0)) {\n                applyMove(b, idx, old, best.c, placeCnt, fullCnt);\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n}\n\nstatic int countDots(const Board& b) {\n    int d = 0;\n    for (int i = 0; i < CELLS; ++i) d += (b[i] == DOT);\n    return d;\n}\n\nstatic int pruneAttempt(const Board& src, bool coverOrder, mt19937_64& rng, Board& out) {\n    Board b = src;\n    vector<u8> placeCnt(places.size());\n    vector<int> fullCnt(M);\n    recomputeCounts(b, placeCnt, fullCnt);\n\n    int dots = 0;\n    vector<int> ord(CELLS);\n    iota(ord.begin(), ord.end(), 0);\n\n    static int seen[MAXM];\n    static int lost[MAXM];\n    static int stamp = 1000000;\n\n    while (true) {\n        ++stamp;\n\n        if (coverOrder) {\n            vector<int> cover(CELLS, 0);\n            for (int sid = 0; sid < M; ++sid) {\n                if (fullCnt[sid] == 0) continue;\n                for (int pid : wordPlaces[sid]) {\n                    if (placeCnt[pid] == places[pid].len) {\n                        const Place& p = places[pid];\n                        if (p.ori == 0) {\n                            int c = p.st;\n                            int base = p.line * N;\n                            for (int t = 0; t < p.len; ++t) {\n                                ++cover[base + c];\n                                if (++c == N) c = 0;\n                            }\n                        } else {\n                            int r = p.st;\n                            int c = p.line;\n                            for (int t = 0; t < p.len; ++t) {\n                                ++cover[cid(r, c)];\n                                if (++r == N) r = 0;\n                            }\n                        }\n                    }\n                }\n            }\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cover[a] != cover[b]) return cover[a] < cover[b];\n                return a < b;\n            });\n        } else {\n            shuffle(ord.begin(), ord.end(), rng);\n        }\n\n        bool changed = false;\n\n        for (int idx : ord) {\n            if (b[idx] == DOT) continue;\n            u8 old = b[idx];\n\n            vector<int> touched;\n            touched.reserve(M);\n\n            for (int pid : cellByChar[idx][old]) {\n                if (placeCnt[pid] == places[pid].len) {\n                    int sid = places[pid].sid;\n                    if (seen[sid] != stamp) {\n                        seen[sid] = stamp;\n                        lost[sid] = 0;\n                        touched.push_back(sid);\n                    }\n                    ++lost[sid];\n                }\n            }\n\n            bool safe = true;\n            for (int sid : touched) {\n                if (lost[sid] >= fullCnt[sid]) {\n                    safe = false;\n                    break;\n                }\n            }\n            if (!safe) continue;\n\n            for (int pid : cellByChar[idx][old]) {\n                int sid = places[pid].sid;\n                if (placeCnt[pid] == places[pid].len) --fullCnt[sid];\n                --placeCnt[pid];\n            }\n\n            b[idx] = DOT;\n            ++dots;\n            changed = true;\n        }\n\n        if (!changed) break;\n    }\n\n    out = b;\n    return dots;\n}\n\nstatic void outputBoard(const Board& b) {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            u8 x = b[cid(r, c)];\n            cout << (x == DOT ? '.' : char('A' + x));\n        }\n        cout << '\\n';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> Ninput >> M;\n    (void)Ninput;\n\n    words.resize(M);\n    for (int i = 0; i < M; ++i) {\n        string s;\n        cin >> s;\n        words[i].len = (int)s.size();\n        for (int j = 0; j < words[i].len; ++j) words[i].ch[j] = u8(s[j] - 'A');\n    }\n\n    wordPlaces.assign(M, {});\n    places.reserve((size_t)M * N * N);\n\n    // First pass: build places and count cell support.\n    for (int sid = 0; sid < M; ++sid) {\n        wordPlaces[sid].reserve(N * N);\n        const Word& w = words[sid];\n        for (int ori = 0; ori < 2; ++ori) {\n            for (int line = 0; line < N; ++line) {\n                for (int st = 0; st < N; ++st) {\n                    int pid = (int)places.size();\n                    places.push_back(Place{sid, (u8)w.len, (u8)ori, (u8)line, (u8)st});\n                    wordPlaces[sid].push_back(pid);\n\n                    if (ori == 0) {\n                        int c = st;\n                        for (int t = 0; t < w.len; ++t) {\n                            ++cellSupport[cid(line, c)][w.ch[t]];\n                            if (++c == N) c = 0;\n                        }\n                    } else {\n                        int r = st;\n                        for (int t = 0; t < w.len; ++t) {\n                            ++cellSupport[cid(r, line)][w.ch[t]];\n                            if (++r == N) r = 0;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    // Second pass: build cell -> pids by expected character.\n    for (int i = 0; i < CELLS; ++i) {\n        for (int c = 0; c < SIG; ++c) cellByChar[i][c].reserve(cellSupport[i][c]);\n    }\n    for (int sid = 0; sid < M; ++sid) {\n        const Word& w = words[sid];\n        for (int pid : wordPlaces[sid]) {\n            const Place& p = places[pid];\n            if (p.ori == 0) {\n                int c = p.st;\n                for (int t = 0; t < p.len; ++t) {\n                    cellByChar[cid(p.line, c)][w.ch[t]].push_back(pid);\n                    if (++c == N) c = 0;\n                }\n            } else {\n                int r = p.st;\n                for (int t = 0; t < p.len; ++t) {\n                    cellByChar[cid(r, p.line)][w.ch[t]].push_back(pid);\n                    if (++r == N) r = 0;\n                }\n            }\n        }\n    }\n\n    vector<int> byLen(M);\n    iota(byLen.begin(), byLen.end(), 0);\n    sort(byLen.begin(), byLen.end(), [&](int a, int b) {\n        if (words[a].len != words[b].len) return words[a].len > words[b].len;\n        return a < b;\n    });\n\n    mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    Score3 bestScore{-1, -1, -1};\n    Board bestLetters{};\n    Board bestFullBoard{};\n    int bestDots = -1;\n    bool haveFull = false;\n\n    auto tryBoard = [&](Board b, bool doEM) {\n        if (elapsed() > 2.75) return;\n\n        if (doEM) {\n            emRound(b, 6, 0);\n            emRound(b, 5, 1);\n            emRound(b, 2, 1);\n        }\n\n        vector<u8> placeCnt(places.size());\n        vector<int> fullCnt(M);\n        recomputeCounts(b, placeCnt, fullCnt);\n        greedyOptimize(b, placeCnt, fullCnt, rng);\n        recomputeCounts(b, placeCnt, fullCnt);\n\n        Score3 sc = boardScore(b, fullCnt);\n        if (sc.sat > bestScore.sat ||\n            (sc.sat == bestScore.sat && (sc.fulls > bestScore.fulls ||\n             (sc.fulls == bestScore.fulls && sc.sup > bestScore.sup)))) {\n            bestScore = sc;\n            bestLetters = b;\n        }\n\n        if (sc.sat == M && elapsed() < 2.90) {\n            Board pr;\n            int d1 = pruneAttempt(b, true, rng, pr);\n            if (d1 > bestDots) {\n                bestDots = d1;\n                bestFullBoard = pr;\n                haveFull = true;\n            }\n            if (elapsed() < 2.90) {\n                int d2 = pruneAttempt(b, false, rng, pr);\n                if (d2 > bestDots) {\n                    bestDots = d2;\n                    bestFullBoard = pr;\n                    haveFull = true;\n                }\n            }\n        }\n    };\n\n    Board support1 = makeSupportBoard(rng);\n    Board support2 = makeSupportBoard(rng);\n    Board seed = makeSeedBoard(support1, byLen, rng);\n    Board noisy = makeNoisyBoard(support2, byLen, rng);\n\n    tryBoard(support1, false);\n    tryBoard(support1, true);\n    tryBoard(seed, true);\n    tryBoard(noisy, true);\n\n    int attempts = 0;\n    while (elapsed() < 2.75 && attempts < 4) {\n        Board b = bestLetters;\n        int mut = (bestScore.sat < M / 2 ? 20 : (bestScore.sat < M ? 8 : 4));\n        mutateBoard(b, rng, mut);\n        tryBoard(b, true);\n        ++attempts;\n    }\n\n    if (haveFull) {\n        outputBoard(bestFullBoard);\n    } else {\n        outputBoard(bestLetters);\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INF = (1LL << 60);\n\nstruct HSeg { int row, l, r; };\nstruct VSeg { int col, u, d; };\n\nstatic const int di[4] = {-1, 1, 0, 0};\nstatic const int dj[4] = {0, 0, -1, 1};\nstatic const char dc[4] = {'U', 'D', 'L', 'R'};\nstatic const int invd[4] = {1, 0, 3, 2};\n\nstruct Solver {\n    int N, si, sj, M, start;\n    vector<string> grid;\n    vector<int> wt, rowOf, colOf;\n    vector<char> road;\n    vector<int> hOf, vOf;\n    vector<vector<int>> hCells, vCells;\n    vector<HSeg> hsegs;\n    vector<VSeg> vsegs;\n\n    vector<vector<pair<int,int>>> adjCell;     // original directed graph: u -> v cost wt[v]\n    vector<vector<pair<int,int>>> revAdjCell;  // reverse-cost graph: v -> u cost wt[u]\n\n    void read_input() {\n        cin >> N >> si >> sj;\n        grid.resize(N);\n        for (int i = 0; i < N; ++i) cin >> grid[i];\n\n        M = N * N;\n        start = si * N + sj;\n\n        wt.assign(M, 0);\n        rowOf.assign(M, 0);\n        colOf.assign(M, 0);\n        road.assign(M, 0);\n        hOf.assign(M, -1);\n        vOf.assign(M, -1);\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int id = i * N + j;\n                rowOf[id] = i;\n                colOf[id] = j;\n                if (grid[i][j] != '#') {\n                    road[id] = 1;\n                    wt[id] = grid[i][j] - '0';\n                }\n            }\n        }\n\n        adjCell.assign(M, {});\n        revAdjCell.assign(M, {});\n        for (int id = 0; id < M; ++id) {\n            if (!road[id]) continue;\n            int i = rowOf[id], j = colOf[id];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int to = ni * N + nj;\n                if (!road[to]) continue;\n                adjCell[id].push_back({to, wt[to]});\n                // reverse graph for exact return-cost estimation:\n                // original path x -> ... -> start has cost sum wt[next]\n                // reverse-cost graph start -> ... -> x uses cost wt[current]\n                revAdjCell[to].push_back({id, wt[id]});\n            }\n        }\n\n        // Horizontal segments on even rows\n        for (int i = 0; i < N; i += 2) {\n            int j = 0;\n            while (j < N) {\n                while (j < N && !road[i * N + j]) ++j;\n                if (j >= N) break;\n                int l = j;\n                vector<int> cells;\n                while (j < N && road[i * N + j]) {\n                    int id = i * N + j;\n                    cells.push_back(id);\n                    ++j;\n                }\n                int r = j - 1;\n                int sid = (int)hsegs.size();\n                hsegs.push_back({i, l, r});\n                hCells.push_back(cells);\n                for (int x : cells) hOf[x] = sid;\n            }\n        }\n\n        // Vertical segments on even cols\n        for (int j = 0; j < N; j += 2) {\n            int i = 0;\n            while (i < N) {\n                while (i < N && !road[i * N + j]) ++i;\n                if (i >= N) break;\n                int u = i;\n                vector<int> cells;\n                while (i < N && road[i * N + j]) {\n                    int id = i * N + j;\n                    cells.push_back(id);\n                    ++i;\n                }\n                int d = i - 1;\n                int sid = (int)vsegs.size();\n                vsegs.push_back({j, u, d});\n                vCells.push_back(cells);\n                for (int x : cells) vOf[x] = sid;\n            }\n        }\n    }\n\n    void dijkstraCells(int src, const vector<vector<pair<int,int>>>& g,\n                       vector<ll>& dist, vector<int>& parent) const {\n        int V = (int)g.size();\n        dist.assign(V, INF);\n        parent.assign(V, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[src] = 0;\n        parent[src] = src;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, w] : g[u]) {\n                ll nd = d + w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n\n    pair<bool, ll> simulate(const string& s) const {\n        int ci = si, cj = sj;\n        vector<char> covH(hsegs.size(), 0), covV(vsegs.size(), 0);\n        int covered = 0;\n\n        auto cover = [&](int id) {\n            int h = hOf[id];\n            if (h != -1 && !covH[h]) {\n                covH[h] = 1;\n                ++covered;\n            }\n            int v = vOf[id];\n            if (v != -1 && !covV[v]) {\n                covV[v] = 1;\n                ++covered;\n            }\n        };\n\n        cover(start);\n        ll cost = 0;\n\n        for (char c : s) {\n            int d = -1;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            else return {false, 0};\n\n            int ni = ci + di[d], nj = cj + dj[d];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) return {false, 0};\n            int nid = ni * N + nj;\n            if (!road[nid]) return {false, 0};\n\n            ci = ni;\n            cj = nj;\n            cost += wt[nid];\n            cover(nid);\n        }\n\n        if (ci != si || cj != sj) return {false, 0};\n        if (covered != (int)hsegs.size() + (int)vsegs.size()) return {false, 0};\n        return {true, cost};\n    }\n\n    string buildGreedy(int mode) const {\n        struct Tune {\n            array<long double, 3> bonus;\n            array<long double, 3> retCoef;\n            array<long double, 3> pickAlpha;\n        };\n\n        static const Tune tunes[3] = {\n            // aggressive\n            {{24.0L, 18.0L, 13.0L}, {0.02L, 0.05L, 0.10L}, {0.00L, 0.03L, 0.06L}},\n            // balanced\n            {{18.0L, 14.0L, 10.0L}, {0.05L, 0.10L, 0.18L}, {0.05L, 0.10L, 0.15L}},\n            // return-aware\n            {{15.0L, 12.0L, 9.0L},  {0.12L, 0.22L, 0.35L}, {0.12L, 0.25L, 0.40L}}\n        };\n\n        const Tune& cfg = tunes[mode];\n\n        // Exact return-cost estimate:\n        // reverse-cost graph from start gives distRev[x] = best cost from start to x in reverse-cost graph\n        // original best cost from x to start = distRev[x] + wt[start] - wt[x]\n        vector<ll> distRev;\n        vector<int> dummyParent;\n        dijkstraCells(start, revAdjCell, distRev, dummyParent);\n\n        auto returnCost = [&](int id) -> ll {\n            return distRev[id] + wt[start] - wt[id];\n        };\n\n        vector<char> covH(hsegs.size(), 0), covV(vsegs.size(), 0);\n        int coveredCnt = 0;\n\n        auto coverCell = [&](int id) {\n            int h = hOf[id];\n            if (h != -1 && !covH[h]) {\n                covH[h] = 1;\n                ++coveredCnt;\n            }\n            int v = vOf[id];\n            if (v != -1 && !covV[v]) {\n                covV[v] = 1;\n                ++coveredCnt;\n            }\n        };\n\n        coverCell(start);\n\n        vector<ll> dist;\n        vector<int> parent;\n        vector<int> seenH(hsegs.size(), 0), seenV(vsegs.size(), 0);\n        int stamp = 1;\n\n        int current = start;\n        string route;\n        route.reserve(40000);\n\n        auto appendPath = [&](const vector<int>& path) {\n            int prev = current;\n            for (int id : path) {\n                int pi = rowOf[prev], pj = colOf[prev];\n                int i = rowOf[id], j = colOf[id];\n                if (i == pi - 1 && j == pj) route.push_back('U');\n                else if (i == pi + 1 && j == pj) route.push_back('D');\n                else if (i == pi && j == pj - 1) route.push_back('L');\n                else if (i == pi && j == pj + 1) route.push_back('R');\n                else {\n                    // should never happen\n                }\n                coverCell(id);\n                prev = id;\n            }\n            current = prev;\n        };\n\n        int totalSeg = (int)hsegs.size() + (int)vsegs.size();\n        vector<int> candidates, bestPrefix, tmpPath;\n\n        while (coveredCnt < totalSeg) {\n            dijkstraCells(current, adjCell, dist, parent);\n\n            int rem = totalSeg - coveredCnt;\n            int phase = (rem * 3 > totalSeg * 2 ? 0 : (rem * 3 > totalSeg ? 1 : 2));\n\n            candidates.clear();\n            vector<char> candMark(M, 0);\n            auto addCand = [&](int id) {\n                if (id < 0 || id >= M) return;\n                if (!road[id]) return;\n                if (candMark[id]) return;\n                candMark[id] = 1;\n                candidates.push_back(id);\n            };\n\n            auto considerSegment = [&](const vector<int>& cells) {\n                if (cells.empty()) return;\n                int mid = cells[(int)cells.size() / 2];\n                int bestDistCell = -1, bestTradeCell = -1;\n                ll bestDist = INF;\n                long double bestTrade = 1e100L;\n\n                for (int id : cells) {\n                    if (dist[id] >= INF / 2) continue;\n\n                    if (dist[id] < bestDist || (dist[id] == bestDist && returnCost(id) < returnCost(bestDistCell))) {\n                        bestDist = dist[id];\n                        bestDistCell = id;\n                    }\n\n                    long double trade = (long double)dist[id] + cfg.pickAlpha[phase] * (long double)returnCost(id);\n                    if (trade < bestTrade - 1e-12L ||\n                        (fabsl(trade - bestTrade) <= 1e-12L && dist[id] < dist[bestTradeCell])) {\n                        bestTrade = trade;\n                        bestTradeCell = id;\n                    }\n                }\n\n                addCand(bestDistCell);\n                addCand(bestTradeCell);\n                addCand(mid);\n            };\n\n            for (int i = 0; i < (int)hsegs.size(); ++i) if (!covH[i]) considerSegment(hCells[i]);\n            for (int i = 0; i < (int)vsegs.size(); ++i) if (!covV[i]) considerSegment(vCells[i]);\n\n            if (candidates.empty()) break;\n\n            long double bestScore = -1e100L;\n            int bestGain = -1;\n            ll bestPrefixCost = INF;\n            ll bestReturn = INF;\n            bestPrefix.clear();\n\n            for (int cand : candidates) {\n                if (dist[cand] >= INF / 2) continue;\n\n                tmpPath.clear();\n                int x = cand;\n                bool ok = true;\n                while (x != current) {\n                    if (x < 0 || x >= M || parent[x] == -1) {\n                        ok = false;\n                        break;\n                    }\n                    tmpPath.push_back(x);\n                    x = parent[x];\n                }\n                if (!ok || tmpPath.empty()) continue;\n\n                reverse(tmpPath.begin(), tmpPath.end());\n\n                ++stamp;\n                ll prefCost = 0;\n                int gain = 0;\n                int lastPos = -1;\n                ll lastPrefixCost = 0;\n                int lastEnd = -1;\n\n                for (int pos = 0; pos < (int)tmpPath.size(); ++pos) {\n                    int id = tmpPath[pos];\n                    prefCost += wt[id];\n\n                    int add = 0;\n                    int h = hOf[id];\n                    if (h != -1 && !covH[h] && seenH[h] != stamp) {\n                        seenH[h] = stamp;\n                        ++add;\n                    }\n                    int v = vOf[id];\n                    if (v != -1 && !covV[v] && seenV[v] != stamp) {\n                        seenV[v] = stamp;\n                        ++add;\n                    }\n                    if (add) {\n                        gain += add;\n                        lastPos = pos;\n                        lastPrefixCost = prefCost;\n                        lastEnd = id;\n                    }\n                }\n\n                if (gain == 0) continue;\n\n                long double score = cfg.bonus[phase] * (long double)gain\n                                  - (long double)lastPrefixCost\n                                  - cfg.retCoef[phase] * (long double)returnCost(lastEnd);\n\n                if (score > bestScore + 1e-12L ||\n                    (fabsl(score - bestScore) <= 1e-12L &&\n                     (gain > bestGain ||\n                      (gain == bestGain && (lastPrefixCost < bestPrefixCost ||\n                                            (lastPrefixCost == bestPrefixCost && returnCost(lastEnd) < bestReturn)))))) {\n                    bestScore = score;\n                    bestGain = gain;\n                    bestPrefixCost = lastPrefixCost;\n                    bestReturn = returnCost(lastEnd);\n                    bestPrefix.assign(tmpPath.begin(), tmpPath.begin() + lastPos + 1);\n                }\n            }\n\n            if (bestPrefix.empty()) {\n                // fallback: first reachable candidate\n                bool found = false;\n                for (int cand : candidates) {\n                    tmpPath.clear();\n                    int x = cand;\n                    bool ok = true;\n                    while (x != current) {\n                        if (x < 0 || x >= M || parent[x] == -1) {\n                            ok = false;\n                            break;\n                        }\n                        tmpPath.push_back(x);\n                        x = parent[x];\n                    }\n                    if (ok && !tmpPath.empty()) {\n                        reverse(tmpPath.begin(), tmpPath.end());\n                        bestPrefix = tmpPath;\n                        found = true;\n                        break;\n                    }\n                }\n                if (!found) break;\n            }\n\n            appendPath(bestPrefix);\n        }\n\n        if (current != start) {\n            dijkstraCells(current, adjCell, dist, parent);\n            vector<int> back;\n            int x = start;\n            while (x != current) {\n                if (x < 0 || x >= M || parent[x] == -1) {\n                    back.clear();\n                    break;\n                }\n                back.push_back(x);\n                x = parent[x];\n            }\n            if (!back.empty()) {\n                reverse(back.begin(), back.end());\n                appendPath(back);\n            }\n        }\n\n        return route;\n    }\n\n    string buildPostman() const {\n        struct Edge {\n            int u, v;\n            int cost;\n            string moves;\n        };\n\n        vector<int> deg(M, 0);\n        for (int id = 0; id < M; ++id) if (road[id]) deg[id] = (int)adjCell[id].size();\n\n        vector<char> isNode(M, 0);\n        vector<int> nodeCells;\n        for (int id = 0; id < M; ++id) {\n            if (!road[id]) continue;\n            bool node = false;\n            if (id == start) node = true;\n            else if (deg[id] != 2) node = true;\n            else {\n                int a = adjCell[id][0].first;\n                int b = adjCell[id][1].first;\n                if (!(rowOf[a] == rowOf[b] || colOf[a] == colOf[b])) node = true;\n            }\n            if (node) {\n                isNode[id] = 1;\n                nodeCells.push_back(id);\n            }\n        }\n\n        vector<int> nodeId(M, -1);\n        for (int i = 0; i < (int)nodeCells.size(); ++i) nodeId[nodeCells[i]] = i;\n        int V = (int)nodeCells.size();\n\n        auto step = [&](int id, int d) -> int {\n            int ni = rowOf[id] + di[d];\n            int nj = colOf[id] + dj[d];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) return -1;\n            return ni * N + nj;\n        };\n\n        vector<array<char, 4>> usedStep(M);\n        for (auto &a : usedStep) a.fill(0);\n\n        vector<Edge> edges;\n        vector<vector<pair<int,int>>> g(V); // node graph: to, edgeId\n\n        for (int s : nodeCells) {\n            for (int d = 0; d < 4; ++d) {\n                int nxt = step(s, d);\n                if (nxt < 0 || !road[nxt] || usedStep[s][d]) continue;\n\n                int cur = s;\n                int prev = s;\n                int dir = d;\n                int cell = nxt;\n                int cost = 0;\n                string moves;\n\n                while (true) {\n                    usedStep[cur][dir] = 1;\n                    usedStep[cell][invd[dir]] = 1;\n\n                    moves.push_back(dc[dir]);\n                    cost += wt[cell];\n\n                    prev = cur;\n                    cur = cell;\n                    if (isNode[cur]) break;\n\n                    int nd = -1, nc = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int t = step(cur, d2);\n                        if (t < 0 || !road[t] || t == prev) continue;\n                        nd = d2;\n                        nc = t;\n                        break;\n                    }\n                    if (nd == -1) break; // should not happen\n                    dir = nd;\n                    cell = nc;\n                }\n\n                int a = nodeId[s];\n                int b = nodeId[cur];\n                int eid = (int)edges.size();\n                edges.push_back({a, b, cost, moves});\n                if (a == b) {\n                    g[a].push_back({b, eid});\n                    g[a].push_back({b, eid});\n                } else {\n                    g[a].push_back({b, eid});\n                    g[b].push_back({a, eid});\n                }\n            }\n        }\n\n        int K = (int)nodeCells.size();\n        vector<int> odd;\n        for (int i = 0; i < K; ++i) {\n            if ((int)g[i].size() % 2 == 1) odd.push_back(i);\n        }\n        int O = (int)odd.size();\n\n        vector<vector<ll>> dmat(O, vector<ll>(O, INF));\n        vector<vector<int>> parV(O, vector<int>(K, -1));\n        vector<vector<int>> parE(O, vector<int>(K, -1));\n\n        auto dijkstraNode = [&](int src, vector<ll>& dist, vector<int>& pV, vector<int>& pE) {\n            dist.assign(K, INF);\n            pV.assign(K, -1);\n            pE.assign(K, -1);\n            priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n            dist[src] = 0;\n            pV[src] = src;\n            pq.push({0, src});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                if (d != dist[u]) continue;\n                for (auto [v, eid] : g[u]) {\n                    ll nd = d + edges[eid].cost;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        pV[v] = u;\n                        pE[v] = eid;\n                        pq.push({nd, v});\n                    }\n                }\n            }\n        };\n\n        for (int i = 0; i < O; ++i) {\n            vector<ll> dist;\n            dijkstraNode(odd[i], dist, parV[i], parE[i]);\n            for (int j = 0; j < O; ++j) dmat[i][j] = dist[odd[j]];\n        }\n\n        auto totalPairCost = [&](const vector<pair<int,int>>& ps) -> ll {\n            ll sum = 0;\n            for (auto [a, b] : ps) sum += dmat[a][b];\n            return sum;\n        };\n\n        auto improve_pairs = [&](vector<pair<int,int>>& ps) {\n            for (int iter = 0; iter < 4; ++iter) {\n                bool changed = false;\n                for (int a = 0; a < (int)ps.size(); ++a) {\n                    for (int b = a + 1; b < (int)ps.size(); ++b) {\n                        auto [i, j] = ps[a];\n                        auto [k, l] = ps[b];\n                        ll cur = dmat[i][j] + dmat[k][l];\n                        ll s1 = dmat[i][k] + dmat[j][l];\n                        ll s2 = dmat[i][l] + dmat[j][k];\n                        if (s1 < cur || s2 < cur) {\n                            if (s1 <= s2) {\n                                ps[a] = {i, k};\n                                ps[b] = {j, l};\n                            } else {\n                                ps[a] = {i, l};\n                                ps[b] = {j, k};\n                            }\n                            changed = true;\n                        }\n                    }\n                }\n                if (!changed) break;\n            }\n        };\n\n        auto make_pairs_exact = [&]() -> vector<pair<int,int>> {\n            int full = (1 << O) - 1;\n            vector<ll> dp(1 << O, INF);\n            vector<int> preMask(1 << O, -1), pickI(1 << O, -1), pickJ(1 << O, -1);\n            dp[0] = 0;\n\n            for (int mask = 0; mask <= full; ++mask) {\n                if (dp[mask] >= INF / 2) continue;\n                int i = 0;\n                while (i < O && (mask & (1 << i))) ++i;\n                if (i == O) continue;\n                for (int j = i + 1; j < O; ++j) {\n                    if (mask & (1 << j)) continue;\n                    int nm = mask | (1 << i) | (1 << j);\n                    ll nd = dp[mask] + dmat[i][j];\n                    if (nd < dp[nm]) {\n                        dp[nm] = nd;\n                        preMask[nm] = mask;\n                        pickI[nm] = i;\n                        pickJ[nm] = j;\n                    }\n                }\n            }\n\n            vector<pair<int,int>> ps;\n            int mask = full;\n            while (mask) {\n                int i = pickI[mask], j = pickJ[mask];\n                if (i < 0 || j < 0) break;\n                ps.push_back({i, j});\n                mask = preMask[mask];\n            }\n            return ps;\n        };\n\n        auto make_pairs_order = [&](vector<int> order) -> vector<pair<int,int>> {\n            vector<char> used(O, 0);\n            vector<pair<int,int>> ps;\n            for (int x : order) {\n                if (used[x]) continue;\n                used[x] = 1;\n                int bestY = -1;\n                ll best = INF;\n                for (int y = 0; y < O; ++y) {\n                    if (used[y] || y == x) continue;\n                    if (dmat[x][y] < best) {\n                        best = dmat[x][y];\n                        bestY = y;\n                    }\n                }\n                if (bestY != -1) {\n                    used[bestY] = 1;\n                    ps.push_back({x, bestY});\n                }\n            }\n            return ps;\n        };\n\n        vector<pair<int,int>> bestPairs;\n        ll bestPairCost = INF;\n\n        if (O == 0) {\n            bestPairs.clear();\n            bestPairCost = 0;\n        } else if (O <= 20) {\n            bestPairs = make_pairs_exact();\n            bestPairCost = totalPairCost(bestPairs);\n        } else {\n            vector<int> base(O);\n            iota(base.begin(), base.end(), 0);\n\n            vector<vector<int>> orders;\n            orders.push_back(base);\n\n            auto rev = base;\n            reverse(rev.begin(), rev.end());\n            orders.push_back(rev);\n\n            auto rngOrder = base;\n            mt19937 rng(712367 + N * 10007 + si * 1009 + sj * 9176);\n            shuffle(rngOrder.begin(), rngOrder.end(), rng);\n            orders.push_back(rngOrder);\n\n            vector<int> byRow = base;\n            sort(byRow.begin(), byRow.end(), [&](int a, int b) {\n                ll sa = 0, sb = 0;\n                for (int t = 0; t < O; ++t) {\n                    if (a != t) sa += min(dmat[a][t], (ll)1e9);\n                    if (b != t) sb += min(dmat[b][t], (ll)1e9);\n                }\n                return sa < sb;\n            });\n            orders.push_back(byRow);\n\n            for (auto ord : orders) {\n                auto ps = make_pairs_order(ord);\n                improve_pairs(ps);\n                ll c = totalPairCost(ps);\n                if (c < bestPairCost) {\n                    bestPairCost = c;\n                    bestPairs = ps;\n                }\n            }\n\n            if (bestPairs.empty()) bestPairs = make_pairs_order(base);\n        }\n\n        vector<int> dup(edges.size(), 0);\n        for (auto [a, b] : bestPairs) {\n            if (a < 0 || b < 0) continue;\n            int v = odd[b];\n            while (v != odd[a]) {\n                int eid = parE[a][v];\n                if (eid < 0) break;\n                dup[eid]++;\n                v = parV[a][v];\n            }\n        }\n\n        struct UseEdge {\n            int u, v, orig;\n        };\n\n        vector<UseEdge> uses;\n        vector<vector<pair<int,int>>> mg(K); // multigraph adjacency: to, useId\n\n        for (int eid = 0; eid < (int)edges.size(); ++eid) {\n            int cnt = 1 + dup[eid];\n            for (int k = 0; k < cnt; ++k) {\n                int uid = (int)uses.size();\n                uses.push_back({edges[eid].u, edges[eid].v, eid});\n                if (edges[eid].u == edges[eid].v) {\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                } else {\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                    mg[edges[eid].v].push_back({edges[eid].u, uid});\n                }\n            }\n        }\n\n        if (start < 0 || start >= M || nodeId[start] < 0) return \"\";\n\n        vector<int> it(K, 0), stV, stE, stRev;\n        vector<char> usedUse(uses.size(), 0);\n        vector<pair<int,int>> circuit;\n\n        stV.push_back(nodeId[start]);\n\n        while (!stV.empty()) {\n            int v = stV.back();\n            auto &adj = mg[v];\n            while (it[v] < (int)adj.size() && usedUse[adj[it[v]].second]) ++it[v];\n            if (it[v] == (int)adj.size()) {\n                stV.pop_back();\n                if (!stE.empty()) {\n                    circuit.push_back({stE.back(), stRev.back()});\n                    stE.pop_back();\n                    stRev.pop_back();\n                }\n            } else {\n                auto [to, uid] = adj[it[v]++];\n                if (usedUse[uid]) continue;\n                usedUse[uid] = 1;\n                bool rev = (v != uses[uid].u);\n                stV.push_back(to);\n                stE.push_back(uid);\n                stRev.push_back(rev ? 1 : 0);\n            }\n        }\n\n        reverse(circuit.begin(), circuit.end());\n\n        string route;\n        route.reserve(40000);\n\n        auto invertMove = [&](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        for (auto [uid, rev] : circuit) {\n            const auto &e = edges[uses[uid].orig];\n            if (!rev) {\n                route += e.moves;\n            } else {\n                for (int i = (int)e.moves.size() - 1; i >= 0; --i) {\n                    route.push_back(invertMove(e.moves[i]));\n                }\n            }\n        }\n\n        return route;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.read_input();\n\n    vector<string> routes;\n    routes.push_back(solver.buildGreedy(0));\n    routes.push_back(solver.buildGreedy(1));\n    routes.push_back(solver.buildGreedy(2));\n    routes.push_back(solver.buildPostman());\n\n    string best = routes[0];\n    ll bestCost = INF;\n    size_t bestLen = (size_t)4e18;\n\n    for (const auto& r : routes) {\n        auto [ok, cost] = solver.simulate(r);\n        if (!ok) continue;\n        if (cost < bestCost || (cost == bestCost && r.size() < bestLen)) {\n            bestCost = cost;\n            bestLen = r.size();\n            best = r;\n        }\n    }\n\n    if (bestCost == INF) {\n        best = routes[0];\n    }\n\n    cout << best << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskNode {\n    long long pr;\n    int id;\n};\n\nstruct TaskCmp {\n    bool operator()(const TaskNode& a, const TaskNode& b) const {\n        if (a.pr != b.pr) return a.pr < b.pr; // max-heap by priority\n        return a.id > b.id;                  // smaller id first on tie\n    }\n};\n\nstatic const double INIT_SKILL = 5.0;\n\nvector<int> hungarian_min_cost(const vector<vector<double>>& a) {\n    int n = (int)a.size();\n    const double INF = 1e100;\n    vector<double> u(n + 1, 0.0), v(n + 1, 0.0), minv(n + 1);\n    vector<int> p(n + 1, 0), way(n + 1, 0);\n\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        fill(minv.begin(), minv.end(), INF);\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            double delta = INF;\n            int j1 = 0;\n\n            for (int j = 1; j <= n; ++j) {\n                if (used[j]) continue;\n                double cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n\n            for (int j = 0; j <= n; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    vector<int> ans(n, -1);\n    for (int j = 1; j <= n; ++j) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<vector<int>> d(N, vector<int>(K));\n    vector<long long> sumd(N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            cin >> d[i][k];\n            sumd[i] += d[i][k];\n        }\n    }\n\n    vector<vector<int>> succ(N);\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Weighted criticality: own difficulty + longest downstream chain difficulty.\n    vector<long long> workRemain(N, 0), height(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        long long bestWork = 0;\n        long long bestH = 0;\n        for (int v : succ[i]) {\n            bestWork = max(bestWork, workRemain[v]);\n            bestH = max(bestH, height[v]);\n        }\n        workRemain[i] = sumd[i] + bestWork;\n        height[i] = 1 + bestH;\n    }\n\n    vector<long long> priority(N, 0);\n    for (int i = 0; i < N; ++i) {\n        priority[i] = workRemain[i] * 1000LL + height[i];\n    }\n\n    priority_queue<TaskNode, vector<TaskNode>, TaskCmp> pq;\n    for (int i = 0; i < N; ++i) {\n        if (indeg[i] == 0) pq.push({priority[i], i});\n    }\n\n    vector<int> busyTask(M, -1);\n    vector<int> startDay(M, -1);\n    vector<int> taskStatus(N, 0); // 0=not started, 1=started, 2=done\n    vector<vector<double>> skill(M, vector<double>(K, INIT_SKILL));\n    vector<int> obsCnt(M, 0);\n\n    auto predict_duration = [&](int mem, int task) -> double {\n        double w = 0.0;\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill[mem][k]) {\n                w += (double)d[task][k] - skill[mem][k];\n            }\n        }\n        return max(1.0, w);\n    };\n\n    auto update_skill = [&](int mem, int task, int dur) {\n        double w = 0.0;\n        vector<double> gap(K, 0.0);\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill[mem][k]) {\n                gap[k] = (double)d[task][k] - skill[mem][k];\n                w += gap[k];\n            }\n        }\n\n        double pred = max(1.0, w);\n        double err = (double)dur - pred;\n        err = max(-4.0, min(4.0, err));\n\n        double eta = 0.5 / sqrt((double)obsCnt[mem] + 1.0);\n\n        if (w > 1e-9) {\n            for (int k = 0; k < K; ++k) {\n                if (gap[k] <= 0.0) continue;\n                skill[mem][k] -= eta * err * (gap[k] / w);\n                if (skill[mem][k] < 0.0) skill[mem][k] = 0.0;\n                if (skill[mem][k] > 100.0) skill[mem][k] = 100.0;\n            }\n        } else if (err > 0.0) {\n            // If predicted exactly 1, but actual duration was longer, lower all skills slightly.\n            double dec = eta * err / max(1, K);\n            for (int k = 0; k < K; ++k) {\n                skill[mem][k] = max(0.0, skill[mem][k] - dec);\n            }\n        }\n\n        obsCnt[mem]++;\n    };\n\n    int day = 1;\n    while (true) {\n        vector<int> freeMembers;\n        freeMembers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (busyTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        int freeCount = (int)freeMembers.size();\n        int take = min(freeCount, (int)pq.size());\n\n        vector<int> selected;\n        selected.reserve(take);\n        for (int t = 0; t < take; ++t) {\n            selected.push_back(pq.top().id);\n            pq.pop();\n        }\n\n        vector<pair<int,int>> outPairs;\n\n        if (freeCount > 0 && !selected.empty()) {\n            int n = freeCount;\n            int L = (int)selected.size();\n\n            vector<vector<double>> cost(n, vector<double>(n, 0.0));\n            for (int r = 0; r < n; ++r) {\n                int mem = freeMembers[r];\n                for (int c = 0; c < L; ++c) {\n                    cost[r][c] = predict_duration(mem, selected[c]);\n                }\n                for (int c = L; c < n; ++c) {\n                    cost[r][c] = 0.0; // dummy task\n                }\n            }\n\n            vector<int> assign = hungarian_min_cost(cost);\n\n            for (int r = 0; r < n; ++r) {\n                int c = assign[r];\n                if (c >= 0 && c < L) {\n                    int mem = freeMembers[r];\n                    int task = selected[c];\n                    outPairs.push_back({mem, task});\n                    busyTask[mem] = task;\n                    startDay[mem] = day;\n                    taskStatus[task] = 1;\n                }\n            }\n        }\n\n        cout << outPairs.size();\n        for (auto &p : outPairs) {\n            cout << ' ' << (p.first + 1) << ' ' << (p.second + 1);\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        vector<int> finished(cnt);\n        for (int i = 0; i < cnt; ++i) cin >> finished[i];\n\n        for (int mem1 : finished) {\n            int mem = mem1 - 1;\n            int task = busyTask[mem];\n            if (task < 0) continue;\n\n            int dur = day - startDay[mem] + 1;\n            update_skill(mem, task, dur);\n\n            busyTask[mem] = -1;\n            startDay[mem] = -1;\n            taskStatus[task] = 2;\n\n            for (int v : succ[task]) {\n                if (--indeg[v] == 0) {\n                    pq.push({priority[v], v});\n                }\n            }\n        }\n\n        day++;\n    }\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic constexpr int N = 1000;\nstatic constexpr ll INFLL = (1LL << 60);\n\nstruct Pt {\n    int x, y;\n};\n\nstruct Order {\n    Pt p, q;\n    ll pq;\n    ll op, oq;\n    ll mx2, my2;     // midpoint * 2\n    ll midOffice;    // |mx2-800| + |my2-800|\n    double ang;      // angle of midpoint around office\n};\n\nstruct Event {\n    int id;\n    int type; // 0 pickup, 1 delivery\n};\n\nstruct InsInfo {\n    ll delta = INFLL;\n    int i = 0, j = 0;\n    bool same = true;\n};\n\nstruct State {\n    ll cost = INFLL;\n    vector<Event> seq;\n    array<char, N> used{};\n};\n\nstruct Cand {\n    vector<int> sel;\n    int scoreId = -1;\n    ll quickCost = INFLL;\n};\n\nstatic constexpr Pt OFFICE{400, 400};\nvector<Order> ord(N);\n\nstatic inline ll absl(ll x) { return x >= 0 ? x : -x; }\nstatic inline ll md(const Pt& a, const Pt& b) {\n    return absl((ll)a.x - b.x) + absl((ll)a.y - b.y);\n}\nstatic inline Pt pointOf(const Event& e) {\n    return (e.type == 0 ? ord[e.id].p : ord[e.id].q);\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\nstatic vector<Pt> buildPts(const vector<Event>& seq) {\n    vector<Pt> pts;\n    pts.reserve(seq.size() + 2);\n    pts.push_back(OFFICE);\n    for (const auto& e : seq) pts.push_back(pointOf(e));\n    pts.push_back(OFFICE);\n    return pts;\n}\n\nstatic ll seqCost(const vector<Event>& seq) {\n    ll cost = 0;\n    Pt cur = OFFICE;\n    for (const auto& e : seq) {\n        Pt nxt = pointOf(e);\n        cost += md(cur, nxt);\n        cur = nxt;\n    }\n    cost += md(cur, OFFICE);\n    return cost;\n}\n\nstatic InsInfo bestInsert(const vector<Event>& seq, int id) {\n    vector<Pt> pts = buildPts(seq);\n    int m = (int)seq.size();\n\n    const Pt& P = ord[id].p;\n    const Pt& Q = ord[id].q;\n\n    ll best = INFLL;\n    int bi = 0, bj = 0;\n    bool bsame = true;\n\n    for (int i = 0; i <= m; ++i) {\n        ll edge0 = md(pts[i], pts[i + 1]);\n\n        // pickup then delivery consecutively\n        ll dSame = md(pts[i], P) + ord[id].pq + md(Q, pts[i + 1]) - edge0;\n        if (dSame < best) {\n            best = dSame;\n            bi = i;\n            bj = i;\n            bsame = true;\n        }\n\n        ll left = md(pts[i], P) + md(P, pts[i + 1]) - edge0;\n        for (int j = i + 1; j <= m; ++j) {\n            ll edge1 = md(pts[j], pts[j + 1]);\n            ll d = left + md(pts[j], Q) + md(Q, pts[j + 1]) - edge1;\n            if (d < best) {\n                best = d;\n                bi = i;\n                bj = j;\n                bsame = false;\n            }\n        }\n    }\n\n    return {best, bi, bj, bsame};\n}\n\nstatic void applyInsert(vector<Event>& seq, const InsInfo& ins, int id) {\n    seq.insert(seq.begin() + ins.i, Event{id, 0});\n    if (ins.same) {\n        seq.insert(seq.begin() + ins.i + 1, Event{id, 1});\n    } else {\n        seq.insert(seq.begin() + ins.j + 1, Event{id, 1});\n    }\n}\n\nstatic State makeState(const vector<int>& sel, vector<Event>&& seq) {\n    State st;\n    st.seq = std::move(seq);\n    st.used.fill(0);\n    for (int id : sel) st.used[id] = 1;\n    st.cost = seqCost(st.seq);\n    return st;\n}\n\nstatic vector<int> selectedIds(const array<char, N>& used) {\n    vector<int> ids;\n    for (int i = 0; i < N; ++i) if (used[i]) ids.push_back(i);\n    return ids;\n}\n\nstatic vector<Event> removeOrderSeq(const vector<Event>& seq, int id) {\n    vector<Event> res;\n    res.reserve(seq.size() - 2);\n    for (const auto& e : seq) if (e.id != id) res.push_back(e);\n    return res;\n}\n\nstatic vector<int> orderByScore(const vector<int>& sel, const vector<ll>& sc, bool desc) {\n    vector<int> ords = sel;\n    sort(ords.begin(), ords.end(), [&](int a, int b) {\n        if (sc[a] != sc[b]) return desc ? (sc[a] > sc[b]) : (sc[a] < sc[b]);\n        return a < b;\n    });\n    return ords;\n}\n\nstatic vector<int> orderByPQ(const vector<int>& sel, bool desc) {\n    vector<int> ords = sel;\n    sort(ords.begin(), ords.end(), [&](int a, int b) {\n        if (ord[a].pq != ord[b].pq) return desc ? (ord[a].pq > ord[b].pq) : (ord[a].pq < ord[b].pq);\n        return a < b;\n    });\n    return ords;\n}\n\nstatic vector<int> orderByKey(const vector<int>& sel, int keyType, bool desc) {\n    vector<int> ords = sel;\n    sort(ords.begin(), ords.end(), [&](int a, int b) {\n        if (keyType == 4) {\n            if (ord[a].ang != ord[b].ang) return desc ? (ord[a].ang > ord[b].ang) : (ord[a].ang < ord[b].ang);\n        } else {\n            ll ka = 0, kb = 0;\n            if (keyType == 0) {\n                ka = ord[a].mx2 + ord[a].my2;\n                kb = ord[b].mx2 + ord[b].my2;\n            } else if (keyType == 1) {\n                ka = ord[a].mx2 - ord[a].my2;\n                kb = ord[b].mx2 - ord[b].my2;\n            } else if (keyType == 2) {\n                ka = ord[a].mx2;\n                kb = ord[b].mx2;\n            } else {\n                ka = ord[a].my2;\n                kb = ord[b].my2;\n            }\n            if (ka != kb) return desc ? (ka > kb) : (ka < kb);\n        }\n        return a < b;\n    });\n    return ords;\n}\n\nstatic State buildInsertionState(const vector<int>& sel, const vector<int>& order) {\n    State st;\n    st.used.fill(0);\n    for (int id : sel) st.used[id] = 1;\n\n    st.seq.clear();\n    st.seq.reserve(sel.size() * 2);\n\n    st.cost = 0;\n    for (int id : order) {\n        InsInfo ins = bestInsert(st.seq, id);\n        applyInsert(st.seq, ins, id);\n        st.cost += ins.delta;\n    }\n    st.cost = seqCost(st.seq);\n    return st;\n}\n\nstatic State buildSweepState(const vector<int>& sel, int keyType, bool block) {\n    vector<int> ords = orderByKey(sel, keyType, false);\n    vector<Event> seq;\n    seq.reserve(sel.size() * 2);\n\n    if (block) {\n        for (int id : ords) {\n            seq.push_back({id, 0});\n            seq.push_back({id, 1});\n        }\n    } else {\n        for (int id : ords) seq.push_back({id, 0});\n        for (int i = (int)ords.size() - 1; i >= 0; --i) seq.push_back({ords[i], 1});\n    }\n\n    return makeState(sel, std::move(seq));\n}\n\nstatic vector<int> selectTop50(const vector<ll>& score, bool jitter, uint64_t seed) {\n    vector<pair<ll, int>> arr;\n    arr.reserve(N);\n    for (int i = 0; i < N; ++i) {\n        ll s = score[i];\n        if (jitter) {\n            ll noise = (ll)(splitmix64(seed ^ (uint64_t)i) % 61ULL) - 30LL;\n            s += noise;\n        }\n        arr.push_back({s, i});\n    }\n    nth_element(arr.begin(), arr.begin() + 50, arr.end());\n    sort(arr.begin(), arr.begin() + 50);\n    vector<int> sel;\n    sel.reserve(50);\n    for (int i = 0; i < 50; ++i) sel.push_back(arr[i].second);\n    sort(sel.begin(), sel.end());\n    return sel;\n}\n\nstatic vector<int> buildPool(const vector<vector<int>>& rankLists,\n                             const vector<int>& rankIds,\n                             const array<char, N>& used,\n                             int takePerRank = 80) {\n    vector<int> pool;\n    array<char, N> seen{};\n    seen.fill(0);\n\n    for (int rid : rankIds) {\n        int cnt = 0;\n        for (int id : rankLists[rid]) {\n            if (used[id] || seen[id]) continue;\n            seen[id] = 1;\n            pool.push_back(id);\n            if (++cnt == takePerRank) break;\n        }\n    }\n    return pool;\n}\n\nstatic void optimizeAdj(State& st) {\n    for (int iter = 0; iter < 60; ++iter) {\n        bool improved = false;\n        int m = (int)st.seq.size();\n        for (int i = 0; i + 1 < m; ++i) {\n            if (st.seq[i].id == st.seq[i + 1].id) continue;\n\n            Pt prev = (i == 0 ? OFFICE : pointOf(st.seq[i - 1]));\n            Pt a = pointOf(st.seq[i]);\n            Pt b = pointOf(st.seq[i + 1]);\n            Pt nxt = (i + 2 == m ? OFFICE : pointOf(st.seq[i + 2]));\n\n            ll before = md(prev, a) + md(a, b) + md(b, nxt);\n            ll after  = md(prev, b) + md(b, a) + md(a, nxt);\n\n            if (after < before) {\n                swap(st.seq[i], st.seq[i + 1]);\n                st.cost += (after - before);\n                improved = true;\n                break;\n            }\n        }\n        if (!improved) break;\n    }\n}\n\nstatic bool pairReinsertImprove(State& st) {\n    vector<int> ids = selectedIds(st.used);\n    vector<pair<ll, int>> gain;\n    gain.reserve(ids.size());\n\n    for (int id : ids) {\n        vector<Event> reduced = removeOrderSeq(st.seq, id);\n        ll redCost = seqCost(reduced);\n        gain.push_back({st.cost - redCost, id});\n    }\n\n    sort(gain.begin(), gain.end(), [&](const auto& a, const auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    int limit = min(15, (int)gain.size());\n    for (int t = 0; t < limit; ++t) {\n        int id = gain[t].second;\n        vector<Event> reduced = removeOrderSeq(st.seq, id);\n        ll redCost = seqCost(reduced);\n        InsInfo ins = bestInsert(reduced, id);\n        ll nc = redCost + ins.delta;\n\n        if (nc < st.cost) {\n            st.seq = std::move(reduced);\n            applyInsert(st.seq, ins, id);\n            st.cost = nc;\n            return true;\n        }\n    }\n    return false;\n}\n\nstatic bool swapImprove(State& st,\n                        const vector<vector<int>>& rankLists,\n                        const vector<int>& rankIds) {\n    vector<int> pool = buildPool(rankLists, rankIds, st.used, 80);\n    int addLimit = min(30, (int)pool.size());\n\n    vector<int> ids = selectedIds(st.used);\n    vector<pair<ll, int>> gain;\n    gain.reserve(ids.size());\n\n    for (int id : ids) {\n        vector<Event> reduced = removeOrderSeq(st.seq, id);\n        ll redCost = seqCost(reduced);\n        gain.push_back({st.cost - redCost, id});\n    }\n\n    sort(gain.begin(), gain.end(), [&](const auto& a, const auto& b) {\n        if (a.first != b.first) return a.first > b.first; // expensive orders first\n        return a.second < b.second;\n    });\n\n    int selLimit = min(8, (int)gain.size());\n\n    for (int t = 0; t < selLimit; ++t) {\n        int remId = gain[t].second;\n        vector<Event> reduced = removeOrderSeq(st.seq, remId);\n        ll redCost = seqCost(reduced);\n\n        int checked = 0;\n        for (int addId : pool) {\n            if (st.used[addId]) continue;\n            InsInfo ins = bestInsert(reduced, addId);\n            ll nc = redCost + ins.delta;\n            if (nc < st.cost) {\n                st.seq = std::move(reduced);\n                applyInsert(st.seq, ins, addId);\n                st.cost = nc;\n                st.used[remId] = 0;\n                st.used[addId] = 1;\n                return true;\n            }\n            if (++checked >= addLimit) break;\n        }\n    }\n    return false;\n}\n\nstatic void fullImprove(State& st,\n                        const vector<vector<int>>& rankLists,\n                        const vector<int>& poolRankIds) {\n    st.cost = seqCost(st.seq);\n\n    for (int round = 0; round < 4; ++round) {\n        bool changed = false;\n\n        while (pairReinsertImprove(st)) {\n            changed = true;\n            optimizeAdj(st);\n        }\n\n        optimizeAdj(st);\n\n        if (swapImprove(st, rankLists, poolRankIds)) {\n            changed = true;\n            while (pairReinsertImprove(st)) {\n                optimizeAdj(st);\n            }\n            optimizeAdj(st);\n        }\n\n        if (!changed) break;\n    }\n\n    st.cost = seqCost(st.seq);\n}\n\nstatic State buildVariantState(const vector<int>& sel,\n                               int scoreId,\n                               int variant,\n                               const vector<vector<ll>>& scoreVecs) {\n    if (variant == 0) {\n        vector<int> order = orderByScore(sel, scoreVecs[scoreId], false);\n        return buildInsertionState(sel, order);\n    }\n    if (variant == 1) {\n        vector<int> order = orderByScore(sel, scoreVecs[scoreId], true);\n        return buildInsertionState(sel, order);\n    }\n    if (variant == 2) {\n        vector<int> order = orderByPQ(sel, true);\n        return buildInsertionState(sel, order);\n    }\n    if (variant == 3) {\n        vector<int> order = sel;\n        uint64_t seed = splitmix64(123456789ULL ^ (uint64_t)scoreId * 1000003ULL ^ (uint64_t)sel[0] * 10007ULL);\n        mt19937_64 rng(seed);\n        shuffle(order.begin(), order.end(), rng);\n        return buildInsertionState(sel, order);\n    }\n    if (variant == 4) return buildSweepState(sel, 0, false);\n    if (variant == 5) return buildSweepState(sel, 1, false);\n    if (variant == 6) return buildSweepState(sel, 4, false);\n    if (variant == 7) return buildSweepState(sel, 0, true);\n    return buildSweepState(sel, 4, true);\n}\n\nstatic ll quickEvalCand(const Cand& c, const vector<vector<ll>>& scoreVecs) {\n    ll best = INFLL;\n    // quick but diverse\n    vector<int> variants = {0, 1, 4, 7};\n    for (int v : variants) {\n        State st = buildVariantState(c.sel, c.scoreId, v, scoreVecs);\n        best = min(best, st.cost);\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; ++i) {\n        cin >> ord[i].p.x >> ord[i].p.y >> ord[i].q.x >> ord[i].q.y;\n        ord[i].pq = md(ord[i].p, ord[i].q);\n        ord[i].op = md(ord[i].p, OFFICE);\n        ord[i].oq = md(ord[i].q, OFFICE);\n        ord[i].mx2 = ord[i].p.x + ord[i].q.x;\n        ord[i].my2 = ord[i].p.y + ord[i].q.y;\n        ord[i].midOffice = absl(ord[i].mx2 - 800) + absl(ord[i].my2 - 800);\n        ord[i].ang = atan2((double)(ord[i].my2 - 800), (double)(ord[i].mx2 - 800));\n    }\n\n    vector<vector<ll>> scoreVecs;\n    int idPair = -1, idOff = -1, idMidOffice = -1, idLine0 = -1;\n\n    auto addScoreVec = [&](vector<ll>&& sc) -> int {\n        scoreVecs.push_back(std::move(sc));\n        return (int)scoreVecs.size() - 1;\n    };\n\n    // 25 grid anchors, 3 formulas each\n    vector<int> coord = {0, 200, 400, 600, 800};\n    for (int ax : coord) {\n        for (int ay : coord) {\n            Pt a{ax, ay};\n\n            vector<ll> sMid(N), sSum(N), sMax(N);\n            for (int i = 0; i < N; ++i) {\n                ll dp = md(ord[i].p, a);\n                ll dq = md(ord[i].q, a);\n                ll mid = absl(ord[i].mx2 - 2LL * ax) + absl(ord[i].my2 - 2LL * ay);\n                sMid[i] = mid + ord[i].pq;\n                sSum[i] = dp + dq + 2LL * ord[i].pq;\n                sMax[i] = max(dp, dq) + 2LL * ord[i].pq;\n            }\n            addScoreVec(std::move(sMid));\n            addScoreVec(std::move(sSum));\n            addScoreVec(std::move(sMax));\n        }\n    }\n\n    // line-like scores\n    for (int type = 0; type < 4; ++type) {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) {\n            ll d1, d2;\n            if (type == 0) { // horizontal y=400\n                d1 = absl((ll)ord[i].p.y - 400);\n                d2 = absl((ll)ord[i].q.y - 400);\n            } else if (type == 1) { // vertical x=400\n                d1 = absl((ll)ord[i].p.x - 400);\n                d2 = absl((ll)ord[i].q.x - 400);\n            } else if (type == 2) { // x+y=800\n                d1 = absl((ll)ord[i].p.x + ord[i].p.y - 800);\n                d2 = absl((ll)ord[i].q.x + ord[i].q.y - 800);\n            } else { // x-y=0\n                d1 = absl((ll)ord[i].p.x - ord[i].p.y);\n                d2 = absl((ll)ord[i].q.x - ord[i].q.y);\n            }\n            sc[i] = max(d1, d2) + ord[i].pq;\n        }\n        int id = addScoreVec(std::move(sc));\n        if (type == 0) idLine0 = id;\n    }\n\n    // global scores\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = ord[i].pq;\n        idPair = addScoreVec(std::move(sc));\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = ord[i].op + ord[i].oq + ord[i].pq;\n        idOff = addScoreVec(std::move(sc));\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = ord[i].midOffice + ord[i].pq;\n        idMidOffice = addScoreVec(std::move(sc));\n    }\n\n    // ranking lists for swap pool\n    vector<vector<int>> rankLists(scoreVecs.size());\n    for (int sid = 0; sid < (int)scoreVecs.size(); ++sid) {\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        sort(ids.begin(), ids.end(), [&](int a, int b) {\n            if (scoreVecs[sid][a] != scoreVecs[sid][b]) return scoreVecs[sid][a] < scoreVecs[sid][b];\n            return a < b;\n        });\n        rankLists[sid] = std::move(ids);\n    }\n\n    vector<Cand> cands;\n    unordered_set<string> seen;\n\n    auto keyOfSel = [&](const vector<int>& sel) {\n        string s;\n        s.reserve(200);\n        for (int x : sel) {\n            s += to_string(x);\n            s.push_back(',');\n        }\n        return s;\n    };\n\n    for (int sid = 0; sid < (int)scoreVecs.size(); ++sid) {\n        for (int jitter = 0; jitter < 2; ++jitter) {\n            uint64_t seed = splitmix64(987654321ULL ^ (uint64_t)sid * 1234567ULL ^ (uint64_t)jitter * 891011ULL);\n            vector<int> sel = selectTop50(scoreVecs[sid], jitter == 1, seed);\n            string key = keyOfSel(sel);\n            if (seen.insert(key).second) {\n                cands.push_back({std::move(sel), sid, INFLL});\n            }\n        }\n    }\n\n    // quick evaluation\n    for (auto& c : cands) {\n        c.quickCost = quickEvalCand(c, scoreVecs);\n    }\n\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.quickCost != b.quickCost) return a.quickCost < b.quickCost;\n        return a.scoreId < b.scoreId;\n    });\n\n    int REFINE = min(10, (int)cands.size());\n\n    State globalBest;\n    globalBest.cost = INFLL;\n\n    vector<int> poolRankIds = {idPair, idOff, idMidOffice, idLine0};\n\n    for (int t = 0; t < REFINE; ++t) {\n        const Cand& c = cands[t];\n\n        vector<State> vars;\n        vars.reserve(9);\n        for (int v = 0; v <= 8; ++v) {\n            vars.push_back(buildVariantState(c.sel, c.scoreId, v, scoreVecs));\n        }\n\n        sort(vars.begin(), vars.end(), [&](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        int TAKE = min(2, (int)vars.size());\n        for (int i = 0; i < TAKE; ++i) {\n            State st = vars[i];\n            fullImprove(st, rankLists, {c.scoreId, idPair, idOff, idMidOffice, idLine0});\n            if (st.cost < globalBest.cost) globalBest = std::move(st);\n        }\n    }\n\n    // fallback: if something went wrong, use the best quick candidate\n    if (globalBest.cost == INFLL) {\n        const Cand& c = cands[0];\n        globalBest = buildVariantState(c.sel, c.scoreId, 0, scoreVecs);\n    }\n\n    vector<int> chosen = selectedIds(globalBest.used);\n    sort(chosen.begin(), chosen.end());\n\n    cout << 50;\n    for (int id : chosen) cout << ' ' << (id + 1);\n    cout << '\\n';\n\n    cout << globalBest.seq.size() + 2;\n    cout << ' ' << OFFICE.x << ' ' << OFFICE.y;\n    for (const auto& e : globalBest.seq) {\n        Pt p = pointOf(e);\n        cout << ' ' << p.x << ' ' << p.y;\n    }\n    cout << ' ' << OFFICE.x << ' ' << OFFICE.y << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        iota(p.begin(), p.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstatic inline int rounded_dist(int x1, int y1, int x2, int y2) {\n    long long dx = (long long)x1 - x2;\n    long long dy = (long long)y1 - y2;\n    long long s = dx * dx + dy * dy;\n    return (int)llround(sqrt((long double)s));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        edges[i].d = rounded_dist(\n            x[edges[i].u], y[edges[i].u],\n            x[edges[i].v], y[edges[i].v]\n        );\n    }\n\n    // Build the backbone tree by Kruskal on d.\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (edges[a].d != edges[b].d) return edges[a].d < edges[b].d;\n        return a < b;\n    });\n\n    vector<char> is_base(M, 0);\n    DSU dsu_build(N);\n    int base_cnt = 0;\n    for (int id : ord) {\n        if (dsu_build.unite(edges[id].u, edges[id].v)) {\n            is_base[id] = 1;\n            ++base_cnt;\n        }\n    }\n\n    // Tree structure of the backbone.\n    vector<vector<pair<int,int>>> g(N);\n    for (int id = 0; id < M; ++id) {\n        if (!is_base[id]) continue;\n        int u = edges[id].u, v = edges[id].v;\n        g[u].push_back({v, id});\n        g[v].push_back({u, id});\n    }\n\n    vector<int> parent(N, -1), depth(N, 0), pedge(N, -1);\n    {\n        stack<int> st;\n        st.push(0);\n        parent[0] = 0;\n        while (!st.empty()) {\n            int v = st.top();\n            st.pop();\n            for (auto [to, id] : g[v]) {\n                if (to == parent[v]) continue;\n                parent[to] = v;\n                depth[to] = depth[v] + 1;\n                pedge[to] = id;\n                st.push(to);\n            }\n        }\n    }\n\n    DSU dsu(N);\n    vector<char> base_seen(M, 0);\n\n    int seen_base_cnt = 0;\n    int extra_cnt = 0;\n    constexpr int EXTRA_LIMIT = 120;\n\n    auto evaluate_path = [&](int u, int v) {\n        int best_d = -1;\n        int best_id = -1;\n        int cnt_future = 0;\n\n        auto consider_edge = [&](int id) {\n            if (id < 0) return;\n            if (!base_seen[id]) {\n                ++cnt_future;\n                if (edges[id].d > best_d) {\n                    best_d = edges[id].d;\n                    best_id = id;\n                }\n            }\n        };\n\n        while (depth[u] > depth[v]) {\n            consider_edge(pedge[u]);\n            u = parent[u];\n        }\n        while (depth[v] > depth[u]) {\n            consider_edge(pedge[v]);\n            v = parent[v];\n        }\n        while (u != v) {\n            consider_edge(pedge[u]);\n            consider_edge(pedge[v]);\n            u = parent[u];\n            v = parent[v];\n        }\n        return tuple<int,int,int>(best_d, best_id, cnt_future);\n    };\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n\n        bool take = false;\n\n        if (is_base[i]) {\n            base_seen[i] = 1;\n            ++seen_base_cnt;\n\n            // Always keep backbone edges if they still connect components.\n            if (dsu.unite(edges[i].u, edges[i].v)) {\n                take = true;\n            }\n        } else {\n            // Conservative extra-edge policy.\n            if (extra_cnt < EXTRA_LIMIT && seen_base_cnt < base_cnt) {\n                if (dsu.find(edges[i].u) != dsu.find(edges[i].v)) {\n                    auto [best_d, best_id, cnt_future] = evaluate_path(edges[i].u, edges[i].v);\n\n                    // Only consider if there is still a future backbone edge on the path.\n                    if (best_d >= 30 && best_id != -1) {\n                        double thr = 1.10\n                                   + 0.02 * min(cnt_future, 5)\n                                   + 0.04 * (double)(base_cnt - seen_base_cnt) / base_cnt;\n\n                        if (best_d >= 50)  thr += 0.03;\n                        if (best_d >= 100) thr += 0.04;\n                        if (best_d >= 200) thr += 0.04;\n                        thr = min(thr, 1.38);\n\n                        if ((double)l <= thr * (double)best_d) {\n                            if (dsu.unite(edges[i].u, edges[i].v)) {\n                                take = true;\n                                ++extra_cnt;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        cout << (take ? 1 : 0) << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstatic const int HN = 30;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<Point> pets(N);\n    vector<int> ptype(N);\n    vector<vector<int>> petOcc(HN + 1, vector<int>(HN + 1, 0));\n\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> ptype[i];\n        petOcc[pets[i].x][pets[i].y]++;\n    }\n\n    int M;\n    cin >> M;\n    vector<Point> humans(M);\n    for (int i = 0; i < M; ++i) cin >> humans[i].x >> humans[i].y;\n\n    // Prefix sum of initial pet positions\n    vector<vector<int>> ps(HN + 1 + 1, vector<int>(HN + 1 + 1, 0)); // 32 x 32 enough\n    for (int i = 1; i <= HN; ++i) {\n        for (int j = 1; j <= HN; ++j) {\n            ps[i][j] = petOcc[i][j] + ps[i - 1][j] + ps[i][j - 1] - ps[i - 1][j - 1];\n        }\n    }\n\n    auto rectSum = [&](int r1, int c1, int r2, int c2) -> int {\n        if (r1 > r2 || c1 > c2) return 0;\n        return ps[r2][c2] - ps[r1 - 1][c2] - ps[r2][c1 - 1] + ps[r1 - 1][c1 - 1];\n    };\n\n    auto clampv = [](int v, int l, int r) {\n        return max(l, min(r, v));\n    };\n\n    auto distRect = [&](Point p, int r1, int r2, int c1, int c2) -> int {\n        int dx = 0, dy = 0;\n        if (p.x < r1) dx = r1 - p.x;\n        else if (p.x > r2) dx = p.x - r2;\n        if (p.y < c1) dy = c1 - p.y;\n        else if (p.y > c2) dy = p.y - c2;\n        return dx + dy;\n    };\n\n    struct BestRect {\n        int r1 = -1, r2 = -1, c1 = -1, c2 = -1;\n        long long score = LLONG_MIN;\n        int area = 0;\n    } best;\n\n    // Search an empty rectangle Q.\n    // Final safe area is the inner rectangle Q shrunk by 2 cells on each side.\n    for (int r1 = 1; r1 <= HN; ++r1) {\n        for (int r2 = r1 + 4; r2 <= HN; ++r2) { // height >= 5\n            for (int c1 = 1; c1 <= HN; ++c1) {\n                for (int c2 = c1 + 4; c2 <= HN; ++c2) { // width >= 5\n                    if (rectSum(r1, c1, r2, c2) != 0) continue;\n\n                    int h = r2 - r1 + 1;\n                    int w = c2 - c1 + 1;\n                    int innerH = h - 4;\n                    int innerW = w - 4;\n                    if (innerH <= 0 || innerW <= 0) continue;\n\n                    long long area = 1LL * innerH * innerW;\n                    long long perim = 2LL * (h + w);\n\n                    long long pen = 0;\n                    for (auto &p : pets) {\n                        int d = distRect(p, r1, r2, c1, c2);\n                        pen += 1000LL / (d + 1);\n                    }\n\n                    long long score = area * 100000LL - perim * 1000LL - pen;\n\n                    if (score > best.score) {\n                        best.score = score;\n                        best.r1 = r1; best.r2 = r2;\n                        best.c1 = c1; best.c2 = c2;\n                        best.area = (int)area;\n                    }\n                }\n            }\n        }\n    }\n\n    // If no usable rectangle is found, fall back to doing nothing.\n    if (best.r1 == -1 || best.area <= 0) {\n        for (int turn = 0; turn < 300; ++turn) {\n            cout << string(M, '.') << '\\n' << flush;\n            for (int i = 0; i < N; ++i) {\n                string s;\n                cin >> s;\n            }\n        }\n        return 0;\n    }\n\n    int r1 = best.r1, r2 = best.r2, c1 = best.c1, c2 = best.c2;\n    int x1 = r1 + 2, x2 = r2 - 2;\n    int y1 = c1 + 2, y2 = c2 - 2;\n    int H = x2 - x1 + 1; // inner height\n    int W = y2 - y1 + 1; // inner width\n\n    // Roles:\n    // 0: TOP    - start at (x1, y1), wall up, move right\n    // 1: LEFT   - start at (x1, y1), wall left, move down\n    // 2: BOTTOM - start at (x2, y1), wall down, move right\n    // 3: RIGHT  - start at (x1, y2), wall right, move down\n    enum Role { IDLE = 0, TOP = 1, LEFT = 2, BOTTOM = 3, RIGHT = 4 };\n\n    vector<int> role(M, IDLE);\n    vector<Point> target(M);\n\n    Point topStart{ x1, y1 };\n    Point leftStart{ x1, y1 };\n    Point bottomStart{ x2, y1 };\n    Point rightStart{ x1, y2 };\n\n    Point centerTarget{ clampv((x1 + x2) / 2, x1, x2), clampv((y1 + y2) / 2, y1, y2) };\n\n    // Choose 4 distinct humans for the 4 builder roles.\n    long long bestEval = LLONG_MAX;\n    array<int, 4> bestPick{-1, -1, -1, -1};\n\n    auto dman = [&](int i, Point t) -> int {\n        return abs(humans[i].x - t.x) + abs(humans[i].y - t.y);\n    };\n\n    vector<Point> roleTargets = { topStart, leftStart, bottomStart, rightStart };\n\n    for (int a = 0; a < M; ++a) for (int b = 0; b < M; ++b) if (b != a)\n    for (int c = 0; c < M; ++c) if (c != a && c != b)\n    for (int d = 0; d < M; ++d) if (d != a && d != b && d != c) {\n        array<int, 4> pick{a, b, c, d};\n\n        long long mx = 0, sum = 0;\n        bool used[20] = {};\n        for (int id : pick) used[id] = true;\n\n        mx = max<long long>(mx, dman(a, roleTargets[0]));\n        mx = max<long long>(mx, dman(b, roleTargets[1]));\n        mx = max<long long>(mx, dman(c, roleTargets[2]));\n        mx = max<long long>(mx, dman(d, roleTargets[3]));\n        sum += dman(a, roleTargets[0]);\n        sum += dman(b, roleTargets[1]);\n        sum += dman(c, roleTargets[2]);\n        sum += dman(d, roleTargets[3]);\n\n        for (int i = 0; i < M; ++i) if (!used[i]) {\n            Point t{ clampv(humans[i].x, x1, x2), clampv(humans[i].y, y1, y2) };\n            int dd = dman(i, t);\n            mx = max<long long>(mx, dd);\n            sum += dd;\n        }\n\n        long long eval = mx * 100000LL + sum;\n        if (eval < bestEval) {\n            bestEval = eval;\n            bestPick = pick;\n        }\n    }\n\n    // Assign roles\n    vector<Point> idleTarget(M);\n    for (int i = 0; i < M; ++i) idleTarget[i] = { clampv(humans[i].x, x1, x2), clampv(humans[i].y, y1, y2) };\n\n    role[bestPick[0]] = TOP;\n    role[bestPick[1]] = LEFT;\n    role[bestPick[2]] = BOTTOM;\n    role[bestPick[3]] = RIGHT;\n\n    target[bestPick[0]] = topStart;\n    target[bestPick[1]] = leftStart;\n    target[bestPick[2]] = bottomStart;\n    target[bestPick[3]] = rightStart;\n\n    for (int i = 0; i < M; ++i) {\n        if (role[i] == IDLE) target[i] = idleTarget[i];\n    }\n\n    // Movement phase duration\n    int moveTurns = 0;\n    for (int i = 0; i < M; ++i) {\n        moveTurns = max(moveTurns, abs(humans[i].x - target[i].x) + abs(humans[i].y - target[i].y));\n    }\n\n    // Builder state\n    struct BuilderState {\n        int idx = 0;\n        bool needWall = true;\n        bool done = false;\n    };\n    vector<BuilderState> bs(M);\n\n    auto inBoard = [](int x, int y) {\n        return 1 <= x && x <= HN && 1 <= y && y <= HN;\n    };\n\n    vector<vector<int>> humanOcc(HN + 1, vector<int>(HN + 1, 0));\n    for (auto &h : humans) humanOcc[h.x][h.y]++;\n\n    auto rebuildHumanOcc = [&]() {\n        for (int i = 1; i <= HN; ++i) fill(humanOcc[i].begin(), humanOcc[i].end(), 0);\n        for (auto &h : humans) humanOcc[h.x][h.y]++;\n    };\n\n    auto safeToWall = [&](int x, int y) -> bool {\n        if (!inBoard(x, y)) return false;\n        if (petOcc[x][y] > 0) return false;\n        if (humanOcc[x][y] > 0) return false;\n        static int dx[4] = {-1, 1, 0, 0};\n        static int dy[4] = {0, 0, -1, 1};\n        for (int dir = 0; dir < 4; ++dir) {\n            int nx = x + dx[dir], ny = y + dy[dir];\n            if (inBoard(nx, ny) && petOcc[nx][ny] > 0) return false;\n        }\n        return true;\n    };\n\n    auto petInsideTarget = [&]() -> bool {\n        for (auto &p : pets) {\n            if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) return true;\n        }\n        return false;\n    };\n\n    auto wallChar = [&](int r) -> char {\n        if (r == TOP) return 'u';\n        if (r == BOTTOM) return 'd';\n        if (r == LEFT) return 'l';\n        return 'r';\n    };\n\n    auto moveChar = [&](int r) -> char {\n        if (r == TOP || r == BOTTOM) return 'R';\n        return 'D';\n    };\n\n    auto wallTarget = [&](int r, const Point &p) -> Point {\n        if (r == TOP) return { p.x - 1, p.y };\n        if (r == BOTTOM) return { p.x + 1, p.y };\n        if (r == LEFT) return { p.x, p.y - 1 };\n        return { p.x, p.y + 1 };\n    };\n\n    auto sideLen = [&](int r) -> int {\n        if (r == TOP || r == BOTTOM) return W;\n        if (r == LEFT || r == RIGHT) return H;\n        return 0;\n    };\n\n    // To reduce risk of pets wandering into the target area while we wait,\n    // we allow a short waiting period after humans reach their targets.\n    const int WAIT_LIMIT = 20;\n\n    for (int turn = 0; turn < 300; ++turn) {\n        string out(M, '.');\n        vector<Point> nextPos = humans;\n\n        if (turn < moveTurns) {\n            // Move each human toward its assigned target.\n            for (int i = 0; i < M; ++i) {\n                if (humans[i].x < target[i].x) {\n                    out[i] = 'D';\n                    nextPos[i].x++;\n                } else if (humans[i].x > target[i].x) {\n                    out[i] = 'U';\n                    nextPos[i].x--;\n                } else if (humans[i].y < target[i].y) {\n                    out[i] = 'R';\n                    nextPos[i].y++;\n                } else if (humans[i].y > target[i].y) {\n                    out[i] = 'L';\n                    nextPos[i].y--;\n                } else {\n                    out[i] = '.';\n                }\n            }\n        } else {\n            bool forced = (turn >= moveTurns + WAIT_LIMIT);\n            bool canBuild = forced || !petInsideTarget();\n\n            if (canBuild) {\n                for (int i = 0; i < M; ++i) {\n                    if (role[i] == IDLE) continue;\n                    if (bs[i].done) continue;\n\n                    int len = sideLen(role[i]);\n                    if (len <= 0) {\n                        bs[i].done = true;\n                        continue;\n                    }\n\n                    if (bs[i].needWall) {\n                        Point wt = wallTarget(role[i], humans[i]);\n                        if (safeToWall(wt.x, wt.y)) {\n                            out[i] = wallChar(role[i]);\n                            // Wall built (or already impassable) if target is safe.\n                            // Mark it in our local map.\n                            // (If the cell was already impassable, this is harmless.)\n                            // We only need the wall map implicitly for safety checks.\n                            // No separate wall grid is necessary for the logic.\n                            // The target is inside the board by construction.\n                            // If the current cell is the last one, finish after walling.\n                            if (bs[i].idx == len - 1) {\n                                bs[i].done = true;\n                            } else {\n                                bs[i].needWall = false;\n                            }\n                        } else {\n                            out[i] = '.';\n                        }\n                    } else {\n                        if (bs[i].idx + 1 < len) {\n                            out[i] = moveChar(role[i]);\n                            if (role[i] == TOP || role[i] == BOTTOM) nextPos[i].y++;\n                            else nextPos[i].x++;\n                            bs[i].idx++;\n                            bs[i].needWall = true;\n                        } else {\n                            bs[i].done = true;\n                            out[i] = '.';\n                        }\n                    }\n                }\n            } else {\n                // Wait a bit for pets to leave the target area.\n                // All humans do nothing.\n            }\n        }\n\n        cout << out << '\\n' << flush;\n\n        // Apply human moves\n        humans = nextPos;\n        rebuildHumanOcc();\n\n        // Read pet movement strings and update pet positions.\n        vector<string> mv(N);\n        for (int i = 0; i < N; ++i) cin >> mv[i];\n\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].x, y = pets[i].y;\n            for (char ch : mv[i]) {\n                if (ch == 'U') --x;\n                else if (ch == 'D') ++x;\n                else if (ch == 'L') --y;\n                else if (ch == 'R') ++y;\n            }\n            pets[i] = {x, y};\n        }\n\n        // Rebuild pet occupancy\n        for (int i = 1; i <= HN; ++i) fill(petOcc[i].begin(), petOcc[i].end(), 0);\n        for (auto &p : pets) petOcc[p.x][p.y]++;\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int MAXL = 200;\nstatic constexpr double P_INF = 1e100;\n\nint si, sj, ti, tj;\ndouble p, qprob;\nvector<string> hwall(20), vwall(19);\n\nint startPos, goalPos;\nint moveTo[4][N];\nint distGoal[N];\nint c2d[256];\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\ninline int id(int i, int j) { return i * W + j; }\n\nbool open_move(int pos, int dir) {\n    int i = pos / W, j = pos % W;\n    if (dir == 0) return i > 0 && vwall[i - 1][j] == '0';\n    if (dir == 1) return i + 1 < H && vwall[i][j] == '0';\n    if (dir == 2) return j > 0 && hwall[i][j - 1] == '0';\n    if (dir == 3) return j + 1 < W && hwall[i][j] == '0';\n    return false;\n}\n\nstruct State {\n    array<double, N> prob{};\n    double score = 0.0;\n    double bound = 0.0;\n    int len = 0;\n    string s;\n};\n\ndouble computeBound(const State& st) {\n    double pot = 0.0;\n    for (int pos = 0; pos < N; ++pos) {\n        if (pos == goalPos) continue;\n        double pr = st.prob[pos];\n        if (pr == 0.0) continue;\n        double rem = 401.0 - st.len - distGoal[pos];\n        if (rem > 0.0) pot += pr * rem;\n    }\n    return st.score + pot;\n}\n\nState makeInitialState() {\n    State st;\n    st.prob.fill(0.0);\n    st.prob[startPos] = 1.0;\n    st.score = 0.0;\n    st.len = 0;\n    st.s.clear();\n    st.bound = computeBound(st);\n    return st;\n}\n\nbool uselessDir(const State& st, int dir) {\n    for (int pos = 0; pos < N; ++pos) {\n        double pr = st.prob[pos];\n        if (pr == 0.0) continue;\n        if (pos == goalPos) continue;\n        if (moveTo[dir][pos] != pos) return false;\n    }\n    return true;\n}\n\nState advanceState(const State& st, int dir) {\n    State ch;\n    ch.prob.fill(0.0);\n    ch.score = st.score;\n    ch.len = st.len + 1;\n    ch.s = st.s;\n    ch.s.push_back(dch[dir]);\n\n    double reward = 401.0 - ch.len;\n\n    for (int pos = 0; pos < N; ++pos) {\n        double pr = st.prob[pos];\n        if (pr == 0.0) continue;\n\n        if (pos == goalPos) {\n            ch.prob[goalPos] += pr;\n            continue;\n        }\n\n        double stay = pr * p;\n        double mv = pr * qprob;\n        ch.prob[pos] += stay;\n\n        int np = moveTo[dir][pos];\n        if (np == goalPos) {\n            ch.score += mv * reward;\n            ch.prob[goalPos] += mv;\n        } else {\n            ch.prob[np] += mv;\n        }\n    }\n\n    ch.bound = computeBound(ch);\n    return ch;\n}\n\nState simulateApprox(const string& s) {\n    State st = makeInitialState();\n    for (char c : s) {\n        int d = c2d[(unsigned char)c];\n        if (d < 0) continue;\n        st = advanceState(st, d);\n    }\n    return st;\n}\n\ndouble evalExact(const string& s) {\n    array<double, N> cur{}, nxt{};\n    cur.fill(0.0);\n    nxt.fill(0.0);\n    cur[startPos] = 1.0;\n\n    double score = 0.0;\n\n    for (int t = 0; t < (int)s.size(); ++t) {\n        if (cur[goalPos] >= 1.0 - 1e-15) break;\n\n        nxt.fill(0.0);\n        int dir = c2d[(unsigned char)s[t]];\n        if (dir < 0) return 0.0;\n\n        double reward = 401.0 - (t + 1);\n\n        for (int pos = 0; pos < N; ++pos) {\n            double pr = cur[pos];\n            if (pr == 0.0) continue;\n\n            if (pos == goalPos) {\n                nxt[goalPos] += pr;\n                continue;\n            }\n\n            double stay = pr * p;\n            double mv = pr * qprob;\n\n            nxt[pos] += stay;\n\n            int np = moveTo[dir][pos];\n            if (np == goalPos) {\n                score += mv * reward;\n                nxt[goalPos] += mv;\n            } else {\n                nxt[np] += mv;\n            }\n        }\n\n        cur.swap(nxt);\n    }\n\n    return score;\n}\n\nstring bfsShortestPath() {\n    vector<int> dist(N, -1), par(N, -1);\n    vector<char> pch(N, '?');\n    queue<int> q;\n    dist[startPos] = 0;\n    q.push(startPos);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == goalPos) break;\n        for (int d = 0; d < 4; ++d) {\n            int nv = moveTo[d][v];\n            if (nv == v) continue;\n            if (dist[nv] != -1) continue;\n            dist[nv] = dist[v] + 1;\n            par[nv] = v;\n            pch[nv] = dch[d];\n            q.push(nv);\n        }\n    }\n\n    if (dist[goalPos] == -1) return \"\";\n    string s;\n    for (int cur = goalPos; cur != startPos; cur = par[cur]) s.push_back(pch[cur]);\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstring bfsMonotoneDR() {\n    vector<int> dist(N, -1), par(N, -1);\n    vector<char> pch(N, '?');\n    queue<int> q;\n    dist[startPos] = 0;\n    q.push(startPos);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == goalPos) break;\n        for (int d : {1, 3}) {\n            int nv = moveTo[d][v];\n            if (nv == v) continue;\n            if (dist[nv] != -1) continue;\n            dist[nv] = dist[v] + 1;\n            par[nv] = v;\n            pch[nv] = dch[d];\n            q.push(nv);\n        }\n    }\n\n    if (dist[goalPos] == -1) return \"\";\n    string s;\n    for (int cur = goalPos; cur != startPos; cur = par[cur]) s.push_back(pch[cur]);\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstring directLShape(bool rowThenCol) {\n    string s;\n    if (rowThenCol) {\n        // D... then R...\n        for (int i = si; i < ti; ++i) if (vwall[i][sj] == '1') return \"\";\n        for (int j = sj; j < tj; ++j) if (hwall[ti][j] == '1') return \"\";\n        s.append(ti - si, 'D');\n        s.append(tj - sj, 'R');\n    } else {\n        // R... then D...\n        for (int j = sj; j < tj; ++j) if (hwall[si][j] == '1') return \"\";\n        for (int i = si; i < ti; ++i) if (vwall[i][tj] == '1') return \"\";\n        s.append(tj - sj, 'R');\n        s.append(ti - si, 'D');\n    }\n    return s;\n}\n\nstring dijkstraTurnPenalty(int turnPenalty) {\n    const long long INF = (1LL << 60);\n    int S = N * 5;\n    vector<long long> dist(S, INF);\n    vector<int> par(S, -1);\n    vector<char> pch(S, '?');\n\n    auto sid = [&](int pos, int prev) { return pos * 5 + prev; };\n\n    int st = sid(startPos, 4);\n    dist[st] = 0;\n\n    using P = pair<long long, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.push({0, st});\n\n    while (!pq.empty()) {\n        auto [cd, cur] = pq.top();\n        pq.pop();\n        if (cd != dist[cur]) continue;\n\n        int pos = cur / 5;\n        int prev = cur % 5;\n\n        for (int d = 0; d < 4; ++d) {\n            int np = moveTo[d][pos];\n            if (np == pos) continue;\n            long long nd = cd + 1 + ((prev != 4 && prev != d) ? turnPenalty : 0);\n            int ns = sid(np, d);\n            if (nd < dist[ns]) {\n                dist[ns] = nd;\n                par[ns] = cur;\n                pch[ns] = dch[d];\n                pq.push({nd, ns});\n            }\n        }\n    }\n\n    int best = -1;\n    long long bestd = INF;\n    for (int prev = 0; prev < 4; ++prev) {\n        int gs = sid(goalPos, prev);\n        if (dist[gs] < bestd) {\n            bestd = dist[gs];\n            best = gs;\n        }\n    }\n    if (best == -1 || bestd == INF) return \"\";\n\n    string s;\n    for (int cur = best; cur != st; cur = par[cur]) s.push_back(pch[cur]);\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstring greedyBoundTemplate() {\n    State cur = makeInitialState();\n    string s;\n    s.reserve(MAXL);\n\n    for (int step = 0; step < MAXL; ++step) {\n        int bestDir = -1;\n        State bestCh;\n\n        for (int d = 0; d < 4; ++d) {\n            if (uselessDir(cur, d)) continue;\n            State ch = advanceState(cur, d);\n            if (bestDir == -1 ||\n                ch.bound > bestCh.bound ||\n                (ch.bound == bestCh.bound && ch.score > bestCh.score)) {\n                bestDir = d;\n                bestCh = std::move(ch);\n            }\n        }\n\n        if (bestDir == -1) break;\n        if (bestCh.bound <= cur.score + 1e-12) break;\n\n        s.push_back(dch[bestDir]);\n        cur = std::move(bestCh);\n    }\n\n    return s;\n}\n\nvoid addPrefixes(vector<string>& seeds, const string& raw) {\n    if (raw.empty()) return;\n    string s = raw;\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n\n    vector<int> cuts;\n    int L = (int)s.size();\n    for (int c : {10, 20, 40, 80, L}) {\n        if (c > 0) cuts.push_back(min(c, L));\n    }\n    sort(cuts.begin(), cuts.end());\n    cuts.erase(unique(cuts.begin(), cuts.end()), cuts.end());\n\n    for (int c : cuts) seeds.push_back(s.substr(0, c));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj >> ti >> tj >> p;\n    qprob = 1.0 - p;\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    startPos = id(si, sj);\n    goalPos = id(ti, tj);\n\n    for (int i = 0; i < 256; ++i) c2d[i] = -1;\n    c2d[(unsigned char)'U'] = 0;\n    c2d[(unsigned char)'D'] = 1;\n    c2d[(unsigned char)'L'] = 2;\n    c2d[(unsigned char)'R'] = 3;\n\n    for (int pos = 0; pos < N; ++pos) {\n        for (int d = 0; d < 4; ++d) {\n            moveTo[d][pos] = open_move(pos, d) ? (\n                [&]() {\n                    int i = pos / W, j = pos % W;\n                    if (d == 0) return id(i - 1, j);\n                    if (d == 1) return id(i + 1, j);\n                    if (d == 2) return id(i, j - 1);\n                    return id(i, j + 1);\n                }()\n            ) : pos;\n        }\n    }\n\n    // Shortest distances from every cell to goal.\n    {\n        fill(distGoal, distGoal + N, -1);\n        queue<int> q;\n        distGoal[goalPos] = 0;\n        q.push(goalPos);\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nv = moveTo[d][v];\n                if (nv == v) continue;\n                if (distGoal[nv] != -1) continue;\n                distGoal[nv] = distGoal[v] + 1;\n                q.push(nv);\n            }\n        }\n    }\n\n    vector<string> rawTemplates;\n    rawTemplates.reserve(16);\n\n    // Baselines\n    rawTemplates.push_back(bfsShortestPath());\n    rawTemplates.push_back(bfsMonotoneDR());\n    rawTemplates.push_back(directLShape(true));\n    rawTemplates.push_back(directLShape(false));\n    rawTemplates.push_back(greedyBoundTemplate());\n\n    for (int pen : {1, 4, 16, 64, 256}) {\n        rawTemplates.push_back(dijkstraTurnPenalty(pen));\n    }\n\n    // Build seed strings with prefixes.\n    vector<string> seedStrings;\n    seedStrings.reserve(128);\n    seedStrings.push_back(\"\"); // empty seed\n    for (const string& t : rawTemplates) addPrefixes(seedStrings, t);\n\n    sort(seedStrings.begin(), seedStrings.end());\n    seedStrings.erase(unique(seedStrings.begin(), seedStrings.end()), seedStrings.end());\n\n    // Simulate seeds to initialize beam.\n    vector<State> beam;\n    beam.reserve(seedStrings.size());\n    for (const string& s : seedStrings) {\n        State st = simulateApprox(s);\n        beam.push_back(std::move(st));\n    }\n\n    auto cmpBound = [](const State& a, const State& b) {\n        if (a.bound != b.bound) return a.bound > b.bound;\n        if (a.score != b.score) return a.score > b.score;\n        return a.len < b.len;\n    };\n\n    const int BEAM = 80;\n\n    // Keep an exact candidate pool as strings.\n    vector<string> pool;\n    pool.reserve(800);\n    for (const string& s : seedStrings) pool.push_back(s);\n\n    string bestApproxScoreStr = \"\";\n    double bestApproxScoreVal = -1e100;\n    string bestApproxBoundStr = \"\";\n    double bestApproxBoundVal = -1e100;\n\n    // Initialize best approx with seeds.\n    for (const State& st : beam) {\n        if (st.score > bestApproxScoreVal) {\n            bestApproxScoreVal = st.score;\n            bestApproxScoreStr = st.s;\n        }\n        if (st.bound > bestApproxBoundVal) {\n            bestApproxBoundVal = st.bound;\n            bestApproxBoundStr = st.s;\n        }\n    }\n\n    // Beam search over prefixes.\n    for (int iter = 0; iter < MAXL; ++iter) {\n        vector<State> cand;\n        cand.reserve(beam.size() * 4);\n\n        for (const State& st : beam) {\n            if (st.len >= MAXL) continue;\n            if (st.bound <= st.score + 1e-12) continue; // no future improvement possible\n\n            for (int d = 0; d < 4; ++d) {\n                if (uselessDir(st, d)) continue;\n                State ch = advanceState(st, d);\n\n                if (ch.score > bestApproxScoreVal) {\n                    bestApproxScoreVal = ch.score;\n                    bestApproxScoreStr = ch.s;\n                }\n                if (ch.bound > bestApproxBoundVal) {\n                    bestApproxBoundVal = ch.bound;\n                    bestApproxBoundStr = ch.s;\n                }\n\n                cand.push_back(std::move(ch));\n            }\n        }\n\n        if (cand.empty()) break;\n\n        int bestScoreIdx = 0, bestBoundIdx = 0;\n        for (int i = 1; i < (int)cand.size(); ++i) {\n            if (cand[i].score > cand[bestScoreIdx].score ||\n                (cand[i].score == cand[bestScoreIdx].score && cand[i].bound > cand[bestScoreIdx].bound)) {\n                bestScoreIdx = i;\n            }\n            if (cand[i].bound > cand[bestBoundIdx].bound ||\n                (cand[i].bound == cand[bestBoundIdx].bound && cand[i].score > cand[bestBoundIdx].score)) {\n                bestBoundIdx = i;\n            }\n        }\n        pool.push_back(cand[bestScoreIdx].s);\n        pool.push_back(cand[bestBoundIdx].s);\n\n        if ((int)cand.size() > BEAM) {\n            nth_element(cand.begin(), cand.begin() + BEAM, cand.end(), cmpBound);\n            cand.resize(BEAM);\n        }\n\n        beam = std::move(cand);\n    }\n\n    // Add final beam states and global best approximate strings.\n    for (const State& st : beam) pool.push_back(st.s);\n    pool.push_back(bestApproxScoreStr);\n    pool.push_back(bestApproxBoundStr);\n\n    sort(pool.begin(), pool.end());\n    pool.erase(unique(pool.begin(), pool.end()), pool.end());\n\n    // Exact evaluation of pooled candidates.\n    string answer = \"\";\n    double bestExact = -1.0;\n    for (const string& s : pool) {\n        double sc = evalExact(s);\n        if (sc > bestExact) {\n            bestExact = sc;\n            answer = s;\n        }\n    }\n\n    if (answer.empty()) {\n        // Safety fallback.\n        answer = bfsShortestPath();\n        if ((int)answer.size() > MAXL) answer.resize(MAXL);\n    }\n\n    cout << answer << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int S = N * N;\nstatic constexpr int ST = S * 4;\n\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\nint baseTo[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1},\n};\n\nint nxtDir[8][4][4]; // nxtDir[t][rot][entry_dir] -> exit_dir, or -1\n\nusing RotArr = array<uint8_t, S>;\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 EvalResult {\n    long long score = -1;\n    int cycles = 0;\n    int l1 = 0, l2 = 0;\n    vector<int> hotCells;\n};\n\nint rotCorner[8][4];\nint rotPair[8][2];\n\nstatic inline bool better(const EvalResult& a, const EvalResult& b) {\n    if (a.score != b.score) return a.score > b.score;\n    if (a.cycles != b.cycles) return a.cycles > b.cycles;\n    if (a.l1 + a.l2 != b.l1 + b.l2) return a.l1 + a.l2 > b.l1 + b.l2;\n    if (a.l1 != b.l1) return a.l1 > b.l1;\n    return a.l2 > b.l2;\n}\n\nstatic inline void apply_sym(int sym, int i, int j, int& u, int& v) {\n    switch (sym) {\n        case 0: u = i; v = j; break;\n        case 1: u = i; v = N - 1 - j; break;\n        case 2: u = N - 1 - i; v = j; break;\n        case 3: u = N - 1 - i; v = N - 1 - j; break;\n        case 4: u = j; v = i; break;\n        case 5: u = j; v = N - 1 - i; break;\n        case 6: u = N - 1 - j; v = i; break;\n        case 7: u = N - 1 - j; v = N - 1 - i; break;\n    }\n}\n\nstatic inline int pattern_value(int pid, int u, int v, uint64_t seed) {\n    switch (pid) {\n        case 0: return u + v;\n        case 1: return u - v + 29;\n        case 2: return ((u & 1) << 1) | (v & 1);                 // 2x2 checkerboard\n        case 3: return (u / 2) * 4 + (v / 2);                    // 2x2 coarse\n        case 4: return (u / 3) * 4 + (v / 3);                    // 3x3 coarse\n        case 5: return min(min(u, 29 - u), min(v, 29 - v));      // border distance\n        case 6: return abs(u - 15) + abs(v - 15);                // center distance\n        case 7: return (int)(splitmix64(seed + (uint64_t)u * 10007ULL + (uint64_t)v * 10009ULL) & 1023ULL);\n    }\n    return u + v;\n}\n\nEvalResult evaluate(const RotArr& rot, const array<int, S>& tile) {\n    static int succ[ST];\n    static uint8_t vis[ST];\n    static int pos[ST];\n    static uint8_t mark[S];\n\n    memset(vis, 0, sizeof(vis));\n    memset(mark, 0, sizeof(mark));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int base = (i * N + j) * 4;\n            int t = tile[i * N + j];\n            int r = rot[i * N + j];\n            for (int d = 0; d < 4; ++d) {\n                int d2 = nxtDir[t][r][d];\n                if (d2 < 0) {\n                    succ[base + d] = -1;\n                    continue;\n                }\n                int ni = i + di[d2];\n                int nj = j + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    succ[base + d] = -1;\n                    continue;\n                }\n                int nd = (d2 + 2) & 3;\n                succ[base + d] = (ni * N + nj) * 4 + nd;\n            }\n        }\n    }\n\n    vector<int> lens;\n    vector<vector<int>> cycStates;\n    vector<int> st;\n    st.reserve(ST);\n    lens.reserve(1024);\n    cycStates.reserve(1024);\n\n    for (int s = 0; s < ST; ++s) {\n        if (vis[s]) continue;\n        int cur = s;\n        st.clear();\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;\n            pos[cur] = (int)st.size();\n            st.push_back(cur);\n            cur = succ[cur];\n        }\n        if (cur != -1 && vis[cur] == 1) {\n            vector<int> cyc(st.begin() + pos[cur], st.end());\n            lens.push_back((int)cyc.size());\n            cycStates.push_back(move(cyc));\n        }\n        for (int v : st) vis[v] = 2;\n    }\n\n    EvalResult res;\n    res.cycles = (int)lens.size();\n    if (res.cycles >= 1) {\n        vector<int> ord(res.cycles);\n        iota(ord.begin(), ord.end(), 0);\n        int top = min(4, res.cycles);\n        partial_sort(ord.begin(), ord.begin() + top, ord.end(), [&](int a, int b) {\n            if (lens[a] != lens[b]) return lens[a] > lens[b];\n            return a < b;\n        });\n\n        res.l1 = lens[ord[0]];\n        if (res.cycles >= 2) res.l2 = lens[ord[1]];\n        res.score = (res.cycles >= 2 ? 1LL * res.l1 * res.l2 : 0LL);\n\n        auto add_hot = [&](int cell) {\n            if (cell < 0 || cell >= S) return;\n            mark[cell] = 1;\n            int i = cell / N, j = cell % N;\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) mark[ni * N + nj] = 1;\n            }\n        };\n\n        for (int k = 0; k < top; ++k) {\n            for (int stid : cycStates[ord[k]]) {\n                add_hot(stid / 4);\n            }\n        }\n\n        for (int i = 0; i < S; ++i) if (mark[i]) res.hotCells.push_back(i);\n    }\n\n    return res;\n}\n\nRotArr make_candidate(const array<int, S>& tile, int pid, int sym, int mode, uint64_t seed) {\n    RotArr rot{};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u, v;\n            apply_sym(sym, i, j, u, v);\n            int x = pattern_value(pid, u, v, seed);\n            int t = tile[i * N + j];\n\n            if (t <= 3) {\n                int kind;\n                if (mode == 0) kind = x & 3;\n                else kind = (x ^ (x >> 1)) & 3;\n                int r = rotCorner[t][kind];\n                if (r < 0) r = 0;\n                rot[i * N + j] = (uint8_t)r;\n            } else {\n                int kind;\n                if (mode == 0) kind = x & 1;\n                else kind = (x ^ (x >> 1)) & 1;\n                int r = rotPair[t][kind];\n                if (r < 0) r = 0;\n                rot[i * N + j] = (uint8_t)r;\n            }\n        }\n    }\n    return rot;\n}\n\nstatic inline int pick_cell(const vector<int>& hot, mt19937_64& rng) {\n    if (!hot.empty() && (rng() % 100) < 75) return hot[rng() % hot.size()];\n    return (int)(rng() % S);\n}\n\nbool try_best_cell(RotArr& cur, EvalResult& curEv, const array<int, S>& tile, int cell) {\n    uint8_t old = cur[cell];\n    uint8_t bestR = old;\n    EvalResult bestEv = curEv;\n\n    for (int r = 0; r < 4; ++r) {\n        if (r == old) continue;\n        cur[cell] = (uint8_t)r;\n        EvalResult ev = evaluate(cur, tile);\n        if (better(ev, bestEv)) {\n            bestEv = move(ev);\n            bestR = (uint8_t)r;\n        }\n    }\n\n    cur[cell] = bestR;\n    if (bestR != old) {\n        curEv = move(bestEv);\n        return true;\n    }\n    return false;\n}\n\nbool try_best_block(RotArr& cur, EvalResult& curEv, const array<int, S>& tile, int bi, int bj, mt19937_64& rng) {\n    RotArr bak = cur;\n    EvalResult bakEv = curEv;\n\n    array<int, 4> cells = {\n        bi * N + bj,\n        bi * N + (bj + 1),\n        (bi + 1) * N + bj,\n        (bi + 1) * N + (bj + 1)\n    };\n\n    bool changed = false;\n    for (int pass = 0; pass < 2; ++pass) {\n        shuffle(cells.begin(), cells.end(), rng);\n        for (int c : cells) {\n            changed |= try_best_cell(cur, curEv, tile, c);\n        }\n    }\n\n    if (!better(curEv, bakEv)) {\n        cur = bak;\n        curEv = bakEv;\n        return false;\n    }\n    return changed;\n}\n\nvoid local_search(RotArr& cur, EvalResult& curEv, const array<int, S>& tile,\n                  RotArr& globalBestRot, EvalResult& globalBestEv,\n                  chrono::steady_clock::time_point deadline, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    auto update_global = [&]() {\n        if (better(curEv, globalBestEv)) {\n            globalBestEv = curEv;\n            globalBestRot = cur;\n        }\n    };\n\n    // Initial greedy sweep on hot cells.\n    {\n        vector<int> ord = curEv.hotCells;\n        shuffle(ord.begin(), ord.end(), rng);\n        int lim = min<int>(60, ord.size());\n        for (int i = 0; i < lim; ++i) {\n            if (chrono::steady_clock::now() >= deadline) return;\n            try_best_cell(cur, curEv, tile, ord[i]);\n            update_global();\n        }\n    }\n\n    int stagnation = 0;\n    while (chrono::steady_clock::now() < deadline) {\n        if (stagnation > 150) {\n            // Restart from the best-known solution with a small random shake.\n            cur = globalBestRot;\n            curEv = globalBestEv;\n\n            for (int k = 0; k < 5; ++k) {\n                int c = (int)(rng() % S);\n                cur[c] = (uint8_t)(rng() & 3);\n            }\n            curEv = evaluate(cur, tile);\n            update_global();\n\n            stagnation = 0;\n            continue;\n        }\n\n        int mode = (int)(rng() % 100);\n        bool moved = false;\n\n        if (mode < 62) {\n            int cell = pick_cell(curEv.hotCells, rng);\n            moved = try_best_cell(cur, curEv, tile, cell);\n        } else if (mode < 90) {\n            int cell = pick_cell(curEv.hotCells, rng);\n            int i = cell / N, j = cell % N;\n            int bi = max(0, min(i - 1, N - 2));\n            int bj = max(0, min(j - 1, N - 2));\n            moved = try_best_block(cur, curEv, tile, bi, bj, rng);\n        } else {\n            // Random shake; accept sometimes even if worse to escape local minima.\n            RotArr bak = cur;\n            EvalResult bakEv = curEv;\n\n            if (!curEv.hotCells.empty() && (rng() % 100) < 70) {\n                int cell = curEv.hotCells[rng() % curEv.hotCells.size()];\n                int i = cell / N, j = cell % N;\n                int bi = max(0, min(i - 1, N - 2));\n                int bj = max(0, min(j - 1, N - 2));\n                for (int di2 = 0; di2 < 2; ++di2) {\n                    for (int dj2 = 0; dj2 < 2; ++dj2) {\n                        int c = (bi + di2) * N + (bj + dj2);\n                        cur[c] = (uint8_t)(rng() & 3);\n                    }\n                }\n            } else {\n                for (int k = 0; k < 4; ++k) {\n                    int c = (int)(rng() % S);\n                    cur[c] = (uint8_t)(rng() & 3);\n                }\n            }\n\n            curEv = evaluate(cur, tile);\n            if (better(curEv, bakEv) || (rng() % 250 == 0)) {\n                moved = true;\n            } else {\n                cur = bak;\n                curEv = bakEv;\n            }\n        }\n\n        update_global();\n        if (moved) stagnation = 0;\n        else ++stagnation;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    array<int, S> tile{};\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) tile[i * N + j] = s[j] - '0';\n    }\n\n    // Precompute rotations for each tile type / desired kind.\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            for (int d = 0; d < 4; ++d) {\n                int bd = (d + r) & 3; // world dir -> base dir\n                int be = baseTo[t][bd];\n                if (be < 0) nxtDir[t][r][d] = -1;\n                else nxtDir[t][r][d] = (be - r + 4) & 3;\n            }\n        }\n    }\n\n    for (int t = 0; t < 8; ++t) {\n        for (int k = 0; k < 4; ++k) rotCorner[t][k] = -1;\n        for (int k = 0; k < 2; ++k) rotPair[t][k] = -1;\n    }\n\n    auto corner_kind = [&](int a, int b) -> int {\n        if (a > b) swap(a, b);\n        if (a == 0 && b == 1) return 0; // left-up\n        if (a == 1 && b == 2) return 1; // up-right\n        if (a == 2 && b == 3) return 2; // right-down\n        if (a == 0 && b == 3) return 3; // left-down\n        return -1;\n    };\n    auto straight_kind = [&](int a, int b) -> int {\n        if (a > b) swap(a, b);\n        if (a == 0 && b == 2) return 0; // horizontal\n        if (a == 1 && b == 3) return 1; // vertical\n        return -1;\n    };\n\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            vector<pair<int,int>> prs;\n            for (int d = 0; d < 4; ++d) {\n                int e = nxtDir[t][r][d];\n                if (e != -1 && d < e) prs.push_back({d, e});\n            }\n            sort(prs.begin(), prs.end());\n\n            if (t <= 3 && prs.size() == 1) {\n                int k = corner_kind(prs[0].first, prs[0].second);\n                if (k >= 0 && rotCorner[t][k] == -1) rotCorner[t][k] = r;\n            } else if (t <= 5 && prs.size() == 2) {\n                int a = corner_kind(prs[0].first, prs[0].second);\n                int b = corner_kind(prs[1].first, prs[1].second);\n                if ((a == 0 && b == 2) || (a == 2 && b == 0)) {\n                    if (rotPair[t][0] == -1) rotPair[t][0] = r;\n                }\n                if ((a == 3 && b == 1) || (a == 1 && b == 3)) {\n                    if (rotPair[t][1] == -1) rotPair[t][1] = r;\n                }\n            } else if (t >= 6 && prs.size() == 1) {\n                int k = straight_kind(prs[0].first, prs[0].second);\n                if (k >= 0 && rotPair[t][k] == -1) rotPair[t][k] = r;\n            }\n        }\n    }\n\n    auto start = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85;\n\n    struct Node {\n        EvalResult ev;\n        RotArr rot;\n    };\n\n    vector<Node> nodes;\n    nodes.reserve(128);\n\n    // Diverse structured candidates.\n    for (int pid = 0; pid < 8; ++pid) {\n        for (int sym = 0; sym < 8; ++sym) {\n            for (int mode = 0; mode < 2; ++mode) {\n                uint64_t seed = splitmix64(0x123456789abcdef0ULL ^ (uint64_t)pid * 0x9e3779b97f4a7c15ULL ^\n                                           (uint64_t)sym * 0xbf58476d1ce4e5b9ULL ^ (uint64_t)mode * 0x94d049bb133111ebULL);\n                RotArr cand = make_candidate(tile, pid, sym, mode, seed);\n                EvalResult ev = evaluate(cand, tile);\n                nodes.push_back(Node{move(ev), move(cand)});\n            }\n        }\n    }\n\n    sort(nodes.begin(), nodes.end(), [&](const Node& a, const Node& b) {\n        return better(a.ev, b.ev);\n    });\n\n    RotArr globalBestRot = nodes.front().rot;\n    EvalResult globalBestEv = nodes.front().ev;\n\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    // Refine the top few candidates within remaining time.\n    int use = min<int>(3, nodes.size());\n    for (int k = 0; k < use; ++k) {\n        double rem = TIME_LIMIT - elapsed();\n        if (rem <= 0.01) break;\n        double slice = rem / (use - k);\n        auto deadline = chrono::steady_clock::now() +\n                        chrono::duration_cast<chrono::steady_clock::duration>(chrono::duration<double>(slice));\n\n        RotArr cur = nodes[k].rot;\n        EvalResult curEv = nodes[k].ev;\n\n        local_search(cur, curEv, tile, globalBestRot, globalBestEv, deadline,\n                     splitmix64(0xabcdef0123456789ULL ^ (uint64_t)k * 0x9e3779b97f4a7c15ULL));\n\n        if (better(curEv, globalBestEv)) {\n            globalBestEv = curEv;\n            globalBestRot = cur;\n        }\n        if (elapsed() > TIME_LIMIT) break;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << int(globalBestRot[i * N + j]);\n        }\n    }\n    cout << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100;\n\nstruct EvalRes {\n    int exact = 0;    // largest tree component size\n    int near = 0;     // almost-tree component potential\n    int largest = 0;  // largest connected component size\n    int goodDeg = 0;  // degree matches tile degree\n    int diffDeg = 0;  // sum of abs(deg - need)\n    int shape = 0;    // border/center heuristic\n};\n\nstruct Node {\n    array<uint8_t, MAXC> bd{};\n    int blank = -1;\n    uint64_t hash = 0;\n    EvalRes ev;\n    int parent = -1;\n    char move = '?';\n    int depth = 0; // depth from the start of this search\n};\n\nstruct SearchResult {\n    string path; // path from the original root, if used by caller\n    Node end;\n    long long score = 0;\n};\n\nint N, T;\nint cells, fullV;\n\nint adjPos[MAXC][4];\nuint64_t zob[MAXC][16];\nint pcnt[16];\nint shapeW[5][5];\n\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\nchrono::steady_clock::time_point gStart;\ndouble gDeadline = 2.85;\n\ninline double elapsedSec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - gStart).count();\n}\n\ninline int parseHex(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + (c - 'a');\n}\n\ninline bool vecGreater(const array<int, 6>& a, const array<int, 6>& b) {\n    for (int i = 0; i < 6; ++i) {\n        if (a[i] != b[i]) return a[i] > b[i];\n    }\n    return false;\n}\n\ninline array<int, 6> modeKey(const EvalRes& e, int mode) {\n    if (mode == 0) {\n        return {e.exact, e.near, e.goodDeg, -e.diffDeg, e.shape, e.largest};\n    } else if (mode == 1) {\n        return {e.exact, e.shape, e.goodDeg, e.near, -e.diffDeg, e.largest};\n    } else {\n        return {e.exact, e.goodDeg, e.near, e.shape, -e.diffDeg, e.largest};\n    }\n}\n\ninline array<int, 6> partialKey(const EvalRes& e) {\n    return {e.exact, e.near, e.goodDeg, e.shape, -e.diffDeg, e.largest};\n}\n\ninline bool betterEvalMode(const EvalRes& a, const EvalRes& b, int mode) {\n    return vecGreater(modeKey(a, mode), modeKey(b, mode));\n}\n\ninline bool betterPartialScore(const EvalRes& a, const EvalRes& b) {\n    // Compare by actual judge score for partial states (depends only on exact).\n    if (a.exact != b.exact) return a.exact > b.exact;\n    return vecGreater(partialKey(a), partialKey(b));\n}\n\ninline long long partialScore(int exact) {\n    return (500000LL * exact + fullV / 2) / fullV;\n}\n\ninline long long fullScore(int totalLen) {\n    return llround(500000.0L * (2.0L - (long double)totalLen / (long double)T));\n}\n\ninline long long actualScore(const Node& n, int prefixLen) {\n    if (n.ev.exact == fullV) {\n        return fullScore(prefixLen + n.depth);\n    }\n    return partialScore(n.ev.exact);\n}\n\nEvalRes evaluate(const array<uint8_t, MAXC>& bd) {\n    int id[MAXC];\n    int V = 0;\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] != 0) id[i] = V++;\n        else id[i] = -1;\n    }\n\n    int deg[MAXC] = {};\n    int adj[MAXC][4];\n    int shape = 0;\n    int E = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int m = bd[idx];\n            if (!m) continue;\n\n            int ring = min(min(i, j), min(N - 1 - i, N - 1 - j));\n            if (ring > 4) ring = 4;\n            int need = pcnt[m];\n            int desired = min(4, ring + 1);\n            shape += shapeW[need][ring];\n\n            if (j + 1 < N) {\n                int idx2 = idx + 1;\n                int m2 = bd[idx2];\n                if (m2 && (m & 4) && (m2 & 1)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n            if (i + 1 < N) {\n                int idx2 = idx + N;\n                int m2 = bd[idx2];\n                if (m2 && (m & 8) && (m2 & 2)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n        }\n    }\n\n    bool vis[MAXC] = {};\n    int q[MAXC];\n\n    EvalRes res;\n    for (int s = 0; s < V; ++s) {\n        if (vis[s]) continue;\n\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n\n        int cnt = 0;\n        int sumdeg = 0;\n\n        while (head < tail) {\n            int x = q[head++];\n            ++cnt;\n            sumdeg += deg[x];\n            for (int k = 0; k < deg[x]; ++k) {\n                int y = adj[x][k];\n                if (!vis[y]) {\n                    vis[y] = true;\n                    q[tail++] = y;\n                }\n            }\n        }\n\n        int edges = sumdeg / 2;\n        int excess = edges - cnt + 1; // cycle rank of the component\n        res.largest = max(res.largest, cnt);\n        res.near = max(res.near, cnt - 2 * excess);\n        if (excess == 0) res.exact = max(res.exact, cnt);\n    }\n\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] == 0) continue;\n        res.goodDeg += 0; // placeholder, filled below\n    }\n\n    // Recompute degrees for local consistency metrics.\n    // (We keep this separate for clarity and because the board is tiny.)\n    memset(deg, 0, sizeof(deg));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int m = bd[idx];\n            if (!m) continue;\n            if (j + 1 < N) {\n                int idx2 = idx + 1;\n                int m2 = bd[idx2];\n                if (m2 && (m & 4) && (m2 & 1)) {\n                    ++deg[id[idx]];\n                    ++deg[id[idx2]];\n                }\n            }\n            if (i + 1 < N) {\n                int idx2 = idx + N;\n                int m2 = bd[idx2];\n                if (m2 && (m & 8) && (m2 & 2)) {\n                    ++deg[id[idx]];\n                    ++deg[id[idx2]];\n                }\n            }\n        }\n    }\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] == 0) continue;\n        int need = pcnt[bd[i]];\n        int d = deg[id[i]];\n        if (d == need) ++res.goodDeg;\n        res.diffDeg += abs(d - need);\n    }\n\n    res.shape = shape;\n    return res;\n}\n\nNode applyMove(const Node& cur, int dir, int parentId) {\n    Node nxt = cur;\n    int a = cur.blank;\n    int b = adjPos[a][dir];\n    uint8_t x = nxt.bd[a];\n    uint8_t y = nxt.bd[b];\n    nxt.hash ^= zob[a][x] ^ zob[a][y] ^ zob[b][y] ^ zob[b][x];\n    swap(nxt.bd[a], nxt.bd[b]);\n    nxt.blank = b;\n    nxt.parent = parentId;\n    nxt.move = dirChar[dir];\n    nxt.depth = cur.depth + 1;\n    nxt.ev = evaluate(nxt.bd);\n    return nxt;\n}\n\nstring buildPath(const vector<Node>& nodes, int id) {\n    string s;\n    while (id != -1 && nodes[id].parent != -1) {\n        s.push_back(nodes[id].move);\n        id = nodes[id].parent;\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstruct Cand {\n    int id;\n    array<int, 6> key;\n    array<int, 6> self;\n    uint32_t noise;\n};\n\nbool betterCand(const Cand& a, const Cand& b) {\n    if (vecGreater(a.key, b.key)) return true;\n    if (vecGreater(b.key, a.key)) return false;\n    if (vecGreater(a.self, b.self)) return true;\n    if (vecGreater(b.self, a.self)) return false;\n    return a.noise > b.noise;\n}\n\nSearchResult searchBeam(const Node& start, int prefixLen, int mode, int beamWidth, int depthLimit, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    vector<Node> nodes;\n    nodes.reserve((size_t)beamWidth * (size_t)depthLimit * 4 + 64);\n\n    Node root = start;\n    root.parent = -1;\n    root.move = '?';\n    root.depth = 0;\n    nodes.push_back(root);\n\n    vector<int> layer = {0};\n\n    unordered_set<uint64_t> seen;\n    seen.reserve((size_t)beamWidth * (size_t)depthLimit * 6 + 64);\n    seen.insert(root.hash);\n\n    int bestId = 0;\n    long long bestScore = actualScore(nodes[0], prefixLen);\n    array<int, 6> bestHeu = modeKey(nodes[0].ev, mode);\n\n    for (int depth = 0; depth < depthLimit; ++depth) {\n        if ((depth & 3) == 0 && elapsedSec() > gDeadline) break;\n\n        unordered_map<uint64_t, Cand> bestMap;\n        bestMap.reserve(layer.size() * 4 + 32);\n\n        int generated = 0;\n\n        for (int pid : layer) {\n            const Node cur = nodes[pid];\n\n            for (int dir = 0; dir < 4; ++dir) {\n                int nb = adjPos[cur.blank][dir];\n                if (nb == -1) continue;\n\n                Node child = applyMove(cur, dir, pid);\n                if (seen.count(child.hash)) continue;\n                seen.insert(child.hash);\n\n                int childId = (int)nodes.size();\n                nodes.push_back(child);\n\n                long long scChild = actualScore(nodes[childId], prefixLen);\n                array<int, 6> heuChild = modeKey(nodes[childId].ev, mode);\n\n                if (scChild > bestScore || (scChild == bestScore && vecGreater(heuChild, bestHeu))) {\n                    bestScore = scChild;\n                    bestId = childId;\n                    bestHeu = heuChild;\n                }\n\n                array<int, 6> bestKey = heuChild;\n\n                // One-step lookahead for ranking and possibly better actual-score samples.\n                for (int ndir = 0; ndir < 4; ++ndir) {\n                    int nnb = adjPos[child.blank][ndir];\n                    if (nnb == -1) continue;\n                    if (nnb == cur.blank) continue; // immediate backtrack\n\n                    Node grand = applyMove(child, ndir, childId);\n                    if (seen.count(grand.hash)) continue;\n\n                    array<int, 6> heuGrand = modeKey(grand.ev, mode);\n                    if (vecGreater(heuGrand, bestKey)) bestKey = heuGrand;\n\n                    long long scGrand = actualScore(grand, prefixLen);\n                    if (scGrand > bestScore || (scGrand == bestScore && vecGreater(heuGrand, bestHeu))) {\n                        int gid = (int)nodes.size();\n                        nodes.push_back(grand);\n                        bestScore = scGrand;\n                        bestId = gid;\n                        bestHeu = heuGrand;\n                    }\n                }\n\n                Cand cand{childId, bestKey, heuChild, (uint32_t)rng()};\n                auto it = bestMap.find(child.hash);\n                if (it == bestMap.end() || betterCand(cand, it->second)) {\n                    bestMap[child.hash] = cand;\n                }\n\n                ++generated;\n                if ((generated & 31) == 0 && elapsedSec() > gDeadline) break;\n            }\n\n            if (elapsedSec() > gDeadline) break;\n        }\n\n        if (bestMap.empty()) break;\n\n        vector<Cand> candVec;\n        candVec.reserve(bestMap.size());\n        for (auto& kv : bestMap) candVec.push_back(kv.second);\n\n        sort(candVec.begin(), candVec.end(), [](const Cand& a, const Cand& b) {\n            return betterCand(a, b);\n        });\n\n        if ((int)candVec.size() > beamWidth) candVec.resize(beamWidth);\n\n        layer.clear();\n        layer.reserve(candVec.size());\n        for (const auto& c : candVec) {\n            layer.push_back(c.id);\n        }\n    }\n\n    SearchResult res;\n    res.end = nodes[bestId];\n    res.path = buildPath(nodes, bestId);\n    res.score = bestScore;\n    return res;\n}\n\nSearchResult searchGreedy(const Node& start, int prefixLen, int mode, int maxSteps, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    Node cur = start;\n    cur.parent = -1;\n    cur.move = '?';\n    cur.depth = 0;\n\n    string path;\n    string bestPath;\n    Node best = cur;\n    long long bestScore = actualScore(cur, prefixLen);\n    array<int, 6> bestHeu = modeKey(cur.ev, mode);\n\n    unordered_set<uint64_t> seen;\n    seen.reserve((size_t)maxSteps * 4 + 32);\n    seen.insert(cur.hash);\n\n    int stagnation = 0;\n\n    for (int step = 0; step < maxSteps; ++step) {\n        if ((step & 7) == 0 && elapsedSec() > gDeadline) break;\n\n        struct GCand {\n            int dir;\n            Node st;\n            array<int, 6> key;\n            array<int, 6> self;\n            uint32_t noise;\n        };\n\n        vector<GCand> cands;\n        cands.reserve(4);\n\n        for (int dir = 0; dir < 4; ++dir) {\n            int nb = adjPos[cur.blank][dir];\n            if (nb == -1) continue;\n\n            Node child = applyMove(cur, dir, -1);\n            if (seen.count(child.hash)) continue;\n\n            array<int, 6> selfKey = modeKey(child.ev, mode);\n            array<int, 6> bestKey = selfKey;\n\n            for (int ndir = 0; ndir < 4; ++ndir) {\n                int nnb = adjPos[child.blank][ndir];\n                if (nnb == -1) continue;\n                if (nnb == cur.blank) continue;\n\n                Node grand = applyMove(child, ndir, -1);\n                if (seen.count(grand.hash)) continue;\n                array<int, 6> gk = modeKey(grand.ev, mode);\n                if (vecGreater(gk, bestKey)) bestKey = gk;\n            }\n\n            cands.push_back({dir, child, bestKey, selfKey, (uint32_t)rng()});\n        }\n\n        if (cands.empty()) break;\n\n        sort(cands.begin(), cands.end(), [](const GCand& a, const GCand& b) {\n            if (vecGreater(a.key, b.key)) return true;\n            if (vecGreater(b.key, a.key)) return false;\n            if (vecGreater(a.self, b.self)) return true;\n            if (vecGreater(b.self, a.self)) return false;\n            return a.noise > b.noise;\n        });\n\n        int pick = 0;\n        if ((int)cands.size() >= 2) {\n            uint32_t r = (uint32_t)rng();\n            if (r % 100 < 18) pick = 1;\n            if ((int)cands.size() >= 3 && r % 100 < 7) pick = 2;\n        }\n\n        cur = cands[pick].st;\n        path.push_back(dirChar[cands[pick].dir]);\n        seen.insert(cur.hash);\n\n        long long sc = actualScore(cur, prefixLen);\n        array<int, 6> heu = modeKey(cur.ev, mode);\n        if (sc > bestScore || (sc == bestScore && vecGreater(heu, bestHeu))) {\n            bestScore = sc;\n            best = cur;\n            bestPath = path;\n            bestHeu = heu;\n            stagnation = 0;\n        } else {\n            ++stagnation;\n        }\n\n        if (cur.ev.exact == fullV) {\n            // A full tree is valuable; continue only if it is still improving score.\n            long long fullSc = actualScore(cur, prefixLen);\n            if (fullSc >= bestScore) {\n                bestScore = fullSc;\n                best = cur;\n                bestPath = path;\n                bestHeu = heu;\n            }\n        }\n\n        if (stagnation > 50) break;\n    }\n\n    SearchResult res;\n    res.end = best;\n    res.path = bestPath;\n    res.score = bestScore;\n    return res;\n}\n\nstruct FinalCand {\n    string path;\n    Node end;\n    long long score;\n};\n\nbool betterFinal(const FinalCand& a, const FinalCand& b) {\n    if (a.score != b.score) return a.score > b.score;\n    if (a.end.ev.exact == fullV && b.end.ev.exact == fullV && a.path.size() != b.path.size()) {\n        return a.path.size() < b.path.size();\n    }\n    return a.path.size() < b.path.size();\n}\n\nuint64_t splitmix64(uint64_t& x) {\n    x += 0x9e3779b97f4a7c15ULL;\n    uint64_t z = x;\n    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n    z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n    return z ^ (z >> 31);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    cells = N * N;\n    fullV = cells - 1;\n\n    vector<string> s(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n\n    for (int i = 0; i < 16; ++i) {\n        pcnt[i] = __builtin_popcount((unsigned)i);\n    }\n\n    // Mild shape heuristic: leaves on border, higher degree toward center.\n    for (int need = 1; need <= 4; ++need) {\n        for (int ring = 0; ring <= 4; ++ring) {\n            int desired = min(4, ring + 1);\n            shapeW[need][ring] = 8 - 2 * abs(need - desired);\n        }\n    }\n\n    Node root;\n    int blankPos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int v = parseHex(s[i][j]);\n            root.bd[idx] = (uint8_t)v;\n            if (v == 0) blankPos = idx;\n        }\n    }\n    root.blank = blankPos;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            adjPos[idx][0] = (i > 0 ? idx - N : -1);\n            adjPos[idx][1] = (i + 1 < N ? idx + N : -1);\n            adjPos[idx][2] = (j > 0 ? idx - 1 : -1);\n            adjPos[idx][3] = (j + 1 < N ? idx + 1 : -1);\n        }\n    }\n\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    uint64_t sm = seed ^ 0x123456789abcdef0ULL;\n    for (int i = 0; i < cells; ++i) {\n        for (int v = 0; v < 16; ++v) {\n            zob[i][v] = splitmix64(sm);\n        }\n    }\n\n    root.hash = 0;\n    for (int i = 0; i < cells; ++i) root.hash ^= zob[i][root.bd[i]];\n    root.ev = evaluate(root.bd);\n    root.parent = -1;\n    root.move = '?';\n    root.depth = 0;\n\n    gStart = chrono::steady_clock::now();\n    gDeadline = 2.85;\n\n    vector<FinalCand> finals;\n\n    auto addCand = [&](const SearchResult& r) {\n        finals.push_back({r.path, r.end, r.score});\n    };\n\n    // Stage 1: several diverse searches from the root.\n    {\n        int rootDepth = min(80, T);\n        int rootBeam = 120;\n        int rootGreedy = min(80, T);\n\n        uint64_t s1 = splitmix64(sm);\n        uint64_t s2 = splitmix64(sm);\n        uint64_t s3 = splitmix64(sm);\n        uint64_t s4 = splitmix64(sm);\n\n        SearchResult r1 = searchBeam(root, 0, 0, rootBeam, rootDepth, s1);\n        SearchResult r2 = searchBeam(root, 0, 1, rootBeam, rootDepth, s2);\n        SearchResult r3 = searchBeam(root, 0, 2, rootBeam, rootDepth, s3);\n        SearchResult r4 = searchGreedy(root, 0, 2, rootGreedy, s4);\n\n        addCand(r1);\n        addCand(r2);\n        addCand(r3);\n        addCand(r4);\n\n        if (elapsedSec() < gDeadline) {\n            vector<SearchResult> roots = {r1, r2, r3, r4};\n\n            // Pick promising partial states for refinement:\n            // sort by actual score (which is already path-aware for full states),\n            // then by remaining budget, then by heuristic quality.\n            struct Pick {\n                SearchResult r;\n                int remaining;\n                array<int, 6> pk;\n            };\n            vector<Pick> picks;\n            for (auto& rr : roots) {\n                if (rr.end.ev.exact == fullV) continue; // already full; keep as final candidate\n                int rem = T - (int)rr.path.size();\n                if (rem <= 0) continue;\n                picks.push_back({rr, rem, partialKey(rr.end.ev)});\n            }\n\n            sort(picks.begin(), picks.end(), [&](const Pick& a, const Pick& b) {\n                if (a.r.score != b.r.score) return a.r.score > b.r.score;\n                if (a.remaining != b.remaining) return a.remaining > b.remaining;\n                if (vecGreater(a.pk, b.pk)) return true;\n                if (vecGreater(b.pk, a.pk)) return false;\n                return a.r.path.size() < b.r.path.size();\n            });\n\n            vector<Pick> uniq;\n            unordered_set<uint64_t> used;\n            used.reserve(8);\n            for (auto& p : picks) {\n                if (used.insert(p.r.end.hash).second) uniq.push_back(p);\n                if ((int)uniq.size() >= 2) break;\n            }\n\n            if (!uniq.empty() && elapsedSec() < gDeadline) {\n                auto doRefine = [&](const Pick& p, int mode, int beamWidth, int depthCap, uint64_t seedX) {\n                    int rem = T - (int)p.r.path.size();\n                    if (rem <= 0) return;\n                    int lim = min(depthCap, rem);\n                    SearchResult ext = searchBeam(p.r.end, (int)p.r.path.size(), mode, beamWidth, lim, seedX);\n                    FinalCand fc;\n                    fc.path = p.r.path + ext.path;\n                    fc.end = ext.end;\n                    fc.score = ext.score;\n                    addCand(ext); // ext.score already includes prefixLen inside the search\n                    finals.push_back(fc);\n                };\n\n                // Refine the best candidate with both beam and greedy.\n                {\n                    const auto& p = uniq[0];\n                    uint64_t sa = splitmix64(sm);\n                    uint64_t sb = splitmix64(sm);\n                    int rem = T - (int)p.r.path.size();\n                    if (rem > 0) {\n                        int lim = min(160, rem);\n                        SearchResult ext1 = searchBeam(p.r.end, (int)p.r.path.size(), 0, 160, lim, sa);\n                        FinalCand fc1{p.r.path + ext1.path, ext1.end, ext1.score};\n                        finals.push_back(fc1);\n\n                        SearchResult ext2 = searchGreedy(p.r.end, (int)p.r.path.size(), 1, min(160, rem), sb);\n                        FinalCand fc2{p.r.path + ext2.path, ext2.end, ext2.score};\n                        finals.push_back(fc2);\n                    }\n                }\n\n                if (uniq.size() >= 2 && elapsedSec() < gDeadline) {\n                    const auto& p = uniq[1];\n                    uint64_t sc = splitmix64(sm);\n                    int rem = T - (int)p.r.path.size();\n                    if (rem > 0) {\n                        int lim = min(160, rem);\n                        SearchResult ext = searchBeam(p.r.end, (int)p.r.path.size(), 1, 160, lim, sc);\n                        FinalCand fc{p.r.path + ext.path, ext.end, ext.score};\n                        finals.push_back(fc);\n                    }\n                }\n            }\n        }\n    }\n\n    // Choose the best final candidate by the judge score.\n    if (finals.empty()) {\n        cout << '\\n';\n        return 0;\n    }\n\n    FinalCand best = finals[0];\n    for (int i = 1; i < (int)finals.size(); ++i) {\n        if (betterFinal(finals[i], best)) best = finals[i];\n    }\n\n    if ((int)best.path.size() > T) {\n        // Safety fallback: should not happen, but keep output legal.\n        best.path.resize(T);\n    }\n\n    cout << best.path << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const double PI = acos(-1.0);\nstatic const int MAXS = 101;          // strips = cuts + 1, cuts <= 100\nstatic const int MAXCELLS = 10201;     // 101 * 101\n\nint N, K;\narray<int, 11> A{};\nvector<int> X, Y;\n\nstruct Partition {\n    bool ok = false;\n    vector<ll> cuts;   // threshold values for ax + by = c\n    vector<int> bin;    // bin index of each point\n};\n\nstruct Family {\n    int a = 0, b = 0;  // primitive normal vector\n    vector<ll> proj;\n    vector<int> ord;\n    vector<ll> sortedVals;\n\n    vector<ll> uniq;\n    vector<int> pref;\n    vector<ll> gapCut;\n    vector<int> gapLeft;\n\n    vector<Partition> cache;\n    vector<char> built;\n\n    Family() : cache(MAXS + 1), built(MAXS + 1, 0) {}\n};\n\nvector<Family> families;\nmap<pair<int,int>, int> familyId;\n\npair<int,int> normalize(int a, int b) {\n    if (a == 0 && b == 0) return {0, 0};\n    int g = std::gcd(abs(a), abs(b));\n    a /= g;\n    b /= g;\n    if (b < 0 || (b == 0 && a < 0)) {\n        a = -a;\n        b = -b;\n    }\n    return {a, b};\n}\n\nint addFamily(int a, int b) {\n    auto [na, nb] = normalize(a, b);\n    auto key = make_pair(na, nb);\n    auto it = familyId.find(key);\n    if (it != familyId.end()) return it->second;\n\n    int id = (int)families.size();\n    familyId[key] = id;\n    families.emplace_back();\n    Family &F = families.back();\n    F.a = na;\n    F.b = nb;\n\n    F.proj.resize(N);\n    F.ord.resize(N);\n    for (int i = 0; i < N; i++) {\n        F.proj[i] = 1LL * F.a * X[i] + 1LL * F.b * Y[i];\n    }\n    iota(F.ord.begin(), F.ord.end(), 0);\n    sort(F.ord.begin(), F.ord.end(), [&](int i, int j) {\n        if (F.proj[i] != F.proj[j]) return F.proj[i] < F.proj[j];\n        return i < j;\n    });\n\n    F.sortedVals.resize(N);\n    for (int i = 0; i < N; i++) F.sortedVals[i] = F.proj[F.ord[i]];\n\n    // compress\n    vector<int> cnt;\n    for (ll v : F.sortedVals) {\n        if (F.uniq.empty() || F.uniq.back() != v) {\n            F.uniq.push_back(v);\n            cnt.push_back(1);\n        } else {\n            cnt.back()++;\n        }\n    }\n\n    F.pref.assign((int)cnt.size() + 1, 0);\n    for (int i = 0; i < (int)cnt.size(); i++) F.pref[i + 1] = F.pref[i] + cnt[i];\n\n    for (int k = 0; k + 1 < (int)F.uniq.size(); k++) {\n        if (F.uniq[k + 1] - F.uniq[k] >= 2) {\n            F.gapLeft.push_back(F.pref[k + 1]);\n            F.gapCut.push_back(F.uniq[k] + 1); // integer strictly inside the gap\n        }\n    }\n\n    return id;\n}\n\nPartition buildPartition(const Family &F, int s) {\n    Partition res;\n    if (s < 1 || s > MAXS) return res;\n    if (s == 1) {\n        res.ok = true;\n        res.bin.assign(N, 0);\n        return res;\n    }\n    if ((int)F.gapLeft.size() < s - 1) return res;\n\n    vector<ll> cuts;\n    cuts.reserve(s - 1);\n\n    int start = 0;\n    for (int j = 1; j <= s - 1; j++) {\n        int remain = (s - 1) - j;\n        int lo = start;\n        int hi = (int)F.gapLeft.size() - 1 - remain;\n        if (lo > hi) return res;\n\n        ll target = (ll)((1LL * j * N + s / 2) / s); // rounded quantile\n\n        auto it = lower_bound(F.gapLeft.begin() + lo, F.gapLeft.begin() + hi + 1, target);\n        int idx;\n        if (it == F.gapLeft.begin() + lo) {\n            idx = lo;\n        } else if (it == F.gapLeft.begin() + hi + 1) {\n            idx = hi;\n        } else {\n            int p = (int)(it - F.gapLeft.begin());\n            ll d0 = llabs((ll)F.gapLeft[p - 1] - target);\n            ll d1 = llabs((ll)F.gapLeft[p] - target);\n            idx = (d0 <= d1 ? p - 1 : p);\n        }\n\n        cuts.push_back(F.gapCut[idx]);\n        start = idx + 1;\n    }\n\n    vector<int> bin(N, 0);\n    int ptr = 0;\n    for (int j = 0; j < s - 1; j++) {\n        while (ptr < N && F.sortedVals[ptr] < cuts[j]) {\n            bin[F.ord[ptr]] = j;\n            ptr++;\n        }\n    }\n    while (ptr < N) {\n        bin[F.ord[ptr]] = s - 1;\n        ptr++;\n    }\n\n    res.ok = true;\n    res.cuts = std::move(cuts);\n    res.bin = std::move(bin);\n    return res;\n}\n\nPartition& getPartition(int fid, int s) {\n    Family &F = families[fid];\n    if (!F.built[s]) {\n        F.cache[s] = buildPartition(F, s);\n        F.built[s] = 1;\n    }\n    return F.cache[s];\n}\n\nll extgcd(ll a, ll b, ll &x, ll &y) {\n    if (b == 0) {\n        x = 1;\n        y = 0;\n        return a;\n    }\n    ll x1, y1;\n    ll g = extgcd(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\nstruct LineOut {\n    ll x1, y1, x2, y2;\n};\n\nLineOut makeLine(ll a, ll b, ll c) {\n    // a*x + b*y = c, with primitive integer (a,b)\n    ll x, y;\n\n    if (a == 0) {\n        // b must be \u00b11 after normalization\n        x = 0;\n        y = c / b;\n    } else if (b == 0) {\n        x = c / a;\n        y = 0;\n    } else {\n        ll xa, ya;\n        extgcd(llabs(a), llabs(b), xa, ya); // abs(a)*xa + abs(b)*ya = 1\n        x = xa * c;\n        y = ya * c;\n        if (a < 0) x = -x;\n        if (b < 0) y = -y;\n    }\n\n    // direction vector on the line is (b, -a)\n    return {x, y, x + b, y - a};\n}\n\nstruct Candidate {\n    int score = -1;\n    int cuts = INT_MAX;\n    int f1 = -1, f2 = -1;\n    int s1 = 1, s2 = 1;\n};\n\nCandidate bestCand;\n\nCandidate evalPair(int f1, int f2, int s1, int s2) {\n    Candidate res;\n    if (s1 < 1 || s1 > MAXS || s2 < 1 || s2 > MAXS) return res;\n    int cuts = (s1 - 1) + (s2 - 1);\n    if (cuts > K) return res;\n\n    Partition &P1 = getPartition(f1, s1);\n    Partition &P2 = getPartition(f2, s2);\n    if (!P1.ok || !P2.ok) return res;\n\n    static int cell[MAXCELLS];\n    int m = s1 * s2;\n    fill(cell, cell + m, 0);\n\n    for (int i = 0; i < N; i++) {\n        cell[P1.bin[i] * s2 + P2.bin[i]]++;\n    }\n\n    int hist[11] = {};\n    for (int i = 0; i < m; i++) {\n        int v = cell[i];\n        if (1 <= v && v <= 10) hist[v]++;\n    }\n\n    int score = 0;\n    for (int d = 1; d <= 10; d++) {\n        score += min(A[d], hist[d]);\n    }\n\n    res.score = score;\n    res.cuts = cuts;\n    res.f1 = f1;\n    res.f2 = f2;\n    res.s1 = s1;\n    res.s2 = s2;\n    return res;\n}\n\nvoid consider(const Candidate &cand) {\n    if (cand.score > bestCand.score ||\n        (cand.score == bestCand.score && cand.cuts < bestCand.cuts)) {\n        bestCand = cand;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> K;\n    int totalA = 0;\n    for (int d = 1; d <= 10; d++) {\n        cin >> A[d];\n        totalA += A[d];\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    // PCA-based orientation as an extra candidate\n    double mx = 0, my = 0;\n    for (int i = 0; i < N; i++) {\n        mx += X[i];\n        my += Y[i];\n    }\n    mx /= N;\n    my /= N;\n\n    double cxx = 0, cyy = 0, cxy = 0;\n    for (int i = 0; i < N; i++) {\n        double dx = X[i] - mx;\n        double dy = Y[i] - my;\n        cxx += dx * dx;\n        cyy += dy * dy;\n        cxy += dx * dy;\n    }\n\n    double theta = 0.5 * atan2(2.0 * cxy, cxx - cyy);\n    int pcaA = (int)llround(cos(theta) * 20.0);\n    int pcaB = (int)llround(sin(theta) * 20.0);\n    auto pcaNorm = normalize(pcaA, pcaB);\n\n    // Build families and orientation pairs\n    vector<pair<int,int>> baseNormals = {\n        pcaNorm,\n        {1, 0},\n        {1, 1},\n        {2, 1},\n        {3, 1},\n        {1, 2},\n        {1, 3},\n        {2, 3},\n        {3, 2},\n        {4, 3},\n        {3, 4},\n        {5, 1},\n        {1, 5},\n    };\n\n    vector<pair<int,int>> orientationPairs; // family ids (normal, orthogonal)\n    set<pair<int,int>> seenPairIds;\n\n    for (auto [a, b] : baseNormals) {\n        auto n = normalize(a, b);\n        if (n == make_pair(0, 0)) continue;\n\n        int f1 = addFamily(n.first, n.second);\n        auto ort = normalize(-n.second, n.first);\n        int f2 = addFamily(ort.first, ort.second);\n        if (f1 == f2) continue;\n\n        pair<int,int> idp = {f1, f2};\n        if (seenPairIds.insert(idp).second) {\n            orientationPairs.push_back(idp);\n        }\n    }\n\n    // Candidate strip counts\n    vector<pair<int,int>> stripPairs;\n    set<long long> seenStrip;\n\n    auto addStrip = [&](int s1, int s2) {\n        if (s1 < 1 || s1 > MAXS || s2 < 1 || s2 > MAXS) return;\n        if (s1 + s2 - 2 > K) return;\n        long long key = 1LL * s1 * 1000 + s2;\n        if (seenStrip.insert(key).second) stripPairs.push_back({s1, s2});\n    };\n    auto addBoth = [&](int s1, int s2) {\n        addStrip(s1, s2);\n        addStrip(s2, s1);\n    };\n\n    // Single-direction candidates\n    for (int s = 1; s <= MAXS; s++) {\n        addBoth(s, 1);\n    }\n\n    // Around the expected number of pieces A, and mild variations\n    vector<int> targets = {\n        max(1, totalA),\n        max(1, (2 * totalA + 2) / 3),\n        max(1, (3 * totalA + 1) / 2)\n    };\n\n    for (int T : targets) {\n        for (int s1 = 1; s1 <= 60; s1++) {\n            int s2 = max(1, (T + s1 / 2) / s1);\n            for (int d = -1; d <= 1; d++) {\n                addBoth(s1, s2 + d);\n            }\n        }\n    }\n\n    sort(stripPairs.begin(), stripPairs.end(), [&](auto &p1, auto &p2) {\n        long long d1 = llabs(1LL * p1.first * p1.second - totalA);\n        long long d2 = llabs(1LL * p2.first * p2.second - totalA);\n        if (d1 != d2) return d1 < d2;\n        int c1 = p1.first + p1.second;\n        int c2 = p2.first + p2.second;\n        if (c1 != c2) return c1 < c2;\n        return p1 < p2;\n    });\n\n    // Main search\n    for (auto [f1, f2] : orientationPairs) {\n        for (auto [s1, s2] : stripPairs) {\n            Candidate cand = evalPair(f1, f2, s1, s2);\n            consider(cand);\n            if (bestCand.score == totalA) break;\n        }\n        if (bestCand.score == totalA) break;\n    }\n\n    // Small local refinement around the best candidate\n    if (bestCand.score < totalA && bestCand.f1 != -1) {\n        for (int dr = -2; dr <= 2; dr++) {\n            for (int dc = -2; dc <= 2; dc++) {\n                int s1 = bestCand.s1 + dr;\n                int s2 = bestCand.s2 + dc;\n                if (1 <= s1 && s1 <= MAXS && 1 <= s2 && s2 <= MAXS && s1 + s2 - 2 <= K) {\n                    consider(evalPair(bestCand.f1, bestCand.f2, s1, s2));\n                }\n                if (1 <= s2 && s2 <= MAXS && 1 <= s1 && s1 <= MAXS && s2 + s1 - 2 <= K) {\n                    consider(evalPair(bestCand.f1, bestCand.f2, s2, s1));\n                }\n            }\n        }\n    }\n\n    // Fallback safety\n    if (bestCand.f1 == -1) {\n        int f1 = orientationPairs[0].first;\n        int f2 = orientationPairs[0].second;\n        bestCand = evalPair(f1, f2, 1, 1);\n    }\n\n    // Output\n    Partition &P1 = getPartition(bestCand.f1, bestCand.s1);\n    Partition &P2 = getPartition(bestCand.f2, bestCand.s2);\n\n    vector<tuple<ll,ll,ll,ll>> lines;\n    lines.reserve((int)P1.cuts.size() + (int)P2.cuts.size());\n\n    const Family &F1 = families[bestCand.f1];\n    const Family &F2 = families[bestCand.f2];\n\n    for (ll c : P1.cuts) {\n        LineOut L = makeLine(F1.a, F1.b, c);\n        lines.emplace_back(L.x1, L.y1, L.x2, L.y2);\n    }\n    for (ll c : P2.cuts) {\n        LineOut L = makeLine(F2.a, F2.b, c);\n        lines.emplace_back(L.x1, L.y1, L.x2, L.y2);\n    }\n\n    cout << lines.size() << '\\n';\n    for (auto [x1, y1, x2, y2] : lines) {\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cand {\n    array<uint16_t, 4> c{};\n    array<uint16_t, 64> bd{};\n    array<uint16_t, 64> sg{};\n    uint8_t bdLen = 0;\n    uint8_t sgLen = 0;\n    int perim = 0;\n};\n\nstruct Op {\n    array<int, 8> a{};\n};\n\nstruct Node {\n    long long score;\n    int ver;\n    int cid;\n    bool operator<(const Node& other) const {\n        return score < other.score;\n    }\n};\n\nstruct Params {\n    long long A, B, C, D;\n    uint64_t seed;\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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto t0 = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - t0).count();\n    };\n\n    int N, M;\n    cin >> N >> M;\n\n    const int V = N * N;\n    const long long C = (N - 1) / 2;\n\n    auto pid = [&](int x, int y) -> int { return x * N + y; };\n\n    vector<long long> wt(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long dx = x - C, dy = y - C;\n            wt[pid(x, y)] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    vector<uint8_t> initOcc(V, 0);\n    vector<int> initIds;\n    long long initSum = 0;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        int p = pid(x, y);\n        if (!initOcc[p]) {\n            initOcc[p] = 1;\n            initIds.push_back(p);\n            initSum += wt[p];\n        }\n    }\n\n    // Prefix sums for initial occupied dots\n    vector<vector<int>> rowPref(N, vector<int>(N + 1, 0));\n    vector<vector<int>> colPref(N, vector<int>(N + 1, 0));\n    for (int y = 0; y < N; ++y) {\n        for (int x = 0; x < N; ++x) {\n            rowPref[y][x + 1] = rowPref[y][x] + initOcc[pid(x, y)];\n        }\n    }\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            colPref[x][y + 1] = colPref[x][y] + initOcc[pid(x, y)];\n        }\n    }\n\n    int D = 2 * N - 1;\n    vector<int> diag1Start(D), diag2Start(D);\n    vector<vector<int>> diag1Pref(D), diag2Pref(D);\n\n    for (int diff = -(N - 1); diff <= N - 1; ++diff) {\n        int idx = diff + (N - 1);\n        int sx = max(0, diff);\n        int len = N - abs(diff);\n        diag1Start[idx] = sx;\n        diag1Pref[idx].assign(len + 1, 0);\n        for (int i = 0; i < len; ++i) {\n            int x = sx + i;\n            int y = x - diff;\n            diag1Pref[idx][i + 1] = diag1Pref[idx][i] + initOcc[pid(x, y)];\n        }\n    }\n    for (int s = 0; s <= 2 * N - 2; ++s) {\n        int sx = max(0, s - (N - 1));\n        int ex = min(N - 1, s);\n        int len = ex - sx + 1;\n        diag2Start[s] = sx;\n        diag2Pref[s].assign(len + 1, 0);\n        for (int i = 0; i < len; ++i) {\n            int x = sx + i;\n            int y = s - x;\n            diag2Pref[s][i + 1] = diag2Pref[s][i] + initOcc[pid(x, y)];\n        }\n    }\n\n    auto rowCnt = [&](int y, int l, int r) -> int {\n        if (l > r) return 0;\n        return rowPref[y][r + 1] - rowPref[y][l];\n    };\n    auto colCnt = [&](int x, int l, int r) -> int {\n        if (l > r) return 0;\n        return colPref[x][r + 1] - colPref[x][l];\n    };\n    auto diag1Cnt = [&](int diff, int l, int r) -> int {\n        if (l > r) return 0;\n        int idx = diff + (N - 1);\n        int sx = diag1Start[idx];\n        return diag1Pref[idx][r - sx + 1] - diag1Pref[idx][l - sx];\n    };\n    auto diag2Cnt = [&](int s, int l, int r) -> int {\n        if (l > r) return 0;\n        int sx = diag2Start[s];\n        return diag2Pref[s][r - sx + 1] - diag2Pref[s][l - sx];\n    };\n\n    const int H = N * (N - 1);\n    const int DD = (N - 1) * (N - 1);\n    const int totalSeg = 2 * H + 2 * DD;\n\n    auto hid = [&](int x, int y) -> int { return y * (N - 1) + x; };\n    auto vid = [&](int x, int y) -> int { return H + x * (N - 1) + y; };\n    auto pdiag = [&](int x, int y) -> int { return 2 * H + y * (N - 1) + x; };\n    auto ndiag = [&](int x, int y) -> int { return 2 * H + DD + y * (N - 1) + x; };\n\n    vector<Cand> cands;\n    cands.reserve(1000000);\n\n    vector<uint8_t> initCnt;\n    vector<int> initReadyMiss;\n    vector<pair<int, int>> initReady; // (cid, missing point)\n\n    vector<vector<int>> cornerInc(V), boundaryInc(V), segInc(totalSeg);\n    vector<array<int, 4>> initBucket(V);\n    vector<int> initBdAliveCnt(V, 0);\n    for (int i = 0; i < V; ++i) initBucket[i] = {0, 0, 0, 0};\n\n    auto addCandidate = [&](Cand&& cd, uint8_t cnt, int missPoint) {\n        if (cnt == 4) return;\n        int cid = (int)cands.size();\n        cands.push_back(cd);\n        initCnt.push_back(cnt);\n        if (cnt == 3) {\n            initReadyMiss.push_back(missPoint);\n            initReady.emplace_back(cid, missPoint);\n        } else {\n            initReadyMiss.push_back(-1);\n        }\n\n        const Cand& c = cands.back();\n        for (int i = 0; i < 4; ++i) {\n            int p = c.c[i];\n            cornerInc[p].push_back(cid);\n            initBucket[p][cnt]++;\n        }\n        for (int i = 0; i < c.bdLen; ++i) {\n            int p = c.bd[i];\n            boundaryInc[p].push_back(cid);\n            initBdAliveCnt[p]++;\n        }\n        for (int i = 0; i < c.sgLen; ++i) {\n            segInc[c.sg[i]].push_back(cid);\n        }\n    };\n\n    auto tryAddAxis = [&](int x, int y, int w, int h) {\n        if (rowCnt(y, x + 1, x + w - 1) > 0) return;\n        if (rowCnt(y + h, x + 1, x + w - 1) > 0) return;\n        if (colCnt(x, y + 1, y + h - 1) > 0) return;\n        if (colCnt(x + w, y + 1, y + h - 1) > 0) return;\n\n        Cand cd;\n        cd.bdLen = cd.sgLen = 0;\n        cd.c = { (uint16_t)pid(x, y), (uint16_t)pid(x + w, y), (uint16_t)pid(x + w, y + h), (uint16_t)pid(x, y + h) };\n\n        int cnt = 0;\n        for (int i = 0; i < 4; ++i) cnt += initOcc[cd.c[i]];\n        if (cnt == 4) return;\n\n        for (int xx = x + 1; xx < x + w; ++xx) cd.bd[cd.bdLen++] = (uint16_t)pid(xx, y);\n        for (int yy = y + 1; yy < y + h; ++yy) cd.bd[cd.bdLen++] = (uint16_t)pid(x + w, yy);\n        for (int xx = x + w - 1; xx > x; --xx) cd.bd[cd.bdLen++] = (uint16_t)pid(xx, y + h);\n        for (int yy = y + h - 1; yy > y; --yy) cd.bd[cd.bdLen++] = (uint16_t)pid(x, yy);\n\n        for (int xx = x; xx < x + w; ++xx) cd.sg[cd.sgLen++] = (uint16_t)hid(xx, y);\n        for (int yy = y; yy < y + h; ++yy) cd.sg[cd.sgLen++] = (uint16_t)vid(x + w, yy);\n        for (int xx = x + w - 1; xx >= x; --xx) cd.sg[cd.sgLen++] = (uint16_t)hid(xx, y + h);\n        for (int yy = y + h - 1; yy >= y; --yy) cd.sg[cd.sgLen++] = (uint16_t)vid(x, yy);\n\n        cd.perim = cd.sgLen;\n        int miss = -1;\n        if (cnt == 3) {\n            for (int i = 0; i < 4; ++i) if (!initOcc[cd.c[i]]) miss = cd.c[i];\n        }\n        addCandidate(std::move(cd), (uint8_t)cnt, miss);\n    };\n\n    auto tryAddDiag = [&](int x, int y, int a, int b) {\n        int diff1 = x - y;\n        int diff2 = x - y + 2 * b;\n        int sum1 = x + y;\n        int sum2 = x + y + 2 * a;\n\n        if (diag1Cnt(diff1, x + 1, x + a - 1) > 0) return;\n        if (diag2Cnt(sum2, x + a + 1, x + a + b - 1) > 0) return;\n        if (diag2Cnt(sum1, x + 1, x + b - 1) > 0) return;\n        if (diag1Cnt(diff2, x + b + 1, x + a + b - 1) > 0) return;\n\n        Cand cd;\n        cd.bdLen = cd.sgLen = 0;\n        cd.c = { (uint16_t)pid(x, y),\n                 (uint16_t)pid(x + a, y + a),\n                 (uint16_t)pid(x + a + b, y + a - b),\n                 (uint16_t)pid(x + b, y - b) };\n\n        int cnt = 0;\n        for (int i = 0; i < 4; ++i) cnt += initOcc[cd.c[i]];\n        if (cnt == 4) return;\n\n        for (int t = 1; t < a; ++t) cd.bd[cd.bdLen++] = (uint16_t)pid(x + t, y + t);\n        for (int t = 1; t < b; ++t) cd.bd[cd.bdLen++] = (uint16_t)pid(x + a + t, y + a - t);\n        for (int t = 1; t < b; ++t) cd.bd[cd.bdLen++] = (uint16_t)pid(x + t, y - t);\n        for (int t = 1; t < a; ++t) cd.bd[cd.bdLen++] = (uint16_t)pid(x + b + t, y - b + t);\n\n        for (int t = 0; t < a; ++t) cd.sg[cd.sgLen++] = (uint16_t)pdiag(x + t, y + t);\n        for (int t = 0; t < b; ++t) cd.sg[cd.sgLen++] = (uint16_t)ndiag(x + a + t, y + a - t - 1);\n        for (int t = 0; t < a; ++t) cd.sg[cd.sgLen++] = (uint16_t)pdiag(x + b + t, y - b + t);\n        for (int t = 0; t < b; ++t) cd.sg[cd.sgLen++] = (uint16_t)ndiag(x + t, y - t - 1);\n\n        cd.perim = cd.sgLen;\n        int miss = -1;\n        if (cnt == 3) {\n            for (int i = 0; i < 4; ++i) if (!initOcc[cd.c[i]]) miss = cd.c[i];\n        }\n        addCandidate(std::move(cd), (uint8_t)cnt, miss);\n    };\n\n    // Balanced rectangles\n    const int BAL = 15;\n    const int THIN_MAX = 30;\n\n    for (int w = 1; w <= BAL; ++w) {\n        for (int h = 1; h <= BAL; ++h) {\n            for (int x = 0; x + w < N; ++x) {\n                for (int y = 0; y + h < N; ++y) {\n                    tryAddAxis(x, y, w, h);\n                }\n            }\n        }\n    }\n\n    // Thin long rectangles\n    for (int w = 1; w <= THIN_MAX; ++w) {\n        for (int h = 1; h <= THIN_MAX; ++h) {\n            if (w <= BAL && h <= BAL) continue;\n            if (min(w, h) > 2) continue;\n            for (int x = 0; x + w < N; ++x) {\n                for (int y = 0; y + h < N; ++y) {\n                    tryAddAxis(x, y, w, h);\n                }\n            }\n        }\n    }\n\n    // Balanced 45-degree rectangles\n    for (int a = 1; a <= BAL - 1; ++a) {\n        for (int b = 1; a + b <= BAL; ++b) {\n            for (int x = 0; x + a + b < N; ++x) {\n                for (int y = b; y + a < N; ++y) {\n                    tryAddDiag(x, y, a, b);\n                }\n            }\n        }\n    }\n\n    // Thin long 45-degree rectangles\n    for (int a = 1; a <= THIN_MAX - 1; ++a) {\n        for (int b = 1; a + b <= THIN_MAX; ++b) {\n            if (a + b <= BAL) continue;\n            if (min(a, b) > 2) continue;\n            for (int x = 0; x + a + b < N; ++x) {\n                for (int y = b; y + a < N; ++y) {\n                    tryAddDiag(x, y, a, b);\n                }\n            }\n        }\n    }\n\n    int Ccand = (int)cands.size();\n\n    auto simulate = [&](const Params& ps) -> pair<long long, vector<Op>> {\n        vector<array<int, 4>> bucket = initBucket;\n        vector<int> bdAliveCnt = initBdAliveCnt;\n        vector<uint8_t> occ = initOcc;\n        vector<uint8_t> cnt = initCnt;\n        vector<uint8_t> alive(Ccand, 1);\n        vector<int> readyMiss(Ccand, -1);\n        vector<int> ver(Ccand, 0);\n        vector<uint8_t> segUsed(totalSeg, 0);\n\n        vector<vector<int>> readyList(V);\n        vector<uint8_t> mark(V, 0);\n        vector<int> touched;\n        touched.reserve(1024);\n\n        auto touch = [&](int p) {\n            if (!occ[p] && !mark[p]) {\n                mark[p] = 1;\n                touched.push_back(p);\n            }\n        };\n\n        auto addContrib = [&](int cid, int k) {\n            const Cand& cd = cands[cid];\n            for (int i = 0; i < 4; ++i) {\n                int p = cd.c[i];\n                bucket[p][k]++;\n                touch(p);\n            }\n        };\n\n        auto removeContrib = [&](int cid, int k) {\n            const Cand& cd = cands[cid];\n            for (int i = 0; i < 4; ++i) {\n                int p = cd.c[i];\n                bucket[p][k]--;\n                touch(p);\n            }\n        };\n\n        auto killCandidate = [&](int cid) {\n            if (!alive[cid]) return;\n            int k = cnt[cid];\n            removeContrib(cid, k);\n            const Cand& cd = cands[cid];\n            for (int i = 0; i < cd.bdLen; ++i) {\n                int p = cd.bd[i];\n                --bdAliveCnt[p];\n                touch(p);\n            }\n            alive[cid] = 0;\n            readyMiss[cid] = -1;\n            cnt[cid] = 4;\n        };\n\n        auto scoreCand = [&](int cid, int miss) -> long long {\n            long long support = 8LL * bucket[miss][2] + 3LL * bucket[miss][1] + 1LL * bucket[miss][3];\n            long long s = ps.A * wt[miss] + ps.B * support - ps.C * bdAliveCnt[miss] - ps.D * cands[cid].perim;\n            uint64_t z = splitmix64((uint64_t)cid ^ ps.seed);\n            s += (long long)(z % 11) - 5;\n            return s;\n        };\n\n        priority_queue<Node> pq;\n\n        for (auto [cid, miss] : initReady) {\n            readyMiss[cid] = miss;\n            readyList[miss].push_back(cid);\n            ver[cid] = 1;\n            pq.push(Node{scoreCand(cid, miss), ver[cid], cid});\n        }\n\n        vector<Op> ops;\n        ops.reserve(200000);\n        long long curSum = initSum;\n\n        while (!pq.empty()) {\n            if (elapsed() > 4.7) break;\n\n            Node cur = pq.top();\n            pq.pop();\n\n            int cid = cur.cid;\n            if (cur.ver != ver[cid]) continue;\n            if (!alive[cid] || cnt[cid] != 3 || readyMiss[cid] < 0) continue;\n\n            int miss = readyMiss[cid];\n            if (occ[miss]) continue;\n\n            // Apply this rectangle\n            int missIdx = -1;\n            for (int i = 0; i < 4; ++i) if (cands[cid].c[i] == miss) missIdx = i;\n            if (missIdx < 0) continue; // safety\n\n            Op op;\n            for (int t = 0; t < 4; ++t) {\n                int p = cands[cid].c[(missIdx + t) & 3];\n                op.a[2 * t] = p / N;\n                op.a[2 * t + 1] = p % N;\n            }\n\n            ops.push_back(op);\n            curSum += wt[miss];\n\n            occ[miss] = 1;\n            killCandidate(cid);\n\n            // Candidates that contain the new point as a corner\n            for (int nid : cornerInc[miss]) {\n                if (!alive[nid]) continue;\n\n                int old = cnt[nid];\n                if (old == 3) {\n                    killCandidate(nid);\n                    continue;\n                }\n\n                removeContrib(nid, old);\n                ++cnt[nid];\n                addContrib(nid, cnt[nid]);\n\n                if (cnt[nid] == 3) {\n                    int mm = -1;\n                    for (int i = 0; i < 4; ++i) if (!occ[cands[nid].c[i]]) mm = cands[nid].c[i];\n                    readyMiss[nid] = mm;\n                    readyList[mm].push_back(nid);\n                }\n            }\n\n            // Candidates whose perimeter contains the new point\n            for (int nid : boundaryInc[miss]) {\n                if (alive[nid]) killCandidate(nid);\n            }\n\n            // Candidates sharing a segment with the chosen rectangle\n            const Cand& chosen = cands[cid];\n            for (int i = 0; i < chosen.sgLen; ++i) {\n                int s = chosen.sg[i];\n                if (segUsed[s]) continue;\n                segUsed[s] = 1;\n                for (int nid : segInc[s]) {\n                    if (alive[nid]) killCandidate(nid);\n                }\n            }\n\n            // Refresh all ready candidates whose missing point was affected\n            for (int p : touched) {\n                if (!occ[p]) {\n                    for (int nid : readyList[p]) {\n                        if (!alive[nid] || cnt[nid] != 3 || readyMiss[nid] != p) continue;\n                        ++ver[nid];\n                        pq.push(Node{scoreCand(nid, p), ver[nid], nid});\n                    }\n                }\n                mark[p] = 0;\n            }\n            touched.clear();\n        }\n\n        return {curSum, ops};\n    };\n\n    int simCount = 3;\n    if (Ccand > 950000) simCount = 2;\n    if (Ccand > 1300000) simCount = 1;\n    if (elapsed() > 3.8) simCount = min(simCount, 1);\n    else if (elapsed() > 2.8) simCount = min(simCount, 2);\n\n    vector<Params> variants = {\n        {1300,  90, 4, 10, 0x123456789abcdefULL},\n        {1000, 120, 5,  8, 0x223456789abcdefULL},\n        { 800, 160, 6,  6, 0x323456789abcdefULL}\n    };\n    if (simCount < (int)variants.size()) variants.resize(simCount);\n\n    long long bestSum = initSum;\n    vector<Op> bestOps;\n\n    for (int i = 0; i < simCount; ++i) {\n        if (elapsed() > 4.7) break;\n        auto [sum, ops] = simulate(variants[i]);\n        if (sum > bestSum || (sum == bestSum && ops.size() > bestOps.size())) {\n            bestSum = sum;\n            bestOps = move(ops);\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n    for (const auto& op : bestOps) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << op.a[i];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int CELLS = 100;\n\nstruct Board {\n    array<uint8_t, CELLS> a{};\n};\n\nint F[CELLS];\nint prefCnt[CELLS + 1][4];\nint remainAfter[CELLS + 1][4];\nint NB[CELLS][4]; // down, up, right, left\n\ninline void initNeighbors() {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            NB[id][0] = (r + 1 < N ? (r + 1) * N + c : -1);\n            NB[id][1] = (r - 1 >= 0 ? (r - 1) * N + c : -1);\n            NB[id][2] = (c + 1 < N ? r * N + (c + 1) : -1);\n            NB[id][3] = (c - 1 >= 0 ? r * N + (c - 1) : -1);\n        }\n    }\n}\n\ninline int kthEmpty(const Board& b, int p) {\n    for (int i = 0; i < CELLS; ++i) {\n        if (b.a[i] == 0) {\n            --p;\n            if (p == 0) return i;\n        }\n    }\n    return -1;\n}\n\ninline Board tilt(const Board& b, char d) {\n    Board r;\n    r.a.fill(0);\n\n    if (d == 'L') {\n        for (int r0 = 0; r0 < N; ++r0) {\n            int w = 0;\n            int base = r0 * N;\n            for (int c = 0; c < N; ++c) {\n                uint8_t v = b.a[base + c];\n                if (v) r.a[base + w++] = v;\n            }\n        }\n    } else if (d == 'R') {\n        for (int r0 = 0; r0 < N; ++r0) {\n            int w = N - 1;\n            int base = r0 * N;\n            for (int c = N - 1; c >= 0; --c) {\n                uint8_t v = b.a[base + c];\n                if (v) r.a[base + w--] = v;\n            }\n        }\n    } else if (d == 'F') {\n        for (int c = 0; c < N; ++c) {\n            int w = 0;\n            for (int r0 = 0; r0 < N; ++r0) {\n                uint8_t v = b.a[r0 * N + c];\n                if (v) r.a[w++ * N + c] = v;\n            }\n        }\n    } else { // 'B'\n        for (int c = 0; c < N; ++c) {\n            int w = N - 1;\n            for (int r0 = N - 1; r0 >= 0; --r0) {\n                uint8_t v = b.a[r0 * N + c];\n                if (v) r.a[w-- * N + c] = v;\n            }\n        }\n    }\n    return r;\n}\n\ninline long long exactScore(const Board& b) {\n    bool vis[CELLS] = {};\n    int q[CELLS];\n    long long ans = 0;\n\n    for (int s = 0; s < CELLS; ++s) {\n        if (b.a[s] == 0 || vis[s]) continue;\n        uint8_t col = b.a[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            ++sz;\n            for (int k = 0; k < 4; ++k) {\n                int to = NB[v][k];\n                if (to != -1 && !vis[to] && b.a[to] == col) {\n                    vis[to] = true;\n                    q[tail++] = to;\n                }\n            }\n        }\n\n        ans += 1LL * sz * sz;\n    }\n    return ans;\n}\n\nstruct Info {\n    long long sumSq = 0;\n    int top[4][3]{};       // top[color][0..2]\n    int rowCnt[4][N]{};    // row counts per color\n    int colCnt[4][N]{};    // col counts per color\n    int adj = 0;\n};\n\ninline void updTop(int t[3], int x) {\n    if (x > t[0]) {\n        t[2] = t[1];\n        t[1] = t[0];\n        t[0] = x;\n    } else if (x > t[1]) {\n        t[2] = t[1];\n        t[1] = x;\n    } else if (x > t[2]) {\n        t[2] = x;\n    }\n}\n\ninline Info analyze(const Board& b) {\n    Info res;\n    bool vis[CELLS] = {};\n    int q[CELLS];\n\n    // Connected components\n    for (int s = 0; s < CELLS; ++s) {\n        if (b.a[s] == 0 || vis[s]) continue;\n        uint8_t col = b.a[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            ++sz;\n            for (int k = 0; k < 4; ++k) {\n                int to = NB[v][k];\n                if (to != -1 && !vis[to] && b.a[to] == col) {\n                    vis[to] = true;\n                    q[tail++] = to;\n                }\n            }\n        }\n\n        res.sumSq += 1LL * sz * sz;\n        updTop(res.top[col], sz);\n    }\n\n    // Row/column concentration and adjacency\n    for (int i = 0; i < CELLS; ++i) {\n        if (b.a[i] == 0) continue;\n        int r = i / N, c = i % N;\n        int col = b.a[i];\n        res.rowCnt[col][r]++;\n        res.colCnt[col][c]++;\n        if (c + 1 < N && b.a[i + 1] == b.a[i]) res.adj++;\n        if (r + 1 < N && b.a[i + N] == b.a[i]) res.adj++;\n    }\n\n    return res;\n}\n\ninline double heuristic(const Board& b, int nextIdx) {\n    Info info = analyze(b);\n\n    double s = (double)info.sumSq;\n\n    for (int col = 1; col <= 3; ++col) {\n        int rem = remainAfter[nextIdx][col];\n\n        double pot = (double)info.top[col][0]\n                   + 0.75 * (double)info.top[col][1]\n                   + 0.45 * (double)info.top[col][2];\n\n        long long line = 0;\n        for (int i = 0; i < N; ++i) {\n            line += 1LL * info.rowCnt[col][i] * info.rowCnt[col][i];\n            line += 1LL * info.colCnt[col][i] * info.colCnt[col][i];\n        }\n\n        s += 1.8 * rem * pot;\n        s += 0.015 * (double)line;\n    }\n\n    s += 0.05 * (double)info.adj;\n    return s;\n}\n\n// Estimate the value of a board after finishing turn \"idx-1\".\n// idx is the index of the next candy to be inserted.\ninline double evalState(const Board& b, int idx) {\n    if (idx >= CELLS) return (double)exactScore(b);\n\n    // Only the last candy remains: insert it and score exactly.\n    if (idx == CELLS - 1) {\n        int empties[CELLS];\n        int ec = 0;\n        for (int i = 0; i < CELLS; ++i) {\n            if (b.a[i] == 0) empties[ec++] = i;\n        }\n        double sum = 0.0;\n        for (int i = 0; i < ec; ++i) {\n            Board t = b;\n            t.a[empties[i]] = (uint8_t)F[idx];\n            sum += (double)exactScore(t);\n        }\n        return sum / ec;\n    }\n\n    return heuristic(b, idx);\n}\n\n// One-step expected lookahead from a board after the current candy has been placed and tilted.\ninline double scoreCurrentCandidate(const Board& cand, int nextIdx) {\n    int empties[CELLS];\n    int ec = 0;\n    for (int i = 0; i < CELLS; ++i) {\n        if (cand.a[i] == 0) empties[ec++] = i;\n    }\n\n    // If only the last candy remains, the next move is exact.\n    if (nextIdx == CELLS - 1) {\n        double sum = 0.0;\n        for (int i = 0; i < ec; ++i) {\n            Board t = cand;\n            t.a[empties[i]] = (uint8_t)F[nextIdx];\n            sum += (double)exactScore(t);\n        }\n        return sum / ec;\n    }\n\n    static const char dirs[4] = {'F', 'B', 'L', 'R'};\n    double sum = 0.0;\n\n    for (int i = 0; i < ec; ++i) {\n        Board t = cand;\n        t.a[empties[i]] = (uint8_t)F[nextIdx];\n\n        double best = -1e100;\n        for (char d : dirs) {\n            Board u = tilt(t, d);\n            double v = evalState(u, nextIdx + 1);\n            if (v > best) best = v;\n        }\n        sum += best;\n    }\n\n    return sum / ec;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    initNeighbors();\n\n    for (int i = 0; i < CELLS; ++i) cin >> F[i];\n\n    for (int i = 0; i < CELLS; ++i) {\n        for (int c = 1; c <= 3; ++c) prefCnt[i + 1][c] = prefCnt[i][c];\n        prefCnt[i + 1][F[i]]++;\n    }\n    for (int i = 0; i <= CELLS; ++i) {\n        for (int c = 1; c <= 3; ++c) {\n            remainAfter[i][c] = prefCnt[CELLS][c] - prefCnt[i][c];\n        }\n    }\n\n    Board board;\n    static const char dirs[4] = {'F', 'B', 'L', 'R'};\n\n    for (int t = 0; t < CELLS; ++t) {\n        int p;\n        cin >> p;\n\n        Board cur = board;\n        int pos = kthEmpty(cur, p);\n        cur.a[pos] = (uint8_t)F[t];\n\n        if (t == CELLS - 1) {\n            // No tilt on the 100th candy.\n            board = cur;\n            break;\n        }\n\n        int nextIdx = t + 1;\n        double bestScore = -1e100;\n        Board bestBoard = cur;\n        char bestDir = 'F';\n\n        for (char d : dirs) {\n            Board cand = tilt(cur, d);\n            double sc = scoreCurrentCandidate(cand, nextIdx);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestBoard = cand;\n                bestDir = d;\n            }\n        }\n\n        board = bestBoard;\n        cout << bestDir << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 100;\nstatic constexpr int T = N * (N - 1) / 2;\nstatic constexpr long double TINY = 1e-300L;\n\nstruct Cand {\n    vector<int> parts;\n    bool comp;\n    array<long double, N> sqrtp{};\n    array<long double, N> logp{};\n};\n\nstatic string build_graph(const vector<int>& parts, bool comp) {\n    array<int, N> grp{};\n    int p = 0;\n    for (int id = 0; id < (int)parts.size(); ++id) {\n        for (int k = 0; k < parts[id]; ++k) grp[p++] = id;\n    }\n\n    string s;\n    s.reserve(T);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            bool same = (grp[i] == grp[j]);\n            bool e = comp ? !same : same;\n            s.push_back(e ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    long double eps;\n    cin >> M >> eps;\n\n    // Precompute binomial tables.\n    vector<vector<long double>> bin_stay(N, vector<long double>(N, 0.0L));\n    vector<vector<long double>> bin_flip(N, vector<long double>(N, 0.0L));\n\n    auto make_binom = [&](long double q, vector<vector<long double>>& dp) {\n        dp.assign(N, vector<long double>(N, 0.0L));\n        dp[0][0] = 1.0L;\n        for (int n = 1; n < N; ++n) {\n            dp[n][0] = dp[n - 1][0] * (1.0L - q);\n            for (int k = 1; k < n; ++k) {\n                dp[n][k] = dp[n - 1][k] * (1.0L - q) + dp[n - 1][k - 1] * q;\n            }\n            dp[n][n] = dp[n - 1][n - 1] * q;\n        }\n    };\n\n    make_binom(1.0L - eps, bin_stay);\n    make_binom(eps, bin_flip);\n\n    // degree distribution for a vertex inside a clique of size s\n    // (original degree = s-1)\n    vector<array<long double, N>> degDist(N + 1);\n    for (int s = 1; s <= N; ++s) {\n        array<long double, N> p{};\n        p.fill(0.0L);\n        int a = s - 1;     // present edges\n        int b = N - s;     // absent edges\n        for (int x = 0; x <= a; ++x) {\n            long double px = bin_stay[a][x];\n            if (px == 0.0L) continue;\n            for (int y = 0; y <= b; ++y) {\n                p[x + y] += px * bin_flip[b][y];\n            }\n        }\n        degDist[s] = p;\n    }\n\n    vector<Cand> pool;\n    pool.reserve(5000);\n\n    auto add_candidate = [&](const vector<int>& parts, bool comp) {\n        Cand c;\n        c.parts = parts;\n        c.comp = comp;\n\n        array<long double, N> p{};\n        p.fill(0.0L);\n\n        for (int s : parts) {\n            long double w = (long double)s / (long double)N;\n            for (int d = 0; d < N; ++d) p[d] += w * degDist[s][d];\n        }\n\n        if (comp) {\n            array<long double, N> q{};\n            for (int d = 0; d < N; ++d) q[d] = p[N - 1 - d];\n            p = q;\n        }\n\n        long double sum = 0.0L;\n        for (int d = 0; d < N; ++d) sum += p[d];\n        if (sum <= 0) sum = 1.0L;\n\n        for (int d = 0; d < N; ++d) {\n            long double v = p[d] / sum;\n            if (v < TINY) v = TINY;\n            c.sqrtp[d] = sqrtl(v);\n            c.logp[d] = logl(v);\n        }\n\n        pool.push_back(std::move(c));\n    };\n\n    // Minimum clique size: slightly larger when noise is high.\n    int minS = (eps > 0.25L ? 9 : 8);\n\n    // 3-clique partitions\n    for (int a = minS; a <= N - 2 * minS; ++a) {\n        for (int b = a; b <= (N - a) / 2; ++b) {\n            int c = N - a - b;\n            if (c < b || c < minS) continue;\n            vector<int> parts = {a, b, c};\n            add_candidate(parts, false);\n            add_candidate(parts, true);\n        }\n    }\n\n    // 4-clique partitions\n    for (int a = minS; a <= N - 3 * minS; ++a) {\n        for (int b = a; b <= N - a - 2 * minS; ++b) {\n            for (int c = b; c <= (N - a - b) / 2; ++c) {\n                int d = N - a - b - c;\n                if (d < c || d < minS) continue;\n                vector<int> parts = {a, b, c, d};\n                add_candidate(parts, false);\n                add_candidate(parts, true);\n            }\n        }\n    }\n\n    int P = (int)pool.size();\n\n    // Choose a central seed: the most balanced partition.\n    int seed = 0;\n    long double bestVar = 1e100L;\n    for (int i = 0; i < P; ++i) {\n        const auto& parts = pool[i].parts;\n        long double mean = (long double)N / (long double)parts.size();\n        long double var = 0.0L;\n        for (int x : parts) {\n            long double d = (long double)x - mean;\n            var += d * d;\n        }\n        if (var < bestVar - 1e-18L) {\n            bestVar = var;\n            seed = i;\n        }\n    }\n\n    auto hellinger_dist = [&](const Cand& a, const Cand& b) -> long double {\n        long double bc = 0.0L;\n        for (int d = 0; d < N; ++d) bc += a.sqrtp[d] * b.sqrtp[d];\n        return 1.0L - bc; // monotone with Hellinger distance\n    };\n\n    vector<long double> best(P, 1e100L);\n    vector<char> used(P, 0);\n    vector<int> order;\n    order.reserve(min(M, P));\n\n    used[seed] = 1;\n    order.push_back(seed);\n    for (int i = 0; i < P; ++i) {\n        best[i] = used[i] ? -1.0L : hellinger_dist(pool[i], pool[seed]);\n    }\n\n    for (int step = 1; step < min(M, P); ++step) {\n        int u = -1;\n        long double val = -1.0L;\n        for (int i = 0; i < P; ++i) {\n            if (used[i]) continue;\n            if (u == -1 || best[i] > val || (fabsl(best[i] - val) < 1e-18L && i < u)) {\n                u = i;\n                val = best[i];\n            }\n        }\n        order.push_back(u);\n        used[u] = 1;\n\n        for (int i = 0; i < P; ++i) {\n            if (used[i]) continue;\n            long double d = hellinger_dist(pool[i], pool[u]);\n            if (d < best[i]) best[i] = d;\n        }\n    }\n\n    // Select M codewords.\n    vector<Cand> chosen;\n    chosen.reserve(M);\n    for (int i = 0; i < M; ++i) chosen.push_back(pool[order[i]]);\n\n    // Output graphs.\n    cout << N << '\\n';\n    for (const auto& c : chosen) {\n        cout << build_graph(c.parts, c.comp) << '\\n';\n    }\n    cout.flush();\n\n    // Decode 100 queries.\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n\n        array<int, N> deg{};\n        int idx = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j, ++idx) {\n                if (H[idx] == '1') {\n                    ++deg[i];\n                    ++deg[j];\n                }\n            }\n        }\n\n        array<int, N> cnt{};\n        cnt.fill(0);\n        for (int d : deg) ++cnt[d];\n\n        int ans = 0;\n        long double bestScore = -1e300L;\n\n        for (int id = 0; id < M; ++id) {\n            long double sc = 0.0L;\n            for (int d = 0; d < N; ++d) {\n                sc += (long double)cnt[d] * chosen[id].logp[d];\n            }\n            if (sc > bestScore) {\n                bestScore = sc;\n                ans = id;\n            }\n        }\n\n        cout << ans << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ld = long double;\n\nstatic constexpr int MAXD = 31;\nstatic constexpr int GRID = 20;\nstatic constexpr int CELLS = GRID * GRID;\nstatic constexpr ll INFLL = (1LL << 62);\n\nstruct Edge {\n    int u, v;\n    ll w;\n    int cell = 0;\n    uint64_t morton = 0;\n    ld imp = 0.0L;\n};\n\nstatic inline ll sqdist(int x1, int y1, int x2, int y2) {\n    ll dx = (ll)x1 - x2;\n    ll dy = (ll)y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nstatic inline uint32_t part1by1(uint32_t n) {\n    n &= 0x0000ffffu;\n    n = (n | (n << 8)) & 0x00FF00FFu;\n    n = (n | (n << 4)) & 0x0F0F0F0Fu;\n    n = (n | (n << 2)) & 0x33333333u;\n    n = (n | (n << 1)) & 0x55555555u;\n    return n;\n}\n\nstatic inline uint64_t mortonCode(int x, int y) {\n    return (uint64_t)part1by1((uint32_t)x) | ((uint64_t)part1by1((uint32_t)y) << 1);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<int> deg(N, 0);\n\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        deg[u]++;\n        deg[v]++;\n    }\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    vector<vector<pair<int,int>>> g(N);\n    for (int i = 0; i < N; ++i) g[i].reserve(deg[i]);\n    for (int i = 0; i < M; ++i) {\n        g[edges[i].u].push_back({edges[i].v, i});\n        g[edges[i].v].push_back({edges[i].u, i});\n    }\n\n    // Day capacity multiset: every day gets floor(M/D) or ceil(M/D), all <= K.\n    vector<int> cap(D, M / D);\n    for (int i = 0; i < M % D; ++i) cap[i]++;\n\n    // Edge spatial features.\n    for (int i = 0; i < M; ++i) {\n        int mx = xs[edges[i].u] + xs[edges[i].v]; // 0..2000\n        int my = ys[edges[i].u] + ys[edges[i].v];\n        int cx = min(GRID - 1, (mx * GRID) / 2001);\n        int cy = min(GRID - 1, (my * GRID) / 2001);\n        edges[i].cell = cx * GRID + cy;\n        edges[i].morton = mortonCode(mx, my);\n    }\n\n    // Neighboring cell lists for coarse spatial clustering.\n    vector<vector<int>> neigh(CELLS);\n    for (int x = 0; x < GRID; ++x) {\n        for (int y = 0; y < GRID; ++y) {\n            int id = x * GRID + y;\n            for (int dx = -1; dx <= 1; ++dx) {\n                for (int dy = -1; dy <= 1; ++dy) {\n                    int nx = x + dx, ny = y + dy;\n                    if (0 <= nx && nx < GRID && 0 <= ny && ny < GRID) {\n                        neigh[id].push_back(nx * GRID + ny);\n                    }\n                }\n            }\n        }\n    }\n\n    // ----- Source sampling: farthest-point sampling in coordinate space -----\n    int Simp = min(N, 50);   // for edge-importance estimation\n    int Seval = min(N - Simp, 5); // for candidate evaluation\n    int Stotal = Simp + Seval;\n\n    vector<int> sources;\n    sources.reserve(Stotal);\n\n    int first = 0;\n    for (int i = 1; i < N; ++i) {\n        if (deg[i] > deg[first]) first = i;\n    }\n    sources.push_back(first);\n\n    vector<ll> mind2(N, INFLL);\n    vector<char> used(N, false);\n    used[first] = true;\n    for (int v = 0; v < N; ++v) mind2[v] = sqdist(xs[v], ys[v], xs[first], ys[first]);\n\n    for (int t = 1; t < Stotal; ++t) {\n        int best = -1;\n        ll bestd = -1;\n        int bestDeg = -1;\n        for (int v = 0; v < N; ++v) if (!used[v]) {\n            if (mind2[v] > bestd || (mind2[v] == bestd && deg[v] > bestDeg)) {\n                best = v;\n                bestd = mind2[v];\n                bestDeg = deg[v];\n            }\n        }\n        sources.push_back(best);\n        used[best] = true;\n        for (int v = 0; v < N; ++v) if (!used[v]) {\n            mind2[v] = min(mind2[v], sqdist(xs[v], ys[v], xs[best], ys[best]));\n        }\n    }\n\n    // ----- Single-source weighted Brandes to estimate edge importance -----\n    vector<ld> edgeBC(M, 0.0L);\n    vector<ll> dist(N);\n    vector<ld> sigma(N), delta(N);\n    vector<vector<int>> predV(N), predE(N);\n    for (int v = 0; v < N; ++v) {\n        predV[v].reserve(deg[v] + 2);\n        predE[v].reserve(deg[v] + 2);\n    }\n    vector<int> order;\n    order.reserve(N);\n\n    vector<vector<ll>> fullDist(Stotal, vector<ll>(N));\n\n    auto runBrandes = [&](int s, bool accumulate) {\n        fill(dist.begin(), dist.end(), INFLL);\n        fill(sigma.begin(), sigma.end(), 0.0L);\n        fill(delta.begin(), delta.end(), 0.0L);\n        for (int v = 0; v < N; ++v) {\n            predV[v].clear();\n            predE[v].clear();\n        }\n        order.clear();\n\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        sigma[s] = 1.0L;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n            order.push_back(v);\n\n            for (auto [to, eid] : g[v]) {\n                ll nd = d + edges[eid].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n                    sigma[to] = sigma[v];\n                    predV[to].clear();\n                    predE[to].clear();\n                    predV[to].push_back(v);\n                    predE[to].push_back(eid);\n                } else if (nd == dist[to]) {\n                    sigma[to] += sigma[v];\n                    predV[to].push_back(v);\n                    predE[to].push_back(eid);\n                }\n            }\n        }\n\n        for (int idx = (int)order.size() - 1; idx >= 0; --idx) {\n            int w = order[idx];\n            for (int k = 0; k < (int)predV[w].size(); ++k) {\n                int v = predV[w][k];\n                int eid = predE[w][k];\n                ld c = (sigma[v] / sigma[w]) * (1.0L + delta[w]);\n                if (accumulate) edgeBC[eid] += c;\n                delta[v] += c;\n            }\n        }\n    };\n\n    for (int i = 0; i < Stotal; ++i) {\n        runBrandes(sources[i], i < Simp);\n        fullDist[i] = dist;\n    }\n\n    if (Simp > 0) {\n        for (int i = 0; i < M; ++i) edgeBC[i] /= (2.0L * (ld)Simp);\n    }\n\n    ld sumW = 0.0L;\n    for (int i = 0; i < M; ++i) sumW += (ld)edges[i].w;\n    ld meanW = sumW / max(1, M);\n    if (meanW <= 0) meanW = 1.0L;\n\n    vector<ld> imp(M);\n    for (int i = 0; i < M; ++i) {\n        ld b = max<ld>(0.0L, edgeBC[i]);\n        // Compress heavy-tail values, and keep a tiny length bias.\n        imp[i] = sqrtl(b + 1.0L) * (1.0L + 0.03L * ((ld)edges[i].w / meanW));\n        edges[i].imp = imp[i];\n    }\n    ld avgImp = 0.0L;\n    for (ld x : imp) avgImp += x;\n    avgImp /= max(1, M);\n    if (avgImp <= 0) avgImp = 1.0L;\n\n    // Precomputed orders.\n    uint64_t baseSeed = 88172645463393265ULL\n                      ^ (uint64_t)N * 1000003ULL\n                      ^ (uint64_t)M * 10007ULL\n                      ^ (uint64_t)D * 1000000007ULL\n                      ^ (uint64_t)K * 1000000009ULL;\n\n    auto makeImportanceOrder = [&](uint64_t seed) {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        vector<uint64_t> tie(M);\n        mt19937_64 rng(seed);\n        for (int i = 0; i < M; ++i) tie[i] = rng();\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n            if (tie[a] != tie[b]) return tie[a] < tie[b];\n            return a < b;\n        });\n        return ord;\n    };\n\n    auto makeMortonOrder = [&](uint64_t seed) {\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        vector<uint64_t> tie(M);\n        mt19937_64 rng(seed);\n        for (int i = 0; i < M; ++i) tie[i] = rng();\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].morton != edges[b].morton) return edges[a].morton < edges[b].morton;\n            if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n            if (tie[a] != tie[b]) return tie[a] < tie[b];\n            return a < b;\n        });\n        return ord;\n    };\n\n    auto buildSequential = [&](const vector<int>& ord) {\n        vector<int> ans(M, 0);\n        int ptr = 0;\n        for (int d = 0; d < D; ++d) {\n            for (int c = 0; c < cap[d]; ++c) {\n                ans[ord[ptr++]] = d;\n            }\n        }\n        return ans;\n    };\n\n    auto buildCluster = [&](ld wV, ld wCell, ld wNear, ld pen, uint64_t seed) {\n        vector<int> ord = makeImportanceOrder(seed);\n\n        vector<array<int, MAXD>> vcnt(N), ccnt(CELLS);\n        for (auto &a : vcnt) a.fill(0);\n        for (auto &a : ccnt) a.fill(0);\n\n        vector<ld> dayImp(D, 0.0L);\n        vector<int> dayCnt(D, 0);\n        vector<int> ans(M, -1);\n\n        for (int e : ord) {\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n\n            int bestD = -1;\n            ld bestScore = -1e100L;\n\n            for (int d = 0; d < D; ++d) {\n                if (dayCnt[d] >= cap[d]) continue;\n\n                int nearSum = 0;\n                for (int c2 : neigh[c]) nearSum += ccnt[c2][d];\n\n                ld score = wV * (ld)(vcnt[u][d] + vcnt[v][d])\n                         + wCell * (ld)ccnt[c][d]\n                         + wNear * (ld)nearSum\n                         - pen * (dayImp[d] / avgImp);\n\n                if (bestD == -1 || score > bestScore + 1e-18L ||\n                    (fabsl(score - bestScore) <= 1e-18L && (dayImp[d] < dayImp[bestD] ||\n                    (dayImp[d] == dayImp[bestD] && dayCnt[d] < dayCnt[bestD])))) {\n                    bestScore = score;\n                    bestD = d;\n                }\n            }\n\n            if (bestD == -1) {\n                bestD = 0;\n                for (int d = 1; d < D; ++d) if (dayCnt[d] < dayCnt[bestD]) bestD = d;\n            }\n\n            ans[e] = bestD;\n            dayCnt[bestD]++;\n            dayImp[bestD] += imp[e];\n            vcnt[u][bestD]++;\n            vcnt[v][bestD]++;\n            ccnt[c][bestD]++;\n        }\n        return ans;\n    };\n\n    auto buildSpread = [&](uint64_t seed) {\n        vector<int> ord = makeImportanceOrder(seed);\n\n        vector<array<int, MAXD>> vcnt(N), ccnt(CELLS);\n        for (auto &a : vcnt) a.fill(0);\n        for (auto &a : ccnt) a.fill(0);\n\n        vector<ld> dayImp(D, 0.0L);\n        vector<int> dayCnt(D, 0);\n        vector<int> ans(M, -1);\n\n        ld aV = avgImp * 0.80L;\n        ld aCell = avgImp * 0.25L;\n        ld aNear = avgImp * 0.08L;\n\n        for (int e : ord) {\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n\n            int bestD = -1;\n            ld bestScore = 1e100L;\n\n            for (int d = 0; d < D; ++d) {\n                if (dayCnt[d] >= cap[d]) continue;\n\n                int nearSum = 0;\n                for (int c2 : neigh[c]) nearSum += ccnt[c2][d];\n\n                ld score = dayImp[d]\n                         + aV * (ld)(vcnt[u][d] + vcnt[v][d])\n                         + aCell * (ld)ccnt[c][d]\n                         + aNear * (ld)nearSum;\n\n                if (bestD == -1 || score < bestScore - 1e-18L ||\n                    (fabsl(score - bestScore) <= 1e-18L && (dayImp[d] < dayImp[bestD] ||\n                    (dayImp[d] == dayImp[bestD] && dayCnt[d] < dayCnt[bestD])))) {\n                    bestScore = score;\n                    bestD = d;\n                }\n            }\n\n            if (bestD == -1) {\n                bestD = 0;\n                for (int d = 1; d < D; ++d) if (dayCnt[d] < dayCnt[bestD]) bestD = d;\n            }\n\n            ans[e] = bestD;\n            dayCnt[bestD]++;\n            dayImp[bestD] += imp[e];\n            vcnt[u][bestD]++;\n            vcnt[v][bestD]++;\n            ccnt[c][bestD]++;\n        }\n        return ans;\n    };\n\n    // ----- Build several candidate schedules -----\n    vector<vector<int>> candidates;\n\n    candidates.push_back(buildCluster(4.5L, 1.5L, 0.8L, 0.03L, baseSeed + 11));\n    candidates.push_back(buildCluster(1.5L, 4.5L, 2.0L, 0.02L, baseSeed + 29));\n\n    vector<int> ordImp = makeImportanceOrder(baseSeed + 101);\n    vector<int> ordMorton = makeMortonOrder(baseSeed + 202);\n    candidates.push_back(buildSequential(ordImp));\n    candidates.push_back(buildSequential(ordMorton));\n\n    candidates.push_back(buildSpread(baseSeed + 303));\n\n    // ----- Evaluate candidates on held-out sampled sources -----\n    vector<int> evalIds;\n    for (int i = Simp; i < Stotal; ++i) evalIds.push_back(i);\n\n    auto dijkstraSkip = [&](int s, const vector<int>& dayOf, int bannedDay, vector<ll>& out) {\n        fill(out.begin(), out.end(), INFLL);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        out[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != out[v]) continue;\n\n            for (auto [to, eid] : g[v]) {\n                if (dayOf[eid] == bannedDay) continue;\n                ll nd = d + edges[eid].w;\n                if (nd < out[to]) {\n                    out[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    auto evalSchedule = [&](const vector<int>& dayOf) -> ll {\n        ll total = 0;\n        vector<ll> tmp(N);\n        for (int sid : evalIds) {\n            int s = sources[sid];\n            const vector<ll>& base = fullDist[sid];\n\n            for (int d = 0; d < D; ++d) {\n                dijkstraSkip(s, dayOf, d, tmp);\n                for (int v = 0; v < N; ++v) {\n                    ll cur = (tmp[v] >= INFLL / 2 ? 1000000000LL : tmp[v]);\n                    total += cur - base[v];\n                }\n            }\n        }\n        return total;\n    };\n\n    auto t0 = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - t0).count();\n    };\n\n    vector<int> bestAns = candidates[0];\n    ll bestScore = evalSchedule(candidates[0]);\n\n    for (int i = 1; i < (int)candidates.size(); ++i) {\n        if (elapsed() > 5.55) break;\n        ll sc = evalSchedule(candidates[i]);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestAns = candidates[i];\n        }\n    }\n\n    // Output 1-based day numbers.\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << bestAns[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXD = 14;\nstatic constexpr long long INFLL = (1LL << 60);\nstatic constexpr int STREAK_CAP = 4;\n\nusing Mat = array<array<unsigned char, MAXD>, MAXD>;\n\nstruct Rod {\n    int x, y, l, r;\n    int len() const { return r - l + 1; }\n};\n\nstruct ObjData {\n    int D;\n    vector<string> f, r;\n    int rem[2][MAXD][MAXD][MAXD]; // dir 0: forward z++, dir 1: backward z--\n};\n\nstruct ObjSol {\n    vector<Rod> rods;\n    array<int, MAXD + 1> hist{};\n};\n\nstruct Cand {\n    int dir;           // 0: z increasing, 1: z decreasing\n    bool swapEqual;    // only used when |X| == |Y|\n    long long runC;\n    long long prevC;\n    long long streakC;\n    int sign;          // +1 or -1 for tiny tie-breaking\n};\n\nstatic pair<long long, vector<int>> hungarian_min(const vector<vector<long long>>& a) {\n    int n = (int)a.size();\n    vector<long long> u(n + 1), v(n + 1);\n    vector<int> 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<long long> minv(n + 1, INFLL);\n        vector<char> used(n + 1, false);\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            long long delta = INFLL;\n            int j1 = 0;\n            for (int j = 1; j <= n; ++j) if (!used[j]) {\n                long long cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n\n    vector<int> assign(n);\n    for (int j = 1; j <= n; ++j) {\n        if (p[j] != 0) assign[p[j] - 1] = j - 1;\n    }\n    return {-v[0], assign}; // minimum cost\n}\n\nstatic void precompute_remain(ObjData& obj) {\n    int D = obj.D;\n    memset(obj.rem, 0, sizeof(obj.rem));\n\n    // dir 0: processing z = 0 -> D-1, so run starts at z and goes to larger z\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = D - 1; z >= 0; --z) {\n                if (obj.f[z][x] == '1' && obj.r[z][y] == '1') {\n                    obj.rem[0][z][x][y] = 1 + ((z + 1 < D) ? obj.rem[0][z + 1][x][y] : 0);\n                }\n            }\n        }\n    }\n\n    // dir 1: processing z = D-1 -> 0, so run starts at z and goes to smaller z\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 (obj.f[z][x] == '1' && obj.r[z][y] == '1') {\n                    obj.rem[1][z][x][y] = 1 + ((z > 0) ? obj.rem[1][z - 1][x][y] : 0);\n                }\n            }\n        }\n    }\n}\n\nstatic ObjSol build_object(const ObjData& obj, const Cand& cand) {\n    int D = obj.D;\n    vector<Mat> layers(D, Mat{});\n    Mat prevSel{};\n    array<array<int, MAXD>, MAXD> streak{};\n\n    auto pair_weight = [&](int z, int rowIdx, int colIdx, const vector<int>& rows, const vector<int>& cols, bool rowsAreX) -> long long {\n        int x, y;\n        if (rowsAreX) {\n            x = rows[rowIdx];\n            y = cols[colIdx];\n        } else {\n            x = cols[colIdx];\n            y = rows[rowIdx];\n        }\n        long long rem = obj.rem[cand.dir][z][x][y];\n        long long curStreak = min(streak[x][y], STREAK_CAP);\n        long long tie = (long long)(rowIdx * 16 + colIdx);\n        return cand.runC * rem + cand.prevC * (prevSel[x][y] ? 1LL : 0LL) + cand.streakC * curStreak + cand.sign * tie;\n    };\n\n    for (int step = 0; step < D; ++step) {\n        int z = (cand.dir == 0 ? step : D - 1 - step);\n\n        vector<int> xs, ys;\n        xs.reserve(D);\n        ys.reserve(D);\n        for (int x = 0; x < D; ++x) if (obj.f[z][x] == '1') xs.push_back(x);\n        for (int y = 0; y < D; ++y) if (obj.r[z][y] == '1') ys.push_back(y);\n\n        bool rowsAreX;\n        if ((int)xs.size() < (int)ys.size()) rowsAreX = true;\n        else if ((int)ys.size() < (int)xs.size()) rowsAreX = false;\n        else rowsAreX = !cand.swapEqual;\n\n        const vector<int>& rows = rowsAreX ? xs : ys;\n        const vector<int>& cols = rowsAreX ? ys : xs;\n        int m = (int)rows.size();\n        int n = (int)cols.size();\n\n        vector<vector<long long>> w(m, vector<long long>(n));\n        vector<long long> bestExtraW(n, -INFLL);\n        vector<int> bestExtraRow(n, -1);\n\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < n; ++j) {\n                long long val = pair_weight(z, i, j, rows, cols, rowsAreX);\n                w[i][j] = val;\n                if (val > bestExtraW[j] ||\n                    (val == bestExtraW[j] &&\n                     (bestExtraRow[j] == -1 ||\n                      (cand.sign > 0 ? i < bestExtraRow[j] : i > bestExtraRow[j])))) {\n                    bestExtraW[j] = val;\n                    bestExtraRow[j] = i;\n                }\n            }\n        }\n\n        // Adjusted assignment:\n        // If a column is matched to a real row, we gain w[i][j].\n        // If it is left as \"extra\", we can independently take bestExtraW[j].\n        // So choose the subset of columns maximizing sum (w - bestExtraW).\n        vector<vector<long long>> cost(n, vector<long long>(n, 0));\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < n; ++j) {\n                cost[i][j] = bestExtraW[j] - w[i][j];\n            }\n        }\n        // dummy rows: cost 0\n        auto [dummyCost, assign] = hungarian_min(cost);\n        (void)dummyCost;\n\n        Mat cur{};\n        vector<char> usedCol(n, false);\n\n        for (int i = 0; i < m; ++i) {\n            int j = assign[i];\n            usedCol[j] = true;\n            int x, y;\n            if (rowsAreX) {\n                x = rows[i];\n                y = cols[j];\n            } else {\n                x = cols[j];\n                y = rows[i];\n            }\n            cur[x][y] = 1;\n        }\n\n        for (int j = 0; j < n; ++j) {\n            if (!usedCol[j]) {\n                int i = bestExtraRow[j];\n                int x, y;\n                if (rowsAreX) {\n                    x = rows[i];\n                    y = cols[j];\n                } else {\n                    x = cols[j];\n                    y = rows[i];\n                }\n                cur[x][y] = 1;\n            }\n        }\n\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (cur[x][y]) {\n                    streak[x][y] = prevSel[x][y] ? (streak[x][y] + 1) : 1;\n                } else {\n                    streak[x][y] = 0;\n                }\n            }\n        }\n\n        prevSel = cur;\n        layers[z] = cur;\n    }\n\n    ObjSol sol;\n    sol.hist.fill(0);\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            int s = -1;\n            for (int z = 0; z < D; ++z) {\n                if (layers[z][x][y]) {\n                    if (s == -1) s = z;\n                } else if (s != -1) {\n                    Rod rd{x, y, s, z - 1};\n                    sol.hist[rd.len()]++;\n                    sol.rods.push_back(rd);\n                    s = -1;\n                }\n            }\n            if (s != -1) {\n                Rod rd{x, y, s, D - 1};\n                sol.hist[rd.len()]++;\n                sol.rods.push_back(rd);\n            }\n        }\n    }\n\n    return sol;\n}\n\nstatic long double pair_score(const array<int, MAXD + 1>& a, const array<int, MAXD + 1>& b, int D) {\n    long double res = 0.0L;\n    for (int L = 1; L <= D; ++L) {\n        int k = min(a[L], b[L]);\n        res += (long double)k / (long double)L;\n        res += (long double)(a[L] - k + b[L] - k) * (long double)L;\n    }\n    return res;\n}\n\nstatic int pair_blocks(const array<int, MAXD + 1>& a, const array<int, MAXD + 1>& b, int D) {\n    int res = 0;\n    for (int L = 1; L <= D; ++L) res += max(a[L], b[L]);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    ObjData obj[2];\n    for (int t = 0; t < 2; ++t) {\n        obj[t].D = D;\n        obj[t].f.resize(D);\n        obj[t].r.resize(D);\n        for (int i = 0; i < D; ++i) cin >> obj[t].f[i];\n        for (int i = 0; i < D; ++i) cin >> obj[t].r[i];\n        precompute_remain(obj[t]);\n    }\n\n    vector<Cand> cands;\n    vector<tuple<long long, long long, long long>> coeffs = {\n        {0,    12000,  800},\n        {50,    8000,  400},\n        {200,   4000,  200},\n        {500,   1000,  100},\n        {1000,     0,    0},\n    };\n\n    for (int dir : {0, 1}) {\n        for (bool swapEqual : {false, true}) {\n            for (int sign : {+1, -1}) {\n                for (auto [runC, prevC, streakC] : coeffs) {\n                    cands.push_back(Cand{dir, swapEqual, runC, prevC, streakC, sign});\n                }\n            }\n        }\n    }\n\n    vector<ObjSol> pool[2];\n    pool[0].reserve(cands.size());\n    pool[1].reserve(cands.size());\n\n    for (const auto& c : cands) pool[0].push_back(build_object(obj[0], c));\n    for (const auto& c : cands) pool[1].push_back(build_object(obj[1], c));\n\n    int bestA = 0, bestB = 0;\n    long double bestS = numeric_limits<long double>::infinity();\n    int bestBlocks = INT_MAX;\n\n    for (int i = 0; i < (int)pool[0].size(); ++i) {\n        for (int j = 0; j < (int)pool[1].size(); ++j) {\n            long double s = pair_score(pool[0][i].hist, pool[1][j].hist, D);\n            int bl = pair_blocks(pool[0][i].hist, pool[1][j].hist, D);\n            if (s + 1e-18L < bestS || (fabsl(s - bestS) <= 1e-18L && bl < bestBlocks)) {\n                bestS = s;\n                bestBlocks = bl;\n                bestA = i;\n                bestB = j;\n            }\n        }\n    }\n\n    const ObjSol& A = pool[0][bestA];\n    const ObjSol& B = pool[1][bestB];\n\n    array<vector<int>, MAXD + 1> idxA, idxB;\n    for (int i = 0; i < (int)A.rods.size(); ++i) idxA[A.rods[i].len()].push_back(i);\n    for (int i = 0; i < (int)B.rods.size(); ++i) idxB[B.rods[i].len()].push_back(i);\n\n    vector<int> idA(A.rods.size(), 0), idB(B.rods.size(), 0);\n    int n = 0;\n    for (int L = 1; L <= D; ++L) {\n        int k = min((int)idxA[L].size(), (int)idxB[L].size());\n        for (int i = 0; i < k; ++i) {\n            ++n;\n            idA[idxA[L][i]] = n;\n            idB[idxB[L][i]] = n;\n        }\n        for (int i = k; i < (int)idxA[L].size(); ++i) {\n            ++n;\n            idA[idxA[L][i]] = n;\n        }\n        for (int i = k; i < (int)idxB[L].size(); ++i) {\n            ++n;\n            idB[idxB[L][i]] = n;\n        }\n    }\n\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n\n    auto fill_output = [&](vector<int>& out, const vector<Rod>& rods, const vector<int>& ids) {\n        for (int i = 0; i < (int)rods.size(); ++i) {\n            int id = ids[i];\n            const Rod& rd = rods[i];\n            for (int z = rd.l; z <= rd.r; ++z) {\n                out[rd.x * D * D + rd.y * D + z] = id;\n            }\n        }\n    };\n\n    fill_output(outA, A.rods, idA);\n    fill_output(outB, B.rods, idB);\n\n    cout << 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    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << outB[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INFLL = (1LL << 60);\nstatic const ll PENALTY = 1000000000000LL; // large enough to enforce feasibility\nstatic const int MAXR = 5001;              // radius 0..5000\n\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n + 1);\n        sz.assign(n + 1, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct ConnResult {\n    ll cost = 0;\n    vector<char> used;\n};\n\nstruct EvalResult {\n    vector<int> sel;        // selected stations\n    vector<int> rad;        // radius for selected stations (aligned with sel)\n    vector<int> owner;      // resident -> selected station index, -1 if uncovered\n    vector<int> bestDist;   // resident -> assigned distance\n    vector<char> inSel;     // station is selected?\n    vector<char> used;      // used edges, if requested\n    ll cov = 0;\n    ll conn = 0;\n    ll total = INFLL;\n    int uncovered = 0;\n};\n\nstatic int N, M, K;\nstatic vector<int> xs, ys;\nstatic vector<int> ax, ay;\nstatic vector<Edge> edges;\n\nstatic vector<vector<ll>> distGraph;\nstatic vector<vector<int>> nxtHop;\nstatic vector<vector<int>> edgeId;\nstatic vector<vector<int>> distSR;\n\nstatic vector<int> hardOrder;      // residents sorted by \"difficulty\"\nstatic vector<int> coverCount;     // station coverage count within 5000\nstatic vector<ll> singleCost;      // exact cost of {1, v}\n\nstatic auto startTime = chrono::steady_clock::now();\n\nstatic inline bool time_over() {\n    using namespace chrono;\n    return duration_cast<milliseconds>(steady_clock::now() - startTime).count() > 1850;\n}\n\nstatic int ceil_sqrt_ll(ll x) {\n    long double y = sqrt((long double)x);\n    int r = (int)y;\n    while ((ll)r * r < x) ++r;\n    while (r > 0 && (ll)(r - 1) * (r - 1) >= x) --r;\n    return r;\n}\n\nstatic vector<int> normalize_sel(vector<int> sel) {\n    if (find(sel.begin(), sel.end(), 1) == sel.end()) sel.push_back(1);\n    sort(sel.begin(), sel.end());\n    sel.erase(unique(sel.begin(), sel.end()), sel.end());\n    return sel;\n}\n\nstatic void add_path_edges(int a, int b, vector<char>& mark, vector<int>& cand) {\n    while (a != b) {\n        int c = nxtHop[a][b];\n        int id = edgeId[a][c];\n        if (!mark[id]) {\n            mark[id] = 1;\n            cand.push_back(id);\n        }\n        a = c;\n    }\n}\n\nstatic ConnResult build_conn(const vector<int>& terminals, bool storeUsed) {\n    ConnResult res;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        if (storeUsed) res.used.assign(M, 0);\n        res.cost = 0;\n        return res;\n    }\n\n    // Prim on terminal metric closure\n    vector<ll> best(t, INFLL);\n    vector<int> par(t, -1);\n    vector<char> usedT(t, 0);\n    best[0] = 0;\n\n    vector<pair<int,int>> termEdges;\n    termEdges.reserve(t - 1);\n\n    for (int it = 0; it < t; ++it) {\n        int x = -1;\n        ll bd = INFLL;\n        for (int i = 0; i < t; ++i) {\n            if (!usedT[i] && best[i] < bd) {\n                bd = best[i];\n                x = i;\n            }\n        }\n        usedT[x] = 1;\n        if (par[x] != -1) {\n            termEdges.push_back({terminals[x], terminals[par[x]]});\n        }\n        for (int y = 0; y < t; ++y) {\n            if (usedT[y]) continue;\n            ll d = distGraph[terminals[x]][terminals[y]];\n            if (d < best[y]) {\n                best[y] = d;\n                par[y] = x;\n            }\n        }\n    }\n\n    // Expand terminal MST edges to actual graph edges\n    vector<char> mark(M, 0);\n    vector<int> cand;\n    cand.reserve(2 * M);\n    for (auto [u, v] : termEdges) add_path_edges(u, v, mark, cand);\n\n    // Kruskal on the union of shortest paths\n    sort(cand.begin(), cand.end(), [&](int a, int b) {\n        if (edges[a].w != edges[b].w) return edges[a].w < edges[b].w;\n        return a < b;\n    });\n\n    DSU dsu(N);\n    vector<char> tree(M, 0);\n    ll cost = 0;\n    for (int id : cand) {\n        if (dsu.unite(edges[id].u, edges[id].v)) {\n            tree[id] = 1;\n            cost += edges[id].w;\n        }\n    }\n\n    // Prune non-terminal leaves from the tree\n    vector<int> deg(N + 1, 0);\n    vector<vector<pair<int,int>>> adj(N + 1);\n    vector<char> termMark(N + 1, 0);\n    for (int s : terminals) termMark[s] = 1;\n\n    vector<int> treeIds;\n    for (int id = 0; id < M; ++id) {\n        if (!tree[id]) continue;\n        treeIds.push_back(id);\n        int u = edges[id].u, v = edges[id].v;\n        deg[u]++;\n        deg[v]++;\n        adj[u].push_back({v, id});\n        adj[v].push_back({u, id});\n    }\n\n    queue<int> q;\n    for (int v = 1; v <= N; ++v) {\n        if (!termMark[v] && deg[v] == 1) q.push(v);\n    }\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (termMark[v] || deg[v] != 1) continue;\n\n        int rem = -1, to = -1;\n        for (auto [nx, id] : adj[v]) {\n            if (tree[id]) {\n                rem = id;\n                to = nx;\n                break;\n            }\n        }\n        if (rem == -1) continue;\n\n        tree[rem] = 0;\n        cost -= edges[rem].w;\n        deg[v]--;\n        deg[to]--;\n        if (!termMark[to] && deg[to] == 1) q.push(to);\n    }\n\n    if (storeUsed) {\n        res.used.assign(M, 0);\n        for (int id = 0; id < M; ++id) if (tree[id]) res.used[id] = 1;\n    }\n    res.cost = cost;\n    return res;\n}\n\nstatic EvalResult evaluate_set(vector<int> selRaw, bool storeUsed) {\n    EvalResult res;\n    res.sel = normalize_sel(std::move(selRaw));\n    int t = (int)res.sel.size();\n\n    res.inSel.assign(N + 1, 0);\n    for (int s : res.sel) res.inSel[s] = 1;\n\n    res.rad.assign(t, 0);\n    res.owner.assign(K, -1);\n    res.bestDist.assign(K, INT_MAX);\n\n    vector<int> cnt(t, 0);\n    vector<int> freq(t * MAXR, 0);\n\n    // Greedy assignment in global \"hardness\" order\n    for (int k : hardOrder) {\n        int bestJ = -1;\n        ll bestInc = INFLL;\n        int bestD = INT_MAX;\n\n        for (int j = 0; j < t; ++j) {\n            int d = distSR[res.sel[j]][k];\n            if (d > 5000) continue;\n            ll curR = res.rad[j];\n            ll inc = 1LL * max<ll>(curR, d) * max<ll>(curR, d) - curR * curR;\n            if (inc < bestInc || (inc == bestInc && d < bestD)) {\n                bestInc = inc;\n                bestJ = j;\n                bestD = d;\n            }\n        }\n\n        if (bestJ == -1) {\n            res.uncovered++;\n            continue;\n        }\n\n        res.owner[k] = bestJ;\n        res.bestDist[k] = bestD;\n        cnt[bestJ]++;\n        freq[bestJ * MAXR + bestD]++;\n        if (bestD > res.rad[bestJ]) res.rad[bestJ] = bestD;\n    }\n\n    // One lightweight improvement pass: move residents if it clearly reduces sum of squares\n    if (t > 1) {\n        vector<int> head(MAXR, -1), nxt(K, -1);\n        for (int k = 0; k < K; ++k) {\n            if (res.owner[k] >= 0) {\n                nxt[k] = head[res.bestDist[k]];\n                head[res.bestDist[k]] = k;\n            }\n        }\n\n        for (int d = MAXR - 1; d >= 0; --d) {\n            for (int k = head[d]; k != -1; k = nxt[k]) {\n                int a = res.owner[k];\n                if (a < 0) continue;\n\n                int da = res.bestDist[k];\n                int oldRa = res.rad[a];\n                int newRa = oldRa;\n\n                if (da == oldRa && freq[a * MAXR + da] == 1) {\n                    int x = oldRa - 1;\n                    while (x > 0 && freq[a * MAXR + x] == 0) --x;\n                    newRa = x;\n                }\n\n                ll bestDelta = 0;\n                int bestB = -1, bestDb = 0;\n\n                for (int b = 0; b < t; ++b) {\n                    if (b == a) continue;\n                    int db = distSR[res.sel[b]][k];\n                    if (db > 5000) continue;\n\n                    int oldRb = res.rad[b];\n                    int newRb = max(oldRb, db);\n                    ll delta = 1LL * newRa * newRa + 1LL * newRb * newRb\n                             - 1LL * oldRa * oldRa - 1LL * oldRb * oldRb;\n\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestB = b;\n                        bestDb = db;\n                    }\n                }\n\n                if (bestB != -1) {\n                    // move resident k: a -> bestB\n                    freq[a * MAXR + da]--;\n                    cnt[a]--;\n                    if (cnt[a] == 0) {\n                        res.rad[a] = 0;\n                    } else if (da == oldRa && freq[a * MAXR + oldRa] == 0) {\n                        int x = oldRa - 1;\n                        while (x > 0 && freq[a * MAXR + x] == 0) --x;\n                        res.rad[a] = x;\n                    }\n\n                    freq[bestB * MAXR + bestDb]++;\n                    cnt[bestB]++;\n                    if (bestDb > res.rad[bestB]) res.rad[bestB] = bestDb;\n\n                    res.owner[k] = bestB;\n                    res.bestDist[k] = bestDb;\n                }\n            }\n        }\n    }\n\n    // Final coverage cost\n    res.cov = 0;\n    for (int r : res.rad) res.cov += 1LL * r * r;\n\n    // Connectivity cost\n    ConnResult cr = build_conn(res.sel, storeUsed);\n    res.conn = cr.cost;\n    if (storeUsed) res.used = std::move(cr.used);\n\n    res.total = res.cov + res.conn + PENALTY * res.uncovered;\n    return res;\n}\n\nstatic vector<int> unique_top_union(const vector<int>& a, const vector<int>& b, const vector<int>& c, int limit, const vector<char>& inSel) {\n    vector<int> res;\n    vector<char> seen(N + 1, 0);\n\n    auto addList = [&](const vector<int>& lst) {\n        for (int v : lst) {\n            if (v == 1 || inSel[v] || seen[v]) continue;\n            seen[v] = 1;\n            res.push_back(v);\n            if ((int)res.size() >= limit) return;\n        }\n    };\n\n    addList(a);\n    if ((int)res.size() < limit) addList(b);\n    if ((int)res.size() < limit) addList(c);\n    return res;\n}\n\nstatic vector<int> rank_uncovered_candidates(const EvalResult& cur, int limit) {\n    vector<pair<ll,int>> ord;\n    ord.reserve(N);\n\n    for (int v = 2; v <= N; ++v) {\n        if (cur.inSel[v]) continue;\n        ll cnt = 0, closeness = 0;\n        const auto& row = distSR[v];\n        for (int k = 0; k < K; ++k) {\n            if (cur.owner[k] != -1) continue;\n            int d = row[k];\n            if (d <= 5000) {\n                cnt++;\n                closeness += 5000 - d;\n            }\n        }\n        if (cnt > 0) ord.push_back({cnt * 1000000LL + closeness, v});\n    }\n\n    sort(ord.begin(), ord.end(), [&](auto& x, auto& y) {\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n\n    vector<int> res;\n    for (auto [s, v] : ord) {\n        res.push_back(v);\n        if ((int)res.size() >= limit) break;\n    }\n    return res;\n}\n\nstatic vector<int> rank_gain_candidates(const EvalResult& cur, int limit) {\n    vector<pair<ll,int>> ord;\n    ord.reserve(N);\n\n    for (int v = 2; v <= N; ++v) {\n        if (cur.inSel[v]) continue;\n        ll gain = 0;\n        const auto& row = distSR[v];\n        for (int k = 0; k < K; ++k) {\n            int bd = cur.bestDist[k];\n            if (bd == INT_MAX) continue;\n            int d = row[k];\n            if (d <= 5000 && d < bd) {\n                gain += 1LL * bd * bd - 1LL * d * d;\n            }\n        }\n        ord.push_back({gain, v});\n    }\n\n    sort(ord.begin(), ord.end(), [&](auto& x, auto& y) {\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n\n    vector<int> res;\n    for (auto [s, v] : ord) {\n        res.push_back(v);\n        if ((int)res.size() >= limit) break;\n    }\n    return res;\n}\n\nstatic vector<int> rank_cover_candidates(int limit, const vector<char>& inSel) {\n    vector<pair<ll,int>> ord;\n    ord.reserve(N - 1);\n    for (int v = 2; v <= N; ++v) {\n        if (inSel[v]) continue;\n        ord.push_back({(ll)coverCount[v], v});\n    }\n    sort(ord.begin(), ord.end(), [&](auto& x, auto& y) {\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n    vector<int> res;\n    for (auto [s, v] : ord) {\n        res.push_back(v);\n        if ((int)res.size() >= limit) break;\n    }\n    return res;\n}\n\nstatic vector<int> rank_single_candidates(int limit, const vector<char>& inSel) {\n    vector<pair<ll,int>> ord;\n    ord.reserve(N - 1);\n    for (int v = 2; v <= N; ++v) {\n        if (inSel[v]) continue;\n        ord.push_back({singleCost[v], v});\n    }\n    sort(ord.begin(), ord.end(), [&](auto& x, auto& y) {\n        if (x.first != y.first) return x.first < y.first;\n        return x.second < y.second;\n    });\n    vector<int> res;\n    for (auto [s, v] : ord) {\n        res.push_back(v);\n        if ((int)res.size() >= limit) break;\n    }\n    return res;\n}\n\nstatic EvalResult search_from_seed(vector<int> seed) {\n    EvalResult cur = evaluate_set(seed, false);\n\n    for (int iter = 0; iter < 6 && !time_over(); ++iter) {\n        bool moved = false;\n\n        if (cur.uncovered > 0) {\n            auto p1 = rank_uncovered_candidates(cur, 15);\n            auto p2 = rank_cover_candidates(5, cur.inSel);\n            auto p3 = rank_single_candidates(5, cur.inSel);\n            auto pool = unique_top_union(p1, p2, p3, 20, cur.inSel);\n\n            EvalResult best = cur;\n            for (int v : pool) {\n                vector<int> tmp = cur.sel;\n                tmp.push_back(v);\n                EvalResult cand = evaluate_set(std::move(tmp), false);\n                if (cand.total < best.total) best = std::move(cand);\n                if (time_over()) break;\n            }\n\n            if (best.total < cur.total) {\n                cur = std::move(best);\n                moved = true;\n                continue;\n            }\n\n            // Fallback: if necessary, try all remaining stations once.\n            if (!moved) {\n                best = cur;\n                for (int v = 2; v <= N; ++v) {\n                    if (cur.inSel[v]) continue;\n                    vector<int> tmp = cur.sel;\n                    tmp.push_back(v);\n                    EvalResult cand = evaluate_set(std::move(tmp), false);\n                    if (cand.total < best.total) best = std::move(cand);\n                    if (time_over()) break;\n                }\n                if (best.total < cur.total) {\n                    cur = std::move(best);\n                    moved = true;\n                    continue;\n                }\n            }\n\n            if (!moved) break;\n        } else {\n            auto p1 = rank_gain_candidates(cur, 10);\n            auto p2 = rank_cover_candidates(5, cur.inSel);\n            auto p3 = rank_single_candidates(5, cur.inSel);\n            auto pool = unique_top_union(p1, p2, p3, 15, cur.inSel);\n\n            EvalResult best = cur;\n\n            // Add phase\n            for (int v : pool) {\n                vector<int> tmp = cur.sel;\n                tmp.push_back(v);\n                EvalResult cand = evaluate_set(std::move(tmp), false);\n                if (cand.total < best.total) best = std::move(cand);\n                if (time_over()) break;\n            }\n\n            // Remove phase\n            for (int s : cur.sel) {\n                if (s == 1) continue;\n                vector<int> tmp;\n                tmp.reserve(cur.sel.size() - 1);\n                for (int x : cur.sel) if (x != s) tmp.push_back(x);\n                EvalResult cand = evaluate_set(std::move(tmp), false);\n                if (cand.total < best.total) best = std::move(cand);\n                if (time_over()) break;\n            }\n\n            // Small swap attempt if still stagnant\n            if (best.total >= cur.total && (int)cur.sel.size() <= 12) {\n                auto swapPool = unique_top_union(p1, p2, p3, 8, cur.inSel);\n                for (int rem : cur.sel) {\n                    if (rem == 1) continue;\n                    for (int add : swapPool) {\n                        vector<int> tmp;\n                        tmp.reserve(cur.sel.size());\n                        for (int x : cur.sel) if (x != rem) tmp.push_back(x);\n                        tmp.push_back(add);\n                        EvalResult cand = evaluate_set(std::move(tmp), false);\n                        if (cand.total < best.total) best = std::move(cand);\n                        if (time_over()) break;\n                    }\n                    if (time_over()) break;\n                }\n            }\n\n            if (best.total < cur.total) {\n                cur = std::move(best);\n                moved = true;\n                continue;\n            }\n\n            if (!moved) break;\n        }\n    }\n\n    return cur;\n}\n\n// A small k-means-like seed builder on residents, then choose best station for each cluster.\nstatic vector<int> make_kmeans_seed(int C) {\n    C = min(C, K);\n    if (C <= 0) return {1};\n\n    auto dist2p = [&](int i, int j) -> ll {\n        ll dx = (ll)ax[i] - ax[j];\n        ll dy = (ll)ay[i] - ay[j];\n        return dx * dx + dy * dy;\n    };\n\n    vector<int> centers;\n    centers.reserve(C);\n    centers.push_back(0);\n\n    vector<ll> mind2(K, INFLL);\n    for (int k = 0; k < K; ++k) mind2[k] = dist2p(k, 0);\n\n    for (int c = 1; c < C; ++c) {\n        int nxt = 0;\n        ll best = -1;\n        for (int k = 0; k < K; ++k) {\n            if (mind2[k] > best) {\n                best = mind2[k];\n                nxt = k;\n            }\n        }\n        centers.push_back(nxt);\n        for (int k = 0; k < K; ++k) mind2[k] = min(mind2[k], dist2p(k, nxt));\n    }\n\n    vector<pair<double,double>> cen(C);\n    for (int i = 0; i < C; ++i) cen[i] = {(double)ax[centers[i]], (double)ay[centers[i]]};\n\n    vector<int> assign(K, 0);\n    for (int it = 0; it < 3; ++it) {\n        vector<vector<int>> groups(C);\n        for (int k = 0; k < K; ++k) {\n            int bestc = 0;\n            long double bestd = 1e100;\n            for (int c = 0; c < C; ++c) {\n                long double dx = (long double)ax[k] - cen[c].first;\n                long double dy = (long double)ay[k] - cen[c].second;\n                long double d = dx * dx + dy * dy;\n                if (d < bestd) {\n                    bestd = d;\n                    bestc = c;\n                }\n            }\n            assign[k] = bestc;\n            groups[bestc].push_back(k);\n        }\n\n        for (int c = 0; c < C; ++c) {\n            if (groups[c].empty()) continue;\n            long double sx = 0, sy = 0;\n            for (int k : groups[c]) {\n                sx += ax[k];\n                sy += ay[k];\n            }\n            cen[c] = {(double)(sx / groups[c].size()), (double)(sy / groups[c].size())};\n        }\n    }\n\n    vector<vector<int>> groups(C);\n    for (int k = 0; k < K; ++k) {\n        int bestc = 0;\n        long double bestd = 1e100;\n        for (int c = 0; c < C; ++c) {\n            long double dx = (long double)ax[k] - cen[c].first;\n            long double dy = (long double)ay[k] - cen[c].second;\n            long double d = dx * dx + dy * dy;\n            if (d < bestd) {\n                bestd = d;\n                bestc = c;\n            }\n        }\n        groups[bestc].push_back(k);\n    }\n\n    vector<int> sel;\n    sel.push_back(1);\n\n    for (int c = 0; c < C; ++c) {\n        if (groups[c].empty()) continue;\n        int bestV = 1;\n        int bestMax = INT_MAX;\n        ll bestSum = INFLL;\n\n        for (int v = 1; v <= N; ++v) {\n            int mx = 0;\n            ll sum = 0;\n            for (int k : groups[c]) {\n                int d = distSR[v][k];\n                mx = max(mx, d);\n                sum += d;\n                if (mx > bestMax) break;\n            }\n            if (mx < bestMax || (mx == bestMax && sum < bestSum)) {\n                bestMax = mx;\n                bestSum = sum;\n                bestV = v;\n            }\n        }\n        sel.push_back(bestV);\n    }\n\n    return normalize_sel(std::move(sel));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    xs.resize(N + 1);\n    ys.resize(N + 1);\n    for (int i = 1; i <= N; ++i) cin >> xs[i] >> ys[i];\n\n    edges.resize(M);\n    edgeId.assign(N + 1, vector<int>(N + 1, -1));\n    distGraph.assign(N + 1, vector<ll>(N + 1, INFLL));\n    nxtHop.assign(N + 1, vector<int>(N + 1, -1));\n\n    for (int i = 1; i <= N; ++i) {\n        distGraph[i][i] = 0;\n        nxtHop[i][i] = i;\n    }\n\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n        edgeId[u][v] = edgeId[v][u] = j;\n        if (w < distGraph[u][v]) {\n            distGraph[u][v] = distGraph[v][u] = w;\n            nxtHop[u][v] = v;\n            nxtHop[v][u] = u;\n        }\n    }\n\n    ax.resize(K);\n    ay.resize(K);\n    for (int i = 0; i < K; ++i) cin >> ax[i] >> ay[i];\n\n    // Floyd-Warshall\n    for (int k = 1; k <= N; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            if (distGraph[i][k] >= INFLL / 4) continue;\n            for (int j = 1; j <= N; ++j) {\n                if (distGraph[k][j] >= INFLL / 4) continue;\n                ll nd = distGraph[i][k] + distGraph[k][j];\n                if (nd < distGraph[i][j]) {\n                    distGraph[i][j] = nd;\n                    nxtHop[i][j] = nxtHop[i][k];\n                }\n            }\n        }\n    }\n\n    // Precompute station-resident distances\n    distSR.assign(N + 1, vector<int>(K, 0));\n    coverCount.assign(N + 1, 0);\n    for (int v = 1; v <= N; ++v) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = (ll)xs[v] - ax[k];\n            ll dy = (ll)ys[v] - ay[k];\n            ll d2 = dx * dx + dy * dy;\n            int d = ceil_sqrt_ll(d2);\n            distSR[v][k] = d;\n            if (d <= 5000) coverCount[v]++;\n        }\n    }\n\n    // Resident difficulty order: harder residents first\n    vector<int> hardness(K);\n    for (int k = 0; k < K; ++k) {\n        int mn = MAXR;\n        for (int v = 1; v <= N; ++v) mn = min(mn, distSR[v][k]);\n        hardness[k] = mn;\n    }\n    hardOrder.resize(K);\n    iota(hardOrder.begin(), hardOrder.end(), 0);\n    sort(hardOrder.begin(), hardOrder.end(), [&](int a, int b) {\n        if (hardness[a] != hardness[b]) return hardness[a] > hardness[b];\n        return a < b;\n    });\n\n    // Precompute exact singleton costs (root + one station)\n    singleCost.assign(N + 1, INFLL);\n    for (int v = 2; v <= N; ++v) {\n        EvalResult e = evaluate_set({1, v}, false);\n        singleCost[v] = e.total;\n    }\n\n    // Build seed sets\n    vector<pair<ll,int>> coverRank, singleRank;\n    for (int v = 2; v <= N; ++v) {\n        coverRank.push_back({-coverCount[v], v}); // descending by coverCount\n        singleRank.push_back({singleCost[v], v});  // ascending by exact cost\n    }\n    sort(coverRank.begin(), coverRank.end());\n    sort(singleRank.begin(), singleRank.end());\n\n    vector<vector<int>> seeds;\n\n    // Seed 1: best singleton\n    if (!singleRank.empty()) {\n        seeds.push_back(normalize_sel({1, singleRank[0].second}));\n    }\n\n    // Seed 2: best cover stations\n    {\n        vector<int> s = {1};\n        for (int i = 0; i < (int)coverRank.size() && i < 4; ++i) s.push_back(coverRank[i].second);\n        seeds.push_back(normalize_sel(std::move(s)));\n    }\n\n    // Seed 3: kmeans-like cluster seed\n    seeds.push_back(make_kmeans_seed(8));\n\n    // Deduplicate seeds\n    {\n        vector<vector<int>> uniq;\n        for (auto s : seeds) {\n            s = normalize_sel(std::move(s));\n            bool dup = false;\n            for (auto& t : uniq) {\n                if (t == s) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) uniq.push_back(std::move(s));\n        }\n        seeds = std::move(uniq);\n    }\n\n    EvalResult bestOverall;\n    bestOverall.total = INFLL;\n\n    for (auto& seed : seeds) {\n        if (time_over()) break;\n        EvalResult cur = search_from_seed(seed);\n        if (cur.total < bestOverall.total) bestOverall = std::move(cur);\n    }\n\n    // Final fallback if needed\n    if (bestOverall.total >= INFLL / 4 || bestOverall.uncovered > 0) {\n        vector<int> allSel;\n        for (int v = 1; v <= N; ++v) allSel.push_back(v);\n        bestOverall = evaluate_set(allSel, true);\n    } else {\n        // Re-evaluate once with edge output requested\n        bestOverall = evaluate_set(bestOverall.sel, true);\n        if (bestOverall.uncovered > 0) {\n            vector<int> allSel;\n            for (int v = 1; v <= N; ++v) allSel.push_back(v);\n            bestOverall = evaluate_set(allSel, true);\n        }\n    }\n\n    // Output P\n    vector<int> P(N + 1, 0);\n    for (int i = 0; i < (int)bestOverall.sel.size(); ++i) {\n        P[bestOverall.sel[i]] = bestOverall.rad[i];\n    }\n    for (int i = 1; i <= N; ++i) {\n        if (i > 1) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n\n    // Output B\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (bestOverall.used.empty() ? 0 : (bestOverall.used[j] ? 1 : 0));\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * (N + 1) / 2; // 465\nstatic constexpr int LIMIT = 10000;\nstatic constexpr int INF = 1e9;\nstatic constexpr int W = 200;             // tradeoff between current length and future frontier\nstatic constexpr int TOP_SCORE = 8;       // shortlist by heuristic score\nstatic constexpr int TOP_LEN = 4;          // shortlist by shortest current length\n\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\nstruct State {\n    array<int, V> board{};\n    array<int, V> pos{};\n    array<unsigned char, V> fixed{};\n    array<unsigned char, V> avail{};\n    array<int, V> parentCnt{};\n};\n\nstruct BFSRes {\n    array<int, V> dist{};\n    array<int, V> par{};\n    array<int, V> pen{};\n};\n\nstruct Choice {\n    int target = -1;\n    int len = INF;\n    long long score = (1LL << 60);\n    vector<int> path;\n};\n\nstruct Cand {\n    long long score;\n    int len;\n    int target;\n};\n\narray<pair<int, int>, V> coord;\narray<int, V> needParents;\narray<int, V> centerDist;\narray<array<unsigned char, V>, V> fullDist;\n\nvector<int> adj[V];\nvector<int> children[V];\n\ninline int id(int x, int y) {\n    return x * (x + 1) / 2 + y;\n}\n\ninline int path_penalty_cell(const State& st, int v) {\n    // Smaller labels are more important to keep undisturbed.\n    return 1 + (V - st.board[v]) / 16;\n}\n\ninline bool better_parent(int a, int b) {\n    if (b == -1) return true;\n    if (coord[a].first != coord[b].first) return coord[a].first > coord[b].first; // deeper preferred\n    if (centerDist[a] != centerDist[b]) return centerDist[a] < centerDist[b];     // more central preferred\n    if (coord[a].second != coord[b].second) return coord[a].second < coord[b].second;\n    return a < b;\n}\n\nvoid precompute_full_dist() {\n    for (int s = 0; s < V; ++s) {\n        array<int, V> dist;\n        dist.fill(-1);\n        vector<int> q;\n        q.reserve(V);\n        q.push_back(s);\n        dist[s] = 0;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int v : adj[u]) {\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                q.push_back(v);\n            }\n        }\n\n        for (int i = 0; i < V; ++i) {\n            fullDist[s][i] = static_cast<unsigned char>(dist[i]);\n        }\n    }\n}\n\nBFSRes bfs_from(const State& st, int src) {\n    BFSRes res;\n    res.dist.fill(-1);\n    res.par.fill(-1);\n    res.pen.fill(INF);\n\n    vector<int> q;\n    q.reserve(V);\n    q.push_back(src);\n    res.dist[src] = 0;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        for (int v : adj[u]) {\n            if (st.fixed[v]) continue;\n            if (res.dist[v] != -1) continue;\n            res.dist[v] = res.dist[u] + 1;\n            q.push_back(v);\n        }\n    }\n\n    res.pen[src] = 0;\n    for (int u : q) {\n        if (res.pen[u] == INF) continue;\n        for (int v : adj[u]) {\n            if (st.fixed[v]) continue;\n            if (res.dist[v] != res.dist[u] + 1) continue;\n\n            int cand = res.pen[u] + path_penalty_cell(st, v);\n            if (cand < res.pen[v] || (cand == res.pen[v] && better_parent(u, res.par[v]))) {\n                res.pen[v] = cand;\n                res.par[v] = u;\n            }\n        }\n    }\n\n    return res;\n}\n\nvector<int> build_path(int src, int tgt, const array<int, V>& par) {\n    vector<int> path;\n    for (int v = tgt;; v = par[v]) {\n        path.push_back(v);\n        if (v == src) break;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\ninline void apply_path(State& st, const vector<int>& path, vector<Move>* ops) {\n    for (int i = 0; i + 1 < (int)path.size(); ++i) {\n        int a = path[i];\n        int b = path[i + 1];\n        int va = st.board[a];\n        int vb = st.board[b];\n        swap(st.board[a], st.board[b]);\n        st.pos[va] = b;\n        st.pos[vb] = a;\n        if (ops) {\n            ops->push_back({coord[a].first, coord[a].second, coord[b].first, coord[b].second});\n        }\n    }\n}\n\ninline void fix_cell(State& st, int t) {\n    st.fixed[t] = 1;\n    st.avail[t] = 0;\n    for (int c : children[t]) {\n        if (st.fixed[c]) continue;\n        ++st.parentCnt[c];\n        if (st.parentCnt[c] == needParents[c]) {\n            st.avail[c] = 1;\n        }\n    }\n}\n\nvoid compute_best_arrays(const State& st,\n                         array<int, V>& best1,\n                         array<int, V>& best2,\n                         array<int, V>& cnt1) {\n    best1.fill(INF);\n    best2.fill(INF);\n    cnt1.fill(0);\n\n    for (int u = 0; u < V; ++u) {\n        if (st.fixed[u]) continue;\n        int b1 = INF, b2 = INF, c1 = 0;\n        for (int a = 0; a < V; ++a) {\n            if (!st.avail[a] || st.fixed[a]) continue;\n            int d = (int)fullDist[u][a];\n            if (d < b1) {\n                b2 = b1;\n                b1 = d;\n                c1 = 1;\n            } else if (d == b1) {\n                ++c1;\n            } else if (d < b2) {\n                b2 = d;\n            }\n        }\n        best1[u] = b1;\n        best2[u] = b2;\n        cnt1[u] = c1;\n    }\n}\n\nlong long calc_future_potential(const State& st,\n                                const array<int, V>& best1,\n                                const array<int, V>& best2,\n                                const array<int, V>& cnt1,\n                                int t,\n                                const int* newChild,\n                                int nc) {\n    long long sum = 0;\n    for (int u = 0; u < V; ++u) {\n        if (st.fixed[u] || u == t) continue;\n\n        int d = best1[u];\n        if ((int)fullDist[u][t] == best1[u] && cnt1[u] == 1) {\n            d = best2[u];\n        }\n        for (int i = 0; i < nc; ++i) {\n            d = min(d, (int)fullDist[u][newChild[i]]);\n        }\n        sum += d;\n    }\n    return sum;\n}\n\nChoice greedy_move(const State& st, int num) {\n    Choice ret;\n    int src = st.pos[num];\n\n    BFSRes bfs = bfs_from(st, src);\n\n    array<int, V> best1, best2, cnt1;\n    compute_best_arrays(st, best1, best2, cnt1);\n\n    long long bestScore = (1LL << 60);\n    int bestTarget = -1;\n    int bestLen = INF;\n\n    for (int t = 0; t < V; ++t) {\n        if (!st.avail[t] || st.fixed[t]) continue;\n        if (bfs.dist[t] == -1) continue;\n\n        int newChild[2];\n        int nc = 0;\n        for (int c : children[t]) {\n            if (st.fixed[c]) continue;\n            if (st.avail[c]) continue;\n            if (st.parentCnt[c] + 1 == needParents[c]) {\n                newChild[nc++] = c;\n            }\n        }\n\n        long long fut = calc_future_potential(st, best1, best2, cnt1, t, newChild, nc);\n        long long sc = 1LL * bfs.dist[t] * W + fut + 2LL * bfs.pen[t];\n\n        if (sc < bestScore ||\n            (sc == bestScore && (bfs.dist[t] < bestLen ||\n             (bfs.dist[t] == bestLen && t < bestTarget)))) {\n            bestScore = sc;\n            bestTarget = t;\n            bestLen = bfs.dist[t];\n        }\n    }\n\n    if (bestTarget == -1) return ret;\n\n    ret.target = bestTarget;\n    ret.len = bestLen;\n    ret.score = bestScore;\n    ret.path = build_path(src, bestTarget, bfs.par);\n    return ret;\n}\n\nChoice select_with_shortlist(const State& st, int num, int usedOps) {\n    Choice finalChoice;\n    int src = st.pos[num];\n    BFSRes bfs = bfs_from(st, src);\n\n    array<int, V> best1, best2, cnt1;\n    compute_best_arrays(st, best1, best2, cnt1);\n\n    vector<Cand> cands;\n    cands.reserve(V);\n\n    for (int t = 0; t < V; ++t) {\n        if (!st.avail[t] || st.fixed[t]) continue;\n        if (bfs.dist[t] == -1) continue;\n        if (usedOps + bfs.dist[t] > LIMIT) continue;\n\n        int newChild[2];\n        int nc = 0;\n        for (int c : children[t]) {\n            if (st.fixed[c]) continue;\n            if (st.avail[c]) continue;\n            if (st.parentCnt[c] + 1 == needParents[c]) {\n                newChild[nc++] = c;\n            }\n        }\n\n        long long fut = calc_future_potential(st, best1, best2, cnt1, t, newChild, nc);\n        long long sc = 1LL * bfs.dist[t] * W + fut + 2LL * bfs.pen[t];\n        cands.push_back({sc, bfs.dist[t], t});\n    }\n\n    if (cands.empty()) return finalChoice;\n\n    sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n        if (a.score != b.score) return a.score < b.score;\n        if (a.len != b.len) return a.len < b.len;\n        return a.target < b.target;\n    });\n\n    vector<int> shortlist;\n    vector<char> seen(V, 0);\n\n    for (int i = 0; i < min(TOP_SCORE, (int)cands.size()); ++i) {\n        int t = cands[i].target;\n        if (!seen[t]) {\n            seen[t] = 1;\n            shortlist.push_back(t);\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n        if (a.len != b.len) return a.len < b.len;\n        if (a.score != b.score) return a.score < b.score;\n        return a.target < b.target;\n    });\n\n    for (int i = 0; i < min(TOP_LEN, (int)cands.size()); ++i) {\n        int t = cands[i].target;\n        if (!seen[t]) {\n            seen[t] = 1;\n            shortlist.push_back(t);\n        }\n    }\n\n    long long bestTotal = (1LL << 60);\n    long long bestFirstScore = (1LL << 60);\n    int bestLen1 = INF;\n    int bestTarget = -1;\n    vector<int> bestPath;\n\n    for (int t : shortlist) {\n        vector<int> path1 = build_path(src, t, bfs.par);\n        int len1 = (int)path1.size() - 1;\n        if (usedOps + len1 > LIMIT) continue;\n\n        State s1 = st;\n        apply_path(s1, path1, nullptr);\n        fix_cell(s1, t);\n\n        long long total = len1;\n\n        if (num + 1 < V) {\n            Choice c2 = greedy_move(s1, num + 1);\n            if (c2.target == -1) continue;\n            total += c2.len;\n\n            State s2 = s1;\n            apply_path(s2, c2.path, nullptr);\n            fix_cell(s2, c2.target);\n\n            if (num + 2 < V) {\n                Choice c3 = greedy_move(s2, num + 2);\n                if (c3.target == -1) continue;\n                total += c3.len;\n            }\n        }\n\n        long long firstScore = 0;\n        // recover first-stage score for tie-break if possible\n        // (not necessary to be exact if unknown; total length is primary)\n        // Use a stable secondary tie-break based on path length and target id.\n        if (total < bestTotal ||\n            (total == bestTotal && (len1 < bestLen1 ||\n             (len1 == bestLen1 && (firstScore < bestFirstScore ||\n              (firstScore == bestFirstScore && t < bestTarget)))))) {\n            bestTotal = total;\n            bestLen1 = len1;\n            bestFirstScore = firstScore;\n            bestTarget = t;\n            bestPath = move(path1);\n        }\n    }\n\n    if (bestTarget == -1) {\n        // Fallback to the simple greedy choice.\n        return greedy_move(st, num);\n    }\n\n    finalChoice.target = bestTarget;\n    finalChoice.len = bestLen1;\n    finalChoice.path = move(bestPath);\n    finalChoice.score = bestFirstScore;\n    return finalChoice;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute coordinates / graph.\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = id(x, y);\n            coord[u] = {x, y};\n            centerDist[u] = abs(2 * y - x);\n\n            if (x == 0) needParents[u] = 0;\n            else if (y == 0 || y == x) needParents[u] = 1;\n            else needParents[u] = 2;\n\n            auto add_edge = [&](int a, int b) {\n                adj[a].push_back(b);\n                adj[b].push_back(a);\n            };\n\n            if (y > 0) {\n                add_edge(u, id(x, y - 1));\n            }\n            if (y < x) {\n                add_edge(u, id(x, y + 1));\n            }\n            if (x + 1 < N) {\n                int d1 = id(x + 1, y);\n                int d2 = id(x + 1, y + 1);\n                add_edge(u, d1);\n                add_edge(u, d2);\n                children[u].push_back(d1);\n                children[u].push_back(d2);\n            }\n        }\n    }\n\n    precompute_full_dist();\n\n    State st;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            int u = id(x, y);\n            st.board[u] = v;\n            st.pos[v] = u;\n        }\n    }\n\n    st.avail[id(0, 0)] = 1;\n\n    vector<Move> ops;\n    ops.reserve(LIMIT);\n\n    for (int num = 0; num < V; ++num) {\n        if ((int)ops.size() >= LIMIT) break;\n\n        Choice ch = select_with_shortlist(st, num, (int)ops.size());\n        if (ch.target == -1) {\n            ch = greedy_move(st, num);\n        }\n        if (ch.target == -1) break;\n\n        if ((int)ops.size() + ch.len > LIMIT) break;\n\n        apply_path(st, ch.path, &ops);\n        fix_cell(st, ch.target);\n    }\n\n    cout << ops.size() << '\\n';\n    for (const auto& mv : ops) {\n        cout << mv.x1 << ' ' << mv.y1 << ' ' << mv.x2 << ' ' << mv.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int INF = 1e9;\n\nstruct TreeMeta {\n    vector<vector<int>> child;\n    vector<int> parent;\n    vector<int> depth;\n    vector<int> subtree;\n    vector<int> childCnt;\n    // rank[0] : depth-based order\n    // rank[1] : preorder-based order\n    // rank[2] : build/BFS-like order\n    vector<vector<int>> rank;\n};\n\nint D, N, M;\nvector<vector<int>> cellId;\nvector<int> cellR, cellC;\nvector<int> gridDist;\nvector<int> nextDeg;\nint er, ec;\n\nconst int dr[4] = {1, 0, 0, -1};\nconst int dc[4] = {0, -1, 1, 0};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nTreeMeta buildTreeA(const vector<vector<bool>>& obstacle) {\n    TreeMeta tr;\n    tr.child.assign(M + 1, {});\n    tr.parent.assign(M + 1, 0);\n    tr.depth.assign(M + 1, 0);\n    tr.subtree.assign(M + 1, 0);\n    tr.childCnt.assign(M + 1, 0);\n    tr.rank.assign(3, vector<int>(M + 1, -1));\n\n    vector<vector<bool>> vis(D, vector<bool>(D, false));\n    queue<int> q;\n\n    vis[er][ec] = true;\n    int bfsOrder = 0;\n\n    // Tree A: plain BFS from entrance, with fixed direction order.\n    for (int k = 0; k < 4; ++k) {\n        int nr = er + dr[k], nc = ec + dc[k];\n        if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n        int v = cellId[nr][nc];\n        if (v == -1) continue;\n        vis[nr][nc] = true;\n        tr.parent[v] = 0;\n        tr.depth[v] = 1;\n        tr.child[0].push_back(v);\n        tr.rank[2][v] = bfsOrder++;\n        q.push(v);\n    }\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        int r = cellR[u], c = cellC[u];\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc] || vis[nr][nc]) continue;\n            int v = cellId[nr][nc];\n            if (v == -1) continue;\n            vis[nr][nc] = true;\n            tr.parent[v] = u;\n            tr.depth[v] = tr.depth[u] + 1;\n            tr.child[u].push_back(v);\n            tr.rank[2][v] = bfsOrder++;\n            q.push(v);\n        }\n    }\n\n    return tr;\n}\n\nTreeMeta buildTreeB(const vector<vector<bool>>& obstacle) {\n    TreeMeta tr;\n    tr.child.assign(M + 1, {});\n    tr.parent.assign(M + 1, 0);\n    tr.depth.assign(M + 1, 0);\n    tr.subtree.assign(M + 1, 0);\n    tr.childCnt.assign(M + 1, 0);\n    tr.rank.assign(3, vector<int>(M + 1, -1));\n\n    vector<int> ord;\n    ord.reserve(M);\n    for (int id = 1; id <= M; ++id) ord.push_back(id);\n\n    // Process shallow cells first, and among them prefer cells with many forward neighbors.\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (gridDist[a] != gridDist[b]) return gridDist[a] < gridDist[b];\n        if (nextDeg[a] != nextDeg[b]) return nextDeg[a] > nextDeg[b];\n        if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n        return cellC[a] < cellC[b];\n    });\n\n    int buildOrder = 0;\n    for (int v : ord) {\n        int d = gridDist[v];\n        if (d == 1) {\n            tr.parent[v] = 0;\n            tr.depth[v] = 1;\n            tr.child[0].push_back(v);\n            tr.rank[2][v] = buildOrder++;\n            continue;\n        }\n\n        int best = -1;\n        int bestScore = INF;\n        int r = cellR[v], c = cellC[v];\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n            if (gridDist[cellId[nr][nc]] != d - 1) continue;\n            int p = cellId[nr][nc];\n            if (p == -1) continue;\n\n            // Prefer parents that currently have fewer children, and among them\n            // those with larger future branching potential.\n            int score = tr.childCnt[p] * 100 - nextDeg[p];\n            if (score < bestScore ||\n                (score == bestScore &&\n                 (cellR[p] < cellR[best] ||\n                  (cellR[p] == cellR[best] && cellC[p] < cellC[best])))) {\n                bestScore = score;\n                best = p;\n            }\n        }\n\n        if (best == -1) {\n            // Fallback should never happen under valid input.\n            best = 0;\n        }\n\n        tr.parent[v] = best;\n        tr.depth[v] = tr.depth[best] + 1;\n        tr.child[best].push_back(v);\n        ++tr.childCnt[best];\n        tr.rank[2][v] = buildOrder++;\n    }\n\n    return tr;\n}\n\nvoid computeMeta(TreeMeta& tr) {\n    // subtree sizes\n    function<int(int)> dfsSub = [&](int u) -> int {\n        int s = 1;\n        for (int v : tr.child[u]) s += dfsSub(v);\n        tr.subtree[u] = s;\n        return s;\n    };\n    dfsSub(0);\n\n    // rank[0] : depth order\n    vector<int> nodes;\n    nodes.reserve(M);\n    for (int i = 1; i <= M; ++i) nodes.push_back(i);\n    sort(nodes.begin(), nodes.end(), [&](int a, int b) {\n        if (tr.depth[a] != tr.depth[b]) return tr.depth[a] < tr.depth[b];\n        if (tr.subtree[a] != tr.subtree[b]) return tr.subtree[a] > tr.subtree[b];\n        if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n        return cellC[a] < cellC[b];\n    });\n    for (int i = 0; i < M; ++i) tr.rank[0][nodes[i]] = i;\n\n    // rank[1] : preorder with larger subtrees first\n    int cnt = 0;\n    function<void(int)> dfsPre = [&](int u) {\n        if (u != 0) tr.rank[1][u] = cnt++;\n        vector<int> ch = tr.child[u];\n        sort(ch.begin(), ch.end(), [&](int a, int b) {\n            if (tr.subtree[a] != tr.subtree[b]) return tr.subtree[a] > tr.subtree[b];\n            if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n            return cellC[a] < cellC[b];\n        });\n        for (int v : ch) dfsPre(v);\n    };\n    dfsPre(0);\n\n    // childCnt\n    for (int i = 0; i <= M; ++i) tr.childCnt[i] = (int)tr.child[i].size();\n}\n\nint chainLen(const TreeMeta& tr, const vector<int>& remChild, int u) {\n    int cnt = 0;\n    int x = u;\n    while (tr.parent[x] != 0 && remChild[tr.parent[x]] == 1) {\n        ++cnt;\n        x = tr.parent[x];\n    }\n    return cnt;\n}\n\nint pickLeaf(const TreeMeta& tr, const vector<int>& remChild, const vector<char>& used,\n             int t, int rankKind, int gamma) {\n    int best = -1;\n    long long bestScore = (1LL << 60);\n    long long bestEff = (1LL << 60);\n    int bestChain = -1;\n\n    for (int u = 1; u <= M; ++u) {\n        if (used[u] || remChild[u] != 0) continue;\n        int ch = chainLen(tr, remChild, u);\n        long long eff = tr.rank[rankKind][u] + 1LL * gamma * ch;\n        long long score = llabs(eff - t);\n\n        if (best == -1 ||\n            score < bestScore ||\n            (score == bestScore && eff < bestEff) ||\n            (score == bestScore && eff == bestEff && ch > bestChain) ||\n            (score == bestScore && eff == bestEff && ch == bestChain &&\n             (cellR[u] < cellR[best] || (cellR[u] == cellR[best] && cellC[u] < cellC[best])))) {\n            best = u;\n            bestScore = score;\n            bestEff = eff;\n            bestChain = ch;\n        }\n    }\n    return best;\n}\n\nlong long simulate(const TreeMeta& tr, const vector<int>& perm, int rankKind, int gamma) {\n    vector<int> remChild = tr.childCnt;\n    vector<char> used(M + 1, 0);\n    vector<int> assigned(M + 1, -1);\n\n    for (int t : perm) {\n        int u = pickLeaf(tr, remChild, used, t, rankKind, gamma);\n        used[u] = 1;\n        assigned[u] = t;\n        int p = tr.parent[u];\n        if (p != 0) --remChild[p];\n    }\n\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int v : tr.child[0]) pq.push({assigned[v], v});\n\n    vector<int> seq;\n    seq.reserve(M);\n    while (!pq.empty()) {\n        auto [lab, u] = pq.top();\n        pq.pop();\n        seq.push_back(lab);\n        for (int v : tr.child[u]) pq.push({assigned[v], v});\n    }\n\n    long long 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 Choice {\n    int treeId = 0;\n    int rankKind = 0;\n    int gamma = 0;\n    long long score = (1LL << 60);\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    er = 0;\n    ec = (D - 1) / 2;\n\n    auto freeCell = [&](int r, int c) {\n        return inside(r, c) && !obstacle[r][c] && !(r == er && c == ec);\n    };\n\n    // Grid distances from entrance\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n    dist[er][ec] = 0;\n    q.push({er, ec});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc] || dist[nr][nc] != -1) continue;\n            dist[nr][nc] = dist[r][c] + 1;\n            q.push({nr, nc});\n        }\n    }\n\n    // Build cell compression\n    M = 0;\n    cellId.assign(D, vector<int>(D, -1));\n    cellR.assign(1, 0);\n    cellC.assign(1, 0);\n    gridDist.assign(1, 0);\n    nextDeg.assign(1, 0);\n\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (freeCell(r, c)) {\n                int id = ++M;\n                cellId[r][c] = id;\n                cellR.push_back(r);\n                cellC.push_back(c);\n                gridDist.push_back(dist[r][c]);\n            }\n        }\n    }\n\n    nextDeg.assign(M + 1, 0);\n    for (int id = 1; id <= M; ++id) {\n        int r = cellR[id], c = cellC[id];\n        int d = gridDist[id];\n        int cnt = 0;\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n            int nid = cellId[nr][nc];\n            if (nid != -1 && gridDist[nid] == d + 1) ++cnt;\n        }\n        nextDeg[id] = cnt;\n    }\n\n    // Build candidate trees\n    vector<TreeMeta> trees;\n    trees.push_back(buildTreeA(obstacle));\n    trees.push_back(buildTreeB(obstacle));\n\n    for (auto& tr : trees) computeMeta(tr);\n\n    // Monte Carlo selection of heuristic parameters\n    vector<vector<int>> samples;\n    {\n        uint64_t seed = 88172645463393265ULL;\n        seed ^= (uint64_t)D * 1000003ULL + (uint64_t)N * 9176ULL;\n        for (int i = 0; i < min(M, 12); ++i) seed ^= (uint64_t)(cellR[i % max(1, M)] + 1) * 1315423911ULL + (uint64_t)(cellC[i % max(1, M)] + 7);\n\n        mt19937_64 rng(seed);\n        int S = 24;\n        samples.reserve(S);\n        vector<int> base(M);\n        iota(base.begin(), base.end(), 0);\n        for (int s = 0; s < S; ++s) {\n            auto perm = base;\n            shuffle(perm.begin(), perm.end(), rng);\n            samples.push_back(move(perm));\n        }\n    }\n\n    vector<int> gammaCandidates = {-2, 0, 1, 2, 4};\n    Choice best;\n\n    for (int ti = 0; ti < (int)trees.size(); ++ti) {\n        for (int rk = 0; rk < 3; ++rk) {\n            for (int gamma : gammaCandidates) {\n                long long sum = 0;\n                for (auto& perm : samples) {\n                    sum += simulate(trees[ti], perm, rk, gamma);\n                }\n                if (sum < best.score ||\n                    (sum == best.score && ti < best.treeId) ||\n                    (sum == best.score && ti == best.treeId && rk < best.rankKind) ||\n                    (sum == best.score && ti == best.treeId && rk == best.rankKind && gamma < best.gamma)) {\n                    best.treeId = ti;\n                    best.rankKind = rk;\n                    best.gamma = gamma;\n                    best.score = sum;\n                }\n            }\n        }\n    }\n\n    TreeMeta& tr = trees[best.treeId];\n    int rankKind = best.rankKind;\n    int gamma = best.gamma;\n\n    // Online placement\n    vector<int> remChild = tr.childCnt;\n    vector<char> used(M + 1, 0);\n    vector<int> assigned(M + 1, -1);\n\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        int u = pickLeaf(tr, remChild, used, t, rankKind, gamma);\n        used[u] = 1;\n        assigned[u] = t;\n        int p = tr.parent[u];\n        if (p != 0) --remChild[p];\n\n        cout << cellR[u] << ' ' << cellC[u] << '\\n' << flush;\n    }\n\n    // Final removal order: smallest available label first on the rooted tree\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int v : tr.child[0]) pq.push({assigned[v], v});\n\n    vector<int> order;\n    order.reserve(M);\n\n    while (!pq.empty()) {\n        auto [lab, u] = pq.top();\n        pq.pop();\n        order.push_back(u);\n        for (int v : tr.child[u]) pq.push({assigned[v], v});\n    }\n\n    for (int u : order) {\n        cout << cellR[u] << ' ' << cellC[u] << '\\n';\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXM = 100;\nstatic const int MAXV = MAXN * MAXN;\nstatic const long long INFLL = (1LL << 60);\n\nint n, m, N;\nvector<int> initBoard, boardCur;\nint nb[MAXV][4];\nint distToBorder[MAXV];\nint sameDegOrig[MAXV];\nint adjColorCountOrig[MAXV];\nbool origB[MAXM + 1];\nbool origAdj[MAXM + 1][MAXM + 1];\nbool requiredStatic[MAXV];\nvector<int> candidateCells;\n\nint curCnt[MAXM + 1];\nint curTouch0[MAXM + 1];\nint curAdj[MAXM + 1][MAXM + 1];\n\nint visStamp[MAXV];\nint stampNow = 1;\n\nuint32_t jitterKey[4][MAXV];\n\ninline int id(int i, int j) { return i * n + j; }\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\nvoid initStatsFromBoard(const vector<int>& b) {\n    boardCur = b;\n    memset(curCnt, 0, sizeof(curCnt));\n    memset(curTouch0, 0, sizeof(curTouch0));\n    memset(curAdj, 0, sizeof(curAdj));\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c > 0) curCnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c == 0) continue;\n\n        // Touching 0 / outside: count edge count.\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1 || boardCur[v] == 0) curTouch0[c]++;\n        }\n\n        // Color-color adjacencies: count each edge once (right/down).\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = boardCur[right];\n            if (d > 0 && d != c) {\n                curAdj[c][d]++;\n                curAdj[d][c]++;\n            }\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = boardCur[down];\n            if (d > 0 && d != c) {\n                curAdj[c][d]++;\n                curAdj[d][c]++;\n            }\n        }\n    }\n}\n\ninline void removeCell(int idx) {\n    int c = boardCur[idx];\n    int same = 0;\n    int loss0 = 0;\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            loss0++;\n        } else if (boardCur[v] == c) {\n            same++;\n        } else {\n            int t = boardCur[v];\n            curAdj[c][t]--;\n            curAdj[t][c]--;\n        }\n    }\n\n    boardCur[idx] = 0;\n    curCnt[c]--;\n    curTouch0[c] += same - loss0;\n}\n\ninline bool isFrontier(int idx) {\n    int c = boardCur[idx];\n    if (c == 0) return false;\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) return true;\n    }\n    return false;\n}\n\nbool canRemove(int idx) {\n    int c = boardCur[idx];\n    if (c == 0) return false;\n    if (!origB[c]) return false;\n    if (requiredStatic[idx]) return false;\n    if (curCnt[c] <= 1) return false;\n\n    int same = 0, loss0 = 0;\n    int loss[MAXM + 1];\n    memset(loss, 0, sizeof(loss));\n    bool frontier = false;\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            frontier = true;\n            loss0++;\n        } else if (boardCur[v] == c) {\n            same++;\n        } else {\n            int t = boardCur[v];\n            if (!origB[t]) return false; // would expose a non-boundary-touching color to 0\n            loss[t]++;\n        }\n    }\n\n    if (!frontier) return false;\n    if (curTouch0[c] - loss0 + same <= 0) return false;\n\n    for (int t = 1; t <= m; ++t) {\n        if (loss[t] == 0) continue;\n        if (curAdj[c][t] <= loss[t]) return false;\n    }\n\n    int start = -1;\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v != -1 && boardCur[v] == c) {\n            start = v;\n            break;\n        }\n    }\n    if (start == -1) return false;\n\n    ++stampNow;\n    vector<int> q;\n    q.reserve(curCnt[c]);\n    q.push_back(start);\n    visStamp[start] = stampNow;\n    int seen = 1;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[u][d];\n            if (v == -1 || v == idx) continue;\n            if (boardCur[v] == c && visStamp[v] != stampNow) {\n                visStamp[v] = stampNow;\n                q.push_back(v);\n                ++seen;\n            }\n        }\n    }\n\n    return seen == curCnt[c] - 1;\n}\n\nlong long staticScore(int idx, int mode) {\n    int c = boardCur[idx];\n    if (c == 0 || !origB[c] || requiredStatic[idx] || curCnt[c] <= 1) return INFLL;\n    if (!isFrontier(idx)) return INFLL;\n\n    int same = 0, loss0 = 0;\n    int loss[MAXM + 1];\n    memset(loss, 0, sizeof(loss));\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            loss0++;\n        } else if (boardCur[v] == c) {\n            same++;\n        } else {\n            int t = boardCur[v];\n            if (!origB[t]) return INFLL;\n            loss[t]++;\n        }\n    }\n\n    if (curTouch0[c] - loss0 + same <= 0) return INFLL;\n    for (int t = 1; t <= m; ++t) {\n        if (loss[t] == 0) continue;\n        if (curAdj[c][t] <= loss[t]) return INFLL;\n    }\n\n    long long sc = 0;\n    if (mode == 0) {\n        sc = 1LL * distToBorder[idx] * 1000\n           + 1LL * adjColorCountOrig[idx] * 100\n           + 1LL * sameDegOrig[idx] * 10;\n    } else {\n        sc = 1LL * sameDegOrig[idx] * 1000\n           + 1LL * adjColorCountOrig[idx] * 100\n           + 1LL * distToBorder[idx];\n    }\n    return sc;\n}\n\nlong long dynamicScore(int idx, int mode) {\n    int c = boardCur[idx];\n    if (c == 0 || !origB[c] || requiredStatic[idx] || curCnt[c] <= 1) return INFLL;\n    if (!isFrontier(idx)) return INFLL;\n\n    int same = 0, loss0 = 0;\n    int loss[MAXM + 1];\n    memset(loss, 0, sizeof(loss));\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            loss0++;\n        } else if (boardCur[v] == c) {\n            same++;\n        } else {\n            int t = boardCur[v];\n            if (!origB[t]) return INFLL;\n            loss[t]++;\n        }\n    }\n\n    if (curTouch0[c] - loss0 + same <= 0) return INFLL;\n\n    int crit = 0;\n    for (int t = 1; t <= m; ++t) {\n        if (loss[t] == 0) continue;\n        if (curAdj[c][t] <= loss[t]) crit++;\n    }\n\n    for (int t = 1; t <= m; ++t) {\n        if (loss[t] == 0) continue;\n        if (curAdj[c][t] <= loss[t]) return INFLL;\n    }\n\n    long long sc = 0;\n    if (mode == 2) {\n        sc = 1LL * crit * 1000\n           + 1LL * same * 100\n           + 1LL * adjColorCountOrig[idx] * 10\n           + 1LL * distToBorder[idx]\n           + jitterKey[mode][idx];\n    } else {\n        sc = 1LL * same * 1000\n           + 1LL * crit * 100\n           + 1LL * adjColorCountOrig[idx] * 10\n           + 1LL * distToBorder[idx]\n           + jitterKey[mode][idx];\n    }\n    return sc;\n}\n\nvector<int> runMode(const vector<int>& startBoard, int mode, uint64_t seed) {\n    initStatsFromBoard(startBoard);\n\n    if (mode >= 2) {\n        for (int idx = 0; idx < N; ++idx) {\n            jitterKey[mode][idx] = (uint32_t)(splitmix64(seed + idx * 1234567ULL + mode * 998244353ULL) & 63ULL);\n        }\n    }\n\n    while (true) {\n        vector<pair<long long, int>> ord;\n        ord.reserve(candidateCells.size());\n\n        for (int idx : candidateCells) {\n            if (boardCur[idx] == 0) continue;\n            long long sc = (mode <= 1 ? staticScore(idx, mode) : dynamicScore(idx, mode));\n            if (sc >= INFLL / 2) continue;\n            ord.emplace_back(sc, idx);\n        }\n\n        if (ord.empty()) break;\n        sort(ord.begin(), ord.end());\n\n        bool removed = false;\n        for (auto [sc, idx] : ord) {\n            if (boardCur[idx] == 0) continue;\n            if (canRemove(idx)) {\n                removeCell(idx);\n                removed = true;\n                break;\n            }\n        }\n        if (!removed) break;\n    }\n\n    return boardCur;\n}\n\nbool validate(const vector<int>& b) {\n    bool outAdj[MAXM + 1][MAXM + 1];\n    memset(outAdj, 0, sizeof(outAdj));\n    bool outTouch0[MAXM + 1];\n    memset(outTouch0, 0, sizeof(outTouch0));\n\n    vector<int> cnt(MAXM + 1, 0);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c > 0) cnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c == 0) continue;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1 || b[v] == 0) {\n                outTouch0[c] = true;\n            } else if (b[v] != c) {\n                int t = b[v];\n                outAdj[c][t] = outAdj[t][c] = true;\n            }\n        }\n    }\n\n    for (int c = 1; c <= m; ++c) {\n        if (outTouch0[c] != origB[c]) return false;\n        for (int d = 1; d <= m; ++d) {\n            if (outAdj[c][d] != origAdj[c][d]) return false;\n        }\n    }\n\n    vector<int> seen(N, 0);\n    int stamp = 1;\n    vector<int> q;\n    q.reserve(N);\n\n    for (int c = 1; c <= m; ++c) {\n        int start = -1;\n        for (int idx = 0; idx < N; ++idx) {\n            if (b[idx] == c) {\n                start = idx;\n                break;\n            }\n        }\n        if (start == -1) return false;\n\n        ++stamp;\n        q.clear();\n        q.push_back(start);\n        seen[start] = stamp;\n        int got = 1;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == c && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                    ++got;\n                }\n            }\n        }\n        if (got != cnt[c]) return false;\n    }\n\n    int zeroCnt = 0;\n    for (int idx = 0; idx < N; ++idx) if (b[idx] == 0) zeroCnt++;\n    if (zeroCnt > 0) {\n        ++stamp;\n        q.clear();\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    int idx = id(i, j);\n                    if (b[idx] == 0 && seen[idx] != stamp) {\n                        seen[idx] = stamp;\n                        q.push_back(idx);\n                    }\n                }\n            }\n        }\n        if (q.empty()) return false;\n\n        int got = 0;\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            ++got;\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == 0 && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                }\n            }\n        }\n        if (got != zeroCnt) return false;\n    }\n\n    return true;\n}\n\nint countZeros(const vector<int>& b) {\n    int z = 0;\n    for (int x : b) if (x == 0) ++z;\n    return z;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    N = n * n;\n    initBoard.assign(N, 0);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c;\n            cin >> c;\n            initBoard[id(i, j)] = c;\n        }\n    }\n\n    // Neighbors and static geometry.\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = id(i, j);\n            nb[idx][0] = (i == 0 ? -1 : id(i - 1, j));\n            nb[idx][1] = (i + 1 == n ? -1 : id(i + 1, j));\n            nb[idx][2] = (j == 0 ? -1 : id(i, j - 1));\n            nb[idx][3] = (j + 1 == n ? -1 : id(i, j + 1));\n            distToBorder[idx] = min(min(i, j), min(n - 1 - i, n - 1 - j));\n        }\n    }\n\n    memset(origB, 0, sizeof(origB));\n    for (int i = 0; i < n; ++i) {\n        origB[initBoard[id(i, 0)]] = true;\n        origB[initBoard[id(i, n - 1)]] = true;\n    }\n    for (int j = 0; j < n; ++j) {\n        origB[initBoard[id(0, j)]] = true;\n        origB[initBoard[id(n - 1, j)]] = true;\n    }\n\n    memset(origAdj, 0, sizeof(origAdj));\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = initBoard[right];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = initBoard[down];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int same = 0;\n        bool seenDiff[MAXM + 1] = {};\n        int diffCnt = 0;\n        bool req = false;\n\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1) continue;\n            int t = initBoard[v];\n            if (t == c) {\n                same++;\n            } else {\n                if (!seenDiff[t]) {\n                    seenDiff[t] = true;\n                    diffCnt++;\n                }\n                if (t > 0 && !origB[t]) req = true;\n            }\n        }\n\n        sameDegOrig[idx] = same;\n        adjColorCountOrig[idx] = diffCnt;\n        requiredStatic[idx] = req;\n    }\n\n    candidateCells.reserve(N);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        if (c > 0 && origB[c] && !requiredStatic[idx]) candidateCells.push_back(idx);\n    }\n\n    vector<int> bestBoard = initBoard;\n    int bestZeros = countZeros(bestBoard);\n\n    // Four candidate modes.\n    vector<pair<int, uint64_t>> modes = {\n        {0, 123456789ULL},\n        {1, 987654321ULL},\n        {2, 19260817ULL},\n        {3, 998244353ULL}\n    };\n\n    for (auto [mode, seed] : modes) {\n        vector<int> cand = runMode(initBoard, mode, seed);\n        if (validate(cand)) {\n            int z = countZeros(cand);\n            if (z > bestZeros) {\n                bestZeros = z;\n                bestBoard = cand;\n            }\n        }\n    }\n\n    // One extra improvement pass from the best board using the dynamic crit-based mode.\n    {\n        vector<int> cand = runMode(bestBoard, 2, 1145141919ULL);\n        if (validate(cand)) {\n            int z = countZeros(cand);\n            if (z > bestZeros) {\n                bestZeros = z;\n                bestBoard = cand;\n            }\n        }\n    }\n\n    if (!validate(bestBoard)) {\n        bestBoard = initBoard;\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << bestBoard[id(i, j)];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ld = long double;\n\nstruct Bucket {\n    vector<int> items;\n    int l = 0, r = -1;      // descending rank interval [l, r]\n    bool sameGroup = false; // all items in this bucket are known equal\n    bool exhausted = false;  // no more useful queries expected here\n    ld value = 0.0L;        // estimated total weight of this interval\n};\n\nstruct PartResult {\n    vector<int> ans;\n    ld score = numeric_limits<ld>::infinity();\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    const ld MU = 100000.0L;\n    const ld CAP = MU * (ld)N / (ld)D;\n\n    mt19937_64 rng(\n        0x9e3779b97f4a7c15ULL ^\n        (uint64_t)N * 1000003ULL ^\n        (uint64_t)D * 10007ULL ^\n        (uint64_t)Q * 10000019ULL\n    );\n\n    auto rand_int = [&](int l, int r) -> int {\n        uniform_int_distribution<int> dist(l, r);\n        return dist(rng);\n    };\n\n    // Rank-based expected weights for descending rank r = 0..N-1.\n    vector<ld> rankExp(N, 0.0L);\n    vector<ld> H(N + 1, 0.0L);\n    for (int i = 1; i <= N; ++i) H[i] = H[i - 1] + 1.0L / (ld)i;\n\n    ld capProb = 1.0L - expl(-CAP / MU);\n    for (int r = 0; r < N; ++r) {\n        ld p = ((ld)N - (ld)r - 0.5L) / (ld)N;\n        if (p < 1e-18L) p = 1e-18L;\n        if (p > 1.0L - 1e-18L) p = 1.0L - 1e-18L;\n\n        ld harm = MU * (H[N] - H[r]);\n        ld quant = -MU * log1pl(-capProb * p);\n\n        ld v = 0.65L * harm + 0.35L * quant;\n        if (v < 1.0L) v = 1.0L;\n        if (v > CAP) v = CAP;\n        rankExp[r] = v;\n    }\n\n    vector<ld> pref(N + 1, 0.0L);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + rankExp[i];\n\n    auto intervalValue = [&](int l, int r) -> ld {\n        if (l > r) return 0.0L;\n        return pref[r + 1] - pref[l];\n    };\n\n    vector<ld> win(N, 0.0L);\n    vector<int> deg(N, 0);\n\n    vector<vector<unsigned char>> seen(N, vector<unsigned char>(N, 0));\n    auto is_seen = [&](int a, int b) -> bool {\n        if (a > b) swap(a, b);\n        return seen[a][b] != 0;\n    };\n    auto mark_seen = [&](int a, int b) {\n        if (a > b) swap(a, b);\n        seen[a][b] = 1;\n    };\n\n    int queries_left = Q;\n\n    auto pct = [&](int i) -> ld {\n        return (win[i] + 0.5L) / (ld)(deg[i] + 1);\n    };\n\n    auto ask = [&](int a, int b) -> int {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n' << flush;\n        char c;\n        cin >> c;\n        --queries_left;\n        mark_seen(a, b);\n\n        int res = (c == '>' ? 1 : (c == '<' ? -1 : 0));\n        ++deg[a];\n        ++deg[b];\n        if (res > 0) {\n            win[a] += 1.0L;\n        } else if (res < 0) {\n            win[b] += 1.0L;\n        } else {\n            win[a] += 0.5L;\n            win[b] += 0.5L;\n        }\n        return res;\n    };\n\n    // Warm-up: a few random disjoint comparisons.\n    {\n        int warm = min({N / 2, max(4, Q / 12), 10});\n        vector<int> perm(N);\n        iota(perm.begin(), perm.end(), 0);\n        shuffle(perm.begin(), perm.end(), rng);\n        for (int i = 0; i < warm; ++i) {\n            ask(perm[2 * i], perm[2 * i + 1]);\n        }\n    }\n\n    vector<Bucket> buckets;\n    {\n        Bucket root;\n        root.items.resize(N);\n        iota(root.items.begin(), root.items.end(), 0);\n        root.l = 0;\n        root.r = N - 1;\n        root.sameGroup = false;\n        root.exhausted = false;\n        root.value = pref[N];\n        buckets.push_back(move(root));\n    }\n\n    auto sort_by_pct = [&](vector<int>& items) {\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n    };\n\n    auto sort_for_pivot = [&](vector<int> items) {\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] < deg[b]; // low-degree pivot preferred\n            return a < b;\n        });\n        return items;\n    };\n\n    auto pick_split_bucket = [&]() -> int {\n        int best = -1;\n        ld bestMetric = -1.0L;\n        ld bestValue = -1.0L;\n\n        for (int i = 0; i < (int)buckets.size(); ++i) {\n            const auto& bk = buckets[i];\n            int m = (int)bk.items.size();\n            if (m <= 1) continue;\n            if (bk.sameGroup || bk.exhausted) continue;\n            if (m - 1 > queries_left) continue;\n\n            ld metric = bk.value / (ld)(m - 1);\n            if (metric > bestMetric + 1e-18L ||\n                (fabsl(metric - bestMetric) <= 1e-18L && bk.value > bestValue)) {\n                bestMetric = metric;\n                bestValue = bk.value;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    auto split_bucket = [&](int idx) {\n        Bucket cur = buckets[idx];\n        buckets[idx] = buckets.back();\n        buckets.pop_back();\n\n        int m = (int)cur.items.size();\n        if (m <= 1) {\n            buckets.push_back(move(cur));\n            return;\n        }\n\n        vector<int> ord = sort_for_pivot(cur.items);\n        int mid = m / 2;\n        int lo = max(0, mid - 1);\n        int hi = min(m - 1, mid + 1);\n\n        int pivot = ord[lo];\n        for (int i = lo + 1; i <= hi; ++i) {\n            if (deg[ord[i]] < deg[pivot]) pivot = ord[i];\n        }\n\n        vector<int> greater, equal, less;\n        greater.reserve(m);\n        equal.reserve(m);\n        less.reserve(m);\n\n        for (int x : cur.items) {\n            if (x == pivot) continue;\n            int res = ask(pivot, x);\n            if (res > 0) {\n                // pivot heavier => x is lighter\n                less.push_back(x);\n            } else if (res < 0) {\n                greater.push_back(x);\n            } else {\n                equal.push_back(x);\n            }\n        }\n\n        int g = (int)greater.size();\n        int e = (int)equal.size();\n\n        if (!greater.empty()) {\n            Bucket bk;\n            bk.items = move(greater);\n            bk.l = cur.l;\n            bk.r = cur.l + g - 1;\n            bk.sameGroup = false;\n            bk.exhausted = (bk.items.size() <= 1);\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n\n        {\n            Bucket bk;\n            bk.items.reserve(1 + e);\n            bk.items.push_back(pivot);\n            for (int x : equal) bk.items.push_back(x);\n            bk.l = cur.l + g;\n            bk.r = cur.l + g + e;\n            bk.sameGroup = (e > 0);\n            bk.exhausted = (bk.items.size() <= 1) || bk.sameGroup;\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n\n        if (!less.empty()) {\n            Bucket bk;\n            bk.items = move(less);\n            bk.l = cur.l + g + e + 1;\n            bk.r = cur.r;\n            bk.sameGroup = false;\n            bk.exhausted = (bk.items.size() <= 1);\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n    };\n\n    // Main splitting phase.\n    while (queries_left > 0) {\n        int idx = pick_split_bucket();\n        if (idx == -1) break;\n        split_bucket(idx);\n    }\n\n    const int SMALL_T = 8;\n    int pairPtr = 0;\n    vector<pair<int, int>> allPairs;\n    allPairs.reserve(N * (N - 1) / 2);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            allPairs.push_back({i, j});\n        }\n    }\n    shuffle(allPairs.begin(), allPairs.end(), rng);\n\n    auto global_adjacent_pair = [&]() -> pair<int, int> {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n        for (int i = 0; i + 1 < N; ++i) {\n            int a = ord[i], b = ord[i + 1];\n            if (!is_seen(a, b)) return {a, b};\n        }\n        return {-1, -1};\n    };\n\n    auto next_random_unseen_pair = [&]() -> pair<int, int> {\n        while (pairPtr < (int)allPairs.size()) {\n            auto [a, b] = allPairs[pairPtr++];\n            if (!is_seen(a, b)) return {a, b};\n        }\n        for (int t = 0; t < 200; ++t) {\n            int a = rand_int(0, N - 1);\n            int b = rand_int(0, N - 2);\n            if (b >= a) ++b;\n            if (!is_seen(a, b)) return {a, b};\n        }\n        return {-1, -1};\n    };\n\n    // Use remaining queries to refine ambiguous areas.\n    while (queries_left > 0) {\n        int bestIdx = -1;\n        ld bestValue = -1.0L;\n        for (int i = 0; i < (int)buckets.size(); ++i) {\n            const auto& bk = buckets[i];\n            if (bk.exhausted) continue;\n            if ((int)bk.items.size() <= 1) continue;\n            if (bk.value > bestValue) {\n                bestValue = bk.value;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx != -1) {\n            auto& bk = buckets[bestIdx];\n            int m = (int)bk.items.size();\n\n            if (m <= SMALL_T) {\n                bool completed = true;\n                for (int i = 0; i < m && queries_left > 0; ++i) {\n                    for (int j = i + 1; j < m && queries_left > 0; ++j) {\n                        int a = bk.items[i], b = bk.items[j];\n                        if (is_seen(a, b)) continue;\n                        ask(a, b);\n                    }\n                }\n                // All pairs in this small bucket have been tried.\n                bk.exhausted = true;\n                continue;\n            } else {\n                vector<int> cand = bk.items;\n                sort(cand.begin(), cand.end(), [&](int a, int b) {\n                    ld pa = pct(a), pb = pct(b);\n                    if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n                    if (deg[a] != deg[b]) return deg[a] > deg[b];\n                    return a < b;\n                });\n                bool found = false;\n                for (int i = 0; i + 1 < m; ++i) {\n                    int a = cand[i], b = cand[i + 1];\n                    if (!is_seen(a, b)) {\n                        ask(a, b);\n                        found = true;\n                        break;\n                    }\n                }\n                if (found) continue;\n            }\n        }\n\n        auto p = global_adjacent_pair();\n        if (p.first != -1) {\n            ask(p.first, p.second);\n            continue;\n        }\n\n        p = next_random_unseen_pair();\n        if (p.first == -1) {\n            // Fallback: any valid distinct pair.\n            int a = rand_int(0, N - 1);\n            int b = rand_int(0, N - 2);\n            if (b >= a) ++b;\n            ask(a, b);\n        } else {\n            ask(p.first, p.second);\n        }\n    }\n\n    // Final estimation of item weights.\n    vector<ld> est(N, 0.0L);\n    for (const auto& bk : buckets) {\n        int m = (int)bk.items.size();\n        if (m == 0) continue;\n\n        ld intervalSum = intervalValue(bk.l, bk.r);\n        ld avg = intervalSum / (ld)m;\n\n        if (bk.sameGroup) {\n            for (int x : bk.items) est[x] = avg;\n            continue;\n        }\n\n        vector<int> ord = bk.items;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n\n        vector<ld> tmp(m);\n        ld sumTmp = 0.0L;\n        for (int j = 0; j < m; ++j) {\n            int x = ord[j];\n            ld target = rankExp[bk.l + j];\n\n            ld conf;\n            if (bk.exhausted) {\n                conf = 0.85L;\n            } else {\n                conf = 0.25L + 0.50L * (ld)deg[x] / ((ld)deg[x] + 10.0L);\n                if (conf > 0.85L) conf = 0.85L;\n            }\n\n            ld v = avg * (1.0L - conf) + target * conf;\n            tmp[j] = v;\n            sumTmp += v;\n        }\n\n        ld scale = (sumTmp > 1e-18L ? intervalSum / sumTmp : 1.0L);\n        for (int j = 0; j < m; ++j) {\n            est[ord[j]] = tmp[j] * scale;\n            if (est[ord[j]] < 1.0L) est[ord[j]] = 1.0L;\n            if (est[ord[j]] > CAP) est[ord[j]] = CAP;\n        }\n    }\n\n    auto local_search = [&](vector<vector<int>>& bins, vector<ld>& load, const vector<ld>& w) {\n        auto remove_from_bin = [&](int item, int b, vector<int>& posInBin, vector<int>& where) {\n            int idx = posInBin[item];\n            int last = bins[b].back();\n            bins[b][idx] = last;\n            posInBin[last] = idx;\n            bins[b].pop_back();\n            where[item] = -1;\n        };\n\n        auto add_to_bin = [&](int item, int b, vector<int>& posInBin, vector<int>& where) {\n            where[item] = b;\n            posInBin[item] = (int)bins[b].size();\n            bins[b].push_back(item);\n        };\n\n        vector<int> where(N, -1), posInBin(N, -1);\n        for (int b = 0; b < D; ++b) {\n            for (int x : bins[b]) {\n                where[x] = b;\n                posInBin[x] = (int)(&x - &bins[b][0]); // placeholder, not used\n            }\n        }\n        // Rebuild positions safely.\n        for (int b = 0; b < D; ++b) {\n            for (int i = 0; i < (int)bins[b].size(); ++i) {\n                int x = bins[b][i];\n                where[x] = b;\n                posInBin[x] = i;\n            }\n        }\n\n        auto apply_move = [&](int item, int from, int to) {\n            int idx = posInBin[item];\n            int last = bins[from].back();\n            bins[from][idx] = last;\n            posInBin[last] = idx;\n            bins[from].pop_back();\n\n            load[from] -= w[item];\n\n            where[item] = to;\n            posInBin[item] = (int)bins[to].size();\n            bins[to].push_back(item);\n            load[to] += w[item];\n        };\n\n        auto apply_swap = [&](int x, int bx, int y, int by) {\n            int ix = posInBin[x];\n            int iy = posInBin[y];\n            bins[bx][ix] = y;\n            bins[by][iy] = x;\n            posInBin[x] = iy;\n            posInBin[y] = ix;\n            where[x] = by;\n            where[y] = bx;\n            load[bx] += w[y] - w[x];\n            load[by] += w[x] - w[y];\n        };\n\n        for (int iter = 0; iter < 160; ++iter) {\n            ld bestDelta = 0.0L;\n            int bestType = 0; // 1: move, 2: swap\n            int ba = -1, bb = -1, bx = -1, by = -1;\n\n            for (int a = 0; a < D; ++a) {\n                for (int b = 0; b < D; ++b) {\n                    if (a == b) continue;\n                    if (load[a] <= load[b] + 1e-18L) continue;\n                    ld d = load[a] - load[b];\n\n                    if ((int)bins[a].size() > 1) {\n                        for (int x : bins[a]) {\n                            ld ww = w[x];\n                            ld delta = 2.0L * ww * (ww - d);\n                            if (delta < bestDelta) {\n                                bestDelta = delta;\n                                bestType = 1;\n                                ba = a; bb = b; bx = x;\n                            }\n                        }\n                    }\n\n                    for (int x : bins[a]) {\n                        for (int y : bins[b]) {\n                            ld diff = w[x] - w[y];\n                            ld delta = 2.0L * diff * (diff - d);\n                            if (delta < bestDelta) {\n                                bestDelta = delta;\n                                bestType = 2;\n                                ba = a; bb = b; bx = x; by = y;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestDelta >= -1e-12L) break;\n\n            if (bestType == 1) {\n                apply_move(bx, ba, bb);\n            } else if (bestType == 2) {\n                apply_swap(bx, ba, by, bb);\n            } else {\n                break;\n            }\n        }\n\n        vector<int> ans(N, 0);\n        for (int b = 0; b < D; ++b) {\n            for (int x : bins[b]) ans[x] = b;\n        }\n\n        ld sumsq = 0.0L;\n        for (int b = 0; b < D; ++b) sumsq += load[b] * load[b];\n        return PartResult{ans, sumsq};\n    };\n\n    auto build_partition = [&](int mode, ld noiseAmp, int offset) -> PartResult {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        vector<ld> key(N, 0.0L);\n        for (int i = 0; i < N; ++i) {\n            ld noise = 0.0L;\n            if (noiseAmp > 0.0L) {\n                ld u = (ld)rand_int(0, 1000000) / 1000000.0L;\n                noise = (2.0L * u - 1.0L) * noiseAmp;\n            }\n            key[i] = est[i] * (1.0L + noise);\n        }\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (fabsl(key[a] - key[b]) > 1e-18L) return key[a] > key[b];\n            return a < b;\n        });\n\n        vector<vector<int>> bins(D);\n        vector<ld> load(D, 0.0L);\n\n        if (mode == 0) {\n            // LPT greedy\n            for (int id : ord) {\n                int best = 0;\n                for (int d = 1; d < D; ++d) {\n                    if (load[d] < load[best] - 1e-18L ||\n                        (fabsl(load[d] - load[best]) <= 1e-18L && bins[d].size() < bins[best].size())) {\n                        best = d;\n                    }\n                }\n                bins[best].push_back(id);\n                load[best] += est[id];\n            }\n        } else {\n            // Cyclic assignment with offset.\n            if (D == 0) offset = 0;\n            offset %= D;\n            if (offset < 0) offset += D;\n            for (int i = 0; i < N; ++i) {\n                int b = (i + offset) % D;\n                bins[b].push_back(ord[i]);\n                load[b] += est[ord[i]];\n            }\n        }\n\n        PartResult res = local_search(bins, load, est);\n        return res;\n    };\n\n    // Try several restarts with different initial packings.\n    PartResult best;\n    int restarts = min(8, 4 + Q / 1000);\n    for (int r = 0; r < restarts; ++r) {\n        int mode = r % 2; // 0 = LPT, 1 = cyclic\n        ld noiseAmp = (r == 0 ? 0.0L : min(0.05L, 0.01L * (ld)r));\n        int offset = (D > 0 ? rand_int(0, D - 1) : 0);\n        PartResult cur = build_partition(mode, noiseAmp, offset);\n        if (cur.score < best.score) best = move(cur);\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << best.ans[i];\n    }\n    cout << '\\n' << flush;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int MAXN = 205;\nstatic constexpr int MAXM = 10;\nstatic constexpr ll INF = (1LL << 60);\n\nint n, m;\n\nstruct Board {\n    int st[MAXM][MAXN];\n    int len[MAXM]{};\n    int posStack[MAXN]{};\n    int posIdx[MAXN]{};\n    int cur = 1; // smallest not yet removed\n};\n\nstruct Preset {\n    int lookK;\n    ll remW, nearW, adjW, sqW, topW, emptyW, maxHW;\n    ll emptyBonus, fitBonus, breakPenalty;\n    int noise;\n};\n\nstruct Solution {\n    ll energy = INF;\n    vector<pair<int,int>> ops;\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\nstatic inline ll noiseValue(uint64_t seed, int a, int b, int c, int d, int mod) {\n    if (mod <= 0) return 0;\n    uint64_t x = seed;\n    x ^= (uint64_t)a * 0x9e3779b97f4a7c15ULL;\n    x ^= (uint64_t)(b + 11) * 0xbf58476d1ce4e5b9ULL;\n    x ^= (uint64_t)(c + 23) * 0x94d049bb133111ebULL;\n    x ^= (uint64_t)(d + 37) * 0xda942042e4dd58b5ULL;\n    return (ll)(splitmix64(x) % (uint64_t)mod);\n}\n\n// Remove all currently removable boxes (free operation 2).\nstatic inline void flush(Board &b, vector<pair<int,int>> *ops) {\n    while (b.cur <= n) {\n        int x = b.cur;\n        int s = b.posStack[x];\n        if (s < 0) break;\n        if (b.posIdx[x] != b.len[s] - 1) break;\n\n        if (ops) ops->push_back({x, 0});\n        b.len[s]--;\n        b.posStack[x] = -1;\n        b.posIdx[x] = -1;\n        ++b.cur;\n    }\n}\n\n// Operation 1 followed by the forced free removal of the current smallest.\n// IMPORTANT: op1 parameter is the box directly above current smallest,\n// i.e. the bottom of the suffix that is actually moved.\nstatic inline void applyMove(Board &b, ll &spent, int dest, vector<pair<int,int>> *ops) {\n    int x = b.cur;\n    int s = b.posStack[x];\n    int idx = b.posIdx[x];\n\n    int from = idx + 1;               // first moved box (op1 parameter)\n    int k = b.len[s] - from;          // number of moved boxes\n    if (k <= 0) return;               // should not happen if flush() is correct\n\n    spent += k + 1;\n\n    if (ops) ops->push_back({b.st[s][from], dest + 1});\n\n    int base = b.len[dest];\n    for (int t = 0; t < k; ++t) {\n        int v = b.st[s][from + t];\n        b.st[dest][base + t] = v;\n        b.posStack[v] = dest;\n        b.posIdx[v] = base + t;\n    }\n    b.len[dest] += k;\n\n    if (ops) ops->push_back({x, 0});\n\n    // Current smallest is now on top of its stack.\n    b.len[s] = idx;\n    b.posStack[x] = -1;\n    b.posIdx[x] = -1;\n    ++b.cur;\n\n    flush(b, ops);\n}\n\nstatic inline ll heuristic(const Board &b, const Preset &P) {\n    if (b.cur > n) return 0;\n\n    int rem = n - b.cur + 1;\n\n    // Next few smallest boxes: weighted depth from top.\n    ll near = 0;\n    int L = min(rem, P.lookK);\n    for (int t = 0; t < L; ++t) {\n        int v = b.cur + t;\n        int s = b.posStack[v];\n        int depth = b.len[s] - 1 - b.posIdx[v];\n        near += 1LL * (L - t) * depth;\n    }\n\n    ll adjBad = 0;   // adjacent violations of decreasing order bottom->top\n    ll topSum = 0;   // smaller tops are generally easier\n    ll sumSq = 0;    // balance stacks\n    ll empty = 0;\n    ll maxH = 0;\n\n    for (int s = 0; s < m; ++s) {\n        int h = b.len[s];\n        sumSq += 1LL * h * h;\n        maxH = max<ll>(maxH, h);\n        if (h == 0) {\n            ++empty;\n            continue;\n        }\n        topSum += b.st[s][h - 1];\n        for (int i = 0; i + 1 < h; ++i) {\n            if (b.st[s][i] < b.st[s][i + 1]) ++adjBad;\n        }\n    }\n\n    // Tuned to be comparable to the real move costs.\n    ll score = 0;\n    score += P.remW * rem;\n    score += P.nearW * near / 8;\n    score += P.adjW * adjBad;\n    score += P.sqW * sumSq / 20;\n    score += P.topW * topSum / 20;\n    score -= P.emptyW * empty;\n    score += P.maxHW * maxH;\n    return score;\n}\n\n// Destination preference for a single move.\n// Uses current stack top fit + a small per-run randomized stack bias.\nstatic inline ll moveBias(const Board &b, int dest, const Preset &P, const array<int, MAXM> &pref) {\n    int src = b.posStack[b.cur];\n    int idx = b.posIdx[b.cur];\n    int firstMoved = b.st[src][idx + 1];\n\n    ll bias = pref[dest];\n\n    if (b.len[dest] == 0) {\n        return bias - P.emptyBonus;\n    }\n\n    int top = b.st[dest][b.len[dest] - 1];\n    int gap = top - firstMoved;\n\n    if (gap > 0) {\n        // Good fit: smaller positive gap is slightly better.\n        return bias - P.fitBonus + min<ll>(4, gap / 3);\n    } else {\n        // Bad fit: larger violation is worse.\n        return bias + P.breakPenalty + min<ll>(4, (-gap) / 3);\n    }\n}\n\n// 2-ply evaluation of choosing destination d1 from the given state.\nstatic inline ll evaluateFirstMove(\n    const Board &base,\n    ll spent,\n    int d1,\n    const Preset &P,\n    uint64_t seed,\n    const array<int, MAXM> &pref\n) {\n    ll bias1 = moveBias(base, d1, P, pref);\n\n    Board t1 = base;\n    ll s1 = spent;\n    applyMove(t1, s1, d1, nullptr);\n\n    if (t1.cur > n) {\n        return s1 + bias1 + noiseValue(seed, base.cur, d1, base.posStack[base.cur], base.len[d1], P.noise);\n    }\n\n    ll best2 = INF;\n    int src2 = t1.posStack[t1.cur];\n\n    for (int d2 = 0; d2 < m; ++d2) {\n        if (d2 == src2) continue;\n\n        ll bias2 = moveBias(t1, d2, P, pref);\n        Board t2 = t1;\n        ll s2 = s1;\n        applyMove(t2, s2, d2, nullptr);\n\n        ll sc = s2 + bias1 + bias2 + heuristic(t2, P);\n        sc += noiseValue(seed ^ 0x9e3779b97f4a7c15ULL, t1.cur, d2, src2, t1.len[d2], P.noise);\n        best2 = min(best2, sc);\n    }\n\n    return best2;\n}\n\nstatic inline Solution buildOne(const Board &init, const Preset &P, uint64_t seed) {\n    Board b = init;\n    ll spent = 0;\n    vector<pair<int,int>> ops;\n    ops.reserve(1000);\n\n    array<int, MAXM> pref{};\n    for (int s = 0; s < m; ++s) {\n        uint64_t x = splitmix64(seed ^ (uint64_t)(s + 1) * 0x123456789abcdefULL);\n        pref[s] = (int)(x % 5) - 2; // small randomized destination preference in [-2,2]\n    }\n\n    flush(b, &ops);\n\n    while (b.cur <= n) {\n        int src = b.posStack[b.cur];\n\n        ll bestScore = INF;\n        int bestDest = -1;\n\n        for (int d = 0; d < m; ++d) {\n            if (d == src) continue;\n            ll sc = evaluateFirstMove(b, spent, d, P, seed, pref);\n            if (sc < bestScore || (sc == bestScore && d < bestDest)) {\n                bestScore = sc;\n                bestDest = d;\n            }\n        }\n\n        if (bestDest < 0) bestDest = (src + 1) % m;\n\n        applyMove(b, spent, bestDest, &ops);\n    }\n\n    Solution sol;\n    sol.energy = spent;\n    sol.ops = std::move(ops);\n    return sol;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    Board init;\n    uint64_t baseSeed = 1469598103934665603ULL;\n\n    for (int s = 0; s < m; ++s) {\n        int h = n / m;\n        init.len[s] = h;\n        for (int i = 0; i < h; ++i) {\n            int v;\n            cin >> v;\n            init.st[s][i] = v;\n            init.posStack[v] = s;\n            init.posIdx[v] = i;\n            baseSeed = splitmix64(baseSeed ^ (uint64_t)v);\n        }\n    }\n\n    vector<Preset> presets = {\n        {12, 2,  6, 18, 2, 1, 18, 1, 10,  6,  8, 4},\n        {18, 2,  7, 15, 1, 1, 22, 1, 12,  8, 10, 5},\n        {24, 2,  8, 12, 2, 2, 24, 2, 15, 10, 12, 6},\n        {30, 1,  9, 10, 1, 1, 18, 1, 18, 10, 12, 4},\n        {15, 3,  5, 22, 3, 1, 20, 1,  8,  5, 10, 3},\n        {20, 2, 10, 14, 2, 2, 28, 2, 20, 12, 10, 5},\n        {10, 3,  4, 25, 4, 1, 15, 1,  8,  6, 12, 4},\n        {25, 2,  8, 16, 2, 2, 26, 2, 14,  9, 11, 6},\n    };\n\n    Solution best;\n    auto start = chrono::steady_clock::now();\n\n    // Multiple randomized attempts; keep the best exact energy.\n    const int MAX_ATTEMPTS = 32;\n    for (int att = 0; att < MAX_ATTEMPTS; ++att) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > 1.65) break;\n\n        const Preset &P = presets[att % (int)presets.size()];\n        uint64_t seed = splitmix64(baseSeed + 0x9e3779b97f4a7c15ULL * (uint64_t)(att + 1));\n\n        Solution cur = buildOne(init, P, seed);\n        if (cur.energy < best.energy) best = std::move(cur);\n    }\n\n    for (auto [v, i] : best.ops) {\n        cout << v << ' ' << i << '\\n';\n    }\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing i128 = __int128_t;\n\nstatic const int DR[4] = {-1, 1, 0, 0};\nstatic const int DC[4] = {0, 0, -1, 1};\nstatic const int REV[4] = {1, 0, 3, 2};\nstatic const char CH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Edge {\n    int to, dir;\n};\n\nstruct TreeInfo {\n    int root;\n    vector<int> parent;\n    vector<int> order;\n    vector<vector<pair<int,int>>> children;\n    vector<long long> subW;\n    vector<int> subCnt;\n};\n\nint N, TOT;\nvector<int> D;\nvector<vector<Edge>> adj, highAdj, lowAdj;\nvector<array<int,4>> nxt;\nvector<long long> localScore, nodeHeu;\n\n// BFS from origin: shortest paths, but neighbor order prefers low-weight cells\nvector<int> parent0, pdir0, dist0;\n\nstatic void emitTour(int u, const vector<vector<pair<int,int>>>& ch, vector<int>& out) {\n    for (auto [v, dir] : ch[u]) {\n        out.push_back(dir);\n        emitTour(v, ch, out);\n        out.push_back(REV[dir]);\n    }\n}\n\nstatic vector<int> reverseRoute(const vector<int>& dirs) {\n    vector<int> rev;\n    rev.reserve(dirs.size());\n    for (auto it = dirs.rbegin(); it != dirs.rend(); ++it) {\n        rev.push_back(REV[*it]);\n    }\n    return rev;\n}\n\nstatic pair<i128,int> evaluateRoute(const vector<int>& dirs) {\n    vector<int> first(TOT, -1), last(TOT, -1);\n    vector<long long> acc(TOT, 0);\n\n    int cur = 0;\n    int t = 0;\n    for (int dir : dirs) {\n        cur = nxt[cur][dir];\n        ++t;\n        if (first[cur] == -1) {\n            first[cur] = last[cur] = t;\n        } else {\n            int gap = t - last[cur];\n            acc[cur] += 1LL * gap * (gap - 1) / 2;\n            last[cur] = t;\n        }\n    }\n\n    i128 total = 0;\n    for (int u = 0; u < TOT; ++u) {\n        // All cells must be visited in a valid route.\n        int gap = first[u] + t - last[u];\n        acc[u] += 1LL * gap * (gap - 1) / 2;\n        total += (i128)acc[u] * (i128)D[u];\n    }\n    return {total, t};\n}\n\nstatic bool better(i128 num1, int den1, i128 num2, int den2) {\n    // compare num1/den1 < num2/den2\n    return num1 * (i128)den2 < num2 * (i128)den1;\n}\n\nstatic TreeInfo buildTree(int root, const vector<vector<Edge>>& orderAdj, bool bfsMode) {\n    TreeInfo tr;\n    tr.root = root;\n    tr.parent.assign(TOT, -1);\n    tr.order.reserve(TOT);\n    tr.children.assign(TOT, {});\n\n    if (bfsMode) {\n        vector<int> q;\n        q.reserve(TOT);\n        int head = 0;\n        tr.parent[root] = root;\n        q.push_back(root);\n        tr.order.push_back(root);\n\n        while (head < (int)q.size()) {\n            int u = q[head++];\n            for (const auto& e : orderAdj[u]) {\n                int v = e.to;\n                if (tr.parent[v] == -1) {\n                    tr.parent[v] = u;\n                    tr.children[u].push_back({v, e.dir});\n                    tr.order.push_back(v);\n                    q.push_back(v);\n                }\n            }\n        }\n    } else {\n        vector<int> st;\n        vector<int> it(TOT, 0);\n        st.reserve(TOT);\n        tr.parent[root] = root;\n        st.push_back(root);\n        tr.order.push_back(root);\n\n        while (!st.empty()) {\n            int u = st.back();\n            if (it[u] == (int)orderAdj[u].size()) {\n                st.pop_back();\n                continue;\n            }\n            auto e = orderAdj[u][it[u]++];\n            int v = e.to;\n            if (tr.parent[v] == -1) {\n                tr.parent[v] = u;\n                tr.children[u].push_back({v, e.dir});\n                tr.order.push_back(v);\n                st.push_back(v);\n            }\n        }\n    }\n\n    tr.subW.assign(TOT, 0);\n    tr.subCnt.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        tr.subW[u] = D[u];\n        tr.subCnt[u] = 1;\n    }\n    for (int i = TOT - 1; i >= 0; --i) {\n        int u = tr.order[i];\n        if (u == root) continue;\n        int p = tr.parent[u];\n        tr.subW[p] += tr.subW[u];\n        tr.subCnt[p] += tr.subCnt[u];\n    }\n\n    return tr;\n}\n\nstatic vector<int> pathToRoot(int root) {\n    vector<int> dirs;\n    int x = root;\n    while (x != 0) {\n        dirs.push_back(pdir0[x]);\n        x = parent0[x];\n    }\n    reverse(dirs.begin(), dirs.end());\n    return dirs;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    TOT = N * 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    D.assign(TOT, 0);\n    auto id = [&](int r, int c) { return r * N + c; };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> D[id(i, j)];\n        }\n    }\n\n    adj.assign(TOT, {});\n    nxt.assign(TOT, {});\n    for (int i = 0; i < TOT; ++i) nxt[i].fill(-1);\n\n    auto addEdge = [&](int u, int vtx, int dirUV, int dirVU) {\n        adj[u].push_back({vtx, dirUV});\n        adj[vtx].push_back({u, dirVU});\n        nxt[u][dirUV] = vtx;\n        nxt[vtx][dirVU] = u;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                addEdge(u, id(i + 1, j), 1, 0); // D / U\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                addEdge(u, id(i, j + 1), 3, 2); // R / L\n            }\n        }\n    }\n\n    localScore.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        long long s = D[u];\n        for (auto e : adj[u]) s += D[e.to];\n        localScore[u] = s;\n    }\n\n    // Heuristic importance used for adjacency ordering.\n    nodeHeu.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        nodeHeu[u] = localScore[u] * 1000LL + 100LL * D[u] + (long long)adj[u].size();\n    }\n\n    highAdj = adj;\n    lowAdj = adj;\n    for (int u = 0; u < TOT; ++u) {\n        sort(highAdj[u].begin(), highAdj[u].end(), [&](const Edge& a, const Edge& b) {\n            if (nodeHeu[a.to] != nodeHeu[b.to]) return nodeHeu[a.to] > nodeHeu[b.to];\n            return a.to < b.to;\n        });\n        sort(lowAdj[u].begin(), lowAdj[u].end(), [&](const Edge& a, const Edge& b) {\n            if (nodeHeu[a.to] != nodeHeu[b.to]) return nodeHeu[a.to] < nodeHeu[b.to];\n            return a.to < b.to;\n        });\n    }\n\n    // Shortest paths from origin, preferring low-score cells among shortest options.\n    parent0.assign(TOT, -1);\n    pdir0.assign(TOT, -1);\n    dist0.assign(TOT, -1);\n    {\n        vector<int> q;\n        q.reserve(TOT);\n        int head = 0;\n        q.push_back(0);\n        parent0[0] = 0;\n        dist0[0] = 0;\n\n        while (head < (int)q.size()) {\n            int u = q[head++];\n            for (const auto& e : lowAdj[u]) {\n                int vtx = e.to;\n                if (dist0[vtx] == -1) {\n                    dist0[vtx] = dist0[u] + 1;\n                    parent0[vtx] = u;\n                    pdir0[vtx] = e.dir;\n                    q.push_back(vtx);\n                }\n            }\n        }\n    }\n\n    // Candidate roots from several heuristics.\n    vector<int> roots;\n    vector<char> used(TOT, 0);\n    auto addRoot = [&](int x) {\n        if (!used[x]) {\n            used[x] = 1;\n            roots.push_back(x);\n        }\n    };\n\n    addRoot(0);\n\n    auto addTop = [&](auto scorer, int K) {\n        vector<pair<long double,int>> vec;\n        vec.reserve(TOT);\n        for (int u = 0; u < TOT; ++u) vec.push_back({scorer(u), u});\n        sort(vec.begin(), vec.end(), [&](const auto& a, const auto& b) {\n            if (fabsl(a.first - b.first) > 1e-18L) return a.first > b.first;\n            return a.second < b.second;\n        });\n        for (int i = 0; i < K && i < (int)vec.size(); ++i) addRoot(vec[i].second);\n    };\n\n    addTop([&](int u) -> long double { return (long double)localScore[u]; }, 8);\n    addTop([&](int u) -> long double { return (long double)D[u]; }, 8);\n    addTop([&](int u) -> long double { return (long double)(localScore[u] + 10LL * D[u]) / (dist0[u] + 1.0L); }, 8);\n    addTop([&](int u) -> long double { return (long double)(nodeHeu[u]) / (dist0[u] + 1.0L); }, 8);\n\n    vector<long double> rootRank(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        rootRank[u] = (long double)(localScore[u] + 10LL * D[u]) / (dist0[u] + 1.0L);\n    }\n\n    vector<int> others;\n    others.reserve(roots.size());\n    for (int x : roots) if (x != 0) others.push_back(x);\n    sort(others.begin(), others.end(), [&](int a, int b) {\n        if (fabsl(rootRank[a] - rootRank[b]) > 1e-18L) return rootRank[a] > rootRank[b];\n        if (dist0[a] != dist0[b]) return dist0[a] < dist0[b];\n        return a < b;\n    });\n\n    roots.clear();\n    roots.push_back(0);\n    for (int x : others) roots.push_back(x);\n    if ((int)roots.size() > 12) roots.resize(12);\n\n    // Tree modes: BFS/DFS x high/low adjacency.\n    struct Mode {\n        const vector<vector<Edge>>* ordAdj;\n        bool bfsMode;\n    };\n    vector<Mode> modes = {\n        {&highAdj, true},\n        {&lowAdj,  true},\n        {&highAdj, false},\n        {&lowAdj,  false},\n    };\n\n    string bestRoute;\n    i128 bestNum = 0;\n    int bestDen = 1;\n    bool hasBest = false;\n\n    auto saveCandidate = [&](const vector<int>& dirs) {\n        auto [num, den] = evaluateRoute(dirs);\n        if (!hasBest || better(num, den, bestNum, bestDen) || (!better(bestNum, bestDen, num, den) && den < bestDen)) {\n            hasBest = true;\n            bestNum = num;\n            bestDen = den;\n            bestRoute.clear();\n            bestRoute.reserve(dirs.size());\n            for (int d : dirs) bestRoute.push_back(CH[d]);\n        }\n    };\n\n    auto timeStart = chrono::steady_clock::now();\n    auto timeOver = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - timeStart).count() > 1850;\n    };\n\n    for (int root : roots) {\n        if (timeOver()) break;\n\n        vector<int> path = pathToRoot(root);\n\n        for (const auto& mode : modes) {\n            if (timeOver()) break;\n\n            TreeInfo tr = buildTree(root, *mode.ordAdj, mode.bfsMode);\n\n            vector<long double> keyDensity(TOT), keyWeight(TOT);\n            for (int u = 0; u < TOT; ++u) {\n                keyDensity[u] = (long double)tr.subW[u] / (long double)tr.subCnt[u];\n                keyWeight[u] = (long double)tr.subW[u];\n            }\n\n            for (int variant = 0; variant < 4; ++variant) {\n                if (timeOver()) break;\n\n                vector<vector<pair<int,int>>> ch = tr.children;\n                for (int u = 0; u < TOT; ++u) {\n                    auto cmpAsc = [&](const pair<int,int>& a, const pair<int,int>& b) {\n                        long double ka = (variant < 2 ? keyDensity[a.first] : keyWeight[a.first]);\n                        long double kb = (variant < 2 ? keyDensity[b.first] : keyWeight[b.first]);\n                        if (fabsl(ka - kb) > 1e-18L) {\n                            if (variant % 2 == 0) return ka < kb;\n                            else return ka > kb;\n                        }\n                        return a.first < b.first;\n                    };\n                    if ((int)ch[u].size() >= 2) sort(ch[u].begin(), ch[u].end(), cmpAsc);\n                }\n\n                vector<int> tour;\n                tour.reserve(2 * (TOT - 1));\n                emitTour(root, ch, tour);\n\n                vector<int> dirs;\n                dirs.reserve(path.size() * 2 + tour.size());\n                for (int d : path) dirs.push_back(d);\n                for (int d : tour) dirs.push_back(d);\n                for (auto it = path.rbegin(); it != path.rend(); ++it) dirs.push_back(REV[*it]);\n\n                saveCandidate(dirs);\n\n                vector<int> revDirs = reverseRoute(dirs);\n                saveCandidate(revDirs);\n            }\n        }\n    }\n\n    if (!hasBest) {\n        // Fallback: just output a trivial DFS-like route from origin tree.\n        // In practice this should never happen.\n        TreeInfo tr = buildTree(0, highAdj, true);\n        vector<long double> keyDensity(TOT), keyWeight(TOT);\n        for (int u = 0; u < TOT; ++u) {\n            keyDensity[u] = (long double)tr.subW[u] / (long double)tr.subCnt[u];\n            keyWeight[u] = (long double)tr.subW[u];\n        }\n        vector<vector<pair<int,int>>> ch = tr.children;\n        for (int u = 0; u < TOT; ++u) {\n            sort(ch[u].begin(), ch[u].end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n                if (fabsl(keyDensity[a.first] - keyDensity[b.first]) > 1e-18L) return keyDensity[a.first] < keyDensity[b.first];\n                return a.first < b.first;\n            });\n        }\n        vector<int> tour;\n        emitTour(0, ch, tour);\n        bestRoute.clear();\n        for (int d : tour) bestRoute.push_back(CH[d]);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 15;\nstatic constexpr int CELLS = H * H;\nstatic constexpr int MAXM = 205;\nstatic constexpr int INF = 1e9;\n\nint N, M, si, sj;\nvector<string> words;\nstring suffixes[MAXM][5];\nint suffixLB[MAXM][5];\n\nchar boardChar[H][H];\nint boardIdx[H][H];\nint distCell[CELLS][CELLS];\nint cellToLetterDist[CELLS][26];\nint letterDist[26][26];\nvector<int> cellsByLetter[26];\n\nstruct FastRng {\n    uint64_t x;\n    explicit FastRng(uint64_t seed = 88172645463393265ULL) : x(seed) {}\n    uint64_t next() {\n        uint64_t z = (x += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int nextInt(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n};\n\ninline int minCostState(const array<int, CELLS>& dp) {\n    return *min_element(dp.begin(), dp.end());\n}\n\ninline array<int, CELLS> applyCharCost(const array<int, CELLS>& in, char ch) {\n    int letter = ch - 'A';\n    int row[H][H];\n    array<int, CELLS> out;\n\n    for (int x = 0; x < H; ++x) {\n        int left[H], right[H];\n\n        left[0] = in[x * H + 0];\n        for (int y = 1; y < H; ++y) left[y] = min(in[x * H + y], left[y - 1] + 1);\n\n        right[H - 1] = in[x * H + (H - 1)];\n        for (int y = H - 2; y >= 0; --y) right[y] = min(in[x * H + y], right[y + 1] + 1);\n\n        for (int y = 0; y < H; ++y) row[x][y] = min(left[y], right[y]);\n    }\n\n    for (int y = 0; y < H; ++y) {\n        int up[H], down[H];\n\n        up[0] = row[0][y];\n        for (int x = 1; x < H; ++x) up[x] = min(row[x][y], up[x - 1] + 1);\n\n        down[H - 1] = row[H - 1][y];\n        for (int x = H - 2; x >= 0; --x) down[x] = min(row[x][y], down[x + 1] + 1);\n\n        for (int x = 0; x < H; ++x) {\n            int v = min(up[x], down[x]) + 1;\n            out[x * H + y] = (boardIdx[x][y] == letter ? v : INF);\n        }\n    }\n    return out;\n}\n\nint exactStringCost(const string& s) {\n    array<int, CELLS> dp;\n    dp.fill(INF);\n    dp[si * H + sj] = 0;\n    for (char ch : s) dp = applyCharCost(dp, ch);\n    return minCostState(dp);\n}\n\nint overlapTailWord(const string& tail, int idx) {\n    int lim = min<int>(4, tail.size());\n    const string& w = words[idx];\n    for (int k = lim; k >= 0; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (tail[(int)tail.size() - k + i] != w[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nstring makeStringFromOrder(const vector<int>& ord) {\n    string s = words[ord[0]];\n    string tail = s.substr(max(0, (int)s.size() - 4));\n\n    for (int t = 1; t < (int)ord.size(); ++t) {\n        int idx = ord[t];\n        int ov = overlapTailWord(tail, idx);\n        const string& add = suffixes[idx][ov];\n        s += add;\n        tail += add;\n        if ((int)tail.size() > 4) tail.erase(0, tail.size() - 4);\n    }\n    return s;\n}\n\nint evaluateOrderCost(const vector<int>& ord) {\n    return exactStringCost(makeStringFromOrder(ord));\n}\n\npair<int, vector<int>> solvePathFromString(const string& s) {\n    int L = (int)s.size();\n    vector<array<int16_t, CELLS>> par(L);\n\n    array<int, CELLS> dp, ndp;\n    dp.fill(INF);\n    dp[si * H + sj] = 0;\n\n    for (int i = 0; i < L; ++i) {\n        int c = s[i] - 'A';\n        ndp.fill(INF);\n        par[i].fill(-1);\n\n        for (int q : cellsByLetter[c]) {\n            int best = INF, bestp = -1;\n            for (int p = 0; p < CELLS; ++p) {\n                if (dp[p] >= INF) continue;\n                int v = dp[p] + distCell[p][q] + 1;\n                if (v < best) {\n                    best = v;\n                    bestp = p;\n                }\n            }\n            ndp[q] = best;\n            par[i][q] = (int16_t)bestp;\n        }\n        dp = ndp;\n    }\n\n    int end = -1, best = INF;\n    for (int q : cellsByLetter[s.back() - 'A']) {\n        if (dp[q] < best) {\n            best = dp[q];\n            end = q;\n        }\n    }\n\n    vector<int> path(L);\n    int cur = end;\n    for (int i = L - 1; i >= 0; --i) {\n        path[i] = cur;\n        cur = par[i][cur];\n    }\n    return {best, path};\n}\n\nstruct State {\n    array<int, CELLS> dp{};\n    array<uint64_t, 4> used{};\n    string tail;\n    int lastChar = 0;\n    int lastWord = -1;\n    int parent = -1;\n    int depth = 0;\n    int cost = INF;\n    int future = INF;\n};\n\ninline bool usedBit(const array<uint64_t, 4>& u, int i) {\n    return (u[i >> 6] >> (i & 63)) & 1ULL;\n}\n\ninline void setBit(array<uint64_t, 4>& u, int i) {\n    u[i >> 6] |= (1ULL << (i & 63));\n}\n\nint approxImmediateScore(const State& st, int idx) {\n    int ov = overlapTailWord(st.tail, idx);\n    const string& add = suffixes[idx][ov];\n    int first = add[0] - 'A';\n    int lb = suffixLB[idx][ov];\n\n    int best = INF;\n    for (int p : cellsByLetter[st.lastChar]) {\n        if (st.dp[p] >= INF) continue;\n        best = min(best, st.dp[p] + cellToLetterDist[p][first] + lb);\n    }\n    return best;\n}\n\nint approxFutureScore(const State& st) {\n    int b1 = INF, b2 = INF, b3 = INF;\n    for (int i = 0; i < M; ++i) {\n        if (usedBit(st.used, i)) continue;\n        int sc = approxImmediateScore(st, i);\n        if (sc < b1) {\n            b3 = b2;\n            b2 = b1;\n            b1 = sc;\n        } else if (sc < b2) {\n            b3 = b2;\n            b2 = sc;\n        } else if (sc < b3) {\n            b3 = sc;\n        }\n    }\n    long long sum = 0;\n    if (b1 < INF) sum += b1;\n    if (b2 < INF) sum += b2;\n    if (b3 < INF) sum += b3;\n    return (int)sum;\n}\n\nState buildInitialState(int idx) {\n    State st;\n    st.dp.fill(INF);\n    st.dp[si * H + sj] = 0;\n    for (char ch : words[idx]) st.dp = applyCharCost(st.dp, ch);\n\n    st.used.fill(0);\n    setBit(st.used, idx);\n    st.tail = words[idx].substr(max(0, (int)words[idx].size() - 4));\n    st.lastChar = words[idx].back() - 'A';\n    st.lastWord = idx;\n    st.parent = -1;\n    st.depth = 1;\n    st.cost = minCostState(st.dp);\n    st.future = approxFutureScore(st);\n    return st;\n}\n\nState extendState(const State& st, int idx, int parentId) {\n    State res = st;\n    int ov = overlapTailWord(st.tail, idx);\n    const string& add = suffixes[idx][ov];\n\n    for (char ch : add) res.dp = applyCharCost(res.dp, ch);\n\n    res.used = st.used;\n    setBit(res.used, idx);\n    res.tail += add;\n    if ((int)res.tail.size() > 4) res.tail.erase(0, res.tail.size() - 4);\n    res.lastChar = add.back() - 'A';\n    res.lastWord = idx;\n    res.parent = parentId;\n    res.depth = st.depth + 1;\n    res.cost = minCostState(res.dp);\n    res.future = approxFutureScore(res);\n    return res;\n}\n\nvector<pair<int, int>> pickCandidates(const State& st, int K, FastRng& rng) {\n    vector<pair<int, int>> arr;\n    arr.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        if (usedBit(st.used, i)) continue;\n        int sc = approxImmediateScore(st, i);\n        sc += (int)(rng.next() & 1ULL); // tiny noise for diversity\n        arr.push_back({sc, i});\n    }\n    sort(arr.begin(), arr.end());\n    if ((int)arr.size() > K) arr.resize(K);\n    return arr;\n}\n\nvector<int> reconstructOrder(const vector<State>& pool, int id) {\n    vector<int> ord;\n    while (id != -1) {\n        ord.push_back(pool[id].lastWord);\n        id = pool[id].parent;\n    }\n    reverse(ord.begin(), ord.end());\n    return ord;\n}\n\nvector<int> beamSearchRun(const vector<int>& seeds, int beamSize, int candK, FastRng& rng) {\n    vector<State> pool;\n    pool.reserve(30000);\n    vector<int> beam;\n\n    for (int seed : seeds) {\n        State st = buildInitialState(seed);\n        pool.push_back(st);\n        beam.push_back((int)pool.size() - 1);\n    }\n\n    auto cmpState = [&](int a, int b) {\n        if (pool[a].cost != pool[b].cost) return pool[a].cost < pool[b].cost;\n        if (pool[a].future != pool[b].future) return pool[a].future < pool[b].future;\n        return a < b;\n    };\n\n    sort(beam.begin(), beam.end(), cmpState);\n    if ((int)beam.size() > beamSize) beam.resize(beamSize);\n\n    while (!beam.empty() && pool[beam[0]].depth < M) {\n        vector<int> nxt;\n        nxt.reserve((int)beam.size() * candK);\n\n        for (int pid : beam) {\n            auto cand = pickCandidates(pool[pid], candK, rng);\n            for (auto [sc, idx] : cand) {\n                (void)sc;\n                State child = extendState(pool[pid], idx, pid);\n                pool.push_back(std::move(child));\n                nxt.push_back((int)pool.size() - 1);\n            }\n        }\n\n        if (nxt.empty()) break;\n        sort(nxt.begin(), nxt.end(), cmpState);\n        if ((int)nxt.size() > beamSize) nxt.resize(beamSize);\n        beam.swap(nxt);\n    }\n\n    int best = beam[0];\n    for (int id : beam) {\n        if (cmpState(id, best)) best = id;\n    }\n    return reconstructOrder(pool, best);\n}\n\nvector<int> localImprove(vector<int> ord, FastRng& rng, int iters) {\n    int bestCost = evaluateOrderCost(ord);\n    const int Mloc = (int)ord.size();\n\n    for (int it = 0; it < iters; ++it) {\n        vector<int> cand = ord;\n        int type = rng.nextInt(0, 1);\n\n        if (type == 0) {\n            int i = rng.nextInt(0, Mloc - 1);\n            int j = i + rng.nextInt(-8, 8);\n            j = max(0, min(Mloc - 1, j));\n            if (i == j) continue;\n            swap(cand[i], cand[j]);\n        } else {\n            int i = rng.nextInt(0, Mloc - 1);\n            int j = i + rng.nextInt(-8, 8);\n            j = max(0, min(Mloc - 1, j));\n            if (i == j) continue;\n            int x = cand[i];\n            cand.erase(cand.begin() + i);\n            if (j > i) --j;\n            cand.insert(cand.begin() + j, x);\n        }\n\n        int c = evaluateOrderCost(cand);\n        if (c < bestCost) {\n            bestCost = c;\n            ord.swap(cand);\n        }\n    }\n    return ord;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    cin >> si >> sj;\n    words.resize(M);\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    for (int i = 0; i < M; ++i) cin >> words[i];\n\n    for (int i = 0; i < 26; ++i) cellsByLetter[i].clear();\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            boardChar[i][j] = grid[i][j];\n            boardIdx[i][j] = grid[i][j] - 'A';\n            cellsByLetter[boardIdx[i][j]].push_back(i * H + j);\n        }\n    }\n\n    for (int a = 0; a < CELLS; ++a) {\n        int x1 = a / H, y1 = a % H;\n        for (int b = 0; b < CELLS; ++b) {\n            int x2 = b / H, y2 = b % H;\n            distCell[a][b] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) letterDist[a][b] = INF;\n    }\n\n    for (int a = 0; a < CELLS; ++a) {\n        int ca = boardIdx[a / H][a % H];\n        for (int b = 0; b < CELLS; ++b) {\n            int cb = boardIdx[b / H][b % H];\n            letterDist[ca][cb] = min(letterDist[ca][cb], distCell[a][b]);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        for (int ov = 0; ov < 5; ++ov) {\n            suffixes[i][ov] = words[i].substr(ov);\n            const string& s = suffixes[i][ov];\n            int lb = (int)s.size();\n            for (int j = 1; j < (int)s.size(); ++j) {\n                lb += letterDist[s[j - 1] - 'A'][s[j] - 'A'];\n            }\n            suffixLB[i][ov] = lb;\n        }\n    }\n\n    // Seed ranking\n    vector<pair<pair<int, int>, int>> seedScore; // ((cost, future), idx)\n    seedScore.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        State st = buildInitialState(i);\n        seedScore.push_back({{st.cost, st.future}, i});\n    }\n    sort(seedScore.begin(), seedScore.end());\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n    FastRng rng1(baseSeed ^ 0x123456789abcdefULL);\n    FastRng rng2(baseSeed ^ 0xfedcba987654321ULL);\n    FastRng rng3(baseSeed ^ 0x314159265358979ULL);\n    FastRng rng4(baseSeed ^ 0x271828182845904ULL);\n\n    vector<vector<int>> candidates;\n\n    // Run 1: greedy-like\n    {\n        vector<int> seeds = {seedScore[0].second};\n        candidates.push_back(beamSearchRun(seeds, 1, 24, rng1));\n    }\n\n    // Run 2: small beam from best seeds\n    {\n        vector<int> seeds;\n        for (int i = 0; i < min(6, M); ++i) seeds.push_back(seedScore[i].second);\n        candidates.push_back(beamSearchRun(seeds, 6, 12, rng2));\n    }\n\n    // Run 3: diversified beam from random top-20 seeds\n    {\n        vector<int> top;\n        for (int i = 0; i < min(20, M); ++i) top.push_back(seedScore[i].second);\n        for (int i = (int)top.size() - 1; i > 0; --i) {\n            int j = rng3.nextInt(0, i);\n            swap(top[i], top[j]);\n        }\n        vector<int> seeds;\n        for (int i = 0; i < min(6, (int)top.size()); ++i) seeds.push_back(top[i]);\n        candidates.push_back(beamSearchRun(seeds, 6, 12, rng3));\n    }\n\n    // Choose the best candidate order by exact cost.\n    vector<int> bestOrd = candidates[0];\n    int bestCost = evaluateOrderCost(bestOrd);\n    for (int i = 1; i < (int)candidates.size(); ++i) {\n        int c = evaluateOrderCost(candidates[i]);\n        if (c < bestCost) {\n            bestCost = c;\n            bestOrd = candidates[i];\n        }\n    }\n\n    // Small local improvement on the best one.\n    bestOrd = localImprove(bestOrd, rng4, 18);\n    bestCost = evaluateOrderCost(bestOrd);\n\n    // Final exact path reconstruction and output.\n    string finalString = makeStringFromOrder(bestOrd);\n    auto [pathCost, path] = solvePathFromString(finalString);\n\n    for (int id : path) {\n        cout << id / H << ' ' << id % H << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n\n    // Read prior shape information (unused in this exact solution).\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        for (int t = 0; t < d; ++t) {\n            int i, j;\n            cin >> i >> j;\n        }\n    }\n\n    vector<pair<int,int>> positive;\n    positive.reserve(N * N);\n\n    // Drill every cell exactly once.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << \"q 1 \" << i << ' ' << j << '\\n' << flush;\n            int v;\n            cin >> v;\n            if (v > 0) positive.push_back({i, j});\n        }\n    }\n\n    // Output the exact set of cells with v(i,j) > 0.\n    cout << \"a \" << positive.size();\n    for (auto [i, j] : positive) {\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << '\\n' << flush;\n\n    int ok;\n    cin >> ok;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long NEG = -(1LL << 60);\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) cin >> a[d][k];\n    }\n\n    vector<vector<int>> ans(D, vector<int>(N));\n\n    for (int d = 0; d < D; ++d) {\n        vector<int> h(N, 1);\n        vector<int> q(N), r(N);\n\n        int p = 0; // first index with q > 0\n        for (int k = 0; k < N; ++k) {\n            q[k] = a[d][k] / W;\n            r[k] = a[d][k] % W;\n            if (q[k] == 0) p++;\n        }\n\n        long long baseSum = 0;\n        for (int k = 0; k < N; ++k) {\n            if (q[k] == 0) {\n                h[k] = 1;\n                baseSum += 1;\n            } else {\n                h[k] = q[k];\n                baseSum += q[k];\n            }\n        }\n\n        long long extra = (long long)W - baseSum;\n\n        if (extra >= 0) {\n            // Positive extra: choose beneficial +1 boosts on positive-q runs.\n            // Only positive-q suffix matters; q=0 strips are fixed at height 1.\n            struct Run {\n                int l, r;\n                vector<int> gain; // gain[t] = sum of the last t remainders in the run\n            };\n            vector<Run> runs;\n\n            for (int i = p; i < N; ) {\n                int j = i;\n                while (j + 1 < N && q[j + 1] == q[i]) ++j;\n                Run run;\n                run.l = i;\n                run.r = j;\n                int len = j - i + 1;\n                run.gain.assign(len + 1, 0);\n                for (int t = 1; t <= len; ++t) {\n                    // suffix of length t: take largest remainders in the run\n                    run.gain[t] = run.gain[t - 1] + r[j - t + 1];\n                }\n                runs.push_back(move(run));\n                i = j + 1;\n            }\n\n            int R = (int)runs.size();\n            int E = (int)extra;\n\n            vector<vector<long long>> dp(R + 1, vector<long long>(E + 1, NEG));\n            vector<vector<int>> choice(R + 1, vector<int>(E + 1, -1));\n            dp[0][0] = 0;\n\n            for (int i = 0; i < R; ++i) {\n                vector<long long> ndp(E + 1, NEG);\n                for (int used = 0; used <= E; ++used) {\n                    if (dp[i][used] == NEG) continue;\n                    int len = runs[i].r - runs[i].l + 1;\n                    for (int t = 0; t <= len && used + t <= E; ++t) {\n                        long long cand = dp[i][used] + runs[i].gain[t];\n                        if (cand > ndp[used + t]) {\n                            ndp[used + t] = cand;\n                            choice[i + 1][used + t] = t;\n                        }\n                    }\n                }\n                dp[i + 1].swap(ndp);\n            }\n\n            int bestUsed = 0;\n            for (int used = 1; used <= E; ++used) {\n                if (dp[R][used] > dp[R][bestUsed]) bestUsed = used;\n                // tie-break: keep smaller used, to leave more zero-gain slack on the last strip\n                else if (dp[R][used] == dp[R][bestUsed] && used < bestUsed) bestUsed = used;\n            }\n\n            // Reconstruct chosen suffix lengths.\n            int curUsed = bestUsed;\n            for (int i = R; i >= 1; --i) {\n                int t = choice[i][curUsed];\n                const auto &run = runs[i - 1];\n                for (int j = 0; j < t; ++j) {\n                    h[run.r - j] += 1;\n                }\n                curUsed -= t;\n            }\n\n            // Remaining zero-gain slack goes to the last strip.\n            long long leftover = extra - bestUsed;\n            h[N - 1] += (int)leftover;\n        } else {\n            // Negative extra: need to reduce total height while preserving nondecreasing order.\n            long long need = -extra;\n            for (int i = p; i < N && need > 0; ++i) {\n                int minAllowed = 1;\n                if (i > p) minAllowed = h[i - 1];\n                int canReduce = h[i] - minAllowed;\n                if (canReduce <= 0) continue;\n                int take = (int)min<long long>(need, canReduce);\n                h[i] -= take;\n                need -= take;\n            }\n            // Feasibility should always hold for this problem.\n        }\n\n        ans[d] = h;\n    }\n\n    for (int d = 0; d < D; ++d) {\n        int y = 0;\n        for (int k = 0; k < N; ++k) {\n            int h = ans[d][k];\n            cout << 0 << ' ' << y << ' ' << W << ' ' << (y + h) << '\\n';\n            y += h;\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr ll MOD = 998244353LL;\nstatic constexpr int H = 9;\nstatic constexpr int W = 9;\nstatic constexpr int CELLS = 81;\nstatic constexpr int S = 3;\nstatic constexpr int POS = H - S + 1;   // 7\nstatic constexpr int TOP = 5;\n\nstruct Action {\n    int m = -1, p = -1, q = -1;\n    array<int, CELLS> add{};   // contribution on each cell (0 if unaffected)\n    array<int, 9> cells{};     // the 9 affected cells\n    array<int, 9> vals{};      // stamp values on those cells\n};\n\nstruct Result {\n    array<int, CELLS> cur{};\n    ll score = 0;\n    vector<int> seq;           // action ids, ACTIONS means no-op\n};\n\nint N, M, K;\nint ACTIONS;\n\nvector<array<array<int, S>, S>> stamps;\nvector<Action> acts;\narray<int, CELLS> initBoard{};\nll initScore = 0;\n\ninline ll calc_score(const array<int, CELLS>& b) {\n    ll s = 0;\n    for (int x : b) s += x;\n    return s;\n}\n\ninline void apply_action(array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    for (int t = 0; t < 9; ++t) {\n        int c = ac.cells[t];\n        ll x = (ll)board[c] + ac.vals[t];\n        if (x >= MOD) x -= MOD;\n        board[c] = (int)x;\n    }\n}\n\ninline void insertTop(array<pair<ll, int>, TOP>& top, int& topn, ll gain, int id) {\n    if (topn < TOP) {\n        int pos = topn++;\n        while (pos > 0 && top[pos - 1].first < gain) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {gain, id};\n    } else if (gain > top[TOP - 1].first) {\n        int pos = TOP - 1;\n        while (pos > 0 && top[pos - 1].first < gain) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {gain, id};\n    }\n}\n\nResult build_initial(int mode, mt19937_64& rng) {\n    Result res;\n    res.cur = initBoard;\n    res.score = initScore;\n    res.seq.assign(K, ACTIONS);\n\n    for (int step = 0; step < K; ++step) {\n        array<pair<ll, int>, TOP> top;\n        int topn = 0;\n\n        for (int id = 0; id < ACTIONS; ++id) {\n            ll gain = 0;\n            const auto& ac = acts[id];\n            for (int t = 0; t < 9; ++t) {\n                int c = ac.cells[t];\n                int w = ac.vals[t];\n                ll x = res.cur[c];\n                gain += (x >= MOD - w ? (ll)w - MOD : (ll)w);\n            }\n            insertTop(top, topn, gain, id);\n        }\n\n        ll chosenGain = 0;\n        int chosenId = ACTIONS;\n\n        if (mode == 0) {\n            // deterministic, use all K slots\n            chosenId = top[0].second;\n            chosenGain = top[0].first;\n        } else if (mode == 1) {\n            // randomized, use all K slots\n            int pick = ((rng() & 3) != 0 ? 0 : (int)(rng() % topn)); // 75% best\n            chosenId = top[pick].second;\n            chosenGain = top[pick].first;\n        } else if (mode == 2) {\n            // deterministic, stop when no positive gain\n            if (top[0].first <= 0) break;\n            chosenId = top[0].second;\n            chosenGain = top[0].first;\n        } else {\n            // randomized, stop when no positive gain\n            if (top[0].first <= 0) break;\n            int posn = 0;\n            while (posn < topn && top[posn].first > 0) ++posn;\n            int pick = ((rng() & 3) != 0 ? 0 : (int)(rng() % posn)); // 75% best among positive\n            chosenId = top[pick].second;\n            chosenGain = top[pick].first;\n        }\n\n        apply_action(res.cur, chosenId);\n        res.score += chosenGain;\n        res.seq[step] = chosenId;\n    }\n\n    res.score = calc_score(res.cur);\n    return res;\n}\n\nvoid refine(Result& res, int passes, mt19937_64& rng) {\n    vector<int> ord(K);\n    iota(ord.begin(), ord.end(), 0);\n\n    for (int pass = 0; pass < passes; ++pass) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool any = false;\n\n        for (int idx : ord) {\n            int old = res.seq[idx];\n            ll bestDelta = 0;\n            int bestId = old;\n\n            const int* oa = acts[old].add.data();\n\n            for (int id = 0; id <= ACTIONS; ++id) {\n                if (id == old) continue;\n                const int* na = acts[id].add.data();\n\n                ll delta = 0;\n                for (int c = 0; c < CELLS; ++c) {\n                    int a = oa[c], b = na[c];\n                    if (a == b) continue;\n\n                    ll x = (ll)res.cur[c] - a;\n                    if (x < 0) x += MOD;\n                    x += b;\n                    if (x >= MOD) x -= MOD;\n                    delta += x - res.cur[c];\n                }\n\n                if (delta > bestDelta) {\n                    bestDelta = delta;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != old && bestDelta > 0) {\n                const int* na = acts[bestId].add.data();\n                for (int c = 0; c < CELLS; ++c) {\n                    int a = oa[c], b = na[c];\n                    if (a == b) continue;\n\n                    ll x = (ll)res.cur[c] - a;\n                    if (x < 0) x += MOD;\n                    x += b;\n                    if (x >= MOD) x -= MOD;\n                    res.cur[c] = (int)x;\n                }\n                res.score += bestDelta;\n                res.seq[idx] = bestId;\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    res.score = calc_score(res.cur);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n\n    vector<vector<int>> a(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> a[i][j];\n        }\n    }\n\n    stamps.assign(M, {});\n    for (int m = 0; m < M; ++m) {\n        for (int i = 0; i < S; ++i) {\n            for (int j = 0; j < S; ++j) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    ACTIONS = M * POS * POS;\n    acts.assign(ACTIONS + 1, Action{});\n\n    int id = 0;\n    for (int m = 0; m < M; ++m) {\n        for (int p = 0; p < POS; ++p) {\n            for (int q = 0; q < POS; ++q) {\n                Action ac;\n                ac.m = m;\n                ac.p = p;\n                ac.q = q;\n\n                int t = 0;\n                for (int di = 0; di < S; ++di) {\n                    for (int dj = 0; dj < S; ++dj) {\n                        int c = (p + di) * W + (q + dj);\n                        int w = stamps[m][di][dj];\n                        ac.cells[t] = c;\n                        ac.vals[t] = w;\n                        ac.add[c] = w;\n                        ++t;\n                    }\n                }\n                acts[id++] = ac;\n            }\n        }\n    }\n    acts[ACTIONS] = Action{}; // no-op\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            initBoard[i * W + j] = a[i][j];\n        }\n    }\n    initScore = calc_score(initBoard);\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<int> modes = {0, 1, 2, 3};\n    Result best;\n    best.score = -1;\n\n    for (int mode : modes) {\n        Result cur = build_initial(mode, rng);\n        refine(cur, 2, rng);\n        if (cur.score > best.score) best = std::move(cur);\n    }\n\n    // one more polish on the best candidate\n    refine(best, 1, rng);\n\n    vector<tuple<int, int, int>> ans;\n    ans.reserve(K);\n    for (int id : best.seq) {\n        if (id == ACTIONS) continue;\n        ans.emplace_back(acts[id].m, acts[id].p, acts[id].q);\n    }\n\n    cout << ans.size() << '\\n';\n    for (auto [m, p, q] : ans) {\n        cout << m << ' ' << p << ' ' << q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int FULL_MASK = (1 << N) - 1;\nstatic constexpr int BEAM = 8000; // enough for strong search, still fast\n\nstruct Node {\n    array<uint8_t, N> p{};      // next unread index in each source row\n    array<uint8_t, N> mask{};   // dispatched ranks for each gate (bitmask of ranks 0..4)\n    uint8_t curRow = 0;         // current crane row (if start==false, crane is at (curRow, 4))\n    bool start = true;          // true only at the beginning\n    int turns = 0;             // M0 so far\n    int inv = 0;               // M1 so far\n    int lb = 0;                // optimistic lower bound of remaining inversions\n    int parent = -1;           // parent node index in global pool\n    int choice = -1;           // chosen source row at this step\n    int eval = 0;              // turns + 100*(inv + lb)\n};\n\nstatic inline uint64_t packKey(const Node& s) {\n    // bits:\n    // 0..2   : curRow\n    // 3..27  : mask[0..4] (5 bits each)\n    // 28..42 : p[0..4] (3 bits each)\n    // 43     : start\n    uint64_t k = 0;\n    k |= uint64_t(s.curRow);\n    for (int i = 0; i < N; ++i) {\n        k |= uint64_t(s.mask[i]) << (3 + 5 * i);\n        k |= uint64_t(s.p[i]) << (28 + 3 * i);\n    }\n    if (s.start) k |= 1ULL << 43;\n    return k;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inN;\n    cin >> inN; // fixed to 5\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> A[i][j];\n    }\n\n    // rankOf[v] = local rank 0..4 inside its destination gate\n    array<int, 25> rankOf{};\n    array<vector<int>, N> gateVals;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            gateVals[A[i][j] / N].push_back(A[i][j]);\n        }\n    }\n    for (int g = 0; g < N; ++g) {\n        sort(gateVals[g].begin(), gateVals[g].end());\n        for (int r = 0; r < N; ++r) rankOf[gateVals[g][r]] = r;\n    }\n\n    // addInv[mask][r] = number of already-dispatched ranks in mask that are > r\n    int addInv[32][N]{};\n    // forcedLB[mask] = lower bound of future inversions caused by already-dispatched\n    // higher ranks and still-undispatched lower ranks.\n    int forcedLB[32]{};\n\n    for (int mask = 0; mask < 32; ++mask) {\n        for (int r = 0; r < N; ++r) {\n            addInv[mask][r] = __builtin_popcount((unsigned)(mask >> (r + 1)));\n        }\n        int lb = 0;\n        for (int hi = 0; hi < N; ++hi) if (mask & (1 << hi)) {\n            lb += __builtin_popcount((unsigned)((FULL_MASK ^ mask) & ((1 << hi) - 1)));\n        }\n        forcedLB[mask] = lb;\n    }\n\n    // Exact move cost for one chosen container:\n    // start == true  : current crane is at (0,0)\n    // start == false : current crane is at (curRow, 4)\n    int costStart[N][N];\n    int costMid[N][N][N];\n    for (int r = 0; r < N; ++r) {\n        for (int g = 0; g < N; ++g) {\n            // from (0,0) to (r,0), pick, to (g,4), release\n            costStart[r][g] = r + abs(r - g) + 6; // moves + P + Q\n        }\n    }\n    for (int c = 0; c < N; ++c) {\n        for (int r = 0; r < N; ++r) {\n            for (int g = 0; g < N; ++g) {\n                // from (c,4) to (r,0), pick, to (g,4), release\n                costMid[c][r][g] = abs(c - r) + abs(r - g) + 10;\n            }\n        }\n    }\n\n    vector<Node> pool;\n    pool.reserve(200000);\n\n    Node root;\n    root.start = true;\n    root.curRow = 0;\n    root.turns = 0;\n    root.inv = 0;\n    root.lb = 0;\n    root.eval = 0;\n    pool.push_back(root);\n\n    vector<int> layer = {0};\n\n    for (int step = 0; step < N * N; ++step) {\n        unordered_map<uint64_t, int> pos;\n        pos.reserve(layer.size() * N * 2);\n        pos.max_load_factor(0.7f);\n\n        vector<Node> nxt;\n        nxt.reserve(layer.size() * N);\n\n        for (int gid : layer) {\n            const Node& s = pool[gid];\n            for (int r = 0; r < N; ++r) {\n                if (s.p[r] >= N) continue;\n\n                int v = A[r][s.p[r]];\n                int g = v / N;\n                int rk = rankOf[v];\n\n                Node t = s;\n                t.p[r]++;\n\n                int oldMask = t.mask[g];\n                int newMask = oldMask | (1 << rk);\n\n                t.mask[g] = (uint8_t)newMask;\n                t.inv += addInv[oldMask][rk];\n                t.lb += forcedLB[newMask] - forcedLB[oldMask];\n\n                if (s.start) t.turns += costStart[r][g];\n                else t.turns += costMid[s.curRow][r][g];\n\n                t.curRow = (uint8_t)g;\n                t.start = false;\n                t.parent = gid;\n                t.choice = r;\n                t.eval = t.turns + 100 * (t.inv + t.lb);\n\n                uint64_t key = packKey(t);\n                auto it = pos.find(key);\n                int exact = t.turns + 100 * t.inv;\n\n                if (it == pos.end()) {\n                    pos[key] = (int)nxt.size();\n                    nxt.push_back(t);\n                } else {\n                    Node& u = nxt[it->second];\n                    int exactU = u.turns + 100 * u.inv;\n                    if (exact < exactU) {\n                        u = t;\n                    }\n                }\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        vector<int> ord(nxt.size());\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (nxt[a].eval != nxt[b].eval) return nxt[a].eval < nxt[b].eval;\n            int ea = nxt[a].turns + 100 * nxt[a].inv;\n            int eb = nxt[b].turns + 100 * nxt[b].inv;\n            if (ea != eb) return ea < eb;\n            if (nxt[a].turns != nxt[b].turns) return nxt[a].turns < nxt[b].turns;\n            if (nxt[a].inv != nxt[b].inv) return nxt[a].inv < nxt[b].inv;\n            return nxt[a].lb < nxt[b].lb;\n        });\n\n        if ((int)ord.size() > BEAM) ord.resize(BEAM);\n\n        vector<int> newLayer;\n        newLayer.reserve(ord.size());\n        for (int idx : ord) {\n            pool.push_back(nxt[idx]);\n            newLayer.push_back((int)pool.size() - 1);\n        }\n        layer.swap(newLayer);\n    }\n\n    // Pick the best final node.\n    int bestId = layer[0];\n    int bestScore = pool[bestId].turns + 100 * pool[bestId].inv;\n    for (int id : layer) {\n        int sc = pool[id].turns + 100 * pool[id].inv;\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestId = id;\n        }\n    }\n\n    // Reconstruct chosen source-row sequence.\n    vector<int> order;\n    for (int id = bestId; pool[id].parent != -1; id = pool[id].parent) {\n        order.push_back(pool[id].choice);\n    }\n    reverse(order.begin(), order.end());\n\n    // Emit the operations for the large crane.\n    string big;\n    big.reserve(10000);\n\n    int x = 0, y = 0; // large crane position; starts at (0,0)\n    array<int, N> ptr{};\n    ptr.fill(0);\n\n    auto move_to = [&](int nx, int ny) {\n        while (x < nx) { big.push_back('D'); ++x; }\n        while (x > nx) { big.push_back('U'); --x; }\n        while (y < ny) { big.push_back('R'); ++y; }\n        while (y > ny) { big.push_back('L'); --y; }\n    };\n\n    for (int r : order) {\n        int v = A[r][ptr[r]++];\n        int g = v / N;\n\n        // go to source gate (r,0)\n        move_to(r, 0);\n        big.push_back('P');\n\n        // go to destination gate (g,4)\n        move_to(g, N - 1);\n        big.push_back('Q');\n    }\n\n    int T = (int)big.size();\n    vector<string> ans(N, string(T, '.'));\n\n    // Large crane\n    ans[0] = big;\n\n    // Bomb the 4 small cranes on turn 1, then they do nothing.\n    for (int i = 1; i < N; ++i) ans[i][0] = 'B';\n\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct P {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> H[i][j];\n    }\n\n    auto gen_base_cycle = [&](int N) {\n        vector<P> seq;\n        seq.reserve(N * N);\n        seq.push_back({0, 0});\n        for (int y = 1; y < N; ++y) seq.push_back({0, y});\n\n        for (int x = 1; x <= N - 2; ++x) {\n            if (x % 2 == 1) {\n                for (int y = N - 1; y >= 1; --y) seq.push_back({x, y});\n            } else {\n                for (int y = 1; y <= N - 1; ++y) seq.push_back({x, y});\n            }\n        }\n\n        for (int y = N - 1; y >= 0; --y) seq.push_back({N - 1, y});\n        for (int x = N - 2; x >= 1; --x) seq.push_back({x, 0});\n        return seq;\n    };\n\n    auto transform = [&](const P& p, int t) -> P {\n        int x = p.x, y = p.y;\n        switch (t) {\n            case 0: return {x, y};\n            case 1: return {x, N - 1 - y};\n            case 2: return {N - 1 - x, y};\n            case 3: return {N - 1 - x, N - 1 - y};\n            case 4: return {y, x};\n            case 5: return {y, N - 1 - x};\n            case 6: return {N - 1 - y, x};\n            case 7: return {N - 1 - y, N - 1 - x};\n        }\n        return {x, y};\n    };\n\n    vector<P> base = gen_base_cycle(N);\n\n    ll bestCost = (1LL << 60);\n    vector<P> bestSeq;\n    int bestStart = 0;\n\n    auto eval_candidate = [&](vector<P> seq) {\n        int L = (int)seq.size();\n        vector<ll> pref(L + 1, 0);\n        for (int i = 0; i < L; ++i) {\n            pref[i + 1] = pref[i] + H[seq[i].x][seq[i].y];\n        }\n\n        ll mn = pref[0];\n        for (int i = 1; i < L; ++i) mn = min(mn, pref[i]);\n\n        for (int s = 0; s < L; ++s) {\n            if (pref[s] != mn) continue; // valid rotation start\n\n            ll cost = 100LL * (seq[s].x + seq[s].y); // empty move to the start cell\n            ll cur = 0;\n            for (int k = 0; k < L; ++k) {\n                const P& p = seq[(s + k) % L];\n                cur += H[p.x][p.y];\n                if (k + 1 < L) cost += 100 + cur; // move to next cell\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSeq = seq;\n                bestStart = s;\n            }\n        }\n    };\n\n    for (int t = 0; t < 8; ++t) {\n        vector<P> seq;\n        seq.reserve(base.size());\n        for (const auto& p : base) seq.push_back(transform(p, t));\n\n        eval_candidate(seq);\n        reverse(seq.begin(), seq.end());\n        eval_candidate(seq);\n    }\n\n    // Output operations\n    vector<string> ops;\n    ops.reserve(1000);\n\n    auto add_op = [&](const string& s) {\n        ops.push_back(s);\n    };\n\n    // Move empty from (0,0) to the chosen start cell\n    int cx = 0, cy = 0;\n    P startP = bestSeq[bestStart];\n    while (cx < startP.x) {\n        add_op(\"D\");\n        ++cx;\n    }\n    while (cx > startP.x) {\n        add_op(\"U\");\n        --cx;\n    }\n    while (cy < startP.y) {\n        add_op(\"R\");\n        ++cy;\n    }\n    while (cy > startP.y) {\n        add_op(\"L\");\n        --cy;\n    }\n\n    int L = (int)bestSeq.size();\n    for (int step = 0; step < L; ++step) {\n        int idx = (bestStart + step) % L;\n        P p = bestSeq[idx];\n        int h = H[p.x][p.y];\n        if (h > 0) {\n            add_op(\"+\" + to_string(h));\n        } else if (h < 0) {\n            add_op(\"-\" + to_string(-h));\n        }\n\n        if (step + 1 < L) {\n            P q = bestSeq[(bestStart + step + 1) % L];\n            if (q.x == p.x + 1 && q.y == p.y) add_op(\"D\");\n            else if (q.x == p.x - 1 && q.y == p.y) add_op(\"U\");\n            else if (q.x == p.x && q.y == p.y + 1) add_op(\"R\");\n            else if (q.x == p.x && q.y == p.y - 1) add_op(\"L\");\n            else {\n                // Should never happen for our Hamiltonian cycle.\n                // If it does, the output would be invalid, so keep a safe fallback.\n                // But in practice, this branch is unreachable.\n            }\n        }\n    }\n\n    for (const auto& s : ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXM = 15;\nstatic constexpr int MAXS = 60;\nstatic constexpr int MAXP = 36;\n\nstruct Seed {\n    array<int, MAXM> x{};\n    int sum = 0;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    int S = 2 * N * (N - 1); // 60\n    int P = N * N;           // 36\n\n    vector<Seed> seeds(S);\n\n    auto read_pool = [&]() {\n        for (int i = 0; i < S; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    };\n\n    read_pool();\n\n    vector<pair<int, int>> edges;\n    vector<vector<int>> cellNbs(P);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if (i + 1 < N) {\n                int to = (i + 1) * N + j;\n                edges.push_back({id, to});\n                cellNbs[id].push_back(to);\n                cellNbs[to].push_back(id);\n            }\n            if (j + 1 < N) {\n                int to = i * N + (j + 1);\n                edges.push_back({id, to});\n                cellNbs[id].push_back(to);\n                cellNbs[to].push_back(id);\n            }\n        }\n    }\n\n    vector<int> posDeg, posSnake;\n    vector<int> cellDeg(P, 0);\n    {\n        vector<tuple<int, int, int>> cells;\n        cells.reserve(P);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int id = i * N + j;\n                int deg = (i > 0) + (i + 1 < N) + (j > 0) + (j + 1 < N);\n                cellDeg[id] = deg;\n                int dist = abs(2 * i - (N - 1)) + abs(2 * j - (N - 1));\n                cells.emplace_back(-deg, dist, id);\n            }\n        }\n        sort(cells.begin(), cells.end());\n        for (auto &t : cells) posDeg.push_back(get<2>(t));\n\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; j++) posSnake.push_back(i * N + j);\n            } else {\n                for (int j = N - 1; j >= 0; j--) posSnake.push_back(i * N + j);\n            }\n        }\n    }\n\n    auto score_selection = [&](const vector<int>& sel,\n                               const array<array<int, MAXS>, MAXS>& W,\n                               int betaSel) -> long long {\n        long long pairSum = 0;\n        for (int i = 0; i < P; i++) {\n            for (int j = i + 1; j < P; j++) {\n                pairSum += W[sel[i]][sel[j]];\n            }\n        }\n        int cov = 0;\n        for (int l = 0; l < M; l++) {\n            int mx = 0;\n            for (int id : sel) mx = max(mx, seeds[id].x[l]);\n            cov += mx;\n        }\n        return pairSum + 1LL * betaSel * cov;\n    };\n\n    auto coverage_selection = [&](const vector<int>& sel) -> int {\n        int cov = 0;\n        for (int l = 0; l < M; l++) {\n            int mx = 0;\n            for (int id : sel) mx = max(mx, seeds[id].x[l]);\n            cov += mx;\n        }\n        return cov;\n    };\n\n    auto improve_selection = [&](vector<int> sel,\n                                 const array<array<int, MAXS>, MAXS>& W,\n                                 int betaSel) -> vector<int> {\n        long long curScore = score_selection(sel, W, betaSel);\n\n        // One-pass best-improvement swap search.\n        long long bestScore = curScore;\n        int bestPos = -1, bestSeed = -1;\n\n        vector<char> used(S, 0);\n        for (int id : sel) used[id] = 1;\n\n        for (int pos = 0; pos < P; pos++) {\n            int old = sel[pos];\n            used[old] = 0;\n\n            for (int cand = 0; cand < S; cand++) {\n                if (cand == old || used[cand]) continue;\n                sel[pos] = cand;\n                long long sc = score_selection(sel, W, betaSel);\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestPos = pos;\n                    bestSeed = cand;\n                }\n            }\n\n            sel[pos] = old;\n            used[old] = 1;\n        }\n\n        if (bestPos != -1) {\n            sel[bestPos] = bestSeed;\n        }\n        return sel;\n    };\n\n    auto build_local_info = [&](const vector<int>& sel,\n                                const array<array<int, MAXS>, MAXS>& W,\n                                array<array<int, MAXP>, MAXP>& Wsel,\n                                vector<long long>& localConn,\n                                vector<int>& localSum) {\n        localConn.assign(P, 0);\n        localSum.assign(P, 0);\n        for (int i = 0; i < P; i++) {\n            localSum[i] = seeds[sel[i]].sum;\n            for (int j = 0; j < P; j++) {\n                Wsel[i][j] = W[sel[i]][sel[j]];\n                localConn[i] += Wsel[i][j];\n            }\n        }\n    };\n\n    auto eval_arrangement = [&](const vector<int>& perm,\n                                const array<array<int, MAXP>, MAXP>& Wsel) -> long long {\n        long long sc = 0;\n        for (auto [u, v] : edges) {\n            sc += Wsel[perm[u]][perm[v]];\n        }\n        return sc;\n    };\n\n    auto improve_arrangement = [&](vector<int> perm,\n                                   const array<array<int, MAXP>, MAXP>& Wsel) -> pair<long long, vector<int>> {\n        long long cur = eval_arrangement(perm, Wsel);\n\n        // One pass of best-improvement swap search.\n        long long best = cur;\n        int bi = -1, bj = -1;\n        for (int a = 0; a < P; a++) {\n            for (int b = a + 1; b < P; b++) {\n                swap(perm[a], perm[b]);\n                long long sc = eval_arrangement(perm, Wsel);\n                swap(perm[a], perm[b]);\n                if (sc > best) {\n                    best = sc;\n                    bi = a;\n                    bj = b;\n                }\n            }\n        }\n        if (bi != -1) {\n            swap(perm[bi], perm[bj]);\n            cur = best;\n        }\n\n        return {cur, perm};\n    };\n\n    auto make_perm_by_order = [&](const vector<int>& order, const vector<int>& cellOrder) {\n        vector<int> perm(P, -1);\n        for (int i = 0; i < P; i++) perm[cellOrder[i]] = order[i];\n        return perm;\n    };\n\n    auto build_conn_order = [&](const vector<long long>& localConn,\n                                const vector<int>& localSum) {\n        vector<int> ord(P);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (localConn[a] != localConn[b]) return localConn[a] > localConn[b];\n            if (localSum[a] != localSum[b]) return localSum[a] > localSum[b];\n            return a < b;\n        });\n        return ord;\n    };\n\n    auto build_snake_order = [&](const array<array<int, MAXP>, MAXP>& Wsel,\n                                 const vector<long long>& localConn,\n                                 const vector<int>& localSum) {\n        vector<int> ord;\n        vector<char> used(P, 0);\n\n        int start = 0;\n        for (int i = 1; i < P; i++) {\n            if (localConn[i] > localConn[start] ||\n                (localConn[i] == localConn[start] && localSum[i] > localSum[start])) {\n                start = i;\n            }\n        }\n\n        ord.push_back(start);\n        used[start] = 1;\n\n        while ((int)ord.size() < P) {\n            int last = ord.back();\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < P; i++) if (!used[i]) {\n                long long sc = 6LL * Wsel[last][i] + localConn[i] + localSum[i];\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            used[best] = 1;\n            ord.push_back(best);\n        }\n        return ord;\n    };\n\n    auto build_grow_perm = [&](const array<array<int, MAXP>, MAXP>& Wsel,\n                               const vector<long long>& localConn,\n                               const vector<int>& localSum) {\n        vector<int> perm(P, -1);\n        vector<char> usedSeed(P, 0);\n        vector<char> filled(P, 0);\n\n        int centerA, centerB;\n        if (N % 2 == 0) {\n            int a = N / 2 - 1;\n            int b = N / 2;\n            centerA = a * N + a;\n            centerB = centerA + 1;\n        } else {\n            int c = N / 2;\n            centerA = c * N + c;\n            centerB = centerA;\n        }\n\n        int bestI = 0, bestJ = 1;\n        long long bestPair = -(1LL << 60);\n        for (int i = 0; i < P; i++) {\n            for (int j = i + 1; j < P; j++) {\n                long long sc = 1000LL * Wsel[i][j] + localConn[i] + localConn[j];\n                if (sc > bestPair) {\n                    bestPair = sc;\n                    bestI = i;\n                    bestJ = j;\n                }\n            }\n        }\n\n        perm[centerA] = bestI;\n        usedSeed[bestI] = 1;\n        filled[centerA] = 1;\n\n        if (centerB != centerA) {\n            perm[centerB] = bestJ;\n            usedSeed[bestJ] = 1;\n            filled[centerB] = 1;\n        } else {\n            // fallback for odd N (not used under current constraints)\n            perm[centerA] = bestI;\n        }\n\n        int placed = (centerB == centerA ? 1 : 2);\n\n        while (placed < P) {\n            long long bestSc = -(1LL << 60);\n            int bc = -1, bs = -1;\n\n            for (int c = 0; c < P; c++) if (!filled[c]) {\n                int adj = 0;\n                for (int nb : cellNbs[c]) if (filled[nb]) adj++;\n\n                for (int s = 0; s < P; s++) if (!usedSeed[s]) {\n                    long long sc = 2000LL * adj + 20LL * cellDeg[c] + localConn[s] + localSum[s];\n                    for (int nb : cellNbs[c]) if (filled[nb]) {\n                        sc += 8LL * Wsel[s][perm[nb]];\n                    }\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        bc = c;\n                        bs = s;\n                    }\n                }\n            }\n\n            perm[bc] = bs;\n            usedSeed[bs] = 1;\n            filled[bc] = 1;\n            placed++;\n        }\n\n        return perm;\n    };\n\n    for (int turn = 0; turn < T; turn++) {\n        // Build pair weights for the current pool.\n        array<array<int, MAXS>, MAXS> W{};\n        vector<long long> connAll(S, 0);\n        vector<long long> score0(S, 0);\n\n        for (int i = 0; i < S; i++) {\n            for (int j = i + 1; j < S; j++) {\n                int w = 0;\n                for (int l = 0; l < M; l++) {\n                    w += max(seeds[i].x[l], seeds[j].x[l]);\n                }\n                W[i][j] = W[j][i] = w;\n                connAll[i] += w;\n                connAll[j] += w;\n            }\n        }\n\n        for (int i = 0; i < S; i++) {\n            score0[i] = connAll[i] + 20LL * seeds[i].sum;\n        }\n\n        double rem = (T <= 1 ? 0.0 : double(T - 1 - turn) / double(T - 1));\n        int betaSel = 150 + (int)llround(100.0 * rem); // 250 -> 150\n        double fitAlpha = 2.0 + 4.0 * rem;              // 6 -> 2\n\n        // Candidate 1: top by global connectivity\n        vector<int> ordScore(S);\n        iota(ordScore.begin(), ordScore.end(), 0);\n        sort(ordScore.begin(), ordScore.end(), [&](int a, int b) {\n            if (score0[a] != score0[b]) return score0[a] > score0[b];\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            return a < b;\n        });\n        vector<int> candA(ordScore.begin(), ordScore.begin() + P);\n\n        // Candidate 2: coverage-greedy\n        vector<int> candB;\n        {\n            vector<char> used(S, 0);\n            array<int, MAXM> curMax{};\n            curMax.fill(0);\n\n            for (int step = 0; step < P; step++) {\n                int best = -1;\n                long long bestSc = -(1LL << 60);\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    long long gain = 0;\n                    for (int l = 0; l < M; l++) gain += max(0, seeds[i].x[l] - curMax[l]);\n\n                    long long pairToSel = 0;\n                    for (int j : candB) pairToSel += W[i][j];\n\n                    long long sc = 220LL * gain + 70LL * pairToSel / max(1, (int)candB.size()) + score0[i];\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n                used[best] = 1;\n                candB.push_back(best);\n                for (int l = 0; l < M; l++) curMax[l] = max(curMax[l], seeds[best].x[l]);\n            }\n        }\n\n        // Candidate 3: pair-greedy\n        vector<int> candC;\n        {\n            int bi = 0, bj = 1;\n            long long bestPair = -(1LL << 60);\n            for (int i = 0; i < S; i++) {\n                for (int j = i + 1; j < S; j++) {\n                    long long sc = 200LL * W[i][j] + score0[i] + score0[j];\n                    if (sc > bestPair) {\n                        bestPair = sc;\n                        bi = i;\n                        bj = j;\n                    }\n                }\n            }\n            candC.push_back(bi);\n            candC.push_back(bj);\n\n            vector<char> used(S, 0);\n            used[bi] = used[bj] = 1;\n\n            array<int, MAXM> curMax{};\n            curMax.fill(0);\n            for (int l = 0; l < M; l++) curMax[l] = max(seeds[bi].x[l], seeds[bj].x[l]);\n\n            while ((int)candC.size() < P) {\n                int best = -1;\n                long long bestSc = -(1LL << 60);\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    long long gain = 0;\n                    for (int l = 0; l < M; l++) gain += max(0, seeds[i].x[l] - curMax[l]);\n\n                    long long pairToSel = 0;\n                    for (int j : candC) pairToSel += W[i][j];\n\n                    long long sc = 100LL * pairToSel / (int)candC.size() + 180LL * gain + score0[i] / 2;\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n                used[best] = 1;\n                candC.push_back(best);\n                for (int l = 0; l < M; l++) curMax[l] = max(curMax[l], seeds[best].x[l]);\n            }\n        }\n\n        // Candidate 4: trait-specialist mix\n        vector<int> candD;\n        {\n            vector<char> used(S, 0);\n            for (int l = 0; l < M; l++) {\n                vector<int> ord(S);\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (seeds[a].x[l] != seeds[b].x[l]) return seeds[a].x[l] > seeds[b].x[l];\n                    if (score0[a] != score0[b]) return score0[a] > score0[b];\n                    return a < b;\n                });\n                for (int r = 0; r < 3 && (int)candD.size() < P; r++) {\n                    int id = ord[r];\n                    if (!used[id]) {\n                        used[id] = 1;\n                        candD.push_back(id);\n                    }\n                }\n            }\n            for (int id : ordScore) {\n                if ((int)candD.size() == P) break;\n                if (!used[id]) {\n                    used[id] = 1;\n                    candD.push_back(id);\n                }\n            }\n        }\n\n        vector<vector<int>> candidates = {candA, candB, candC, candD};\n\n        long long bestFit = -(1LL << 60);\n        vector<int> bestSel, bestPerm;\n        long long bestArrScore = -(1LL << 60);\n\n        for (auto cand : candidates) {\n            cand = improve_selection(cand, W, betaSel);\n\n            array<array<int, MAXP>, MAXP> Wsel{};\n            vector<long long> localConn;\n            vector<int> localSum;\n            build_local_info(cand, W, Wsel, localConn, localSum);\n\n            vector<int> connOrd = build_conn_order(localConn, localSum);\n            vector<int> snakeOrd = build_snake_order(Wsel, localConn, localSum);\n\n            vector<int> perm1 = make_perm_by_order(connOrd, posDeg);\n            vector<int> perm2 = make_perm_by_order(connOrd, posSnake);\n            vector<int> perm3 = make_perm_by_order(snakeOrd, posDeg);\n            vector<int> perm4 = make_perm_by_order(snakeOrd, posSnake);\n            vector<int> perm5 = build_grow_perm(Wsel, localConn, localSum);\n\n            vector<vector<int>> perms = {perm1, perm2, perm3, perm4, perm5};\n\n            long long bestLocalArr = -(1LL << 60);\n            vector<int> bestLocalPerm;\n\n            for (auto perm : perms) {\n                auto [sc, p2] = improve_arrangement(perm, Wsel);\n                if (sc > bestLocalArr) {\n                    bestLocalArr = sc;\n                    bestLocalPerm = std::move(p2);\n                }\n            }\n\n            int cov = coverage_selection(cand);\n            long long fit = bestLocalArr + (long long)(fitAlpha * cov + 0.5);\n\n            if (fit > bestFit) {\n                bestFit = fit;\n                bestSel = std::move(cand);\n                bestPerm = std::move(bestLocalPerm);\n                bestArrScore = bestLocalArr;\n            }\n        }\n\n        // Output the chosen planting pattern.\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int pos = i * N + j;\n                int localIdx = bestPerm[pos];\n                int seedId = bestSel[localIdx];\n                cout << seedId << (j + 1 == N ? '\\n' : ' ');\n            }\n        }\n        cout.flush();\n\n        if (turn + 1 < T) {\n            read_pool();\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct PairJob {\n    Point s, t;\n    int mx2, my2; // doubled midpoint coordinates: s+t\n};\n\nstruct Edge {\n    int to;\n    char mv, rot;\n};\n\nstruct BFSRes {\n    vector<int> dist, prev;\n    vector<char> pmv, prot;\n};\n\nstatic const int DX4[4] = {0, 1, 0, -1};   // R, D, L, U\nstatic const int DY4[4] = {1, 0, -1, 0};\nstatic const char MOVEC[5] = {'.', 'U', 'D', 'L', 'R'};\nstatic const int MDX[5] = {0, -1, 1, 0, 0};\nstatic const int MDY[5] = {0, 0, 0, -1, 1};\nstatic const char ROTC[3] = {'.', 'L', 'R'};\nstatic const int RDELTA[3] = {0, 3, 1};\n\nint N, M, V;\nvector<string> S, T;\n\ninline int cellId(int x, int y) { return x * N + y; }\ninline int stateId(int x, int y, int d) { return ((x * N + y) << 2) | d; }\ninline bool inside(int x, int y) { return 0 <= x && x < N && 0 <= y && y < N; }\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\ninline int manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nvector<vector<Edge>> adj;\nvector<int> rootX, rootY, dirD;\nvector<vector<int>> cellGoals;\nint SSTATE;\n\nBFSRes bfs(int start) {\n    BFSRes res;\n    res.dist.assign(SSTATE, -1);\n    res.prev.assign(SSTATE, -1);\n    res.pmv.assign(SSTATE, '.');\n    res.prot.assign(SSTATE, '.');\n\n    vector<int> q;\n    q.reserve(SSTATE);\n    q.push_back(start);\n    res.dist[start] = 0;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        for (const auto& e : adj[u]) {\n            if (res.dist[e.to] == -1) {\n                res.dist[e.to] = res.dist[u] + 1;\n                res.prev[e.to] = u;\n                res.pmv[e.to] = e.mv;\n                res.prot[e.to] = e.rot;\n                q.push_back(e.to);\n            }\n        }\n    }\n    return res;\n}\n\nvector<int> buildPath(const BFSRes& res, int start, int goal) {\n    vector<int> path;\n    if (start == goal) return path;\n    int v = goal;\n    while (v != start) {\n        if (v == -1) {\n            path.clear();\n            return path;\n        }\n        path.push_back(v);\n        v = res.prev[v];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid emitTurn(char mv, char rot, char act) {\n    char buf[4] = {mv, rot, '.', act};\n    cout.write(buf, 4);\n    cout.put('\\n');\n}\n\nvoid emitPath(const BFSRes& res, int start, int goal, char finalAct) {\n    vector<int> path = buildPath(res, start, goal);\n    if (path.empty()) {\n        emitTurn('.', '.', finalAct);\n        return;\n    }\n    for (int i = 0; i < (int)path.size(); ++i) {\n        int v = path[i];\n        char act = (i + 1 == (int)path.size() ? finalAct : '.');\n        emitTurn(res.pmv[v], res.prot[v], act);\n    }\n}\n\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    if (n == 0) return {};\n    const int INF = 1e9;\n\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, 0);\n        do {\n            used[j0] = 1;\n            int i0 = p[j0], j1 = 0;\n            int delta = INF;\n            for (int j = 1; j <= n; j++) if (!used[j]) {\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n\n    vector<int> ans(n);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> V;\n    S.resize(N);\n    T.resize(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<Point> src, tgt;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool a = (S[i][j] == '1');\n            bool b = (T[i][j] == '1');\n            if (a && !b) src.push_back({i, j});\n            if (b && !a) tgt.push_back({i, j});\n        }\n    }\n\n    int K = (int)src.size();\n    if ((int)tgt.size() != K) {\n        // Should not happen, but keep safe.\n        int mn = min((int)src.size(), (int)tgt.size());\n        src.resize(mn);\n        tgt.resize(mn);\n        K = mn;\n    }\n\n    // If nothing needs to move, output a valid tree and stop.\n    if (K == 0) {\n        cout << 2 << '\\n';\n        cout << 0 << ' ' << 1 << '\\n';\n        cout << 0 << ' ' << 0 << '\\n';\n        return 0;\n    }\n\n    // Minimum-cost matching between source-only and target-only cells.\n    vector<vector<int>> cost(K, vector<int>(K));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < K; j++) {\n            cost[i][j] = manhattan(src[i], tgt[j]);\n        }\n    }\n    vector<int> assign = hungarian(cost);\n\n    vector<PairJob> jobs(K);\n    for (int i = 0; i < K; i++) {\n        jobs[i].s = src[i];\n        jobs[i].t = tgt[assign[i]];\n        jobs[i].mx2 = jobs[i].s.x + jobs[i].t.x;\n        jobs[i].my2 = jobs[i].s.y + jobs[i].t.y;\n    }\n\n    auto edgeCost = [&](int a, int b) -> long long {\n        return manhattan(jobs[a].t, jobs[b].s);\n    };\n\n    auto chooseStartRoot = [&](int first, int second) -> pair<long long, Point> {\n        const Point& s = jobs[first].s;\n        const Point& t = jobs[first].t;\n        long long best = (1LL << 60);\n        Point bestP{0, 0};\n        int bestPref = 10;\n        int center = (N - 1) / 2;\n\n        for (int d = 0; d < 4; d++) {\n            int rx = s.x - DX4[d];\n            int ry = s.y - DY4[d];\n            if (!inside(rx, ry)) continue;\n            long long c = manhattan(rx, ry, t.x, t.y);\n            if (second != -1) c += manhattan(rx, ry, jobs[second].s.x, jobs[second].s.y);\n\n            int pref = (rx == s.x && ry == s.y - 1) ? 0 : 1; // prefer the initial right-facing pickup if possible\n            long long tie = abs(rx - center) + abs(ry - center);\n\n            if (c < best || (c == best && (pref < bestPref || (pref == bestPref && tie < abs(bestP.x - center) + abs(bestP.y - center))))) {\n                best = c;\n                bestP = {rx, ry};\n                bestPref = pref;\n            }\n        }\n        return {best, bestP};\n    };\n\n    auto evalOrder = [&](const vector<int>& ord) -> pair<long long, Point> {\n        long long score = 0;\n        auto [sc, root] = chooseStartRoot(ord[0], (int)ord.size() >= 2 ? ord[1] : -1);\n        score += sc;\n        for (int i = 0; i + 1 < (int)ord.size(); i++) score += edgeCost(ord[i], ord[i + 1]);\n        return {score, root};\n    };\n\n    auto buildGreedyOrder = [&](int startIdx) -> vector<int> {\n        vector<int> ord;\n        ord.reserve(K);\n        vector<char> used(K, 0);\n        ord.push_back(startIdx);\n        used[startIdx] = 1;\n        int cur = startIdx;\n\n        while ((int)ord.size() < K) {\n            int best = -1;\n            long long bestD = (1LL << 60);\n            long long bestTie1 = (1LL << 60);\n            long long bestTie2 = (1LL << 60);\n            for (int j = 0; j < K; j++) if (!used[j]) {\n                long long d = manhattan(jobs[cur].t, jobs[j].s);\n                long long tie1 = llabs((long long)jobs[j].mx2 - (N - 1)) + llabs((long long)jobs[j].my2 - (N - 1));\n                long long tie2 = manhattan(jobs[j].s, jobs[j].t);\n                if (d < bestD || (d == bestD && (tie1 < bestTie1 || (tie1 == bestTie1 && tie2 < bestTie2)))) {\n                    bestD = d;\n                    bestTie1 = tie1;\n                    bestTie2 = tie2;\n                    best = j;\n                }\n            }\n            used[best] = 1;\n            ord.push_back(best);\n            cur = best;\n        }\n        return ord;\n    };\n\n    auto refineOrder = [&](vector<int>& ord) {\n        int K2 = (int)ord.size();\n        if (K2 <= 2) return;\n\n        auto startCost = [&](int first, int second) -> long long {\n            auto [c, _] = chooseStartRoot(first, second);\n            return c;\n        };\n\n        for (int pass = 0; pass < 3; pass++) {\n            bool changed = false;\n            for (int i = 0; i + 1 < K2; i++) {\n                long long oldc = 0, newc = 0;\n\n                if (i == 0) {\n                    int a = ord[0], b = ord[1];\n                    oldc = startCost(a, K2 >= 2 ? b : -1);\n                    oldc += edgeCost(a, b);\n                    if (K2 >= 3) oldc += edgeCost(b, ord[2]);\n\n                    newc = startCost(b, a);\n                    newc += edgeCost(b, a);\n                    if (K2 >= 3) newc += edgeCost(a, ord[2]);\n                } else {\n                    int a = ord[i - 1], b = ord[i], c = ord[i + 1];\n                    oldc = edgeCost(a, b) + edgeCost(b, c);\n                    if (i + 2 < K2) oldc += edgeCost(c, ord[i + 2]);\n\n                    newc = edgeCost(a, c) + edgeCost(c, b);\n                    if (i + 2 < K2) newc += edgeCost(b, ord[i + 2]);\n                }\n\n                if (newc < oldc) {\n                    swap(ord[i], ord[i + 1]);\n                    changed = true;\n                }\n            }\n            if (!changed) break;\n        }\n    };\n\n    // Candidate starts: near midpoint, source, and target.\n    vector<int> idx(K);\n    iota(idx.begin(), idx.end(), 0);\n\n    auto scoreMid = [&](int i) {\n        return llabs((long long)jobs[i].mx2 - (N - 1)) + llabs((long long)jobs[i].my2 - (N - 1));\n    };\n    auto scoreSrc = [&](int i) {\n        int c = (N - 1) / 2;\n        return llabs((long long)jobs[i].s.x - c) + llabs((long long)jobs[i].s.y - c);\n    };\n    auto scoreTgt = [&](int i) {\n        int c = (N - 1) / 2;\n        return llabs((long long)jobs[i].t.x - c) + llabs((long long)jobs[i].t.y - c);\n    };\n\n    vector<int> cand;\n    {\n        vector<int> a = idx, b = idx, c = idx;\n        sort(a.begin(), a.end(), [&](int i, int j) { return scoreMid(i) < scoreMid(j); });\n        sort(b.begin(), b.end(), [&](int i, int j) { return scoreSrc(i) < scoreSrc(j); });\n        sort(c.begin(), c.end(), [&](int i, int j) { return scoreTgt(i) < scoreTgt(j); });\n\n        vector<char> used(K, 0);\n        auto addTop = [&](const vector<int>& v) {\n            for (int i = 0; i < (int)v.size() && i < 4; i++) {\n                if (!used[v[i]]) {\n                    used[v[i]] = 1;\n                    cand.push_back(v[i]);\n                }\n            }\n        };\n        addTop(a);\n        addTop(b);\n        addTop(c);\n    }\n\n    long long bestProxy = (1LL << 60);\n    vector<int> bestOrder;\n    Point startRoot{0, 0};\n\n    for (int st : cand) {\n        vector<int> ord = buildGreedyOrder(st);\n\n        // Try the greedy order and its reverse.\n        for (int rev = 0; rev < 2; rev++) {\n            vector<int> cur = ord;\n            if (rev) reverse(cur.begin(), cur.end());\n            refineOrder(cur);\n\n            auto [sc, root] = evalOrder(cur);\n            if (sc < bestProxy) {\n                bestProxy = sc;\n                bestOrder = std::move(cur);\n                startRoot = root;\n            }\n        }\n    }\n\n    // One-finger arm: root + one fingertip of length 1.\n    // Precompute state graph.\n    SSTATE = N * N * 4;\n    adj.assign(SSTATE, {});\n    rootX.assign(SSTATE, 0);\n    rootY.assign(SSTATE, 0);\n    dirD.assign(SSTATE, 0);\n    cellGoals.assign(N * N, {});\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            for (int d = 0; d < 4; d++) {\n                int id = stateId(x, y, d);\n                rootX[id] = x;\n                rootY[id] = y;\n                dirD[id] = d;\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            int cid = cellId(x, y);\n            for (int d = 0; d < 4; d++) {\n                int rx = x - DX4[d];\n                int ry = y - DY4[d];\n                if (inside(rx, ry)) {\n                    cellGoals[cid].push_back(stateId(rx, ry, d));\n                }\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            for (int d = 0; d < 4; d++) {\n                int id = stateId(x, y, d);\n                for (int m = 0; m < 5; m++) {\n                    for (int r = 0; r < 3; r++) {\n                        if (m == 0 && r == 0) continue;\n                        int nx = x + MDX[m];\n                        int ny = y + MDY[m];\n                        if (!inside(nx, ny)) continue;\n                        int nd = (d + RDELTA[r]) & 3;\n                        int to = stateId(nx, ny, nd);\n                        adj[id].push_back({to, MOVEC[m], ROTC[r]});\n                    }\n                }\n            }\n        }\n    }\n\n    // Output the arm.\n    cout << 2 << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n    cout << startRoot.x << ' ' << startRoot.y << '\\n';\n\n    int curState = stateId(startRoot.x, startRoot.y, 0); // initial direction: right\n\n    for (int idxOrd = 0; idxOrd < (int)bestOrder.size(); idxOrd++) {\n        int jid = bestOrder[idxOrd];\n        const auto& job = jobs[jid];\n        int sCell = cellId(job.s.x, job.s.y);\n        int tCell = cellId(job.t.x, job.t.y);\n\n        const auto& srcGoals = cellGoals[sCell];\n        const auto& tgtGoals = cellGoals[tCell];\n\n        vector<int> nextGoals;\n        if (idxOrd + 1 < (int)bestOrder.size()) {\n            int njid = bestOrder[idxOrd + 1];\n            nextGoals = cellGoals[cellId(jobs[njid].s.x, jobs[njid].s.y)];\n        }\n\n        BFSRes curBfs = bfs(curState);\n\n        int bestPIdx = -1, bestQ = -1;\n        long long bestScore = (1LL << 60);\n        vector<int> pStates;\n        vector<BFSRes> pBfsList;\n\n        for (int pi = 0; pi < (int)srcGoals.size(); pi++) {\n            int p = srcGoals[pi];\n            if (curBfs.dist[p] == -1) continue;\n\n            BFSRes pbfs = bfs(p);\n            pStates.push_back(p);\n            pBfsList.emplace_back(std::move(pbfs));\n            int storedIdx = (int)pStates.size() - 1;\n            const BFSRes& now = pBfsList.back();\n\n            for (int q : tgtGoals) {\n                if (now.dist[q] == -1) continue;\n\n                long long future = 0;\n                if (!nextGoals.empty()) {\n                    long long bestFuture = (1LL << 60);\n                    for (int r : nextGoals) {\n                        long long d = llabs((long long)rootX[q] - rootX[r]) + llabs((long long)rootY[q] - rootY[r]);\n                        bestFuture = min(bestFuture, d);\n                    }\n                    future = bestFuture;\n                }\n\n                long long sc = (long long)curBfs.dist[p] + now.dist[q] + future;\n                if (sc < bestScore) {\n                    bestScore = sc;\n                    bestPIdx = storedIdx;\n                    bestQ = q;\n                }\n            }\n        }\n\n        if (bestPIdx == -1) {\n            // Extremely defensive fallback: should never happen.\n            bestPIdx = 0;\n            bestQ = tgtGoals[0];\n        }\n\n        int bestP = pStates[bestPIdx];\n        const BFSRes& bestPBfs = pBfsList[bestPIdx];\n\n        emitPath(curBfs, curState, bestP, 'P');     // pick\n        emitPath(bestPBfs, bestP, bestQ, 'P');      // drop\n        curState = bestQ;\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int MAXC = 100000;\n\nstruct Pt {\n    int x, y, w;\n};\n\nstruct Rect {\n    int x1 = 0, y1 = 0, x2 = 1, y2 = 1;\n    int approx = INT_MIN; // grid score\n    int exact = INT_MIN;  // exact sum of weights inside\n    ll area = 1;\n};\n\nstatic inline bool valid(const Rect& r) {\n    return r.x1 < r.x2 && r.y1 < r.y2;\n}\n\nstatic inline ll rect_area(const Rect& r) {\n    return 1LL * (r.x2 - r.x1) * (r.y2 - r.y1);\n}\n\nstatic inline bool better_exact(const Rect& a, const Rect& b) {\n    if (a.exact != b.exact) return a.exact > b.exact;\n    if (a.area != b.area) return a.area > b.area;\n    if (a.approx != b.approx) return a.approx > b.approx;\n    if (a.x1 != b.x1) return a.x1 < b.x1;\n    if (a.y1 != b.y1) return a.y1 < b.y1;\n    if (a.x2 != b.x2) return a.x2 < b.x2;\n    return a.y2 < b.y2;\n}\n\nstatic inline bool better_approx(const Rect& a, const Rect& b) {\n    if (a.approx != b.approx) return a.approx > b.approx;\n    if (a.area != b.area) return a.area > b.area;\n    if (a.x1 != b.x1) return a.x1 < b.x1;\n    if (a.y1 != b.y1) return a.y1 < b.y1;\n    if (a.x2 != b.x2) return a.x2 < b.x2;\n    return a.y2 < b.y2;\n}\n\nstatic vector<int> uniq_sorted(vector<int> v) {\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nstatic void build_axis(int S, int off, vector<int>& st, vector<int>& en) {\n    st.clear();\n    en.clear();\n    if (off > 0) {\n        st.push_back(0);\n        en.push_back(off - 1);\n    }\n    for (int l = off; l <= MAXC; l += S) {\n        st.push_back(l);\n        en.push_back(min(MAXC, l + S - 1));\n    }\n}\n\nstatic int cell_idx(int v, int S, int off) {\n    if (off > 0 && v < off) return 0;\n    return (off > 0 ? 1 : 0) + (v - off) / S;\n}\n\nstatic vector<pair<int,int>> phase_list(int S) {\n    if (S == 300) {\n        return {{0, 0}, {75, 225}, {225, 75}};\n    }\n    if (S == 500) {\n        return {{0, 0}, {125, 375}, {375, 125}, {250, 250}};\n    }\n    // S == 700\n    return {{0, 0}, {175, 525}, {525, 175}};\n}\n\nstatic Rect grid_search(const vector<Pt>& pts, int S, int ox, int oy) {\n    vector<int> xs, xe, ys, ye;\n    build_axis(S, ox, xs, xe);\n    build_axis(S, oy, ys, ye);\n\n    int nx = (int)xs.size();\n    int ny = (int)ys.size();\n    vector<int> w(nx * ny, 0);\n\n    for (const auto& p : pts) {\n        int ix = cell_idx(p.x, S, ox);\n        int iy = cell_idx(p.y, S, oy);\n        w[ix * ny + iy] += p.w;\n    }\n\n    Rect best;\n    best.approx = INT_MIN;\n    best.area = -1;\n    best.exact = INT_MIN;\n\n    vector<int> col(ny, 0);\n\n    for (int top = 0; top < nx; ++top) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < nx; ++bot) {\n            const int* row = &w[bot * ny];\n            for (int c = 0; c < ny; ++c) col[c] += row[c];\n\n            int cur = 0;\n            int left = 0;\n            for (int c = 0; c < ny; ++c) {\n                if (cur < 0) {\n                    cur = col[c];\n                    left = c;\n                } else {\n                    cur += col[c];\n                }\n\n                if (xe[bot] <= xs[top] || ye[c] <= ys[left]) continue;\n\n                ll ar = 1LL * (xe[bot] - xs[top]) * (ye[c] - ys[left]);\n                if (cur > best.approx || (cur == best.approx && ar > best.area)) {\n                    best.approx = cur;\n                    best.area = ar;\n                    best.x1 = xs[top];\n                    best.y1 = ys[left];\n                    best.x2 = xe[bot];\n                    best.y2 = ye[c];\n                }\n            }\n        }\n    }\n\n    return best;\n}\n\nstatic int exact_score(const Rect& r, const vector<Pt>& pts) {\n    int s = 0;\n    for (const auto& p : pts) {\n        if (r.x1 <= p.x && p.x <= r.x2 && r.y1 <= p.y && p.y <= r.y2) {\n            s += p.w;\n        }\n    }\n    return s;\n}\n\nstatic Rect eval_exact(Rect r, const vector<Pt>& pts) {\n    r.exact = exact_score(r, pts);\n    r.area = rect_area(r);\n    return r;\n}\n\nstatic vector<pair<int,int>> one_dim_options(int v) {\n    if (v <= 0) return {{0, 1}};\n    if (v >= MAXC) return {{MAXC - 1, MAXC}};\n    return {{v - 1, v}, {v, v + 1}};\n}\n\nstatic Rect tiny_best_around_point(const Pt& p, const vector<Pt>& pts) {\n    Rect best;\n    best.exact = INT_MIN;\n    best.area = -1;\n    best.approx = 0;\n\n    auto xs = one_dim_options(p.x);\n    auto ys = one_dim_options(p.y);\n\n    for (auto [x1, x2] : xs) {\n        for (auto [y1, y2] : ys) {\n            Rect r;\n            r.x1 = x1; r.x2 = x2;\n            r.y1 = y1; r.y2 = y2;\n            if (!valid(r)) continue;\n            r.approx = 0;\n            r = eval_exact(r, pts);\n            if (better_exact(r, best)) best = r;\n        }\n    }\n    return best;\n}\n\nstatic vector<int> build_candidates_axis(const Rect& base, const vector<int>& coords, bool isX, int limit) {\n    vector<int> v;\n    v.reserve((int)coords.size() * 3 + 16);\n\n    auto add = [&](int x) {\n        if (0 <= x && x <= MAXC) v.push_back(x);\n    };\n\n    add(0);\n    add(MAXC);\n\n    if (isX) {\n        add(base.x1); add(base.x2);\n        add(base.x1 - 1); add(base.x1 + 1);\n        add(base.x2 - 1); add(base.x2 + 1);\n    } else {\n        add(base.y1); add(base.y2);\n        add(base.y1 - 1); add(base.y1 + 1);\n        add(base.y2 - 1); add(base.y2 + 1);\n    }\n\n    for (int c : coords) {\n        add(c - 1);\n        add(c);\n        add(c + 1);\n    }\n\n    v = uniq_sorted(v);\n    if ((int)v.size() > limit) {\n        vector<int> s;\n        s.reserve(limit);\n        for (int i = 0; i < limit; ++i) {\n            int idx = (long long)i * (v.size() - 1) / (limit - 1);\n            s.push_back(v[idx]);\n        }\n        v = uniq_sorted(s);\n\n        // Ensure important points survive sampling.\n        if (isX) {\n            add(base.x1); add(base.x2);\n            add(base.x1 - 1); add(base.x1 + 1);\n            add(base.x2 - 1); add(base.x2 + 1);\n        } else {\n            add(base.y1); add(base.y2);\n            add(base.y1 - 1); add(base.y1 + 1);\n            add(base.y2 - 1); add(base.y2 + 1);\n        }\n        v = uniq_sorted(v);\n    }\n\n    return v;\n}\n\nstatic bool coordinate_descent(Rect& cur, const vector<int>& candX, const vector<int>& candY, const vector<Pt>& pts) {\n    bool changed_any = false;\n\n    auto improve_x1 = [&]() {\n        Rect best = cur;\n        for (int v : candX) {\n            if (v >= cur.x2) continue;\n            Rect t = cur;\n            t.x1 = v;\n            if (!valid(t)) continue;\n            t = eval_exact(t, pts);\n            if (better_exact(t, best)) best = t;\n        }\n        if (better_exact(best, cur)) {\n            cur = best;\n            changed_any = true;\n        }\n    };\n\n    auto improve_x2 = [&]() {\n        Rect best = cur;\n        for (int v : candX) {\n            if (v <= cur.x1) continue;\n            Rect t = cur;\n            t.x2 = v;\n            if (!valid(t)) continue;\n            t = eval_exact(t, pts);\n            if (better_exact(t, best)) best = t;\n        }\n        if (better_exact(best, cur)) {\n            cur = best;\n            changed_any = true;\n        }\n    };\n\n    auto improve_y1 = [&]() {\n        Rect best = cur;\n        for (int v : candY) {\n            if (v >= cur.y2) continue;\n            Rect t = cur;\n            t.y1 = v;\n            if (!valid(t)) continue;\n            t = eval_exact(t, pts);\n            if (better_exact(t, best)) best = t;\n        }\n        if (better_exact(best, cur)) {\n            cur = best;\n            changed_any = true;\n        }\n    };\n\n    auto improve_y2 = [&]() {\n        Rect best = cur;\n        for (int v : candY) {\n            if (v <= cur.y1) continue;\n            Rect t = cur;\n            t.y2 = v;\n            if (!valid(t)) continue;\n            t = eval_exact(t, pts);\n            if (better_exact(t, best)) best = t;\n        }\n        if (better_exact(best, cur)) {\n            cur = best;\n            changed_any = true;\n        }\n    };\n\n    for (int pass = 0; pass < 4; ++pass) {\n        bool changed = false;\n        if (pass % 2 == 0) {\n            improve_x1(); improve_x2(); improve_y1(); improve_y2();\n        } else {\n            improve_y1(); improve_y2(); improve_x1(); improve_x2();\n        }\n        if (changed_any) changed = true;\n        if (!changed) break;\n    }\n\n    return changed_any;\n}\n\nstatic Rect local_refine(Rect cur, const vector<Pt>& pts) {\n    cur = eval_exact(cur, pts);\n\n    const int MARGIN = 6000;\n    const int LIMIT = 60;\n\n    for (int round = 0; round < 2; ++round) {\n        int lx = max(0, cur.x1 - MARGIN);\n        int rx = min(MAXC, cur.x2 + MARGIN);\n        int ly = max(0, cur.y1 - MARGIN);\n        int ry = min(MAXC, cur.y2 + MARGIN);\n\n        vector<int> xs, ys;\n        xs.reserve(pts.size());\n        ys.reserve(pts.size());\n\n        for (const auto& p : pts) {\n            if (p.x < lx || p.x > rx || p.y < ly || p.y > ry) continue;\n            xs.push_back(p.x);\n            ys.push_back(p.y);\n        }\n\n        vector<int> candX = build_candidates_axis(cur, xs, true, LIMIT);\n        vector<int> candY = build_candidates_axis(cur, ys, false, LIMIT);\n\n        if ((int)candX.size() < 2 || (int)candY.size() < 2) break;\n\n        Rect before = cur;\n        bool changed = coordinate_descent(cur, candX, candY, pts);\n\n        if (!changed || (cur.x1 == before.x1 && cur.x2 == before.x2 &&\n                         cur.y1 == before.y1 && cur.y2 == before.y2)) {\n            break;\n        }\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<Pt> mackerels(N), sardines(N), all;\n    all.reserve(2 * N);\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        mackerels[i].w = +1;\n        all.push_back(mackerels[i]);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        sardines[i].w = -1;\n        all.push_back(sardines[i]);\n    }\n\n    vector<Rect> base;\n    vector<Rect> grid_best_per_scale;\n    vector<Rect> grid_best_per_scale_exact;\n    Rect best_grid_approx_all;\n    best_grid_approx_all.approx = INT_MIN;\n    best_grid_approx_all.area = -1;\n\n    // Multi-scale grid search.\n    for (int S : {300, 500, 700}) {\n        Rect best_this_scale;\n        best_this_scale.approx = INT_MIN;\n        best_this_scale.area = -1;\n\n        for (auto [ox, oy] : phase_list(S)) {\n            Rect r = grid_search(all, S, ox, oy);\n            if (!valid(r)) continue;\n            r = eval_exact(r, all);\n            base.push_back(r);\n\n            if (better_approx(r, best_this_scale)) best_this_scale = r;\n            if (better_approx(r, best_grid_approx_all)) best_grid_approx_all = r;\n        }\n\n        if (valid(best_this_scale)) {\n            grid_best_per_scale.push_back(best_this_scale);\n        }\n    }\n\n    // Mackerel bounding box.\n    int mnx = MAXC, mxx = 0, mny = MAXC, mxy = 0;\n    for (const auto& p : mackerels) {\n        mnx = min(mnx, p.x);\n        mxx = max(mxx, p.x);\n        mny = min(mny, p.y);\n        mxy = max(mxy, p.y);\n    }\n    if (mnx == mxx) {\n        if (mxx < MAXC) ++mxx;\n        else --mnx;\n    }\n    if (mny == mxy) {\n        if (mxy < MAXC) ++mxy;\n        else --mny;\n    }\n    Rect bbox;\n    bbox.x1 = mnx; bbox.x2 = mxx;\n    bbox.y1 = mny; bbox.y2 = mxy;\n    if (valid(bbox)) {\n        bbox = eval_exact(bbox, all);\n        base.push_back(bbox);\n    }\n\n    // Small rectangles around sampled mackerels.\n    int step = max(1, N / 200);\n    for (int i = 0; i < N; i += step) {\n        Rect r = tiny_best_around_point(mackerels[i], all);\n        if (valid(r)) base.push_back(r);\n    }\n\n    // Also add the best approximate grid rectangles explicitly.\n    for (const auto& r : grid_best_per_scale) {\n        if (valid(r)) base.push_back(r);\n    }\n    if (valid(best_grid_approx_all)) {\n        base.push_back(best_grid_approx_all);\n    }\n\n    // Deduplicate by coordinates.\n    sort(base.begin(), base.end(), [](const Rect& a, const Rect& b) {\n        if (a.x1 != b.x1) return a.x1 < b.x1;\n        if (a.y1 != b.y1) return a.y1 < b.y1;\n        if (a.x2 != b.x2) return a.x2 < b.x2;\n        return a.y2 < b.y2;\n    });\n    base.erase(unique(base.begin(), base.end(), [](const Rect& a, const Rect& b) {\n        return a.x1 == b.x1 && a.y1 == b.y1 && a.x2 == b.x2 && a.y2 == b.y2;\n    }), base.end());\n\n    for (auto& r : base) {\n        if (!valid(r)) continue;\n        r = eval_exact(r, all);\n    }\n\n    sort(base.begin(), base.end(), better_exact);\n\n    // Build refinement starters:\n    vector<Rect> starters;\n\n    // Top exact candidates.\n    for (int i = 0; i < (int)base.size() && i < 4; ++i) starters.push_back(base[i]);\n\n    // Per-scale best approximate candidates.\n    for (const auto& r : grid_best_per_scale) starters.push_back(r);\n\n    // Mackerel bbox and a tiny fallback.\n    if (valid(bbox)) starters.push_back(bbox);\n    starters.push_back(tiny_best_around_point(mackerels[0], all));\n\n    // Deduplicate starters by coordinates.\n    sort(starters.begin(), starters.end(), [](const Rect& a, const Rect& b) {\n        if (a.x1 != b.x1) return a.x1 < b.x1;\n        if (a.y1 != b.y1) return a.y1 < b.y1;\n        if (a.x2 != b.x2) return a.x2 < b.x2;\n        return a.y2 < b.y2;\n    });\n    starters.erase(unique(starters.begin(), starters.end(), [](const Rect& a, const Rect& b) {\n        return a.x1 == b.x1 && a.y1 == b.y1 && a.x2 == b.x2 && a.y2 == b.y2;\n    }), starters.end());\n\n    Rect best;\n    best.exact = INT_MIN;\n    best.area = -1;\n    best.approx = INT_MIN;\n\n    for (auto r : starters) {\n        if (!valid(r)) continue;\n        r = local_refine(r, all);\n        if (better_exact(r, best)) best = r;\n    }\n\n    // Safety fallback.\n    if (!valid(best)) {\n        best = tiny_best_around_point(mackerels[0], all);\n    }\n\n    cout << 4 << '\\n';\n    cout << best.x1 << ' ' << best.y1 << '\\n';\n    cout << best.x2 << ' ' << best.y1 << '\\n';\n    cout << best.x2 << ' ' << best.y2 << '\\n';\n    cout << best.x1 << ' ' << best.y2 << '\\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, b;\n    char d;\n};\n\nstruct State {\n    ll W, H;\n    int prev_i, prev_idx;\n};\n\nstruct Cand {\n    vector<Op> ops;\n    ll estW = 0, estH = 0;\n    string sig;\n};\n\nstruct Family {\n    ll bestScore = (1LL << 62);\n    int mode = 0, axis = 0;\n    vector<Cand> cands;\n};\n\nstatic string serialize_ops(const vector<Op>& ops) {\n    string s;\n    s.reserve(ops.size() * 16);\n    for (auto &op : ops) {\n        s += to_string(op.p);\n        s.push_back(',');\n        s += to_string(op.r);\n        s.push_back(',');\n        s.push_back(op.d);\n        s.push_back(',');\n        s += to_string(op.b);\n        s.push_back(';');\n    }\n    return s;\n}\n\nstatic int choose_state_by_weight(const vector<State>& front, ll a, ll b) {\n    int idx = 0;\n    __int128 best = (__int128)a * front[0].W + (__int128)b * front[0].H;\n    for (int i = 1; i < (int)front.size(); ++i) {\n        __int128 cur = (__int128)a * front[i].W + (__int128)b * front[i].H;\n        if (cur < best || (cur == best && (front[i].W < front[idx].W ||\n                                          (front[i].W == front[idx].W && front[i].H < front[idx].H)))) {\n            best = cur;\n            idx = i;\n        }\n    }\n    return idx;\n}\n\nstatic Cand build_candidate_from_state(\n    const vector<vector<State>>& dp,\n    int idx,\n    const vector<int>& rot,\n    const vector<ll>& sh,\n    int axis,\n    int N\n) {\n    vector<pair<int,int>> groups;\n    int cur_i = N, cur_idx = idx;\n    while (cur_i > 0) {\n        const State& s = dp[cur_i][cur_idx];\n        groups.push_back({s.prev_i, cur_i});\n        cur_idx = s.prev_idx;\n        cur_i = s.prev_i;\n    }\n    reverse(groups.begin(), groups.end());\n\n    vector<Op> ops;\n    ops.reserve(N);\n    int prev_anchor = -1;\n\n    for (int g = 0; g < (int)groups.size(); ++g) {\n        int l = groups[g].first;\n        int r = groups[g].second;\n\n        int anchor = l;\n        for (int i = l + 1; i < r; ++i) {\n            if (sh[i] > sh[anchor]) anchor = i;\n        }\n\n        if (axis == 0) { // row packing\n            if (g == 0) ops.push_back({l, rot[l], -1, 'U'});\n            else ops.push_back({l, rot[l], prev_anchor, 'L'});\n            for (int i = l + 1; i < r; ++i) {\n                ops.push_back({i, rot[i], i - 1, 'U'});\n            }\n        } else { // column packing\n            if (g == 0) ops.push_back({l, rot[l], -1, 'U'});\n            else ops.push_back({l, rot[l], prev_anchor, 'U'});\n            for (int i = l + 1; i < r; ++i) {\n                ops.push_back({i, rot[i], i - 1, 'L'});\n            }\n        }\n\n        prev_anchor = anchor;\n    }\n\n    Cand c;\n    c.ops = move(ops);\n    c.estW = dp[N][idx].W;\n    c.estH = dp[N][idx].H;\n    c.sig = serialize_ops(c.ops);\n    return c;\n}\n\nstatic Family build_family(const vector<ll>& baseW, const vector<ll>& baseH, int mode, int axis) {\n    int N = (int)baseW.size();\n    vector<ll> ow(N), oh(N);\n    vector<int> rot(N);\n\n    auto make_oriented = [&](int i, bool width_min) {\n        if (width_min) {\n            if (baseW[i] <= baseH[i]) {\n                ow[i] = baseW[i];\n                oh[i] = baseH[i];\n                rot[i] = 0;\n            } else {\n                ow[i] = baseH[i];\n                oh[i] = baseW[i];\n                rot[i] = 1;\n            }\n        } else {\n            if (baseW[i] >= baseH[i]) {\n                ow[i] = baseW[i];\n                oh[i] = baseH[i];\n                rot[i] = 0;\n            } else {\n                ow[i] = baseH[i];\n                oh[i] = baseW[i];\n                rot[i] = 1;\n            }\n        }\n    };\n\n    for (int i = 0; i < N; ++i) {\n        if (mode == 0) {\n            make_oriented(i, true);   // width-min\n        } else if (mode == 1) {\n            make_oriented(i, false);  // height-min\n        } else if (mode == 2) {\n            if (i & 1) make_oriented(i, false);\n            else make_oriented(i, true);\n        } else {\n            if (i & 1) make_oriented(i, true);\n            else make_oriented(i, false);\n        }\n    }\n\n    vector<ll> sw(N), sh(N);\n    if (axis == 0) {\n        sw = ow;\n        sh = oh;\n    } else {\n        sw = oh;\n        sh = ow;\n    }\n\n    vector<ll> pref(N + 1, 0);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + sw[i];\n\n    vector<vector<ll>> mx(N, vector<ll>(N, 0));\n    for (int l = 0; l < N; ++l) {\n        ll cur = 0;\n        for (int r = l; r < N; ++r) {\n            cur = max(cur, sh[r]);\n            mx[l][r] = cur;\n        }\n    }\n\n    vector<vector<State>> dp(N + 1);\n    dp[0].push_back({0, 0, -1, -1});\n\n    for (int i = 1; i <= N; ++i) {\n        vector<State> cand;\n        for (int j = 0; j < i; ++j) {\n            ll rowW = pref[i] - pref[j];\n            ll rowH = mx[j][i - 1];\n            const auto& vec = dp[j];\n            cand.reserve(cand.size() + vec.size());\n            for (int idx = 0; idx < (int)vec.size(); ++idx) {\n                const State& s = vec[idx];\n                cand.push_back({max(s.W, rowW), s.H + rowH, j, idx});\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const State& a, const State& b) {\n            if (a.W != b.W) return a.W < b.W;\n            return a.H < b.H;\n        });\n\n        vector<State> tmp;\n        tmp.reserve(cand.size());\n        for (auto &s : cand) {\n            if (tmp.empty() || s.W != tmp.back().W) {\n                tmp.push_back(s);\n            } else {\n                if (s.H < tmp.back().H) tmp.back() = s;\n            }\n        }\n\n        ll bestH = (1LL << 62);\n        dp[i].clear();\n        for (auto &s : tmp) {\n            if (s.H < bestH) {\n                dp[i].push_back(s);\n                bestH = s.H;\n            }\n        }\n    }\n\n    const auto& front = dp[N];\n    int M = (int)front.size();\n\n    int idx_best = choose_state_by_weight(front, 1, 1);\n    ll bestScore = front[idx_best].W + front[idx_best].H;\n\n    set<int> idxs;\n    auto add_idx = [&](int idx) {\n        if (0 <= idx && idx < M) idxs.insert(idx);\n    };\n\n    // Core representative points.\n    add_idx(0);\n    add_idx(M - 1);\n    add_idx(idx_best);\n\n    // A broad set of slope-based samples on the Pareto frontier.\n    vector<pair<int,int>> weights = {\n        {2,1}, {1,2}, {3,1}, {1,3}, {4,1}, {1,4},\n        {5,2}, {2,5}, {7,3}, {3,7}, {11,4}, {4,11},\n        {13,5}, {5,13}\n    };\n    for (auto [a, b] : weights) {\n        int idx = choose_state_by_weight(front, a, b);\n        add_idx(idx);\n        add_idx(idx - 1);\n        add_idx(idx + 1);\n    }\n\n    // Evenly sampled frontier states.\n    int K = min(M, 16);\n    if (K >= 2) {\n        for (int k = 0; k < K; ++k) {\n            int idx = (int)((1LL * k * (M - 1)) / (K - 1));\n            add_idx(idx);\n        }\n    } else {\n        add_idx(0);\n    }\n\n    unordered_set<string> localSeen;\n    Family fam;\n    fam.bestScore = bestScore;\n    fam.mode = mode;\n    fam.axis = axis;\n    fam.cands.reserve(idxs.size());\n\n    for (int idx : idxs) {\n        Cand c = build_candidate_from_state(dp, idx, rot, sh, axis, N);\n        if (localSeen.insert(c.sig).second) {\n            fam.cands.push_back(move(c));\n        }\n    }\n\n    return fam;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    ll sigma;\n    cin >> N >> T >> sigma;\n\n    vector<ll> w(N), h(N);\n    for (int i = 0; i < N; ++i) cin >> w[i] >> h[i];\n\n    vector<Family> families;\n    families.reserve(8);\n    for (int mode = 0; mode < 4; ++mode) {\n        for (int axis = 0; axis < 2; ++axis) {\n            families.push_back(build_family(w, h, mode, axis));\n        }\n    }\n\n    sort(families.begin(), families.end(), [](const Family& a, const Family& b) {\n        if (a.bestScore != b.bestScore) return a.bestScore < b.bestScore;\n        if (a.axis != b.axis) return a.axis < b.axis;\n        return a.mode < b.mode;\n    });\n\n    // Collect candidates: first one best per family, then the rest globally.\n    vector<Cand> chosen;\n    chosen.reserve(min(T, 256));\n    unordered_set<string> used;\n    used.reserve(512);\n\n    for (auto &fam : families) {\n        if (fam.cands.empty()) continue;\n        int bestIdx = 0;\n        ll best = fam.cands[0].estW + fam.cands[0].estH;\n        for (int i = 1; i < (int)fam.cands.size(); ++i) {\n            ll cur = fam.cands[i].estW + fam.cands[i].estH;\n            if (cur < best) {\n                best = cur;\n                bestIdx = i;\n            }\n        }\n        if (used.insert(fam.cands[bestIdx].sig).second) {\n            chosen.push_back(fam.cands[bestIdx]);\n        }\n    }\n\n    vector<Cand> rest;\n    rest.reserve(512);\n    for (auto &fam : families) {\n        for (auto &c : fam.cands) {\n            if (!used.count(c.sig)) rest.push_back(c);\n        }\n    }\n\n    sort(rest.begin(), rest.end(), [](const Cand& a, const Cand& b) {\n        ll sa = a.estW + a.estH;\n        ll sb = b.estW + b.estH;\n        if (sa != sb) return sa < sb;\n        if (a.estW != b.estW) return a.estW < b.estW;\n        return a.estH < b.estH;\n    });\n\n    int need = max(0, T - (int)chosen.size());\n    for (int i = 0; i < need && i < (int)rest.size(); ++i) {\n        chosen.push_back(rest[i]);\n        used.insert(rest[i].sig);\n    }\n\n    if (chosen.empty()) {\n        // Fallback: a simple row packing.\n        Cand c;\n        vector<Op> ops;\n        ops.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (i == 0) ops.push_back({i, 0, -1, 'U'});\n            else ops.push_back({i, 0, i - 1, 'U'});\n        }\n        c.ops = move(ops);\n        c.sig = serialize_ops(c.ops);\n        chosen.push_back(move(c));\n    }\n\n    sort(chosen.begin(), chosen.end(), [](const Cand& a, const Cand& b) {\n        ll sa = a.estW + a.estH;\n        ll sb = b.estW + b.estH;\n        if (sa != sb) return sa < sb;\n        if (a.estW != b.estW) return a.estW < b.estW;\n        return a.estH < b.estH;\n    });\n\n    int usedCount = min(T, (int)chosen.size());\n    for (int t = 0; t < usedCount; ++t) {\n        const auto& c = chosen[t];\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm; // Read judge feedback, but we don't need it for this heuristic.\n    }\n\n    for (int t = usedCount; t < T; ++t) {\n        const auto& c = chosen[0];\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm;\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing Key = array<long long, 6>;\n\nstruct Info {\n    vector<vector<int>> children;\n    vector<int> parent, roots, comp, depth, tin, tout, maxDown;\n    vector<long long> subW;\n    vector<vector<int>> compNodes;\n    long long score = 0;\n};\n\nstatic int N, M, H;\nstatic vector<int> A, X, Y, degv, r2v, mort, bucket8, neighSum;\nstatic vector<vector<int>> adj;\nstatic chrono::steady_clock::time_point start_time;\n\nstatic inline bool time_up() {\n    return chrono::duration_cast<chrono::milliseconds>(\n        chrono::steady_clock::now() - start_time\n    ).count() > 1850;\n}\n\nstatic int morton_code(int x, int y) {\n    int z = 0;\n    for (int i = 0; i < 10; ++i) {\n        z |= ((x >> i) & 1) << (2 * i);\n        z |= ((y >> i) & 1) << (2 * i + 1);\n    }\n    return z;\n}\n\nstatic Key mk(long long a, long long b, long long c, long long d, long long e, long long f) {\n    return {a, b, c, d, e, f};\n}\n\nstatic Key orderKey1(int v) { return mk(A[v], r2v[v], -degv[v], neighSum[v], mort[v], v); }\nstatic Key orderKey2(int v) { return mk(A[v], -r2v[v], -degv[v], neighSum[v], mort[v], v); }\nstatic Key orderKey3(int v) { return mk(A[v], bucket8[v], r2v[v], -degv[v], mort[v], v); }\n\nstatic Key prefKey1(int v) { return mk(-degv[v], -A[v], r2v[v], neighSum[v], mort[v], v); }\nstatic Key prefKey2(int v) { return mk(-A[v], -degv[v], r2v[v], neighSum[v], mort[v], v); }\nstatic Key prefKey3(int v) { return mk(-A[v], r2v[v], -degv[v], neighSum[v], mort[v], v); }\n\nstatic Key childKey1(int v) { return mk(-A[v], degv[v], r2v[v], neighSum[v], mort[v], v); }\nstatic Key childKey2(int v) { return mk(-A[v], -r2v[v], degv[v], neighSum[v], mort[v], v); }\n\nstatic Info compute_info(const vector<int>& parent) {\n    Info info;\n    info.parent = parent;\n    info.children.assign(N, {});\n    info.roots.clear();\n\n    for (int v = 0; v < N; ++v) {\n        if (parent[v] == -1) info.roots.push_back(v);\n        else info.children[parent[v]].push_back(v);\n    }\n\n    info.comp.assign(N, -1);\n    info.depth.assign(N, -1);\n    info.tin.assign(N, -1);\n    info.tout.assign(N, -1);\n    info.subW.assign(N, 0);\n    info.maxDown.assign(N, 0);\n    info.compNodes.clear();\n    info.score = 0;\n\n    int timer = 0;\n    int cid = 0;\n\n    for (int r : info.roots) {\n        info.compNodes.push_back({});\n        auto dfs = [&](auto&& self, int v, int d) -> void {\n            info.comp[v] = cid;\n            info.depth[v] = d;\n            info.tin[v] = timer++;\n            info.subW[v] = A[v];\n            info.maxDown[v] = 0;\n            info.score += 1LL * (d + 1) * A[v];\n            info.compNodes.back().push_back(v);\n            for (int ch : info.children[v]) {\n                self(self, ch, d + 1);\n                info.subW[v] += info.subW[ch];\n                info.maxDown[v] = max(info.maxDown[v], info.maxDown[ch] + 1);\n            }\n            info.tout[v] = timer;\n        };\n        dfs(dfs, r, 0);\n        ++cid;\n    }\n\n    return info;\n}\n\ntemplate <class PrefFunc>\nstatic vector<int> build_greedy(const vector<int>& order, PrefFunc pref) {\n    vector<int> parent(N, -2), depth(N, -1);\n\n    for (int v : order) {\n        int best = -1;\n        for (int u : adj[v]) {\n            if (depth[u] == -1 || depth[u] >= H) continue;\n            if (best == -1 ||\n                depth[u] > depth[best] ||\n                (depth[u] == depth[best] && pref(u) < pref(best))) {\n                best = u;\n            }\n        }\n        if (best == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = best;\n            depth[v] = depth[best] + 1;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) if (parent[i] == -2) parent[i] = -1;\n    return parent;\n}\n\nstatic vector<int> choose_seeds(const vector<int>& order, int K = 8) {\n    vector<int> seeds;\n    vector<char> used(N, 0);\n\n    for (int b = 0; b < 8 && (int)seeds.size() < K; ++b) {\n        for (int v : order) {\n            if (!used[v] && bucket8[v] == b) {\n                used[v] = 1;\n                seeds.push_back(v);\n                break;\n            }\n        }\n    }\n    for (int v : order) {\n        if ((int)seeds.size() >= K) break;\n        if (!used[v]) {\n            used[v] = 1;\n            seeds.push_back(v);\n        }\n    }\n    return seeds;\n}\n\ntemplate <class KeyFunc>\nstatic vector<int> build_connected_order(const vector<int>& seeds, KeyFunc key) {\n    vector<int> ord;\n    ord.reserve(N);\n\n    vector<int> starts = seeds;\n    if (starts.empty()) starts.push_back(0);\n\n    using P = pair<Key, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    vector<char> inq(N, 0), vis(N, 0);\n\n    for (int s : starts) {\n        if (!inq[s]) {\n            inq[s] = 1;\n            pq.push({key(s), s});\n        }\n    }\n\n    while (!pq.empty()) {\n        auto [k, v] = pq.top();\n        pq.pop();\n        if (vis[v]) continue;\n        vis[v] = 1;\n        ord.push_back(v);\n        for (int to : adj[v]) {\n            if (!inq[to]) {\n                inq[to] = 1;\n                pq.push({key(to), to});\n            }\n        }\n    }\n    return ord;\n}\n\ntemplate <class ChildKeyFunc>\nstatic vector<int> build_dfs_forest(const vector<int>& rootOrder, ChildKeyFunc childKey) {\n    vector<vector<int>> ordAdj = adj;\n    for (int v = 0; v < N; ++v) {\n        sort(ordAdj[v].begin(), ordAdj[v].end(), [&](int x, int y) {\n            return childKey(x) < childKey(y);\n        });\n    }\n\n    vector<int> parent(N, -2);\n    vector<char> vis(N, 0);\n\n    auto dfs = [&](auto&& self, int v, int d) -> void {\n        vis[v] = 1;\n        if (d == H) return;\n        for (int to : ordAdj[v]) {\n            if (!vis[to]) {\n                parent[to] = v;\n                self(self, to, d + 1);\n            }\n        }\n    };\n\n    for (int r : rootOrder) {\n        if (!vis[r]) {\n            parent[r] = -1;\n            dfs(dfs, r, 0);\n        }\n    }\n\n    for (int v = 0; v < N; ++v) if (parent[v] == -2) parent[v] = -1;\n    return parent;\n}\n\nstatic vector<int> optimize_roots(const vector<int>& parentIn) {\n    vector<int> parent = parentIn;\n    Info info = compute_info(parent);\n    vector<int> newParent = parent;\n\n    for (int cid = 0; cid < (int)info.roots.size(); ++cid) {\n        if (time_up()) break;\n\n        int r = info.roots[cid];\n        const auto& nodes = info.compNodes[cid];\n        if ((int)nodes.size() == 1) continue;\n\n        long long totalW = info.subW[r];\n        long long baseDist = 0;\n        for (int v : nodes) baseDist += 1LL * info.depth[v] * A[v];\n\n        vector<long long> distSum(N, LLONG_MIN / 4);\n        distSum[r] = baseDist;\n\n        auto dfsDist = [&](auto&& self, int v) -> void {\n            for (int ch : info.children[v]) {\n                distSum[ch] = distSum[v] + totalW - 2LL * info.subW[ch];\n                self(self, ch);\n            }\n        };\n        dfsDist(dfsDist, r);\n\n        auto bfs = [&](int s) {\n            vector<int> dist(N, -1);\n            queue<int> q;\n            q.push(s);\n            dist[s] = 0;\n            int far = s;\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n                if (dist[v] > dist[far]) far = v;\n                int p = info.parent[v];\n                if (p != -1 && dist[p] == -1) {\n                    dist[p] = dist[v] + 1;\n                    q.push(p);\n                }\n                for (int ch : info.children[v]) {\n                    if (dist[ch] == -1) {\n                        dist[ch] = dist[v] + 1;\n                        q.push(ch);\n                    }\n                }\n            }\n            return pair<int, vector<int>>(far, move(dist));\n        };\n\n        auto [x, _dx0] = bfs(r);\n        auto [y, dx] = bfs(x);\n        auto [z, dy] = bfs(y);\n        (void)z;\n\n        int best = r;\n        long long bestVal = distSum[r];\n        int bestEcc = max(dx[r], dy[r]);\n\n        for (int v : nodes) {\n            int ecc = max(dx[v], dy[v]);\n            if (ecc > H) continue;\n            if (distSum[v] > bestVal ||\n                (distSum[v] == bestVal && (ecc < bestEcc ||\n                 (ecc == bestEcc && (A[v] < A[best] || (A[v] == A[best] && v < best)))))) {\n                best = v;\n                bestVal = distSum[v];\n                bestEcc = ecc;\n            }\n        }\n\n        if (best == r) continue;\n\n        vector<int> parComp(N, -2);\n        queue<int> q;\n        q.push(best);\n        parComp[best] = -1;\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            auto relax = [&](int to) {\n                if (parComp[to] == -2) {\n                    parComp[to] = v;\n                    q.push(to);\n                }\n            };\n\n            int p = info.parent[v];\n            if (p != -1) relax(p);\n            for (int ch : info.children[v]) relax(ch);\n        }\n\n        for (int v : nodes) newParent[v] = parComp[v];\n    }\n\n    return newParent;\n}\n\nstruct Move {\n    long long gain = 0;\n    int v = -1, u = -1;\n};\n\nstatic Move find_best_move(const Info& info, const vector<int>& parent, mt19937_64& rng) {\n    long long bestGain = 0;\n    vector<pair<int, int>> bestMoves;\n\n    for (int v = 0; v < N; ++v) {\n        if (info.maxDown[v] == H) continue;\n        for (int u : adj[v]) {\n            if (u == parent[v]) continue;\n            if (info.comp[u] == info.comp[v] &&\n                info.tin[v] <= info.tin[u] && info.tin[u] < info.tout[v]) {\n                continue;\n            }\n\n            int nd = info.depth[u] + 1;\n            if (nd <= info.depth[v]) continue;\n            if (nd + info.maxDown[v] > H) continue;\n\n            long long gain = 1LL * (nd - info.depth[v]) * info.subW[v];\n            if (gain <= 0) continue;\n\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestMoves.clear();\n                bestMoves.push_back({v, u});\n            } else if (gain == bestGain) {\n                bestMoves.push_back({v, u});\n            }\n        }\n    }\n\n    if (bestMoves.empty()) return {};\n    auto [v, u] = bestMoves[rng() % bestMoves.size()];\n    return {bestGain, v, u};\n}\n\nstatic vector<int> hill_climb(vector<int> parent, mt19937_64& rng, int maxSteps) {\n    for (int step = 0; step < maxSteps && !time_up(); ++step) {\n        Info info = compute_info(parent);\n        Move mv = find_best_move(info, parent, rng);\n        if (mv.v == -1) break;\n        parent[mv.v] = mv.u;\n    }\n    return parent;\n}\n\nstatic vector<int> refine(vector<int> parent, mt19937_64& rng) {\n    for (int rep = 0; rep < 2 && !time_up(); ++rep) {\n        parent = optimize_roots(parent);\n        parent = hill_climb(parent, rng, rep == 0 ? 120 : 60);\n    }\n    if (!time_up()) parent = optimize_roots(parent);\n    return parent;\n}\n\nstatic long long evaluate_score(const vector<int>& parent) {\n    return compute_info(parent).score;\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 >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    adj.assign(N, {});\n    vector<pair<int, int>> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; ++i) cin >> X[i] >> Y[i];\n\n    degv.resize(N);\n    r2v.resize(N);\n    mort.resize(N);\n    bucket8.resize(N);\n    neighSum.resize(N);\n\n    const double PI = acos(-1.0);\n    for (int i = 0; i < N; ++i) {\n        degv[i] = (int)adj[i].size();\n        r2v[i] = (X[i] - 500) * (X[i] - 500) + (Y[i] - 500) * (Y[i] - 500);\n        mort[i] = morton_code(X[i], Y[i]);\n\n        long long s = 0;\n        for (int to : adj[i]) s += A[to];\n        neighSum[i] = (int)s;\n\n        double ang = atan2((double)Y[i] - 500.0, (double)X[i] - 500.0);\n        if (ang < 0) ang += 2.0 * PI;\n        int b = (int)(ang / (2.0 * PI) * 8.0);\n        if (b < 0) b = 0;\n        if (b >= 8) b = 7;\n        bucket8[i] = b;\n    }\n\n    vector<int> ord1(N), ord2(N), ord3(N);\n    iota(ord1.begin(), ord1.end(), 0);\n    iota(ord2.begin(), ord2.end(), 0);\n    iota(ord3.begin(), ord3.end(), 0);\n    sort(ord1.begin(), ord1.end(), [&](int x, int y) { return orderKey1(x) < orderKey1(y); });\n    sort(ord2.begin(), ord2.end(), [&](int x, int y) { return orderKey2(x) < orderKey2(y); });\n    sort(ord3.begin(), ord3.end(), [&](int x, int y) { return orderKey3(x) < orderKey3(y); });\n\n    vector<int> seeds1 = choose_seeds(ord1, 8);\n    vector<int> seeds2 = choose_seeds(ord2, 8);\n\n    vector<int> rootOrder1 = seeds1;\n    rootOrder1.insert(rootOrder1.end(), ord1.begin(), ord1.end());\n    vector<int> rootOrder2 = seeds2;\n    rootOrder2.insert(rootOrder2.end(), ord2.begin(), ord2.end());\n\n    vector<int> connected1 = build_connected_order(seeds1, orderKey1);\n    vector<int> connected2 = build_connected_order(seeds2, orderKey2);\n\n    vector<int> base1 = build_greedy(ord1, prefKey1);\n    vector<int> base2 = build_greedy(ord2, prefKey2);\n    vector<int> base3 = build_greedy(ord3, prefKey3);\n    vector<int> base4 = build_greedy(connected1, prefKey1);\n    vector<int> base5 = build_greedy(connected2, prefKey2);\n    vector<int> base6 = build_dfs_forest(rootOrder1, childKey1);\n    vector<int> base7 = build_dfs_forest(rootOrder2, childKey2);\n\n    uint64_t seed = 88172645463393265ULL;\n    auto mix = [&](uint64_t x) {\n        seed ^= x + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2);\n    };\n    mix(N); mix(M); mix(H);\n    for (int i = 0; i < N; ++i) {\n        mix((uint64_t)A[i] << 32 ^ (uint64_t)X[i]);\n        mix((uint64_t)Y[i] << 16 ^ (uint64_t)degv[i]);\n    }\n    for (auto [u, v] : edges) {\n        mix(((uint64_t)u << 32) ^ (uint64_t)v);\n    }\n    mt19937_64 rng(seed);\n\n    struct Sol {\n        long long score = -1;\n        vector<int> parent;\n    };\n\n    vector<vector<int>> bases = {base1, base2, base3, base4, base5, base6, base7};\n\n    Sol best;\n    for (auto& b : bases) {\n        if (time_up()) break;\n        vector<int> cur = refine(b, rng);\n        long long sc = evaluate_score(cur);\n        if (sc > best.score) {\n            best.score = sc;\n            best.parent = move(cur);\n        }\n    }\n\n    if (!time_up() && !best.parent.empty()) {\n        vector<int> cur = refine(best.parent, rng);\n        long long sc = evaluate_score(cur);\n        if (sc > best.score) {\n            best.score = sc;\n            best.parent = move(cur);\n        }\n    }\n\n    if (best.parent.empty()) best.parent.assign(N, -1);\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << best.parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cand {\n    uint64_t mask;   // coverage over Oni bits (reduced universe later)\n    int cost;        // 2 * len\n    int len;         // strip length\n    int idx;         // row/col index\n    char dir;        // L/R/U/D\n    int orig;        // original candidate id\n};\n\nstruct U64Hash {\n    size_t operator()(uint64_t x) const noexcept {\n        x ^= x >> 33;\n        x *= 0xff51afd7ed558ccdULL;\n        x ^= x >> 33;\n        x *= 0xc4ceb9fe1a85ec53ULL;\n        x ^= x >> 33;\n        return (size_t)x;\n    }\n};\n\nstatic inline int pop64(uint64_t x) {\n    return __builtin_popcountll(x);\n}\n\nstatic inline char revDir(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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    vector<vector<int>> oniId(N, vector<int>(N, -1));\n    vector<pair<int,int>> oniPos;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'x') {\n                oniId[i][j] = (int)oniPos.size();\n                oniPos.push_back({i, j});\n            }\n        }\n    }\n\n    int M = (int)oniPos.size(); // 40\n    vector<Cand> cands;\n    cands.reserve(200);\n\n    auto addCand = [&](char dir, int idx, int len, uint64_t mask) {\n        if (mask == 0) return;\n        cands.push_back({mask, 2 * len, len, idx, dir, (int)cands.size()});\n    };\n\n    // Generate all useful candidates:\n    // only lengths where the newly removed border cell contains an Oni.\n    for (int i = 0; i < N; ++i) {\n        int firstF = N, lastF = -1;\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'o') {\n                firstF = min(firstF, j);\n                lastF = max(lastF, j);\n            }\n        }\n\n        uint64_t mask = 0;\n        for (int j = 0; j < firstF; ++j) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('L', i, j + 1, mask);\n            }\n        }\n\n        mask = 0;\n        for (int j = N - 1; j > lastF; --j) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('R', i, N - j, mask);\n            }\n        }\n    }\n\n    for (int j = 0; j < N; ++j) {\n        int firstF = N, lastF = -1;\n        for (int i = 0; i < N; ++i) {\n            if (C[i][j] == 'o') {\n                firstF = min(firstF, i);\n                lastF = max(lastF, i);\n            }\n        }\n\n        uint64_t mask = 0;\n        for (int i = 0; i < firstF; ++i) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('U', j, i + 1, mask);\n            }\n        }\n\n        mask = 0;\n        for (int i = N - 1; i > lastF; --i) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('D', j, N - i, mask);\n            }\n        }\n    }\n\n    // Deduplicate identical masks, keep the cheapest one.\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.idx < b.idx;\n    });\n\n    vector<Cand> uniq;\n    for (auto &c : cands) {\n        if (uniq.empty() || uniq.back().mask != c.mask) uniq.push_back(c);\n    }\n    cands.swap(uniq);\n\n    // Remove dominated candidates:\n    // if mask_i \u2286 mask_j and cost_j <= cost_i, i is useless.\n    {\n        int Cn = (int)cands.size();\n        vector<char> bad(Cn, false);\n        for (int i = 0; i < Cn; ++i) {\n            if (bad[i]) continue;\n            for (int j = 0; j < Cn; ++j) {\n                if (i == j || bad[i]) continue;\n                if ((cands[i].mask & ~cands[j].mask) == 0 && cands[j].cost <= cands[i].cost) {\n                    bad[i] = true;\n                    break;\n                }\n            }\n        }\n        vector<Cand> tmp;\n        for (int i = 0; i < Cn; ++i) if (!bad[i]) tmp.push_back(cands[i]);\n        cands.swap(tmp);\n    }\n\n    int Cn = (int)cands.size();\n    uint64_t fullMask = (M == 64 ? ~0ULL : ((1ULL << M) - 1ULL));\n\n    // Build original coverers and force unique-cover candidates.\n    vector<vector<int>> cover0(M);\n    for (int i = 0; i < Cn; ++i) {\n        uint64_t m = cands[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            cover0[b].push_back(i);\n            m &= (m - 1);\n        }\n    }\n\n    vector<char> forcedChosen(Cn, false);\n    vector<int> forcedSel;\n    for (int b = 0; b < M; ++b) {\n        if ((int)cover0[b].size() == 1) {\n            int id = cover0[b][0];\n            if (!forcedChosen[id]) {\n                forcedChosen[id] = true;\n                forcedSel.push_back(id);\n            }\n        }\n    }\n\n    uint64_t residualMask = fullMask;\n    long long forcedCost = 0;\n    for (int id : forcedSel) {\n        residualMask &= ~cands[id].mask;\n        forcedCost += cands[id].cost;\n    }\n\n    // Compress remaining bits.\n    vector<int> bitMap(64, -1);\n    vector<int> bits;\n    for (int b = 0; b < M; ++b) {\n        if ((residualMask >> b) & 1ULL) {\n            bitMap[b] = (int)bits.size();\n            bits.push_back(b);\n        }\n    }\n    int R = (int)bits.size();\n\n    // If forced candidates already cover everything.\n    if (R == 0) {\n        vector<pair<char,int>> ops;\n        for (int id : forcedSel) {\n            auto &c = cands[id];\n            for (int t = 0; t < c.len; ++t) ops.push_back({c.dir, c.idx});\n            for (int t = 0; t < c.len; ++t) ops.push_back({revDir(c.dir), c.idx});\n        }\n        for (auto [d, p] : ops) cout << d << ' ' << p << '\\n';\n        return 0;\n    }\n\n    vector<Cand> red;\n    red.reserve(Cn);\n    for (int i = 0; i < Cn; ++i) {\n        if (forcedChosen[i]) continue;\n        uint64_t m = cands[i].mask & residualMask;\n        if (m == 0) continue;\n        uint64_t nm = 0;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            m &= (m - 1);\n            nm |= 1ULL << bitMap[b];\n        }\n        red.push_back({nm, cands[i].cost, cands[i].len, cands[i].idx, cands[i].dir, cands[i].orig});\n    }\n\n    // Deduplicate and prune again on the reduced instance.\n    sort(red.begin(), red.end(), [&](const Cand& a, const Cand& b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.idx < b.idx;\n    });\n    {\n        vector<Cand> tmp;\n        for (auto &c : red) {\n            if (tmp.empty() || tmp.back().mask != c.mask) tmp.push_back(c);\n        }\n        red.swap(tmp);\n    }\n    {\n        int n = (int)red.size();\n        vector<char> bad(n, false);\n        for (int i = 0; i < n; ++i) {\n            if (bad[i]) continue;\n            for (int j = 0; j < n; ++j) {\n                if (i == j || bad[i]) continue;\n                if ((red[i].mask & ~red[j].mask) == 0 && red[j].cost <= red[i].cost) {\n                    bad[i] = true;\n                    break;\n                }\n            }\n        }\n        vector<Cand> tmp;\n        for (int i = 0; i < n; ++i) if (!bad[i]) tmp.push_back(red[i]);\n        red.swap(tmp);\n    }\n\n    Cn = (int)red.size();\n    vector<vector<int>> coverers(R);\n    vector<int> deg(R, 0), minCostBit(R, INT_MAX), maxCostBit(R, 0);\n\n    for (int i = 0; i < Cn; ++i) {\n        uint64_t m = red[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            coverers[b].push_back(i);\n            m &= (m - 1);\n        }\n    }\n    for (int b = 0; b < R; ++b) {\n        deg[b] = (int)coverers[b].size();\n        for (int id : coverers[b]) {\n            minCostBit[b] = min(minCostBit[b], red[id].cost);\n            maxCostBit[b] = max(maxCostBit[b], red[id].cost);\n        }\n    }\n\n    // Orders for dual lower bound.\n    vector<vector<int>> dualOrders(5, vector<int>(R));\n    for (int t = 0; t < 5; ++t) {\n        iota(dualOrders[t].begin(), dualOrders[t].end(), 0);\n    }\n    sort(dualOrders[0].begin(), dualOrders[0].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        return a < b;\n    });\n    sort(dualOrders[1].begin(), dualOrders[1].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        if (maxCostBit[a] != maxCostBit[b]) return maxCostBit[a] > maxCostBit[b];\n        return a < b;\n    });\n    sort(dualOrders[2].begin(), dualOrders[2].end(), [&](int a, int b) {\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        return a < b;\n    });\n    sort(dualOrders[3].begin(), dualOrders[3].end(), [&](int a, int b) {\n        long long lhs = 1LL * minCostBit[a] * max(1, deg[b]);\n        long long rhs = 1LL * minCostBit[b] * max(1, deg[a]);\n        if (lhs != rhs) return lhs < rhs;\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        return a < b;\n    });\n    sort(dualOrders[4].begin(), dualOrders[4].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] > deg[b];\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        return a < b;\n    });\n\n    auto cleanup = [&](vector<int> sel) -> vector<int> {\n        if (sel.empty()) return sel;\n        vector<int> cnt(R, 0);\n        for (int id : sel) {\n            uint64_t m = red[id].mask;\n            while (m) {\n                int b = __builtin_ctzll(m);\n                cnt[b]++;\n                m &= (m - 1);\n            }\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            sort(sel.begin(), sel.end(), [&](int a, int b) {\n                if (red[a].cost != red[b].cost) return red[a].cost > red[b].cost;\n                return a < b;\n            });\n\n            vector<int> nxt;\n            nxt.reserve(sel.size());\n            for (int id : sel) {\n                bool removable = true;\n                uint64_t m = red[id].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    if (cnt[b] <= 1) {\n                        removable = false;\n                        break;\n                    }\n                    m &= (m - 1);\n                }\n\n                if (removable) {\n                    uint64_t m2 = red[id].mask;\n                    while (m2) {\n                        int b = __builtin_ctzll(m2);\n                        cnt[b]--;\n                        m2 &= (m2 - 1);\n                    }\n                    changed = true;\n                } else {\n                    nxt.push_back(id);\n                }\n            }\n            sel.swap(nxt);\n        }\n        return sel;\n    };\n\n    auto greedySolve = [&](int K, bool ratioMode) -> pair<vector<int>, int> {\n        uint64_t U = (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL));\n        vector<int> sel;\n\n        while (U) {\n            // choose a forced candidate if some bit has only one coverer\n            vector<int> forced;\n            vector<char> seen(Cn, false);\n            uint64_t x = U;\n            while (x) {\n                int b = __builtin_ctzll(x);\n                x &= (x - 1);\n                if ((int)coverers[b].size() == 1) {\n                    int id = coverers[b][0];\n                    if (!seen[id]) {\n                        seen[id] = true;\n                        forced.push_back(id);\n                    }\n                }\n            }\n\n            if (!forced.empty()) {\n                for (int id : forced) {\n                    sel.push_back(id);\n                    U &= ~red[id].mask;\n                }\n                continue;\n            }\n\n            int best = -1;\n            int bestNew = -1;\n            int bestCost = INT_MAX;\n            long long bestScore = LLONG_MIN;\n\n            for (int id = 0; id < Cn; ++id) {\n                uint64_t nm = red[id].mask & U;\n                if (nm == 0) continue;\n                int newCnt = pop64(nm);\n\n                if (!ratioMode) {\n                    long long score = 1LL * K * newCnt - red[id].cost;\n                    if (best == -1 ||\n                        score > bestScore ||\n                        (score == bestScore && (newCnt > bestNew ||\n                                                (newCnt == bestNew && red[id].cost < bestCost)))) {\n                        best = id;\n                        bestScore = score;\n                        bestNew = newCnt;\n                        bestCost = red[id].cost;\n                    }\n                } else {\n                    if (best == -1) {\n                        best = id;\n                        bestNew = newCnt;\n                        bestCost = red[id].cost;\n                    } else {\n                        long long lhs = 1LL * newCnt * bestCost;\n                        long long rhs = 1LL * bestNew * red[id].cost;\n                        if (lhs > rhs ||\n                            (lhs == rhs && (newCnt > bestNew ||\n                                            (newCnt == bestNew && red[id].cost < bestCost)))) {\n                            best = id;\n                            bestNew = newCnt;\n                            bestCost = red[id].cost;\n                        }\n                    }\n                }\n            }\n\n            if (best == -1) break; // should not happen\n            sel.push_back(best);\n            U &= ~red[best].mask;\n        }\n\n        sel = cleanup(sel);\n\n        int cost = 0;\n        uint64_t cover = 0;\n        for (int id : sel) {\n            cost += red[id].cost;\n            cover |= red[id].mask;\n        }\n\n        // Safety fallback: if anything remains uncovered, add cheapest candidates.\n        if (cover != (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL))) {\n            uint64_t rem = ((R == 64 ? ~0ULL : ((1ULL << R) - 1ULL)) & ~cover);\n            while (rem) {\n                int b = __builtin_ctzll(rem);\n                int choose = -1;\n                int chooseCost = INT_MAX;\n                for (int id = 0; id < Cn; ++id) {\n                    if ((red[id].mask >> b) & 1ULL) {\n                        if (red[id].cost < chooseCost) {\n                            choose = id;\n                            chooseCost = red[id].cost;\n                        }\n                    }\n                }\n                if (choose == -1) break;\n                sel.push_back(choose);\n                cover |= red[choose].mask;\n                rem = ((R == 64 ? ~0ULL : ((1ULL << R) - 1ULL)) & ~cover);\n            }\n            sel = cleanup(sel);\n            cost = 0;\n            for (int id : sel) cost += red[id].cost;\n        }\n\n        return {sel, cost};\n    };\n\n    vector<int> bestSel;\n    int bestResCost = INT_MAX;\n\n    // Several greedy seeds.\n    vector<int> Ks = {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 50};\n    for (int K : Ks) {\n        auto [sel, cost] = greedySolve(K, false);\n        if (cost < bestResCost) {\n            bestResCost = cost;\n            bestSel = sel;\n        }\n    }\n    {\n        auto [sel, cost] = greedySolve(0, true);\n        if (cost < bestResCost) {\n            bestResCost = cost;\n            bestSel = sel;\n        }\n    }\n\n    bestSel = cleanup(bestSel);\n    bestResCost = 0;\n    {\n        uint64_t cover = 0;\n        for (int id : bestSel) {\n            bestResCost += red[id].cost;\n            cover |= red[id].mask;\n        }\n        (void)cover;\n    }\n\n    // Branch and bound search on the reduced problem.\n    chrono::steady_clock::time_point deadline = chrono::steady_clock::now() + chrono::milliseconds(1800);\n    bool timedOut = false;\n    uint64_t nodeCounter = 0;\n\n    unordered_map<uint64_t, int, U64Hash> memo;\n    memo.reserve(1 << 16);\n    memo.max_load_factor(0.7f);\n\n    vector<int> cur;\n\n    auto simpleLB = [&](uint64_t U) -> long long {\n        long long sumMin = 0;\n        int maxCover = 0;\n\n        uint64_t x = U;\n        while (x) {\n            int b = __builtin_ctzll(x);\n            x &= (x - 1);\n            sumMin += minCostBit[b];\n        }\n        for (int id = 0; id < Cn; ++id) {\n            int cov = pop64(red[id].mask & U);\n            if (cov > maxCover) maxCover = cov;\n        }\n        if (maxCover == 0) return (long long)1e9;\n        return (sumMin + maxCover - 1) / maxCover;\n    };\n\n    auto dualLB = [&](uint64_t U) -> long long {\n        long long best = 0;\n        for (int t = 0; t < 5; ++t) {\n            vector<int> slack(Cn);\n            for (int i = 0; i < Cn; ++i) slack[i] = red[i].cost;\n\n            long long val = 0;\n            for (int b : dualOrders[t]) {\n                if (((U >> b) & 1ULL) == 0) continue;\n                int delta = INT_MAX;\n                for (int id : coverers[b]) {\n                    delta = min(delta, slack[id]);\n                }\n                if (delta == INT_MAX || delta <= 0) continue;\n                val += delta;\n                for (int id : coverers[b]) slack[id] -= delta;\n            }\n            best = max(best, val);\n        }\n        return best;\n    };\n\n    auto choosePivot = [&](uint64_t U) -> int {\n        int pivot = -1;\n        int bestDeg = INT_MAX;\n        int bestMinCost = -1;\n        uint64_t x = U;\n        while (x) {\n            int b = __builtin_ctzll(x);\n            x &= (x - 1);\n            if (deg[b] < bestDeg || (deg[b] == bestDeg && minCostBit[b] > bestMinCost)) {\n                bestDeg = deg[b];\n                bestMinCost = minCostBit[b];\n                pivot = b;\n            }\n        }\n        return pivot;\n    };\n\n    function<void(uint64_t,int)> dfs = [&](uint64_t U, int cost) {\n        if (timedOut) return;\n        if ((++nodeCounter & 255ULL) == 0) {\n            if (chrono::steady_clock::now() > deadline) {\n                timedOut = true;\n                return;\n            }\n        }\n\n        if (cost >= bestResCost) return;\n        if (U == 0) {\n            bestResCost = cost;\n            bestSel = cur;\n            return;\n        }\n\n        auto it = memo.find(U);\n        if (it != memo.end() && it->second <= cost) return;\n        memo[U] = cost;\n\n        long long lb1 = simpleLB(U);\n        if (cost + lb1 >= bestResCost) return;\n        long long lb2 = dualLB(U);\n        if (cost + lb2 >= bestResCost) return;\n\n        int pivot = choosePivot(U);\n        if (pivot < 0) return;\n\n        vector<int> opts = coverers[pivot];\n        sort(opts.begin(), opts.end(), [&](int a, int b) {\n            int ca = pop64(red[a].mask & U);\n            int cb = pop64(red[b].mask & U);\n            long long lhs = 1LL * red[a].cost * cb;\n            long long rhs = 1LL * red[b].cost * ca;\n            if (lhs != rhs) return lhs < rhs;\n            if (ca != cb) return ca > cb;\n            if (red[a].cost != red[b].cost) return red[a].cost < red[b].cost;\n            return a < b;\n        });\n\n        for (int id : opts) {\n            uint64_t nU = U & ~red[id].mask;\n            if (nU == U) continue;\n            cur.push_back(id);\n            dfs(nU, cost + red[id].cost);\n            cur.pop_back();\n            if (timedOut) return;\n        }\n    };\n\n    uint64_t startU = (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL));\n    dfs(startU, 0);\n\n    // Final cleanup of the reduced selected set.\n    bestSel = cleanup(bestSel);\n    bestResCost = 0;\n    for (int id : bestSel) bestResCost += red[id].cost;\n\n    // Build output operations.\n    vector<pair<char,int>> outOps;\n    outOps.reserve((size_t)(forcedSel.size() + bestSel.size()) * 40);\n\n    auto emitCandidate = [&](const Cand& c) {\n        for (int t = 0; t < c.len; ++t) outOps.push_back({c.dir, c.idx});\n        for (int t = 0; t < c.len; ++t) outOps.push_back({revDir(c.dir), c.idx});\n    };\n\n    for (int id : forcedSel) emitCandidate(cands[id]);\n    for (int id : bestSel) emitCandidate(red[id]);\n\n    for (auto [d, p] : outOps) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T{};\nint avgT = 0;\nint bestTargetNode = 0;\n\nstruct XorShift64 {\n    uint64_t x;\n    explicit XorShift64(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        return (int)(next() % (uint64_t)mod);\n    }\n};\n\nstruct Plan {\n    array<array<int, 2>, MAXN> to;\n};\n\nstruct Eval {\n    Plan plan;\n    array<int, MAXN> cnt{};\n    array<array<int, 2>, MAXN> use{};\n    long long err = (1LL << 60);\n    int last = 0;\n};\n\nstatic inline long long llabsll(long long x) { return x < 0 ? -x : x; }\n\nvoid finalizePlan(Plan &p) {\n    for (int i = 0; i < N; ++i) {\n        if (p.to[i][0] == -1 && p.to[i][1] == -1) {\n            int d = (T[i] >= avgT ? i : bestTargetNode);\n            p.to[i][0] = p.to[i][1] = d;\n        } else if (p.to[i][0] == -1) {\n            p.to[i][0] = p.to[i][1];\n        } else if (p.to[i][1] == -1) {\n            p.to[i][1] = p.to[i][0];\n        }\n    }\n}\n\nint chooseDest(\n    int src,\n    const array<long long, MAXN> &rem,\n    int exclude,\n    long long selfBias,\n    long long samePenalty,\n    XorShift64 &rng\n) {\n    int best = 0;\n    long long bestSc = -(1LL << 60);\n\n    for (int j = 0; j < N; ++j) {\n        long long sc = 0;\n        sc += rem[j] * 200LL;\n        sc += 3LL * T[j];\n        sc -= 4LL * llabsll((long long)T[src] - (long long)T[j]);\n\n        if (j == src) {\n            long long selfAdj = ((long long)T[src] - (long long)avgT) * selfBias / max(1, avgT);\n            sc += selfAdj;\n        }\n\n        if (j == exclude) sc -= samePenalty;\n\n        sc += (long long)(rng.next() & 31ULL) - 15LL;\n\n        if (sc > bestSc) {\n            bestSc = sc;\n            best = j;\n        }\n    }\n    return best;\n}\n\nEval simulate(const Plan &p) {\n    Eval e;\n    e.plan = p;\n    e.cnt.fill(0);\n    for (int i = 0; i < N; ++i) e.use[i][0] = e.use[i][1] = 0;\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        e.cnt[x]++;\n        if (step == L - 1) {\n            e.last = x;\n            break;\n        }\n        int par = e.cnt[x] & 1; // 1 = odd visit -> a_i, 0 = even visit -> b_i\n        e.use[x][par]++;\n        x = p.to[x][par];\n    }\n\n    e.last = x;\n    long long err = 0;\n    for (int i = 0; i < N; ++i) err += llabsll((long long)e.cnt[i] - (long long)T[i]);\n    e.err = err;\n    return e;\n}\n\nPlan buildOnline(uint64_t seed, long long selfBias, long long samePenalty) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    XorShift64 rng(seed);\n    array<int, MAXN> cnt{};\n    cnt.fill(0);\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        cnt[x]++;\n        if (step == L - 1) break;\n\n        int par = cnt[x] & 1;\n        if (p.to[x][0] == -1 && p.to[x][1] == -1) {\n            array<long long, MAXN> rem{};\n            for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (long long)cnt[i];\n\n            int oddDest = chooseDest(x, rem, -1, selfBias, samePenalty, rng);\n            rem[oddDest] -= 1; // tiny bias for the second choice\n            int evenDest = chooseDest(x, rem, oddDest, selfBias, samePenalty, rng);\n\n            p.to[x][1] = oddDest;\n            p.to[x][0] = evenDest;\n        } else if (p.to[x][par] == -1) {\n            array<long long, MAXN> rem{};\n            for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (long long)cnt[i];\n            int other = p.to[x][1 - par];\n            p.to[x][par] = chooseDest(x, rem, other, selfBias, samePenalty, rng);\n        }\n\n        x = p.to[x][par];\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nPlan buildTransportFromSupply(const array<int, MAXN> &supply, int orderType, uint64_t seed, long long selfBias, long long samePenalty) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    XorShift64 rng(seed);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n\n    auto cmpDescSupply = [&](int a, int b) {\n        if (supply[a] != supply[b]) return supply[a] > supply[b];\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    };\n    auto cmpAscSupply = [&](int a, int b) {\n        if (supply[a] != supply[b]) return supply[a] < supply[b];\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    };\n    auto cmpDescT = [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        if (supply[a] != supply[b]) return supply[a] > supply[b];\n        return a < b;\n    };\n\n    if (orderType == 0) {\n        sort(ord.begin(), ord.end(), cmpDescSupply);\n    } else if (orderType == 1) {\n        sort(ord.begin(), ord.end(), cmpAscSupply);\n    } else {\n        // random order\n        for (int i = N - 1; i > 0; --i) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    array<long long, MAXN> rem{};\n    for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (i == 0 ? 1LL : 0LL);\n\n    for (int idx = 0; idx < N; ++idx) {\n        int i = ord[idx];\n        long long wOdd = (supply[i] + 1LL) / 2LL;\n        long long wEven = supply[i] / 2LL;\n\n        int dOdd = chooseDest(i, rem, -1, selfBias, samePenalty, rng);\n        rem[dOdd] -= wOdd;\n\n        int dEven = chooseDest(i, rem, dOdd, selfBias, samePenalty, rng);\n        rem[dEven] -= wEven;\n\n        p.to[i][1] = dOdd;\n        p.to[i][0] = dEven;\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nPlan buildTemplate(int type) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    });\n\n    int h1 = ord[0];\n    int h2 = ord[1];\n\n    for (int pos = 0; pos < N; ++pos) {\n        int i = ord[pos];\n        int nxt = ord[(pos + 1) % N];\n        int prv = ord[(pos + N - 1) % N];\n        int nxt2 = ord[(pos + 2) % N];\n\n        if (type == 0) {\n            if (T[i] >= avgT) {\n                p.to[i][1] = i;\n                p.to[i][0] = nxt;\n            } else {\n                p.to[i][1] = nxt;\n                p.to[i][0] = i;\n            }\n        } else if (type == 1) {\n            if (pos < 15) {\n                p.to[i][1] = i;\n                p.to[i][0] = i;\n            } else if (pos < 45) {\n                p.to[i][1] = i;\n                p.to[i][0] = nxt;\n            } else if (pos < 75) {\n                p.to[i][1] = nxt;\n                p.to[i][0] = i;\n            } else {\n                p.to[i][1] = nxt;\n                p.to[i][0] = nxt2;\n            }\n        } else if (type == 2) {\n            if (i == h1) {\n                p.to[i][1] = h1;\n                p.to[i][0] = h2;\n            } else if (T[i] >= avgT) {\n                p.to[i][1] = i;\n                p.to[i][0] = h1;\n            } else {\n                p.to[i][1] = h1;\n                p.to[i][0] = i;\n            }\n        } else {\n            p.to[i][1] = nxt;\n            p.to[i][0] = prv;\n        }\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nvoid buildCandidates(vector<Eval> &pool, uint64_t baseSeed) {\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    });\n\n    vector<int> ends;\n    for (int i = 0; i < N && (int)ends.size() < 4; ++i) {\n        if (T[ord[i]] > 0) ends.push_back(ord[i]);\n    }\n    if (T[0] > 0 && find(ends.begin(), ends.end(), 0) == ends.end()) ends.push_back(0);\n\n    int randomPositive = -1;\n    {\n        vector<int> pos;\n        for (int i = 0; i < N; ++i) if (T[i] > 0) pos.push_back(i);\n        if (!pos.empty()) {\n            XorShift64 rng(baseSeed ^ 0x123456789abcdefULL);\n            randomPositive = pos[rng.nextInt((int)pos.size())];\n            if (find(ends.begin(), ends.end(), randomPositive) == ends.end()) ends.push_back(randomPositive);\n        }\n    }\n    if ((int)ends.size() > 5) ends.resize(5);\n\n    long long onlineBiases[4] = {700, 1600, 3000, -800};\n    long long transportBiases[2] = {800, 2000};\n\n    int cid = 0;\n    for (int k = 0; k < 4; ++k) {\n        uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(cid + 1));\n        Plan p = buildOnline(seed, onlineBiases[k], 600);\n        pool.push_back(simulate(p));\n        ++cid;\n    }\n\n    for (int e : ends) {\n        array<int, MAXN> supply{};\n        for (int i = 0; i < N; ++i) supply[i] = T[i];\n        if (supply[e] <= 0) continue;\n        supply[e]--;\n\n        for (int ordType = 0; ordType < 3; ++ordType) {\n            for (int b = 0; b < 2; ++b) {\n                uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(cid + 1)) ^ (uint64_t)(e + 1000 * ordType + 17 * b);\n                Plan p = buildTransportFromSupply(supply, ordType, seed, transportBiases[b], 500);\n                pool.push_back(simulate(p));\n                ++cid;\n            }\n        }\n    }\n\n    for (int tp = 0; tp < 4; ++tp) {\n        Plan p = buildTemplate(tp);\n        pool.push_back(simulate(p));\n    }\n}\n\nEval refineByTransport(Eval cur, uint64_t seed) {\n    for (int iter = 0; iter < 2; ++iter) {\n        array<int, MAXN> supply = cur.cnt;\n        supply[cur.last]--;\n        if (supply[cur.last] < 0) supply[cur.last] = 0;\n\n        Plan p = buildTransportFromSupply(supply, 0, seed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(iter + 1)), 1600, 500);\n        Eval e = simulate(p);\n        if (e.err < cur.err) cur = std::move(e);\n        else break;\n    }\n    return cur;\n}\n\nEval localSearch(Eval cur, uint64_t seed, chrono::steady_clock::time_point start) {\n    XorShift64 rng(seed);\n\n    auto nowSeconds = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    for (int round = 0; round < 2; ++round) {\n        if (nowSeconds() > 1.93) break;\n        if (cur.err == 0) break;\n\n        vector<int> over, under;\n        over.reserve(N);\n        under.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            int d = cur.cnt[i] - T[i];\n            if (d > 0) over.push_back(i);\n            else if (d < 0) under.push_back(i);\n        }\n        if (over.empty() || under.empty()) break;\n\n        sort(over.begin(), over.end(), [&](int a, int b) {\n            return (cur.cnt[a] - T[a]) > (cur.cnt[b] - T[b]);\n        });\n        sort(under.begin(), under.end(), [&](int a, int b) {\n            return (T[a] - cur.cnt[a]) > (T[b] - cur.cnt[b]);\n        });\n\n        vector<int> overTop, underTop;\n        for (int i = 0; i < (int)min<size_t>(4, over.size()); ++i) overTop.push_back(over[i]);\n        for (int i = 0; i < (int)min<size_t>(3, under.size()); ++i) underTop.push_back(under[i]);\n\n        struct Slot {\n            int src, p, dest, use;\n        };\n\n        vector<Slot> slots;\n        for (int o : overTop) {\n            for (int i = 0; i < N; ++i) {\n                for (int p = 0; p < 2; ++p) {\n                    if (cur.plan.to[i][p] == o && cur.use[i][p] > 0) {\n                        slots.push_back({i, p, o, cur.use[i][p]});\n                    }\n                }\n            }\n        }\n\n        sort(slots.begin(), slots.end(), [&](const Slot &a, const Slot &b) {\n            return a.use > b.use;\n        });\n\n        long long bestErr = cur.err;\n        Eval bestCand = cur;\n        bool improved = false;\n\n        auto testPlan = [&](const Plan &pp) {\n            if (nowSeconds() > 1.93) return;\n            Eval e = simulate(pp);\n            if (e.err < bestErr) {\n                bestErr = e.err;\n                bestCand = std::move(e);\n                improved = true;\n            }\n        };\n\n        // 1) Change heavily used slots that currently point to overcounted nodes.\n        int slotLimit = min<int>(12, slots.size());\n        for (int i = 0; i < slotLimit; ++i) {\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[slots[i].src][slots[i].p] == u) continue;\n                Plan np = cur.plan;\n                np.to[slots[i].src][slots[i].p] = u;\n                testPlan(np);\n            }\n        }\n\n        // 2) Change one parity edge of overcounted source nodes.\n        for (int s = 0; s < (int)overTop.size(); ++s) {\n            int src = overTop[s];\n            int p = (cur.use[src][0] >= cur.use[src][1] ? 0 : 1);\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[src][p] == u) continue;\n                Plan np = cur.plan;\n                np.to[src][p] = u;\n                testPlan(np);\n            }\n        }\n\n        // 3) Change both edges of a strongly overcounted source to a better undercounted target.\n        for (int s = 0; s < (int)min<size_t>(3, overTop.size()); ++s) {\n            int src = overTop[s];\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[src][0] == u && cur.plan.to[src][1] == u) continue;\n                Plan np = cur.plan;\n                np.to[src][0] = np.to[src][1] = u;\n                testPlan(np);\n            }\n        }\n\n        if (improved) cur = std::move(bestCand);\n        else break;\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    avgT = L / N;\n    bestTargetNode = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[bestTargetNode]) bestTargetNode = i;\n    }\n\n    uint64_t baseSeed = 1469598103934665603ULL;\n    for (int i = 0; i < N; ++i) {\n        baseSeed ^= (uint64_t)(T[i] + 1);\n        baseSeed *= 1099511628211ULL;\n    }\n\n    auto start = chrono::steady_clock::now();\n\n    vector<Eval> pool;\n    pool.reserve(64);\n\n    buildCandidates(pool, baseSeed);\n\n    if (pool.empty()) {\n        Plan p;\n        for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = bestTargetNode;\n        auto e = simulate(p);\n        pool.push_back(std::move(e));\n    }\n\n    sort(pool.begin(), pool.end(), [&](const Eval &a, const Eval &b) {\n        return a.err < b.err;\n    });\n\n    int topK = min<int>(3, pool.size());\n    Eval best = pool[0];\n\n    for (int i = 0; i < topK; ++i) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > 1.90) break;\n\n        Eval cur = pool[i];\n        cur = refineByTransport(cur, baseSeed ^ (0xabcdef0123456789ULL + (uint64_t)i * 1337ULL));\n        cur = localSearch(cur, baseSeed ^ (0x123456789abcdef0ULL + (uint64_t)i * 10007ULL), start);\n\n        if (cur.err < best.err) best = std::move(cur);\n    }\n\n    // Final safety fill.\n    finalizePlan(best.plan);\n\n    for (int i = 0; i < N; ++i) {\n        cout << best.plan.to[i][1] << ' ' << best.plan.to[i][0] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ull = unsigned long long;\n\nstatic const ll INFLL = (1LL << 62);\nstatic const int MAXN = 800;\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<int> exs, eys;\nvector<vector<ll>> dist2Mat;\nvector<double> densityScore;\nvector<int> densityOrder;\n\nint queries_used = 0;\n\nstruct BuiltGroup {\n    vector<int> cities;\n    vector<pair<int,int>> edges;\n};\n\null hilbertOrder(int x, int y) {\n    ull d = 0;\n    for (int s = 1 << 14; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += (ull)s * (ull)s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = s * 2 - 1 - x;\n                y = s * 2 - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\ninline ll d2(int a, int b) {\n    return dist2Mat[a][b];\n}\n\nstruct PrimRes {\n    vector<int> parent;\n    vector<ll> best;\n};\n\nPrimRes primParents(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    PrimRes res;\n    res.parent.assign(k, -1);\n    res.best.assign(k, INFLL);\n    if (k == 0) return res;\n    vector<char> used(k, 0);\n    res.best[0] = 0;\n\n    for (int it = 0; it < k; ++it) {\n        int v = -1;\n        for (int i = 0; i < k; ++i) {\n            if (!used[i] && (v == -1 || res.best[i] < res.best[v])) v = i;\n        }\n        used[v] = 1;\n        int a = nodes[v];\n        for (int to = 0; to < k; ++to) if (!used[to]) {\n            ll w = d2(a, nodes[to]);\n            if (w < res.best[to]) {\n                res.best[to] = w;\n                res.parent[to] = v;\n            }\n        }\n    }\n    return res;\n}\n\ndouble mstCostVec(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    if (k <= 1) return 0.0;\n    auto res = primParents(nodes);\n    double cost = 0.0;\n    for (int i = 1; i < k; ++i) cost += sqrt((double)res.best[i]);\n    return cost;\n}\n\nvector<pair<int,int>> primTree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    vector<pair<int,int>> edges;\n    if (k <= 1) return edges;\n    auto res = primParents(nodes);\n    edges.reserve(k - 1);\n    for (int i = 1; i < k; ++i) {\n        int a = nodes[i], b = nodes[res.parent[i]];\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nvector<pair<int,int>> queryTree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    cout << \"? \" << k;\n    for (int v : nodes) cout << ' ' << v;\n    cout << '\\n' << flush;\n\n    ++queries_used;\n    vector<pair<int,int>> edges;\n    edges.reserve(k - 1);\n    for (int i = 0; i < k - 1; ++i) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nvector<int> buildMSTPreorder(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    if (k <= 2) return nodes;\n\n    auto res = primParents(nodes);\n    vector<vector<pair<ll,int>>> adj(k);\n    for (int i = 1; i < k; ++i) {\n        int p = res.parent[i];\n        ll w = res.best[i];\n        adj[i].push_back({w, p});\n        adj[p].push_back({w, i});\n    }\n\n    int root = 0;\n    ll bestSum = INFLL;\n    for (int i = 0; i < k; ++i) {\n        ll sum = 0;\n        for (int j = 0; j < k; ++j) if (i != j) sum += d2(nodes[i], nodes[j]);\n        if (sum < bestSum || (sum == bestSum && nodes[i] < nodes[root])) {\n            bestSum = sum;\n            root = i;\n        }\n    }\n\n    for (int i = 0; i < k; ++i) {\n        sort(adj[i].begin(), adj[i].end());\n    }\n\n    vector<int> order;\n    order.reserve(k);\n    vector<int> par(k, -1);\n    vector<int> st;\n    st.push_back(root);\n    par[root] = root;\n\n    while (!st.empty()) {\n        int v = st.back();\n        st.pop_back();\n        order.push_back(nodes[v]);\n        for (int i = (int)adj[v].size() - 1; i >= 0; --i) {\n            int to = adj[v][i].second;\n            if (to == par[v]) continue;\n            par[to] = v;\n            st.push_back(to);\n        }\n    }\n    return order;\n}\n\nvector<vector<int>> splitChunks(const vector<int>& ord) {\n    int n = (int)ord.size();\n    vector<vector<int>> chunks;\n    if (n <= L) {\n        chunks.push_back(ord);\n        return chunks;\n    }\n\n    int p = 0, rem = n;\n    while (rem > 0) {\n        int take = min(L, rem);\n        if (rem > L && rem - take == 1) take--;\n        chunks.emplace_back(ord.begin() + p, ord.begin() + p + take);\n        p += take;\n        rem -= take;\n    }\n    return chunks;\n}\n\nvector<vector<ll>> computeChunkWeights(\n    const vector<vector<int>>& chunks,\n    vector<vector<pair<int,int>>>* bestPair = nullptr\n) {\n    int c = (int)chunks.size();\n    vector<vector<ll>> w(c, vector<ll>(c, INFLL));\n    if (bestPair) bestPair->assign(c, vector<pair<int,int>>(c, {INT_MAX, INT_MAX}));\n\n    for (int i = 0; i < c; ++i) {\n        for (int j = i + 1; j < c; ++j) {\n            ll bestW = INFLL;\n            pair<int,int> bestP = {INT_MAX, INT_MAX};\n            for (int a : chunks[i]) {\n                for (int b : chunks[j]) {\n                    ll d = d2(a, b);\n                    pair<int,int> p = (a < b ? make_pair(a, b) : make_pair(b, a));\n                    if (d < bestW || (d == bestW && p < bestP)) {\n                        bestW = d;\n                        bestP = p;\n                    }\n                }\n            }\n            w[i][j] = w[j][i] = bestW;\n            if (bestPair) {\n                (*bestPair)[i][j] = (*bestPair)[j][i] = bestP;\n            }\n        }\n    }\n    return w;\n}\n\ndouble estimateOrderCost(const vector<int>& ord) {\n    int n = (int)ord.size();\n    if (n <= 1) return 0.0;\n    if (n <= L) return mstCostVec(ord);\n\n    auto chunks = splitChunks(ord);\n    double cost = 0.0;\n    for (auto& ch : chunks) cost += mstCostVec(ch);\n\n    auto w = computeChunkWeights(chunks, nullptr);\n    int c = (int)chunks.size();\n    vector<ll> best(c, INFLL);\n    vector<char> used(c, 0);\n    best[0] = 0;\n\n    for (int it = 0; it < c; ++it) {\n        int v = -1;\n        for (int i = 0; i < c; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (best[v] != 0) cost += sqrt((double)best[v]);\n        for (int to = 0; to < c; ++to) if (!used[to]) {\n            if (w[v][to] < best[to]) best[to] = w[v][to];\n        }\n    }\n    return cost;\n}\n\nvector<pair<int,int>> buildChunkMSTEdges(const vector<vector<int>>& chunks) {\n    vector<pair<int,int>> edges;\n    int c = (int)chunks.size();\n    if (c <= 1) return edges;\n\n    vector<vector<pair<int,int>>> bestPair;\n    auto w = computeChunkWeights(chunks, &bestPair);\n\n    vector<ll> best(c, INFLL);\n    vector<int> parent(c, -1);\n    vector<char> used(c, 0);\n    best[0] = 0;\n\n    for (int it = 0; it < c; ++it) {\n        int v = -1;\n        for (int i = 0; i < c; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (parent[v] != -1) edges.push_back(bestPair[v][parent[v]]);\n        for (int to = 0; to < c; ++to) if (!used[to]) {\n            if (w[v][to] < best[to]) {\n                best[to] = w[v][to];\n                parent[to] = v;\n            }\n        }\n    }\n    return edges;\n}\n\nvector<int> growCluster(int seed, int targetSize, const vector<char>& used) {\n    vector<int> cluster;\n    cluster.reserve(targetSize);\n    vector<char> inCluster(N, 0);\n    vector<ll> mind(N, INFLL);\n\n    cluster.push_back(seed);\n    inCluster[seed] = 1;\n    for (int i = 0; i < N; ++i) {\n        if (!used[i] && !inCluster[i]) mind[i] = d2(seed, i);\n    }\n\n    while ((int)cluster.size() < targetSize) {\n        int best = -1;\n        for (int i = 0; i < N; ++i) {\n            if (used[i] || inCluster[i]) continue;\n            if (best == -1 ||\n                mind[i] < mind[best] ||\n                (mind[i] == mind[best] && densityScore[i] < densityScore[best]) ||\n                (mind[i] == mind[best] && densityScore[i] == densityScore[best] && i < best)) {\n                best = i;\n            }\n        }\n        if (best == -1) break;\n        cluster.push_back(best);\n        inCluster[best] = 1;\n        for (int i = 0; i < N; ++i) {\n            if (used[i] || inCluster[i]) continue;\n            ll w = d2(best, i);\n            if (w < mind[i]) mind[i] = w;\n        }\n    }\n    return cluster;\n}\n\nvector<vector<int>> buildDensityGreedyPartition() {\n    vector<vector<int>> groups(M);\n    vector<char> used(N, 0);\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n\n    for (int gi : order) {\n        int s = G[gi];\n\n        if (s == 1) {\n            int seed = -1;\n            for (int v : densityOrder) if (!used[v]) { seed = v; break; }\n            if (seed == -1) seed = 0;\n            used[seed] = 1;\n            groups[gi] = {seed};\n            continue;\n        }\n\n        vector<int> seeds;\n        int seedLimit = min(5, s);\n        for (int v : densityOrder) {\n            if (!used[v]) {\n                seeds.push_back(v);\n                if ((int)seeds.size() >= seedLimit) break;\n            }\n        }\n        if (seeds.empty()) {\n            for (int i = 0; i < N; ++i) if (!used[i]) { seeds.push_back(i); break; }\n        }\n\n        double bestScore = 1e100;\n        vector<int> bestCluster;\n        for (int seed : seeds) {\n            auto cluster = growCluster(seed, s, used);\n            if ((int)cluster.size() != s) continue;\n            double score = mstCostVec(cluster);\n            if (score < bestScore) {\n                bestScore = score;\n                bestCluster = move(cluster);\n            }\n        }\n\n        if ((int)bestCluster.size() != s) {\n            // Fallback: just take the first s unused cities.\n            bestCluster.clear();\n            for (int v : densityOrder) {\n                if (!used[v]) {\n                    bestCluster.push_back(v);\n                    if ((int)bestCluster.size() == s) break;\n                }\n            }\n        }\n\n        for (int v : bestCluster) used[v] = 1;\n        groups[gi] = move(bestCluster);\n    }\n\n    return groups;\n}\n\nvector<vector<int>> buildContiguousPartition(const vector<int>& cityOrder, const vector<int>& groupOrder) {\n    vector<vector<int>> groups(M);\n    int p = 0;\n    for (int gi : groupOrder) {\n        groups[gi].assign(cityOrder.begin() + p, cityOrder.begin() + p + G[gi]);\n        p += G[gi];\n    }\n    return groups;\n}\n\nbool validatePartition(const vector<vector<int>>& groups) {\n    if ((int)groups.size() != M) return false;\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < M; ++i) {\n        if ((int)groups[i].size() != G[i]) return false;\n        for (int v : groups[i]) {\n            if (v < 0 || v >= N) return false;\n            if (++cnt[v] != 1) return false;\n        }\n    }\n    for (int v = 0; v < N; ++v) if (cnt[v] != 1) return false;\n    return true;\n}\n\ndouble evalPartition(const vector<vector<int>>& groups) {\n    double cost = 0.0;\n    for (const auto& g : groups) cost += mstCostVec(g);\n    return cost;\n}\n\nvector<int> chooseBestLocalOrder(const vector<int>& group) {\n    int k = (int)group.size();\n    if (k <= 1) return group;\n    if (k <= L) return group;\n\n    vector<vector<int>> cands;\n\n    auto add = [&](vector<int> v) {\n        cands.push_back(move(v));\n    };\n\n    add(group);\n    {\n        vector<int> v = group;\n        reverse(v.begin(), v.end());\n        add(move(v));\n    }\n\n    auto addSort = [&](auto cmp) {\n        vector<int> v = group;\n        sort(v.begin(), v.end(), cmp);\n        add(move(v));\n    };\n\n    addSort([&](int a, int b) {\n        if (exs[a] != exs[b]) return exs[a] < exs[b];\n        if (eys[a] != eys[b]) return eys[a] < eys[b];\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        if (eys[a] != eys[b]) return eys[a] < eys[b];\n        if (exs[a] != exs[b]) return exs[a] < exs[b];\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        ll sa = (ll)exs[a] + eys[a];\n        ll sb = (ll)exs[b] + eys[b];\n        if (sa != sb) return sa < sb;\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        ll da = (ll)exs[a] - eys[a];\n        ll db = (ll)exs[b] - eys[b];\n        if (da != db) return da < db;\n        return a < b;\n    });\n\n    for (int o = 0; o < 8; ++o) {\n        addSort([&](int a, int b) {\n            ull ka, kb;\n            {\n                int x = exs[a], y = eys[a];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                ka = hilbertOrder(x, y);\n            }\n            {\n                int x = exs[b], y = eys[b];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                kb = hilbertOrder(x, y);\n            }\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n    }\n\n    {\n        vector<int> v = buildMSTPreorder(group);\n        add(move(v));\n        vector<int> w = cands.back();\n        reverse(w.begin(), w.end());\n        add(move(w));\n    }\n\n    double best = 1e100;\n    vector<int> bestOrd = group;\n    for (auto& cand : cands) {\n        double sc = estimateOrderCost(cand);\n        if (sc < best) {\n            best = sc;\n            bestOrd = cand;\n        }\n    }\n    return bestOrd;\n}\n\nBuiltGroup buildGroupTree(const vector<int>& group) {\n    BuiltGroup res;\n    int k = (int)group.size();\n    if (k == 0) return res;\n\n    res.cities = chooseBestLocalOrder(group);\n\n    if (k == 1) return res;\n\n    if (k == 2) {\n        int a = res.cities[0], b = res.cities[1];\n        if (a > b) swap(a, b);\n        res.edges.push_back({a, b});\n        return res;\n    }\n\n    if (k <= L) {\n        if (queries_used < Q) res.edges = queryTree(res.cities);\n        else res.edges = primTree(res.cities);\n        if ((int)res.edges.size() != k - 1) res.edges = primTree(res.cities);\n        return res;\n    }\n\n    auto chunks = splitChunks(res.cities);\n\n    for (auto& ch : chunks) {\n        int s = (int)ch.size();\n        if (s == 1) continue;\n        if (s == 2) {\n            int a = ch[0], b = ch[1];\n            if (a > b) swap(a, b);\n            res.edges.push_back({a, b});\n        } else {\n            vector<pair<int,int>> got;\n            if (queries_used < Q) got = queryTree(ch);\n            else got = primTree(ch);\n            if ((int)got.size() != s - 1) got = primTree(ch);\n            res.edges.insert(res.edges.end(), got.begin(), got.end());\n        }\n    }\n\n    if (chunks.size() > 1) {\n        auto cross = buildChunkMSTEdges(chunks);\n        res.edges.insert(res.edges.end(), cross.begin(), cross.end());\n    }\n\n    if ((int)res.edges.size() != k - 1) {\n        res.edges = primTree(res.cities);\n    }\n\n    return res;\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    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    exs.resize(N);\n    eys.resize(N);\n    for (int i = 0; i < N; ++i) {\n        exs[i] = lx[i] + rx[i];\n        eys[i] = ly[i] + ry[i];\n    }\n\n    dist2Mat.assign(N, vector<ll>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i; j < N; ++j) {\n            ll dx = (ll)exs[i] - exs[j];\n            ll dy = (ll)eys[i] - eys[j];\n            ll d = dx * dx + dy * dy;\n            dist2Mat[i][j] = dist2Mat[j][i] = d;\n        }\n    }\n\n    // Density score: sum of the nearest few estimated distances.\n    int K = min(12, N - 1);\n    densityScore.assign(N, 0.0);\n    for (int i = 0; i < N; ++i) {\n        vector<ll> ds;\n        ds.reserve(N - 1);\n        for (int j = 0; j < N; ++j) if (i != j) ds.push_back(dist2Mat[i][j]);\n        nth_element(ds.begin(), ds.begin() + K, ds.end());\n        double s = 0.0;\n        for (int t = 0; t < K; ++t) s += sqrt((double)ds[t]);\n        densityScore[i] = s;\n    }\n\n    densityOrder.resize(N);\n    iota(densityOrder.begin(), densityOrder.end(), 0);\n    sort(densityOrder.begin(), densityOrder.end(), [&](int a, int b) {\n        if (densityScore[a] != densityScore[b]) return densityScore[a] < densityScore[b];\n        return a < b;\n    });\n\n    // Build candidate city orders.\n    vector<vector<int>> cityOrders;\n\n    auto addOrder = [&](vector<int> ord) {\n        cityOrders.push_back(move(ord));\n    };\n\n    auto makeSorted = [&](auto cmp) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), cmp);\n        return ord;\n    };\n\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            if (eys[a] != eys[b]) return eys[a] < eys[b];\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            if (eys[a] != eys[b]) return eys[a] < eys[b];\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            ll sa = (ll)exs[a] + eys[a];\n            ll sb = (ll)exs[b] + eys[b];\n            if (sa != sb) return sa < sb;\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            ll da = (ll)exs[a] - eys[a];\n            ll db = (ll)exs[b] - eys[b];\n            if (da != db) return da < db;\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        addOrder(densityOrder);\n        auto r = densityOrder;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        vector<int> all(N);\n        iota(all.begin(), all.end(), 0);\n        auto ord = buildMSTPreorder(all);\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    for (int o = 0; o < 8; ++o) {\n        auto ord = makeSorted([&](int a, int b) {\n            ull ka, kb;\n            {\n                int x = exs[a], y = eys[a];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                ka = hilbertOrder(x, y);\n            }\n            {\n                int x = exs[b], y = eys[b];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                kb = hilbertOrder(x, y);\n            }\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n        addOrder(ord);\n    }\n\n    vector<int> groupOrderOrig(M), groupOrderAsc(M), groupOrderDesc(M);\n    iota(groupOrderOrig.begin(), groupOrderOrig.end(), 0);\n    groupOrderAsc = groupOrderOrig;\n    groupOrderDesc = groupOrderOrig;\n    sort(groupOrderAsc.begin(), groupOrderAsc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n    sort(groupOrderDesc.begin(), groupOrderDesc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n\n    vector<vector<int>> groupOrders = {\n        groupOrderOrig, groupOrderAsc, groupOrderDesc\n    };\n\n    // Candidate partitions.\n    vector<vector<int>> fallback = buildContiguousPartition(cityOrders[0], groupOrders[0]);\n    vector<vector<int>> bestGroups = fallback;\n    double bestEval = evalPartition(bestGroups);\n\n    for (const auto& ord : cityOrders) {\n        for (const auto& gOrd : groupOrders) {\n            auto groups = buildContiguousPartition(ord, gOrd);\n            if (!validatePartition(groups)) continue;\n            double val = evalPartition(groups);\n            if (val < bestEval) {\n                bestEval = val;\n                bestGroups = move(groups);\n            }\n        }\n    }\n\n    auto dens = buildDensityGreedyPartition();\n    if (validatePartition(dens)) {\n        double val = evalPartition(dens);\n        if (val < bestEval) {\n            bestEval = val;\n            bestGroups = move(dens);\n        }\n    }\n\n    if (!validatePartition(bestGroups)) {\n        bestGroups = fallback;\n    }\n\n    // Build trees for each group.\n    vector<BuiltGroup> built(M);\n    for (int i = 0; i < M; ++i) {\n        built[i] = buildGroupTree(bestGroups[i]);\n        if ((int)built[i].edges.size() != G[i] - 1) {\n            built[i].cities = bestGroups[i];\n            built[i].edges = primTree(bestGroups[i]);\n        }\n    }\n\n    // Final sanity check before output.\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < M; ++i) {\n        if ((int)built[i].cities.size() != G[i]) {\n            built = {};\n            break;\n        }\n        for (int v : built[i].cities) {\n            if (v < 0 || v >= N) {\n                built = {};\n                break;\n            }\n            cnt[v]++;\n        }\n        if (built.empty()) break;\n    }\n    bool ok = !built.empty();\n    if (ok) {\n        for (int v = 0; v < N; ++v) if (cnt[v] != 1) ok = false;\n    }\n    if (!ok) {\n        bestGroups = fallback;\n        built.assign(M, {});\n        for (int i = 0; i < M; ++i) {\n            built[i] = buildGroupTree(bestGroups[i]);\n            if ((int)built[i].edges.size() != G[i] - 1) {\n                built[i].cities = bestGroups[i];\n                built[i].edges = primTree(bestGroups[i]);\n            }\n        }\n    }\n\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < (int)built[i].cities.size(); ++j) {\n            if (j) cout << ' ';\n            cout << built[i].cities[j];\n        }\n        cout << '\\n';\n        for (auto [a, b] : built[i].edges) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 20;\nstatic constexpr int MAXV = MAXN * MAXN;\nstatic constexpr double UTIL_WEIGHT = 0.7;\n\nstruct BFSState {\n    array<int, MAXV> dist;\n    array<int, MAXV> pre;\n    array<char, MAXV> pact;\n    array<char, MAXV> pdir;\n};\n\nstruct Board {\n    int N;\n    array<array<int, MAXN>, MAXN> b{};\n};\n\nint N, M;\nvector<pair<int,int>> pts;\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\ninline bool inside(int r, int c) {\n    return 0 <= r && r < N && 0 <= c && c < N;\n}\n\nint slide_dest(const Board& bd, int r, int c, int d) {\n    while (true) {\n        int nr = r + dr[d], nc = c + dc[d];\n        if (!inside(nr, nc) || bd.b[nr][nc]) break;\n        r = nr;\n        c = nc;\n    }\n    return r * N + c;\n}\n\nBFSState bfs_all(const Board& bd, int s) {\n    BFSState st;\n    st.dist.fill(-1);\n    st.pre.fill(-1);\n    st.pact.fill(0);\n    st.pdir.fill(0);\n\n    queue<int> q;\n    st.dist[s] = 0;\n    st.pre[s] = -2;\n    q.push(s);\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        int r = u / N, c = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move\n            {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (inside(nr, nc) && !bd.b[nr][nc]) {\n                    int v = nr * N + nc;\n                    if (st.dist[v] == -1) {\n                        st.dist[v] = st.dist[u] + 1;\n                        st.pre[v] = u;\n                        st.pact[v] = 'M';\n                        st.pdir[v] = dch[d];\n                        q.push(v);\n                    }\n                }\n            }\n            // Slide\n            {\n                int v = slide_dest(bd, r, c, d);\n                if (v != u && st.dist[v] == -1) {\n                    st.dist[v] = st.dist[u] + 1;\n                    st.pre[v] = u;\n                    st.pact[v] = 'S';\n                    st.pdir[v] = dch[d];\n                    q.push(v);\n                }\n            }\n        }\n    }\n    return st;\n}\n\nvector<pair<char,char>> reconstruct_path(const BFSState& st, int s, int t) {\n    vector<pair<char,char>> path;\n    if (st.dist[t] == -1) return path;\n    for (int v = t; v != s; v = st.pre[v]) {\n        path.push_back({st.pact[v], st.pdir[v]});\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct Candidate {\n    double score = 1e100;\n    int pathLen = INT_MAX;\n    int cost = INT_MAX;\n    double util = -1e100;\n    vector<pair<int,int>> blocks;\n    vector<pair<char,char>> path;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    pts.resize(M);\n    for (int i = 0; i < M; ++i) cin >> pts[i].first >> pts[i].second;\n\n    Board bd;\n    bd.N = N;\n\n    int cur = pts[0].first * N + pts[0].second;\n\n    for (int k = 0; k < M - 1; ++k) {\n        int r = pts[k].first, c = pts[k].second;\n        int nxt = pts[k + 1].first * N + pts[k + 1].second;\n\n        // Compute lookahead utility for each possible new wall direction.\n        // Future targets are k+2 ... M-1.\n        double sideUtil[4] = {0, 0, 0, 0};\n\n        for (int j = k + 2; j < M; ++j) {\n            int tr = pts[j].first, tc = pts[j].second;\n            if (tr == r) {\n                if (tc < c) {\n                    // Right wall helps future targets on the left.\n                    sideUtil[3] += 1.0 + (N - 1 - c) / 10.0;\n                } else if (tc > c) {\n                    // Left wall helps future targets on the right.\n                    sideUtil[2] += 1.0 + c / 10.0;\n                }\n            }\n            if (tc == c) {\n                if (tr < r) {\n                    // Down wall helps future targets above.\n                    sideUtil[1] += 1.0 + (N - 1 - r) / 10.0;\n                } else if (tr > r) {\n                    // Up wall helps future targets below.\n                    sideUtil[0] += 1.0 + r / 10.0;\n                }\n            }\n        }\n\n        vector<int> candDirs;\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && bd.b[nr][nc] == 0) candDirs.push_back(d);\n        }\n\n        Candidate best;\n\n        int m = (int)candDirs.size();\n        for (int mask = 0; mask < (1 << m); ++mask) {\n            Board temp = bd;\n            vector<pair<int,int>> addBlocks;\n            addBlocks.reserve(4);\n\n            int cost = 0;\n            double util = 0.0;\n            bool ok = true;\n\n            for (int i = 0; i < m; ++i) {\n                if ((mask >> i) & 1) {\n                    int d = candDirs[i];\n                    int nr = r + dr[d], nc = c + dc[d];\n                    temp.b[nr][nc] = 1;\n                    addBlocks.push_back({nr, nc});\n                    ++cost;\n                    util += sideUtil[d];\n                }\n            }\n\n            // Exact reachability check on the modified board.\n            BFSState st = bfs_all(temp, cur);\n            if (st.dist[nxt] == -1) continue;\n\n            bool reachableAll = true;\n            for (int j = k + 1; j < M; ++j) {\n                int id = pts[j].first * N + pts[j].second;\n                if (st.dist[id] == -1) {\n                    reachableAll = false;\n                    break;\n                }\n            }\n            if (!reachableAll) continue;\n\n            vector<pair<char,char>> path = reconstruct_path(st, cur, nxt);\n            if (path.empty() && cur != nxt) continue;\n\n            int L = (int)path.size();\n            double score = (double)L + cost - UTIL_WEIGHT * util;\n\n            if (score + 1e-12 < best.score ||\n                (abs(score - best.score) <= 1e-12 &&\n                 (L < best.pathLen ||\n                  (L == best.pathLen && cost < best.cost)))) {\n                best.score = score;\n                best.pathLen = L;\n                best.cost = cost;\n                best.util = util;\n                best.blocks = std::move(addBlocks);\n                best.path = std::move(path);\n            }\n        }\n\n        if (best.blocks.empty() && best.path.empty()) {\n            // Extremely safe fallback: no new blocks, recompute on current board.\n            BFSState st = bfs_all(bd, cur);\n            best.path = reconstruct_path(st, cur, nxt);\n            best.blocks.clear();\n        }\n\n        // Apply chosen blocks.\n        for (auto [br, bc] : best.blocks) {\n            bd.b[br][bc] = 1;\n            cout << 'A' << ' ' << dch[(br == r - 1 ? 0 : br == r + 1 ? 1 : bc == c - 1 ? 2 : 3)] << '\\n';\n        }\n\n        // Emit the movement path.\n        for (auto [a, d] : best.path) {\n            cout << a << ' ' << d << '\\n';\n        }\n\n        cur = nxt;\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int B = 10000;\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstruct Node {\n    int left = -1, right = -1;\n    int orient = 0;   // 0: vertical, 1: horizontal\n    int cut = 0;\n    int id = -1;      // leaf company id\n    long long sumR = 0;\n    int minx = 0, maxx = 0, miny = 0, maxy = 0;\n    int cnt = 0;\n};\n\nstruct Tree {\n    vector<Node> nodes;\n    int root = -1;\n};\n\nstruct BuildCand {\n    int orient = 0;\n    int cut = 0;\n    double score = -1e100;\n    int span = 0;\n};\n\nstruct Config {\n    int lookDepth = 2;\n    array<int, 3> branchK{1, 1, 1};\n    int radius = 4;\n    double needWeight = 0.12;\n    bool randomize = false;\n    double noise = 0.0;\n    int branchMinSize = 6;\n};\n\nstruct AttemptResult {\n    double score = -1e100;\n    vector<Rect> rects;\n};\n\nclass Solver {\npublic:\n    int n;\n    vector<int> xs, ys;\n    vector<long long> rs;\n    mt19937_64 rng;\n    chrono::steady_clock::time_point startTime;\n    bool aborted = false;\n\n    Solver(int n_, vector<int> x, vector<int> y, vector<long long> r)\n        : n(n_), xs(std::move(x)), ys(std::move(y)), rs(std::move(r)) {}\n\n    void seed(uint64_t s) { rng.seed(s); }\n    void setStart() { startTime = chrono::steady_clock::now(); }\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    }\n\n    double rnd01() {\n        return (double)(rng() >> 11) * (1.0 / (1ULL << 53));\n    }\n\n    static inline int clampInt(int v, int lo, int hi) {\n        return max(lo, min(hi, v));\n    }\n\n    static inline double satScore(long long area, long long target) {\n        long long mn = min(area, target), mx = max(area, target);\n        double t = (double)mn / (double)mx;\n        return 1.0 - (1.0 - t) * (1.0 - t);\n    }\n\n    bool validateRects(const vector<Rect>& rects) const {\n        for (int i = 0; i < n; ++i) {\n            const Rect& r = rects[i];\n            if (!(0 <= r.x1 && r.x1 < r.x2 && r.x2 <= B &&\n                  0 <= r.y1 && r.y1 < r.y2 && r.y2 <= B)) return false;\n            if (!(r.x1 <= xs[i] && xs[i] + 1 <= r.x2 &&\n                  r.y1 <= ys[i] && ys[i] + 1 <= r.y2)) return false;\n        }\n        return true;\n    }\n\n    double scoreRects(const vector<Rect>& rects) const {\n        double sum = 0.0;\n        for (int i = 0; i < n; ++i) {\n            long long area = 1LL * (rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1);\n            sum += satScore(area, rs[i]);\n        }\n        return sum;\n    }\n\n    double scoreSubtree(const Tree& tr, int v, const Rect& box) const {\n        const Node& nd = tr.nodes[v];\n        if (nd.id != -1) {\n            long long area = 1LL * (box.x2 - box.x1) * (box.y2 - box.y1);\n            return satScore(area, rs[nd.id]);\n        }\n        if (nd.orient == 0) {\n            Rect L{box.x1, box.y1, nd.cut, box.y2};\n            Rect R{nd.cut, box.y1, box.x2, box.y2};\n            return scoreSubtree(tr, nd.left, L) + scoreSubtree(tr, nd.right, R);\n        } else {\n            Rect L{box.x1, box.y1, box.x2, nd.cut};\n            Rect R{box.x1, nd.cut, box.x2, box.y2};\n            return scoreSubtree(tr, nd.left, L) + scoreSubtree(tr, nd.right, R);\n        }\n    }\n\n    void materialize(const Tree& tr, int v, const Rect& box, vector<Rect>& out) const {\n        const Node& nd = tr.nodes[v];\n        if (nd.id != -1) {\n            out[nd.id] = box;\n            return;\n        }\n        if (nd.orient == 0) {\n            materialize(tr, nd.left,  Rect{box.x1, box.y1, nd.cut, box.y2}, out);\n            materialize(tr, nd.right, Rect{nd.cut, box.y1, box.x2, box.y2}, out);\n        } else {\n            materialize(tr, nd.left,  Rect{box.x1, box.y1, box.x2, nd.cut}, out);\n            materialize(tr, nd.right, Rect{box.x1, nd.cut, box.x2, box.y2}, out);\n        }\n    }\n\n    bool splitMedian(const vector<int>& ids, const Rect& box, bool vertical,\n                     vector<int>& L, vector<int>& R, Rect& boxL, Rect& boxR) {\n        vector<int> ord = ids;\n        if (vertical) {\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                return a < b;\n            });\n        } else {\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                return a < b;\n            });\n        }\n\n        auto coord = [&](int id) { return vertical ? xs[id] : ys[id]; };\n\n        int m = (int)ord.size();\n        int mid = m / 2 - 1;\n        if (mid < 0) mid = 0;\n        while (mid + 1 < m && coord(ord[mid]) == coord(ord[mid + 1])) ++mid;\n        if (mid + 1 >= m) mid = m / 2 - 1;\n        if (mid < 0) mid = 0;\n\n        int cut = coord(ord[mid]) + 1;\n        int lo = vertical ? box.x1 + 1 : box.y1 + 1;\n        int hi = vertical ? box.x2 - 1 : box.y2 - 1;\n        if (lo > hi) return false;\n        cut = clampInt(cut, lo, hi);\n\n        L.clear(); R.clear();\n        L.reserve(ids.size());\n        R.reserve(ids.size());\n\n        if (vertical) {\n            for (int id : ids) (xs[id] < cut ? L : R).push_back(id);\n            if (L.empty() || R.empty()) return false;\n            boxL = {box.x1, box.y1, cut, box.y2};\n            boxR = {cut, box.y1, box.x2, box.y2};\n        } else {\n            for (int id : ids) (ys[id] < cut ? L : R).push_back(id);\n            if (L.empty() || R.empty()) return false;\n            boxL = {box.x1, box.y1, box.x2, cut};\n            boxR = {box.x1, cut, box.x2, box.y2};\n        }\n        return true;\n    }\n\n    vector<BuildCand> genBuildCandidates(const vector<int>& ids, const Rect& box,\n                                         const Config& cfg, int depth) {\n        vector<BuildCand> cands;\n        int m = (int)ids.size();\n        if (m <= 1) return cands;\n\n        long long T = 0;\n        for (int id : ids) T += rs[id];\n\n        int W = box.x2 - box.x1;\n        int H = box.y2 - box.y1;\n\n        auto addOrientation = [&](bool vertical) {\n            vector<int> ord = ids;\n            if (vertical) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (xs[a] != xs[b]) return xs[a] < xs[b];\n                    if (ys[a] != ys[b]) return ys[a] < ys[b];\n                    return a < b;\n                });\n            } else {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (ys[a] != ys[b]) return ys[a] < ys[b];\n                    if (xs[a] != xs[b]) return xs[a] < xs[b];\n                    return a < b;\n                });\n            }\n\n            vector<long long> prefSum(m);\n            vector<int> prefMinX(m), prefMaxX(m), prefMinY(m), prefMaxY(m);\n            vector<int> sufMinX(m), sufMaxX(m), sufMinY(m), sufMaxY(m);\n\n            prefSum[0] = rs[ord[0]];\n            prefMinX[0] = prefMaxX[0] = xs[ord[0]];\n            prefMinY[0] = prefMaxY[0] = ys[ord[0]];\n            for (int i = 1; i < m; ++i) {\n                prefSum[i] = prefSum[i - 1] + rs[ord[i]];\n                prefMinX[i] = min(prefMinX[i - 1], xs[ord[i]]);\n                prefMaxX[i] = max(prefMaxX[i - 1], xs[ord[i]]);\n                prefMinY[i] = min(prefMinY[i - 1], ys[ord[i]]);\n                prefMaxY[i] = max(prefMaxY[i - 1], ys[ord[i]]);\n            }\n\n            sufMinX[m - 1] = sufMaxX[m - 1] = xs[ord[m - 1]];\n            sufMinY[m - 1] = sufMaxY[m - 1] = ys[ord[m - 1]];\n            for (int i = m - 2; i >= 0; --i) {\n                sufMinX[i] = min(sufMinX[i + 1], xs[ord[i]]);\n                sufMaxX[i] = max(sufMaxX[i + 1], xs[ord[i]]);\n                sufMinY[i] = min(sufMinY[i + 1], ys[ord[i]]);\n                sufMaxY[i] = max(sufMaxY[i + 1], ys[ord[i]]);\n            }\n\n            auto coord = [&](int id) { return vertical ? xs[id] : ys[id]; };\n            int span = vertical ? W : H;\n            int base = vertical ? box.x1 : box.y1;\n\n            for (int i = 0; i + 1 < m; ++i) {\n                if (coord(ord[i]) == coord(ord[i + 1])) continue;\n\n                long long TL = prefSum[i];\n                long long TR = T - TL;\n                if (TL <= 0 || TR <= 0) continue;\n\n                int lo = vertical ? max(box.x1 + 1, coord(ord[i]) + 1)\n                                  : max(box.y1 + 1, coord(ord[i]) + 1);\n                int hi = vertical ? min(box.x2 - 1, coord(ord[i + 1]))\n                                  : min(box.y2 - 1, coord(ord[i + 1]));\n                if (lo > hi) continue;\n\n                long long minAreaL = vertical\n                    ? 1LL * (prefMaxX[i] - prefMinX[i] + 1) * H\n                    : 1LL * W * (prefMaxY[i] - prefMinY[i] + 1);\n                long long minAreaR = vertical\n                    ? 1LL * (sufMaxX[i + 1] - sufMinX[i + 1] + 1) * H\n                    : 1LL * W * (sufMaxY[i + 1] - sufMinY[i + 1] + 1);\n\n                long long needL = max(TL, minAreaL);\n                long long needR = max(TR, minAreaR);\n\n                double rawShare = (double)TL / (double)T;\n                double needShare = (double)needL / (double)(needL + needR);\n                double mixShare = 0.5 * rawShare + 0.5 * needShare;\n\n                int centers[3] = {\n                    base + (int)llround(span * rawShare),\n                    base + (int)llround(span * needShare),\n                    base + (int)llround(span * mixShare),\n                };\n\n                double depthBoost = 1.0 + 0.30 / (1.0 + depth);\n                double w = min(0.60, cfg.needWeight * depthBoost);\n\n                vector<int> tryCuts;\n                auto pushCut = [&](int c) {\n                    if (c < lo || c > hi) return;\n                    tryCuts.push_back(c);\n                };\n\n                pushCut(lo);\n                pushCut(hi);\n                pushCut((lo + hi) / 2);\n\n                for (int cc = 0; cc < 3; ++cc) {\n                    for (int d = -cfg.radius; d <= cfg.radius; ++d) {\n                        pushCut(centers[cc] + d);\n                    }\n                }\n\n                sort(tryCuts.begin(), tryCuts.end());\n                tryCuts.erase(unique(tryCuts.begin(), tryCuts.end()), tryCuts.end());\n\n                for (int cut : tryCuts) {\n                    long long areaL = 1LL * (cut - base) * (vertical ? H : W);\n                    long long areaR = 1LL * W * H - areaL;\n                    if (areaL <= 0 || areaR <= 0) continue;\n\n                    double raw = satScore(areaL, TL) + satScore(areaR, TR);\n                    double need = satScore(areaL, needL) + satScore(areaR, needR);\n                    double score = raw * (1.0 - w) + need * w;\n                    if (cfg.randomize) score += cfg.noise * (rnd01() - 0.5);\n\n                    cands.push_back({vertical ? 0 : 1, cut, score, hi - lo});\n                }\n            }\n        };\n\n        addOrientation(true);\n        addOrientation(false);\n\n        sort(cands.begin(), cands.end(), [&](const BuildCand& a, const BuildCand& b) {\n            if (a.orient != b.orient) return a.orient < b.orient;\n            if (a.cut != b.cut) return a.cut < b.cut;\n            return a.score > b.score;\n        });\n\n        vector<BuildCand> uniq;\n        uniq.reserve(cands.size());\n        for (auto& c : cands) {\n            if (uniq.empty() || uniq.back().orient != c.orient || uniq.back().cut != c.cut) {\n                uniq.push_back(c);\n            } else if (c.score > uniq.back().score) {\n                uniq.back() = c;\n            }\n        }\n\n        sort(uniq.begin(), uniq.end(), [&](const BuildCand& a, const BuildCand& b) {\n            if (fabs(a.score - b.score) > 1e-15) return a.score > b.score;\n            if (a.span != b.span) return a.span > b.span;\n            if (a.cut != b.cut) return a.cut < b.cut;\n            return a.orient < b.orient;\n        });\n\n        return uniq;\n    }\n\n    int buildNode(Tree& tr, const vector<int>& ids, const Rect& box,\n                  const Config& cfg, int depth) {\n        Node nd;\n        nd.cnt = (int)ids.size();\n        nd.sumR = 0;\n        nd.minx = nd.maxx = xs[ids[0]];\n        nd.miny = nd.maxy = ys[ids[0]];\n        for (int id : ids) {\n            nd.sumR += rs[id];\n            nd.minx = min(nd.minx, xs[id]);\n            nd.maxx = max(nd.maxx, xs[id]);\n            nd.miny = min(nd.miny, ys[id]);\n            nd.maxy = max(nd.maxy, ys[id]);\n        }\n\n        int idx = (int)tr.nodes.size();\n        tr.nodes.push_back(nd);\n\n        if ((int)ids.size() == 1) {\n            tr.nodes[idx].id = ids[0];\n            return idx;\n        }\n\n        vector<BuildCand> cands = genBuildCandidates(ids, box, cfg, depth);\n        if (cands.empty()) {\n            vector<int> L, R;\n            Rect boxL, boxR;\n            bool ok = false;\n            if (box.x2 - box.x1 >= box.y2 - box.y1) {\n                ok = splitMedian(ids, box, true, L, R, boxL, boxR) ||\n                     splitMedian(ids, box, false, L, R, boxL, boxR);\n            } else {\n                ok = splitMedian(ids, box, false, L, R, boxL, boxR) ||\n                     splitMedian(ids, box, true, L, R, boxL, boxR);\n            }\n            if (!ok) {\n                // Should be extremely rare.\n                tr.nodes[idx].id = ids[0];\n                return idx;\n            }\n            int lch = buildNode(tr, L, boxL, cfg, depth + 1);\n            int rch = buildNode(tr, R, boxR, cfg, depth + 1);\n            tr.nodes[idx].left = lch;\n            tr.nodes[idx].right = rch;\n            return idx;\n        }\n\n        int limit = 1;\n        if (depth < cfg.lookDepth && (int)ids.size() >= cfg.branchMinSize) {\n            int di = min(depth, 2);\n            limit = min(cfg.branchK[di], (int)cands.size());\n            if (limit < 1) limit = 1;\n        }\n\n        int pick = 0;\n        if (cfg.randomize && limit > 1) {\n            int pool = min(limit, 4);\n            if ((int)(rng() % 1000) < 220) {\n                pick = (int)(rng() % pool);\n            }\n        }\n\n        BuildCand chosen = cands[pick];\n\n        vector<int> L, R;\n        L.reserve(ids.size());\n        R.reserve(ids.size());\n        Rect boxL, boxR;\n        if (chosen.orient == 0) {\n            for (int id : ids) (xs[id] < chosen.cut ? L : R).push_back(id);\n            if (L.empty() || R.empty()) {\n                if (!splitMedian(ids, box, true, L, R, boxL, boxR) &&\n                    !splitMedian(ids, box, false, L, R, boxL, boxR)) {\n                    tr.nodes[idx].id = ids[0];\n                    return idx;\n                }\n            } else {\n                boxL = {box.x1, box.y1, chosen.cut, box.y2};\n                boxR = {chosen.cut, box.y1, box.x2, box.y2};\n            }\n        } else {\n            for (int id : ids) (ys[id] < chosen.cut ? L : R).push_back(id);\n            if (L.empty() || R.empty()) {\n                if (!splitMedian(ids, box, false, L, R, boxL, boxR) &&\n                    !splitMedian(ids, box, true, L, R, boxL, boxR)) {\n                    tr.nodes[idx].id = ids[0];\n                    return idx;\n                }\n            } else {\n                boxL = {box.x1, box.y1, box.x2, chosen.cut};\n                boxR = {box.x1, chosen.cut, box.x2, box.y2};\n            }\n        }\n\n        int lch = buildNode(tr, L, boxL, cfg, depth + 1);\n        int rch = buildNode(tr, R, boxR, cfg, depth + 1);\n        tr.nodes[idx].left = lch;\n        tr.nodes[idx].right = rch;\n        tr.nodes[idx].orient = chosen.orient;\n        tr.nodes[idx].cut = chosen.cut;\n\n        return idx;\n    }\n\n    vector<int> genOptimizeCuts(const Tree& tr, int v, const Rect& box, int depth) {\n        const Node& nd = tr.nodes[v];\n        if (nd.id != -1) return {};\n\n        const Node& L = tr.nodes[nd.left];\n        const Node& R = tr.nodes[nd.right];\n\n        int lo, hi;\n        int W = box.x2 - box.x1;\n        int H = box.y2 - box.y1;\n\n        if (nd.orient == 0) {\n            lo = max(box.x1 + 1, L.maxx + 1);\n            hi = min(box.x2 - 1, R.minx);\n        } else {\n            lo = max(box.y1 + 1, L.maxy + 1);\n            hi = min(box.y2 - 1, R.miny);\n        }\n        if (lo > hi) return {};\n\n        long long TL = L.sumR;\n        long long TR = R.sumR;\n        long long T = TL + TR;\n\n        long long minAreaL, minAreaR;\n        if (nd.orient == 0) {\n            minAreaL = 1LL * (L.maxx - L.minx + 1) * H;\n            minAreaR = 1LL * (R.maxx - R.minx + 1) * H;\n        } else {\n            minAreaL = 1LL * W * (L.maxy - L.miny + 1);\n            minAreaR = 1LL * W * (R.maxy - R.miny + 1);\n        }\n\n        long long needL = max(TL, minAreaL);\n        long long needR = max(TR, minAreaR);\n\n        int span = (nd.orient == 0 ? W : H);\n        int base = (nd.orient == 0 ? box.x1 : box.y1);\n\n        double rawShare = (double)TL / (double)T;\n        double needShare = (double)needL / (double)(needL + needR);\n        double blendShare = 0.5 * rawShare + 0.5 * needShare;\n\n        int rawCut   = base + (int)llround(span * rawShare);\n        int needCut  = base + (int)llround(span * needShare);\n        int blendCut = base + (int)llround(span * blendShare);\n        int midCut   = (lo + hi) / 2;\n\n        vector<int> cuts;\n        auto add = [&](int c) {\n            if (c < lo || c > hi) return;\n            cuts.push_back(c);\n        };\n\n        bool exhaustive = (hi - lo + 1 <= 80) || (nd.cnt <= 12);\n        if (exhaustive) {\n            cuts.reserve(hi - lo + 1);\n            for (int c = lo; c <= hi; ++c) cuts.push_back(c);\n        } else {\n            add(nd.cut);\n            add(rawCut);\n            add(needCut);\n            add(blendCut);\n            add(midCut);\n            add(lo);\n            add(hi);\n\n            int rad = max(2, min(8, 2 + depth));\n            for (int d = 1; d <= rad; ++d) {\n                add(nd.cut - d);\n                add(nd.cut + d);\n                add(rawCut - d);\n                add(rawCut + d);\n                add(needCut - d);\n                add(needCut + d);\n            }\n        }\n\n        sort(cuts.begin(), cuts.end());\n        cuts.erase(unique(cuts.begin(), cuts.end()), cuts.end());\n        return cuts;\n    }\n\n    bool adjustNodeCut(Tree& tr, int v, const Rect& box, const Config& cfg, int depth) {\n        Node& nd = tr.nodes[v];\n        if (nd.id != -1) return false;\n\n        vector<int> cuts = genOptimizeCuts(tr, v, box, depth);\n        if (cuts.empty()) return false;\n\n        int orig = nd.cut;\n        double best = scoreSubtree(tr, v, box);\n        int bestCut = orig;\n\n        for (int c : cuts) {\n            if (elapsed() > 4.75) {\n                aborted = true;\n                break;\n            }\n            if (c == orig) continue;\n            nd.cut = c;\n            double sc = scoreSubtree(tr, v, box);\n            if (sc > best + 1e-12) {\n                best = sc;\n                bestCut = c;\n            }\n            nd.cut = orig;\n        }\n\n        nd.cut = bestCut;\n        return bestCut != orig;\n    }\n\n    void optimizePre(Tree& tr, int v, const Rect& box, const Config& cfg, int depth) {\n        if (aborted || elapsed() > 4.75) {\n            aborted = true;\n            return;\n        }\n        Node& nd = tr.nodes[v];\n        if (nd.id != -1) return;\n\n        adjustNodeCut(tr, v, box, cfg, depth);\n\n        Rect Lbox, Rbox;\n        if (nd.orient == 0) {\n            Lbox = {box.x1, box.y1, nd.cut, box.y2};\n            Rbox = {nd.cut, box.y1, box.x2, box.y2};\n        } else {\n            Lbox = {box.x1, box.y1, box.x2, nd.cut};\n            Rbox = {box.x1, nd.cut, box.x2, box.y2};\n        }\n        optimizePre(tr, nd.left, Lbox, cfg, depth + 1);\n        optimizePre(tr, nd.right, Rbox, cfg, depth + 1);\n    }\n\n    void optimizePost(Tree& tr, int v, const Rect& box, const Config& cfg, int depth) {\n        if (aborted || elapsed() > 4.75) {\n            aborted = true;\n            return;\n        }\n        Node& nd = tr.nodes[v];\n        if (nd.id != -1) return;\n\n        Rect Lbox, Rbox;\n        if (nd.orient == 0) {\n            Lbox = {box.x1, box.y1, nd.cut, box.y2};\n            Rbox = {nd.cut, box.y1, box.x2, box.y2};\n        } else {\n            Lbox = {box.x1, box.y1, box.x2, nd.cut};\n            Rbox = {box.x1, nd.cut, box.x2, box.y2};\n        }\n\n        optimizePost(tr, nd.left, Lbox, cfg, depth + 1);\n        optimizePost(tr, nd.right, Rbox, cfg, depth + 1);\n        if (aborted) return;\n\n        adjustNodeCut(tr, v, box, cfg, depth);\n    }\n\n    AttemptResult runAttempt(uint64_t seed, Config cfg) {\n        seed = seed ^ 0x9e3779b97f4a7c15ULL;\n        this->seed(seed);\n\n        if (cfg.randomize) {\n            auto jitter = [&]() -> double { return 0.85 + 0.30 * rnd01(); };\n            cfg.needWeight *= jitter();\n            cfg.radius = max(2, cfg.radius + (int)(rng() % 3) - 1);\n            for (int i = 0; i < 3; ++i) {\n                int d = (int)(rng() % 3) - 1;\n                cfg.branchK[i] = max(1, cfg.branchK[i] + d);\n            }\n            cfg.noise = max(1e-10, cfg.noise * jitter());\n        }\n\n        vector<int> ids(n);\n        iota(ids.begin(), ids.end(), 0);\n\n        Tree tr;\n        tr.nodes.reserve(2 * n + 5);\n        tr.root = buildNode(tr, ids, Rect{0, 0, B, B}, cfg, 0);\n\n        aborted = false;\n        for (int pass = 0; pass < 2; ++pass) {\n            if (elapsed() > 4.75) break;\n            optimizePost(tr, tr.root, Rect{0, 0, B, B}, cfg, 0);\n            if (aborted || elapsed() > 4.75) break;\n            optimizePre(tr, tr.root, Rect{0, 0, B, B}, cfg, 0);\n            if (aborted) break;\n        }\n\n        vector<Rect> rects(n);\n        materialize(tr, tr.root, Rect{0, 0, B, B}, rects);\n\n        AttemptResult res;\n        if (validateRects(rects)) {\n            res.rects = std::move(rects);\n            res.score = scoreRects(res.rects);\n        }\n        return res;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<int> xs(n), ys(n);\n    vector<long long> rs(n);\n    for (int i = 0; i < n; ++i) cin >> xs[i] >> ys[i] >> rs[i];\n\n    Solver solver(n, xs, ys, rs);\n    solver.setStart();\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n\n    vector<Config> configs = {\n        // Pure area-based baseline.\n        {2, {24, 10, 4}, 4, 0.00, false, 0.0, 6},\n\n        // Mild feasibility-floor bias.\n        {2, {24, 10, 4}, 5, 0.12, false, 0.0, 6},\n\n        // Randomized search.\n        {3, {18, 8, 3}, 5, 0.16, true, 1e-7, 6},\n\n        // Stronger randomized search.\n        {3, {16, 7, 3}, 6, 0.20, true, 2e-7, 6},\n\n        // Root-heavy fallback.\n        {1, {28, 1, 1}, 4, 0.08, false, 0.0, 6},\n    };\n\n    vector<Rect> bestRect;\n    double bestScore = -1e100;\n\n    for (int t = 0; t < (int)configs.size(); ++t) {\n        if (solver.elapsed() > 4.75) break;\n        AttemptResult res = solver.runAttempt(baseSeed + 1000003ULL * (uint64_t)(t + 1), configs[t]);\n        if (!res.rects.empty() && res.score > bestScore) {\n            bestScore = res.score;\n            bestRect = std::move(res.rects);\n        }\n    }\n\n    if (bestRect.empty()) {\n        bestRect.assign(n, Rect{0, 0, B, B});\n    }\n\n    for (int i = 0; i < n; ++i) {\n        cout << bestRect[i].x1 << ' ' << bestRect[i].y1 << ' '\n             << bestRect[i].x2 << ' ' << bestRect[i].y2 << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 50;\nstatic constexpr int W = 50;\nstatic constexpr int N = H * W;\nstatic constexpr int WORDS = (N + 63) / 64;\n\nstruct State {\n    array<uint64_t, WORDS> vis{};\n    int pos = 0;\n    int score = 0;\n    int parent = -1;\n    char mv = 0;\n    int prio = 0;\n};\n\nstruct Cand {\n    int next = -1;\n    char mv = '?';\n    int val = 0;\n    int r1 = 0;\n    int r2 = 0;\n    int fut = 0;\n    int dens = 0;\n    int key = 0;\n};\n\nstruct Mode {\n    int wR2, wR1, wF, wV, wD;\n    int prioMul;\n    int noise;      // percentage for randomized completion\n    int beamDepth;\n    int beamWidth;\n    int finishK;\n};\n\nstruct Result {\n    string path;\n    int score = -1;\n};\n\nint si, sj;\nint tileId[H][W];\nint valGrid[H][W];\n\nint tileOf[N];\nint valueOf[N];\nint densityScore[N];\n\nint adjCnt[N];\nint adjTo[N][4];\nchar adjMv[N][4];\n\ninline int idOf(int r, int c) { return r * W + c; }\n\ninline bool visited(const array<uint64_t, WORDS>& vis, int tid) {\n    return (vis[tid >> 6] >> (tid & 63)) & 1ULL;\n}\ninline void setVisited(array<uint64_t, WORDS>& vis, int tid) {\n    vis[tid >> 6] |= (1ULL << (tid & 63));\n}\n\nstatic inline bool candBetter(const Cand& a, const Cand& b) {\n    if (a.key != b.key) return a.key > b.key;\n    if (a.r2 != b.r2) return a.r2 > b.r2;\n    if (a.r1 != b.r1) return a.r1 > b.r1;\n    if (a.val != b.val) return a.val > b.val;\n    return a.next < b.next;\n}\n\nstatic inline bool nodeBetter(const State& a, const State& b) {\n    if (a.prio != b.prio) return a.prio > b.prio;\n    if (a.score != b.score) return a.score > b.score;\n    return a.pos < b.pos;\n}\n\ninline void applyMove(State& st, int nxt) {\n    st.pos = nxt;\n    st.score += valueOf[nxt];\n    setVisited(st.vis, tileOf[nxt]);\n}\n\nint makeCandidates(const State& st, const Mode& m, Cand out[4]) {\n    int cnt = 0;\n    int curTid = tileOf[st.pos];\n\n    for (int k = 0; k < adjCnt[st.pos]; ++k) {\n        int nxt = adjTo[st.pos][k];\n        int nxtTid = tileOf[nxt];\n        if (visited(st.vis, nxtTid)) continue;\n\n        int directTid[8], directVal[8], directCnt = 0;\n        int reachTid[20], reachVal[20], reachCnt = 0;\n\n        auto addTo = [&](int tid, int val, int tids[], int vals[], int& c) {\n            if (tid == curTid || tid == nxtTid || visited(st.vis, tid)) return;\n            for (int i = 0; i < c; ++i) {\n                if (tids[i] == tid) {\n                    vals[i] = max(vals[i], val);\n                    return;\n                }\n            }\n            tids[c] = tid;\n            vals[c] = val;\n            ++c;\n        };\n\n        for (int e = 0; e < adjCnt[nxt]; ++e) {\n            int x = adjTo[nxt][e];\n            int tx = tileOf[x];\n            addTo(tx, valueOf[x], directTid, directVal, directCnt);\n            addTo(tx, valueOf[x], reachTid, reachVal, reachCnt);\n\n            for (int ee = 0; ee < adjCnt[x]; ++ee) {\n                int y = adjTo[x][ee];\n                int ty = tileOf[y];\n                addTo(ty, valueOf[y], reachTid, reachVal, reachCnt);\n            }\n        }\n\n        sort(reachVal, reachVal + reachCnt, greater<int>());\n        int fut = 0;\n        for (int i = 0; i < min(4, reachCnt); ++i) fut += reachVal[i];\n\n        int dens = densityScore[nxt] / 20;\n        int key = m.wR2 * reachCnt\n                + m.wR1 * directCnt\n                + m.wF  * fut\n                + m.wV  * valueOf[nxt]\n                + m.wD  * dens;\n\n        out[cnt++] = {nxt, adjMv[st.pos][k], valueOf[nxt], directCnt, reachCnt, fut, dens, key};\n    }\n\n    if (cnt == 0) return 0;\n\n    // If there exists a move with positive immediate mobility, discard dead-end moves.\n    bool hasGood = false;\n    for (int i = 0; i < cnt; ++i) {\n        if (out[i].r1 > 0) {\n            hasGood = true;\n            break;\n        }\n    }\n    if (hasGood) {\n        int j = 0;\n        for (int i = 0; i < cnt; ++i) {\n            if (out[i].r1 > 0) out[j++] = out[i];\n        }\n        cnt = j;\n    }\n\n    sort(out, out + cnt, candBetter);\n    return cnt;\n}\n\nstring reconstructPath(const vector<State>& pool, int idx) {\n    string s;\n    while (idx != -1 && pool[idx].parent != -1) {\n        s.push_back(pool[idx].mv);\n        idx = pool[idx].parent;\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nResult completeFrom(State st, string path, const Mode& m, mt19937_64& rng,\n                    chrono::steady_clock::time_point deadline) {\n    while (chrono::steady_clock::now() < deadline) {\n        Cand cand[4];\n        int cnt = makeCandidates(st, m, cand);\n        if (cnt == 0) break;\n\n        int choose = 0;\n        if (m.noise > 0 && cnt > 1 && (int)(rng() % 100) < m.noise) {\n            int minKey = cand[cnt - 1].key;\n            int w[4];\n            int sum = 0;\n            for (int i = 0; i < cnt; ++i) {\n                w[i] = max(1, cand[i].key - minKey + 1);\n                sum += w[i];\n            }\n            uint64_t r = rng() % sum;\n            int acc = 0;\n            for (int i = 0; i < cnt; ++i) {\n                acc += w[i];\n                if (r < (uint64_t)acc) {\n                    choose = i;\n                    break;\n                }\n            }\n        }\n\n        applyMove(st, cand[choose].next);\n        path.push_back(cand[choose].mv);\n    }\n    return {path, st.score};\n}\n\nResult runAttempt(const Mode& m, uint64_t seed, chrono::steady_clock::time_point deadline) {\n    mt19937_64 rng(seed);\n\n    vector<State> pool;\n    pool.reserve(120000);\n\n    State root;\n    int start = idOf(si, sj);\n    root.pos = start;\n    root.score = valueOf[start];\n    setVisited(root.vis, tileOf[start]);\n    root.parent = -1;\n    root.mv = 0;\n    root.prio = root.score;\n    pool.push_back(root);\n\n    vector<int> beam = {0};\n    int bestTerminal = -1;\n\n    for (int depth = 0; depth < m.beamDepth; ++depth) {\n        if (chrono::steady_clock::now() >= deadline) break;\n\n        vector<int> nxt;\n        nxt.reserve(beam.size() * 4 + 8);\n\n        for (int idx : beam) {\n            Cand cand[4];\n            int cnt = makeCandidates(pool[idx], m, cand);\n            if (cnt == 0) {\n                if (bestTerminal == -1 || pool[idx].score > pool[bestTerminal].score) {\n                    bestTerminal = idx;\n                }\n                continue;\n            }\n\n            for (int i = 0; i < cnt; ++i) {\n                State ch = pool[idx];\n                applyMove(ch, cand[i].next);\n                ch.parent = idx;\n                ch.mv = cand[i].mv;\n                int jitter = m.noise ? (int)(rng() % (2ULL * m.noise + 1)) - m.noise : 0;\n                ch.prio = ch.score + m.prioMul * cand[i].key + jitter;\n                pool.push_back(ch);\n                nxt.push_back((int)pool.size() - 1);\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        if ((int)nxt.size() > m.beamWidth) {\n            nth_element(nxt.begin(), nxt.begin() + m.beamWidth, nxt.end(),\n                        [&](int a, int b) {\n                            if (pool[a].prio != pool[b].prio) return pool[a].prio > pool[b].prio;\n                            if (pool[a].score != pool[b].score) return pool[a].score > pool[b].score;\n                            return a < b;\n                        });\n            nxt.resize(m.beamWidth);\n        }\n\n        beam.swap(nxt);\n    }\n\n    vector<int> selected;\n    auto addUnique = [&](int x) {\n        if (x < 0) return;\n        for (int y : selected) if (y == x) return;\n        selected.push_back(x);\n    };\n\n    sort(beam.begin(), beam.end(), [&](int a, int b) {\n        if (pool[a].prio != pool[b].prio) return pool[a].prio > pool[b].prio;\n        if (pool[a].score != pool[b].score) return pool[a].score > pool[b].score;\n        return a < b;\n    });\n\n    for (int i = 0; i < (int)beam.size() && i < m.finishK; ++i) addUnique(beam[i]);\n    if (bestTerminal != -1) addUnique(bestTerminal);\n\n    if (!beam.empty()) {\n        int bestScoreIdx = beam[0];\n        for (int idx : beam) {\n            if (pool[idx].score > pool[bestScoreIdx].score) bestScoreIdx = idx;\n        }\n        addUnique(bestScoreIdx);\n    } else {\n        addUnique(0);\n    }\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[start];\n\n    for (int idx : selected) {\n        if (chrono::steady_clock::now() >= deadline) break;\n\n        string path = reconstructPath(pool, idx);\n        State st = pool[idx];\n        Result r = completeFrom(st, path, m, rng, deadline);\n\n        if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) {\n            best = std::move(r);\n        }\n    }\n\n    return best;\n}\n\npair<bool, int> simulatePath(const string& path) {\n    State st;\n    int start = idOf(si, sj);\n    st.pos = start;\n    st.score = valueOf[start];\n    setVisited(st.vis, tileOf[start]);\n\n    for (char ch : path) {\n        int nxt = -1;\n        for (int k = 0; k < adjCnt[st.pos]; ++k) {\n            if (adjMv[st.pos][k] == ch) {\n                nxt = adjTo[st.pos][k];\n                break;\n            }\n        }\n        if (nxt == -1) return {false, -1};\n        int tid = tileOf[nxt];\n        if (visited(st.vis, tid)) return {false, -1};\n        applyMove(st, nxt);\n    }\n    return {true, st.score};\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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> tileId[i][j];\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> valGrid[i][j];\n    }\n\n    uint64_t baseSeed = 0x123456789abcdefULL;\n    auto mix = [&](uint64_t x) {\n        baseSeed = splitmix64(baseSeed ^ x);\n    };\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            tileOf[id] = tileId[i][j];\n            valueOf[id] = valGrid[i][j];\n            mix((uint64_t)tileId[i][j] << 32 ^ (uint64_t)valGrid[i][j] ^ (uint64_t)(i * 50 + j));\n        }\n    }\n    mix((uint64_t)si << 32 | (uint64_t)sj);\n\n    // adjacency\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            adjCnt[id] = 0;\n            if (i > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i - 1, j);\n                adjMv[id][adjCnt[id]++] = 'U';\n            }\n            if (i + 1 < H) {\n                adjTo[id][adjCnt[id]] = idOf(i + 1, j);\n                adjMv[id][adjCnt[id]++] = 'D';\n            }\n            if (j > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i, j - 1);\n                adjMv[id][adjCnt[id]++] = 'L';\n            }\n            if (j + 1 < W) {\n                adjTo[id][adjCnt[id]] = idOf(i, j + 1);\n                adjMv[id][adjCnt[id]++] = 'R';\n            }\n        }\n    }\n\n    // Local density: weighted sum in Manhattan radius 3\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int sum = 0;\n            for (int dr = -3; dr <= 3; ++dr) {\n                for (int dc = -3; dc <= 3; ++dc) {\n                    int d = abs(dr) + abs(dc);\n                    if (d > 3) continue;\n                    int ni = i + dr, nj = j + dc;\n                    if (ni < 0 || ni >= H || nj < 0 || nj >= W) continue;\n                    int w = 4 - d; // 4,3,2,1\n                    sum += w * valGrid[ni][nj];\n                }\n            }\n            densityScore[idOf(i, j)] = sum;\n        }\n    }\n\n    chrono::steady_clock::time_point startTime = chrono::steady_clock::now();\n    chrono::steady_clock::time_point deadline = startTime + chrono::milliseconds(1850);\n\n    vector<Mode> modes = {\n        // Strong mobility-first\n        {100, 35, 1, 0, 1, 4, 4, 260, 64, 8},\n        // Balanced\n        {70,  25, 3, 1, 2, 4, 6, 220, 72, 8},\n        // Value-balanced\n        {45,  18, 5, 4, 2, 4, 8, 200, 84, 10},\n        // Dense-area explorer\n        {60,  20, 2, 1, 4, 4, 7, 220, 80, 8},\n        // More exploratory\n        {30,  12, 6, 6, 1, 5, 12, 180, 96, 12},\n    };\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[idOf(si, sj)];\n\n    int attempt = 0;\n    while (chrono::steady_clock::now() < deadline) {\n        const Mode& m = modes[attempt % (int)modes.size()];\n        uint64_t seed = splitmix64(baseSeed ^ (uint64_t)attempt * 0x9e3779b97f4a7c15ULL);\n        Result r = runAttempt(m, seed, deadline);\n\n        // Safety check\n        auto [ok, sc] = simulatePath(r.path);\n        if (ok) r.score = sc;\n        else r.path.clear(), r.score = valueOf[idOf(si, sj)];\n\n        if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) {\n            best = std::move(r);\n        }\n\n        ++attempt;\n    }\n\n    auto [ok, sc] = simulatePath(best.path);\n    if (!ok) {\n        best.path.clear();\n    }\n\n    cout << best.path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\n\nstatic constexpr double INIT_W = 5000.0;\nstatic constexpr double MIN_W = 1000.0;\nstatic constexpr double MAX_W = 9000.0;\n\nstatic constexpr double PSEUDO_W = 0.05;      // small prior for unseen edges in row/col fitting\nstatic constexpr double SEG_BLEND = 12.0;     // stronger smoothing from segment mean\nstatic constexpr double COV_BETA = 0.35;      // segment coverage contribution to uncertainty\nstatic constexpr double RISK0 = 180.0;        // uncertainty penalty\nstatic constexpr double RISK1 = 160.0;        // grows slightly over time\nstatic constexpr double STEP_PENALTY = 25.0;   // tiny penalty per step to avoid over-detours\nstatic constexpr double UPDATE_LR = 0.30;      // residual update rate\nstatic constexpr double EPS = 1e-9;\nstatic constexpr double INF = 1e100;\n\ndouble estH[N][N - 1], estV[N - 1][N];\nint cntH[N][N - 1], cntV[N - 1][N];\n\nstruct LineModel {\n    bool split = false;\n    int pos = -1; // [1..28]\n    double mean = INIT_W;\n    double left = INIT_W;\n    double right = INIT_W;\n};\n\nLineModel rowModel[N], colModel[N];\nint rowCov[N][2], colCov[N][2];\n\ndouble pcostH[N][N - 1], pcostV[N - 1][N];\ndouble puncH[N][N - 1], puncV[N - 1][N];\n\nmt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\ninline double clampW(double x) {\n    return max(MIN_W, min(MAX_W, x));\n}\n\ninline int rowSegOf(int r, int c) {\n    return (rowModel[r].split && c >= rowModel[r].pos) ? 1 : 0;\n}\n\ninline int colSegOf(int c, int r) {\n    return (colModel[c].split && r >= colModel[c].pos) ? 1 : 0;\n}\n\ninline double rowSegMean(int r, int c) {\n    if (!rowModel[r].split) return rowModel[r].mean;\n    return (c < rowModel[r].pos ? rowModel[r].left : rowModel[r].right);\n}\n\ninline double colSegMean(int c, int r) {\n    if (!colModel[c].split) return colModel[c].mean;\n    return (r < colModel[c].pos ? colModel[c].left : colModel[c].right);\n}\n\ninline double edgeUncH(int r, int c) {\n    int s = rowSegOf(r, c);\n    return 1.0 / (1.0 + cntH[r][c] + COV_BETA * rowCov[r][s]);\n}\n\ninline double edgeUncV(int r, int c) {\n    int s = colSegOf(c, r);\n    return 1.0 / (1.0 + cntV[r][c] + COV_BETA * colCov[c][s]);\n}\n\ndouble globalMeanH() {\n    double sw = 0.0, sv = 0.0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            if (cntH[i][j] > 0) {\n                double w = sqrt((double)cntH[i][j]);\n                sw += w;\n                sv += w * estH[i][j];\n            }\n        }\n    }\n    return (sw > 0.0 ? sv / sw : INIT_W);\n}\n\ndouble globalMeanV() {\n    double sw = 0.0, sv = 0.0;\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (cntV[i][j] > 0) {\n                double w = sqrt((double)cntV[i][j]);\n                sw += w;\n                sv += w * estV[i][j];\n            }\n        }\n    }\n    return (sw > 0.0 ? sv / sw : INIT_W);\n}\n\nLineModel fitRow(int r, double gH) {\n    double pw[30] = {}, ps[30] = {}, pq[30] = {};\n    int po[30] = {};\n    double totW = 0.0, totS = 0.0, totQ = 0.0;\n    int obs = 0;\n\n    for (int c = 0; c < 29; ++c) {\n        bool seen = (cntH[r][c] > 0);\n        double w = seen ? (sqrt((double)cntH[r][c]) + PSEUDO_W) : PSEUDO_W;\n        double x = seen ? estH[r][c] : gH;\n\n        totW += w;\n        totS += w * x;\n        totQ += w * x * x;\n        obs += seen ? 1 : 0;\n\n        pw[c + 1] = pw[c] + w;\n        ps[c + 1] = ps[c] + w * x;\n        pq[c + 1] = pq[c] + w * x * x;\n        po[c + 1] = po[c] + (seen ? 1 : 0);\n    }\n\n    LineModel m;\n    if (totW <= 0.0) {\n        m.mean = gH;\n        return m;\n    }\n\n    m.mean = totS / totW;\n    if (obs < 6) return m;\n\n    double sse1 = max(0.0, totQ - totS * totS / totW);\n\n    double best2 = INF;\n    int bestPos = -1;\n    double bestL = m.mean, bestR = m.mean;\n\n    for (int cut = 1; cut < 29; ++cut) {\n        double wL = pw[cut], wR = totW - wL;\n        int oL = po[cut], oR = obs - oL;\n        if (oL < 2 || oR < 2) continue;\n        if (wL < 0.5 || wR < 0.5) continue;\n\n        double sL = ps[cut], sR = totS - sL;\n        double qL = pq[cut], qR = totQ - qL;\n        double sse2 = max(0.0, qL - sL * sL / wL) + max(0.0, qR - sR * sR / wR);\n\n        if (sse2 < best2) {\n            best2 = sse2;\n            bestPos = cut;\n            bestL = sL / wL;\n            bestR = sR / wR;\n        }\n    }\n\n    if (bestPos != -1) {\n        double gain = sse1 - best2;\n        if (gain > 1.5e5 && gain > 0.03 * sse1) {\n            m.split = true;\n            m.pos = bestPos;\n            m.left = bestL;\n            m.right = bestR;\n        }\n    }\n\n    return m;\n}\n\nLineModel fitCol(int c, double gV) {\n    double pw[30] = {}, ps[30] = {}, pq[30] = {};\n    int po[30] = {};\n    double totW = 0.0, totS = 0.0, totQ = 0.0;\n    int obs = 0;\n\n    for (int r = 0; r < 29; ++r) {\n        bool seen = (cntV[r][c] > 0);\n        double w = seen ? (sqrt((double)cntV[r][c]) + PSEUDO_W) : PSEUDO_W;\n        double x = seen ? estV[r][c] : gV;\n\n        totW += w;\n        totS += w * x;\n        totQ += w * x * x;\n        obs += seen ? 1 : 0;\n\n        pw[r + 1] = pw[r] + w;\n        ps[r + 1] = ps[r] + w * x;\n        pq[r + 1] = pq[r] + w * x * x;\n        po[r + 1] = po[r] + (seen ? 1 : 0);\n    }\n\n    LineModel m;\n    if (totW <= 0.0) {\n        m.mean = gV;\n        return m;\n    }\n\n    m.mean = totS / totW;\n    if (obs < 6) return m;\n\n    double sse1 = max(0.0, totQ - totS * totS / totW);\n\n    double best2 = INF;\n    int bestPos = -1;\n    double bestL = m.mean, bestR = m.mean;\n\n    for (int cut = 1; cut < 29; ++cut) {\n        double wL = pw[cut], wR = totW - wL;\n        int oL = po[cut], oR = obs - oL;\n        if (oL < 2 || oR < 2) continue;\n        if (wL < 0.5 || wR < 0.5) continue;\n\n        double sL = ps[cut], sR = totS - sL;\n        double qL = pq[cut], qR = totQ - qL;\n        double sse2 = max(0.0, qL - sL * sL / wL) + max(0.0, qR - sR * sR / wR);\n\n        if (sse2 < best2) {\n            best2 = sse2;\n            bestPos = cut;\n            bestL = sL / wL;\n            bestR = sR / wR;\n        }\n    }\n\n    if (bestPos != -1) {\n        double gain = sse1 - best2;\n        if (gain > 1.5e5 && gain > 0.03 * sse1) {\n            m.split = true;\n            m.pos = bestPos;\n            m.left = bestL;\n            m.right = bestR;\n        }\n    }\n\n    return m;\n}\n\nvoid rebuildModelsAndCosts(int q) {\n    double gH = globalMeanH();\n    double gV = globalMeanV();\n\n    for (int i = 0; i < N; ++i) rowModel[i] = fitRow(i, gH);\n    for (int j = 0; j < N; ++j) colModel[j] = fitCol(j, gV);\n\n    for (int i = 0; i < N; ++i) rowCov[i][0] = rowCov[i][1] = 0;\n    for (int j = 0; j < N; ++j) colCov[j][0] = colCov[j][1] = 0;\n\n    for (int i = 0; i < N; ++i) {\n        if (!rowModel[i].split) {\n            int cov = 0;\n            for (int j = 0; j < N - 1; ++j) if (cntH[i][j] > 0) ++cov;\n            rowCov[i][0] = cov;\n        } else {\n            for (int j = 0; j < N - 1; ++j) {\n                if (cntH[i][j] > 0) ++rowCov[i][j >= rowModel[i].pos ? 1 : 0];\n            }\n        }\n    }\n\n    for (int j = 0; j < N; ++j) {\n        if (!colModel[j].split) {\n            int cov = 0;\n            for (int i = 0; i < N - 1; ++i) if (cntV[i][j] > 0) ++cov;\n            colCov[j][0] = cov;\n        } else {\n            for (int i = 0; i < N - 1; ++i) {\n                if (cntV[i][j] > 0) ++colCov[j][i >= colModel[j].pos ? 1 : 0];\n            }\n        }\n    }\n\n    double risk = RISK0 + RISK1 * (double)q / 999.0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            double seg = rowSegMean(i, j);\n            if (cntH[i][j] == 0) estH[i][j] = seg;\n            int s = rowSegOf(i, j);\n            double unc = 1.0 / (1.0 + cntH[i][j] + COV_BETA * rowCov[i][s]);\n            puncH[i][j] = unc;\n            double base = (cntH[i][j] > 0)\n                ? (estH[i][j] * cntH[i][j] + seg * SEG_BLEND) / (cntH[i][j] + SEG_BLEND)\n                : seg;\n            pcostH[i][j] = base + risk * unc;\n        }\n    }\n\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            double seg = colSegMean(j, i);\n            if (cntV[i][j] == 0) estV[i][j] = seg;\n            int s = colSegOf(j, i);\n            double unc = 1.0 / (1.0 + cntV[i][j] + COV_BETA * colCov[j][s]);\n            puncV[i][j] = unc;\n            double base = (cntV[i][j] > 0)\n                ? (estV[i][j] * cntV[i][j] + seg * SEG_BLEND) / (cntV[i][j] + SEG_BLEND)\n                : seg;\n            pcostV[i][j] = base + risk * unc;\n        }\n    }\n}\n\nstruct Candidate {\n    string path;\n    double cost = INF;\n    double unc = INF;\n    double score = INF;\n};\n\nCandidate solveMonotone(int si, int sj, int ti, int tj) {\n    int dy = abs(ti - si);\n    int dx = abs(tj - sj);\n    int sv = (ti >= si ? 1 : -1);\n    int sh = (tj >= sj ? 1 : -1);\n\n    static double dpC[N][N];\n    static double dpU[N][N];\n    static char par[N][N];\n\n    for (int i = 0; i <= dy; ++i) {\n        for (int j = 0; j <= dx; ++j) {\n            dpC[i][j] = INF;\n            dpU[i][j] = INF;\n            par[i][j] = 0;\n        }\n    }\n    dpC[0][0] = 0.0;\n    dpU[0][0] = 0.0;\n\n    auto better = [&](double c1, double u1, double c2, double u2) -> bool {\n        if (c1 + EPS < c2) return true;\n        if (c2 + EPS < c1) return false;\n        return u1 + EPS < u2;\n    };\n\n    for (int i = 0; i <= dy; ++i) {\n        for (int j = 0; j <= dx; ++j) {\n            if (i == 0 && j == 0) continue;\n\n            double bestC = INF, bestU = INF;\n            char bestP = 0;\n\n            if (i > 0) {\n                int px = si + sv * (i - 1);\n                int py = sj + sh * j;\n                int ex = (sv == 1 ? px : px - 1);\n                int ey = py;\n                double candC = dpC[i - 1][j] + pcostV[ex][ey];\n                double candU = dpU[i - 1][j] + puncV[ex][ey];\n                if (better(candC, candU, bestC, bestU)) {\n                    bestC = candC;\n                    bestU = candU;\n                    bestP = (sv == 1 ? 'D' : 'U');\n                }\n            }\n\n            if (j > 0) {\n                int px = si + sv * i;\n                int py = sj + sh * (j - 1);\n                int ex = px;\n                int ey = (sh == 1 ? py : py - 1);\n                double candC = dpC[i][j - 1] + pcostH[ex][ey];\n                double candU = dpU[i][j - 1] + puncH[ex][ey];\n                if (better(candC, candU, bestC, bestU)) {\n                    bestC = candC;\n                    bestU = candU;\n                    bestP = (sh == 1 ? 'R' : 'L');\n                }\n            }\n\n            dpC[i][j] = bestC;\n            dpU[i][j] = bestU;\n            par[i][j] = bestP;\n        }\n    }\n\n    string path;\n    for (int i = dy, j = dx; i > 0 || j > 0; ) {\n        char c = par[i][j];\n        path.push_back(c);\n        if (c == 'D' || c == 'U') --i;\n        else --j;\n    }\n    reverse(path.begin(), path.end());\n\n    Candidate res;\n    res.path = path;\n    res.cost = dpC[dy][dx];\n    res.unc = dpU[dy][dx];\n    res.score = res.cost + STEP_PENALTY * (double)path.size();\n    return res;\n}\n\nCandidate solveDijkstra(int si, int sj, int ti, int tj) {\n    const int S = si * N + sj;\n    const int T = ti * N + tj;\n\n    static double dist[N * N];\n    static double du[N * N];\n    static int par[N * N];\n    static char pmove[N * N];\n\n    for (int i = 0; i < N * N; ++i) {\n        dist[i] = INF;\n        du[i] = INF;\n        par[i] = -1;\n        pmove[i] = 0;\n    }\n\n    priority_queue<tuple<double, double, int>, vector<tuple<double, double, int>>, greater<tuple<double, double, int>>> pq;\n\n    dist[S] = 0.0;\n    du[S] = 0.0;\n    pq.emplace(0.0, 0.0, S);\n\n    while (!pq.empty()) {\n        auto [d, uUnc, u] = pq.top();\n        pq.pop();\n\n        if (d > dist[u] + EPS) continue;\n        if (fabs(d - dist[u]) <= EPS && uUnc > du[u] + EPS) continue;\n        if (u == T) break;\n\n        int x = u / N;\n        int y = u % N;\n\n        // Up\n        if (x > 0) {\n            int v = (x - 1) * N + y;\n            double nd = d + pcostV[x - 1][y];\n            double nu = uUnc + puncV[x - 1][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'U';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Down\n        if (x + 1 < N) {\n            int v = (x + 1) * N + y;\n            double nd = d + pcostV[x][y];\n            double nu = uUnc + puncV[x][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'D';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Left\n        if (y > 0) {\n            int v = x * N + (y - 1);\n            double nd = d + pcostH[x][y - 1];\n            double nu = uUnc + puncH[x][y - 1];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'L';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Right\n        if (y + 1 < N) {\n            int v = x * N + (y + 1);\n            double nd = d + pcostH[x][y];\n            double nu = uUnc + puncH[x][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'R';\n                pq.emplace(nd, nu, v);\n            }\n        }\n    }\n\n    string path;\n    for (int v = T; v != S; v = par[v]) path.push_back(pmove[v]);\n    reverse(path.begin(), path.end());\n\n    Candidate res;\n    res.path = path;\n    res.cost = dist[T];\n    res.unc = du[T];\n    res.score = res.cost + STEP_PENALTY * (double)path.size();\n    return res;\n}\n\nstruct Step {\n    bool isH;\n    int a, b;\n    double est;\n    double unc;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            estH[i][j] = INIT_W;\n            cntH[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            estV[i][j] = INIT_W;\n            cntV[i][j] = 0;\n        }\n    }\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        rebuildModelsAndCosts(q);\n\n        Candidate mono = solveMonotone(si, sj, ti, tj);\n        Candidate dijk = solveDijkstra(si, sj, ti, tj);\n\n        // Choose the route with the better adjusted score.\n        // The tiny step penalty suppresses over-detours.\n        Candidate chosen = mono;\n        if (dijk.score + 1e-9 < mono.score) chosen = dijk;\n\n        cout << chosen.path << '\\n' << flush;\n\n        long long obs;\n        if (!(cin >> obs)) return 0;\n\n        // Predict path length using direct edge estimates.\n        double pred = 0.0;\n        int x = si, y = sj;\n        vector<Step> steps;\n        steps.reserve(chosen.path.size());\n\n        for (char c : chosen.path) {\n            if (c == 'D') {\n                double est = estV[x][y];\n                double unc = puncV[x][y];\n                pred += est;\n                steps.push_back({false, x, y, est, unc});\n                ++x;\n            } else if (c == 'U') {\n                double est = estV[x - 1][y];\n                double unc = puncV[x - 1][y];\n                pred += est;\n                steps.push_back({false, x - 1, y, est, unc});\n                --x;\n            } else if (c == 'R') {\n                double est = estH[x][y];\n                double unc = puncH[x][y];\n                pred += est;\n                steps.push_back({true, x, y, est, unc});\n                ++y;\n            } else { // 'L'\n                double est = estH[x][y - 1];\n                double unc = puncH[x][y - 1];\n                pred += est;\n                steps.push_back({true, x, y - 1, est, unc});\n                --y;\n            }\n        }\n\n        double residual = (double)obs - pred;\n\n        // Cost-proportional, uncertainty-aware residual distribution.\n        // This behaves closer to multiplicative correction than uniform additive updates.\n        double sumW = 0.0;\n        for (auto &st : steps) {\n            double w = st.est * (0.25 + 0.75 * st.unc);\n            sumW += w;\n            st.unc = w; // reuse field as weight\n        }\n        if (sumW <= 0.0) sumW = 1.0;\n\n        for (auto &st : steps) {\n            double delta = UPDATE_LR * residual * (st.unc / sumW);\n            if (st.isH) {\n                estH[st.a][st.b] = clampW(estH[st.a][st.b] + delta);\n                ++cntH[st.a][st.b];\n            } else {\n                estV[st.a][st.b] = clampW(estV[st.a][st.b] + delta);\n                ++cntV[st.a][st.b];\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int CELLS = N * N;\nstatic constexpr int SIG = 8;\nstatic constexpr int MAXL = 12;\nstatic constexpr int MAXM = 800;\n\nstatic constexpr long long SAT_WEIGHT  = 3000000000LL;\nstatic constexpr long long BEST_WEIGHT = 20000LL;\n\nusing Board = array<int, CELLS>;\n\nstruct Word {\n    int len;\n    int weight; // len^2\n    array<int, MAXL> ch{};\n};\n\nstruct Place {\n    int sid;\n    int len;\n    int ori;   // 0 horizontal, 1 vertical\n    int line;\n    int st;\n};\n\nstruct State {\n    int sat = 0;\n    long long bestWeighted = 0;\n    long long supportSum = 0;\n};\n\nstatic int Ninput, M;\nstatic vector<Word> words;\nstatic vector<Place> places;\nstatic vector<vector<int>> wordPlaces;\nstatic vector<int> placeCnt;\nstatic vector<array<int, MAXL + 1>> freq;\nstatic vector<int> bestCnt;\n\nstatic array<array<int, SIG>, CELLS> supW{};\nstatic array<array<int, SIG>, CELLS> supLongW{};\nstatic array<array<vector<int>, SIG>, CELLS> cellByChar{};\nstatic array<array<int, SIG>, CELLS> supportOrder{};\nstatic vector<int> uncertaintyOrder;\nstatic vector<int> longOrder;\n\nstatic Board board;\nstatic State curState;\nstatic mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\nstatic auto startTime = chrono::steady_clock::now();\n\nstatic inline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n}\n\nstatic inline int cid(int r, int c) { return r * N + c; }\n\ntemplate <class F>\nstatic inline void forEachCellOfPlace(int pid, F&& f) {\n    const Place& p = places[pid];\n    if (p.ori == 0) {\n        int c = p.st;\n        int base = p.line * N;\n        for (int t = 0; t < p.len; ++t) {\n            f(base + c);\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = p.st;\n        int c = p.line;\n        for (int t = 0; t < p.len; ++t) {\n            f(cid(r, c));\n            if (++r == N) r = 0;\n        }\n    }\n}\n\nstatic inline int countPlacement(const Board& b, int pid) {\n    const Place& p = places[pid];\n    const Word& w = words[p.sid];\n    int cnt = 0;\n    if (p.ori == 0) {\n        int c = p.st;\n        int base = p.line * N;\n        for (int t = 0; t < p.len; ++t) {\n            cnt += (b[base + c] == w.ch[t]);\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = p.st;\n        int c = p.line;\n        for (int t = 0; t < p.len; ++t) {\n            cnt += (b[cid(r, c)] == w.ch[t]);\n            if (++r == N) r = 0;\n        }\n    }\n    return cnt;\n}\n\ntemplate <class TA, class TB>\nstatic Board makeBoardFromWeighted(const TA& A, const TB& B, int wb) {\n    Board b{};\n    for (int i = 0; i < CELLS; ++i) {\n        int best = -1;\n        int bc = 0;\n        for (int c = 0; c < SIG; ++c) {\n            int sc = A[i][c] + wb * B[i][c];\n            if (sc > best || (sc == best && (rng() & 1ULL))) {\n                best = sc;\n                bc = c;\n            }\n        }\n        b[i] = bc;\n    }\n    return b;\n}\n\nstatic void overlayWord(Board& b, const Word& w, int line, int st, bool horiz) {\n    if (horiz) {\n        int c = st;\n        for (int t = 0; t < w.len; ++t) {\n            b[cid(line, c)] = w.ch[t];\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = st;\n        for (int t = 0; t < w.len; ++t) {\n            b[cid(r, line)] = w.ch[t];\n            if (++r == N) r = 0;\n        }\n    }\n}\n\nstatic Board makeSeededBoard(const Board& base, int shift, int seedCnt = 12) {\n    Board b = base;\n    seedCnt = min(seedCnt, M);\n    for (int i = 0; i < seedCnt; ++i) {\n        int sid = longOrder[(i + shift) % M];\n        bool horiz = ((i + shift) & 1) == 0;\n        int line = (i * 3 + shift * 7) % N;\n        int st = int(rng() % N);\n        overlayWord(b, words[sid], line, st, horiz);\n    }\n    return b;\n}\n\nstatic Board makeRandomBoard() {\n    Board b{};\n    for (int i = 0; i < CELLS; ++i) b[i] = int(rng() & 7ULL);\n    return b;\n}\n\nstatic void mutateBoard(Board& b, int cnt) {\n    int lim = min(120, CELLS);\n    for (int i = 0; i < cnt; ++i) {\n        int idx = uncertaintyOrder[int(rng() % lim)];\n        int cur = b[idx];\n        int alt = cur;\n        for (int t = 0; t < 4 && alt == cur; ++t) {\n            int k = int(rng() % 4);\n            alt = supportOrder[idx][k];\n        }\n        if (alt == cur) alt = (cur + 1) & 7;\n        b[idx] = alt;\n    }\n}\n\nstatic void recomputeAll(const Board& b) {\n    placeCnt.assign(places.size(), 0);\n    freq.assign(M, array<int, MAXL + 1>{});\n    bestCnt.assign(M, 0);\n\n    curState = {};\n    for (int i = 0; i < CELLS; ++i) curState.supportSum += supW[i][b[i]];\n\n    for (int pid = 0; pid < (int)places.size(); ++pid) {\n        int c = countPlacement(b, pid);\n        placeCnt[pid] = c;\n        freq[places[pid].sid][c]++;\n    }\n\n    for (int sid = 0; sid < M; ++sid) {\n        int len = words[sid].len;\n        int best = 0;\n        for (int k = len; k >= 0; --k) {\n            if (freq[sid][k] > 0) {\n                best = k;\n                break;\n            }\n        }\n        bestCnt[sid] = best;\n        curState.sat += (best == len);\n        curState.bestWeighted += 1LL * best * words[sid].weight;\n    }\n}\n\nstatic inline bool betterState(const State& a, const State& b) {\n    if (a.sat != b.sat) return a.sat > b.sat;\n    if (a.bestWeighted != b.bestWeighted) return a.bestWeighted > b.bestWeighted;\n    return a.supportSum > b.supportSum;\n}\n\nstatic long long evalMove(int idx, int cand) {\n    int old = board[idx];\n    if (old == cand) return 0;\n\n    static int diff[MAXM][MAXL + 1];\n    static int seen[MAXM];\n    static int token = 1;\n    ++token;\n\n    static vector<int> touched;\n    touched.clear();\n    touched.reserve(M);\n\n    auto touch = [&](int sid) {\n        if (seen[sid] != token) {\n            seen[sid] = token;\n            memset(diff[sid], 0, sizeof(int) * (words[sid].len + 1));\n            touched.push_back(sid);\n        }\n    };\n\n    auto add = [&](int pid, int delta) {\n        int sid = places[pid].sid;\n        touch(sid);\n        int pc = placeCnt[pid];\n        diff[sid][pc]--;\n        diff[sid][pc + delta]++;\n    };\n\n    for (int pid : cellByChar[idx][old]) add(pid, -1);\n    for (int pid : cellByChar[idx][cand]) add(pid, +1);\n\n    long long dSat = 0, dBest = 0;\n    for (int sid : touched) {\n        int len = words[sid].len;\n        int oldBest = bestCnt[sid];\n        int newBest = 0;\n        for (int k = len; k >= 0; --k) {\n            if (freq[sid][k] + diff[sid][k] > 0) {\n                newBest = k;\n                break;\n            }\n        }\n        dBest += 1LL * (newBest - oldBest) * words[sid].weight;\n        dSat += (newBest == len) - (oldBest == len);\n    }\n\n    long long dSup = 1LL * supW[idx][cand] - supW[idx][old];\n    return dSat * SAT_WEIGHT + dBest * BEST_WEIGHT + dSup;\n}\n\nstatic void applyMove(int idx, int cand) {\n    int old = board[idx];\n    if (old == cand) return;\n\n    static int seen[MAXM];\n    static int token = 1;\n    ++token;\n\n    static vector<int> touched;\n    touched.clear();\n    touched.reserve(M);\n\n    auto touch = [&](int sid) {\n        if (seen[sid] != token) {\n            seen[sid] = token;\n            touched.push_back(sid);\n        }\n    };\n\n    auto upd = [&](const vector<int>& lst, int delta) {\n        for (int pid : lst) {\n            int sid = places[pid].sid;\n            touch(sid);\n            int pc = placeCnt[pid];\n            freq[sid][pc]--;\n            int npc = pc + delta;\n            freq[sid][npc]++;\n            placeCnt[pid] = npc;\n        }\n    };\n\n    upd(cellByChar[idx][old], -1);\n    upd(cellByChar[idx][cand], +1);\n\n    board[idx] = cand;\n    curState.supportSum += 1LL * supW[idx][cand] - supW[idx][old];\n\n    for (int sid : touched) {\n        int len = words[sid].len;\n        int oldBest = bestCnt[sid];\n        int newBest = 0;\n        for (int k = len; k >= 0; --k) {\n            if (freq[sid][k] > 0) {\n                newBest = k;\n                break;\n            }\n        }\n        bestCnt[sid] = newBest;\n        curState.bestWeighted += 1LL * (newBest - oldBest) * words[sid].weight;\n        curState.sat += (newBest == len) - (oldBest == len);\n    }\n}\n\nstatic void emStep(int minLen, int gap) {\n    static long long votes[CELLS][SIG];\n    memset(votes, 0, sizeof(votes));\n\n    for (int sid = 0; sid < M; ++sid) {\n        if (words[sid].len < minLen) continue;\n        int mx = bestCnt[sid];\n        if (mx < 2) continue;\n        int thr = max(1, mx - gap);\n\n        const Word& w = words[sid];\n        for (int pid : wordPlaces[sid]) {\n            int c = placeCnt[pid];\n            if (c < thr) continue;\n\n            long long wt = 1LL * w.weight * (c + 1) * (c + 1);\n            if (c == mx) wt *= 4;\n            if (c == w.len) wt *= 8;\n\n            const Place& p = places[pid];\n            if (p.ori == 0) {\n                int pos = p.st;\n                int base = p.line * N;\n                for (int t = 0; t < p.len; ++t) {\n                    votes[base + pos][w.ch[t]] += wt;\n                    if (++pos == N) pos = 0;\n                }\n            } else {\n                int pos = p.st;\n                int col = p.line;\n                for (int t = 0; t < p.len; ++t) {\n                    votes[cid(pos, col)][w.ch[t]] += wt;\n                    if (++pos == N) pos = 0;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < CELLS; ++i) {\n        int cur = board[i];\n        long long bestV = votes[i][cur] + 1; // inertia\n        int bestC = cur;\n        for (int c = 0; c < SIG; ++c) {\n            if (votes[i][c] > bestV) {\n                bestV = votes[i][c];\n                bestC = c;\n            }\n        }\n        board[i] = bestC;\n    }\n\n    recomputeAll(board);\n}\n\nstatic bool greedySweep(bool reverseOrder) {\n    bool changed = false;\n    if (!reverseOrder) {\n        for (int idx : uncertaintyOrder) {\n            int cur = board[idx];\n            long long bestDelta = 0;\n            int bestCand = cur;\n            for (int c = 0; c < SIG; ++c) {\n                if (c == cur) continue;\n                long long d = evalMove(idx, c);\n                if (d > bestDelta) {\n                    bestDelta = d;\n                    bestCand = c;\n                }\n            }\n            if (bestCand != cur && bestDelta > 0) {\n                applyMove(idx, bestCand);\n                changed = true;\n            }\n        }\n    } else {\n        for (int it = CELLS - 1; it >= 0; --it) {\n            int idx = uncertaintyOrder[it];\n            int cur = board[idx];\n            long long bestDelta = 0;\n            int bestCand = cur;\n            for (int c = 0; c < SIG; ++c) {\n                if (c == cur) continue;\n                long long d = evalMove(idx, c);\n                if (d > bestDelta) {\n                    bestDelta = d;\n                    bestCand = c;\n                }\n            }\n            if (bestCand != cur && bestDelta > 0) {\n                applyMove(idx, bestCand);\n                changed = true;\n            }\n        }\n    }\n    return changed;\n}\n\nstatic int pruneCurrentBoard(Board& outBoard, bitset<CELLS>& outKeep) {\n    vector<vector<int>> fullByWord(M);\n    for (int sid = 0; sid < M; ++sid) {\n        for (int pid : wordPlaces[sid]) {\n            if (placeCnt[pid] == words[sid].len) fullByWord[sid].push_back(pid);\n        }\n        if (fullByWord[sid].empty()) return -1;\n    }\n\n    auto attempt = [&](vector<int> order) -> pair<int, bitset<CELLS>> {\n        bitset<CELLS> keep;\n        keep.reset();\n\n        for (int sid : order) {\n            const auto& cand = fullByWord[sid];\n            int bestPid = cand[0];\n            int bestAdd = INT_MAX;\n\n            for (int pid : cand) {\n                int add = 0;\n                forEachCellOfPlace(pid, [&](int cell) {\n                    if (!keep.test(cell)) ++add;\n                });\n                if (add < bestAdd) {\n                    bestAdd = add;\n                    bestPid = pid;\n                    if (bestAdd == 0) break;\n                }\n            }\n\n            forEachCellOfPlace(bestPid, [&](int cell) {\n                keep.set(cell);\n            });\n        }\n\n        int dots = CELLS - (int)keep.count();\n        return {dots, keep};\n    };\n\n    int bestDots = -1;\n    bitset<CELLS> bestKeep;\n\n    {\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            if (fullByWord[a].size() != fullByWord[b].size()) return fullByWord[a].size() < fullByWord[b].size();\n            if (words[a].len != words[b].len) return words[a].len > words[b].len;\n            return a < b;\n        });\n        auto res = attempt(order);\n        bestDots = res.first;\n        bestKeep = res.second;\n    }\n    {\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            if (words[a].len != words[b].len) return words[a].len > words[b].len;\n            if (fullByWord[a].size() != fullByWord[b].size()) return fullByWord[a].size() < fullByWord[b].size();\n            return a < b;\n        });\n        auto res = attempt(order);\n        if (res.first > bestDots) {\n            bestDots = res.first;\n            bestKeep = res.second;\n        }\n    }\n    {\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        auto res = attempt(order);\n        if (res.first > bestDots) {\n            bestDots = res.first;\n            bestKeep = res.second;\n        }\n    }\n\n    outBoard = board;\n    outKeep = bestKeep;\n    return bestDots;\n}\n\nstatic void outputBoard(const Board& b, const bitset<CELLS>* keep = nullptr) {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int x = b[cid(r, c)];\n            if (keep && !keep->test(cid(r, c))) cout << '.';\n            else cout << char('A' + x);\n        }\n        cout << '\\n';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> Ninput >> M;\n\n    words.resize(M);\n    for (int i = 0; i < M; ++i) {\n        string s;\n        cin >> s;\n        words[i].len = (int)s.size();\n        words[i].weight = words[i].len * words[i].len;\n        for (int j = 0; j < words[i].len; ++j) words[i].ch[j] = s[j] - 'A';\n    }\n\n    longOrder.resize(M);\n    iota(longOrder.begin(), longOrder.end(), 0);\n    sort(longOrder.begin(), longOrder.end(), [&](int a, int b) {\n        if (words[a].len != words[b].len) return words[a].len > words[b].len;\n        return a < b;\n    });\n\n    places.reserve((size_t)M * N * N * 2);\n    wordPlaces.assign(M, {});\n    for (int sid = 0; sid < M; ++sid) wordPlaces[sid].reserve(N * N * 2);\n\n    // Build placements and support tables.\n    for (int sid = 0; sid < M; ++sid) {\n        const Word& w = words[sid];\n        for (int ori = 0; ori < 2; ++ori) {\n            for (int line = 0; line < N; ++line) {\n                for (int st = 0; st < N; ++st) {\n                    int pid = (int)places.size();\n                    places.push_back(Place{sid, w.len, ori, line, st});\n                    wordPlaces[sid].push_back(pid);\n\n                    if (ori == 0) {\n                        int c = st;\n                        for (int t = 0; t < w.len; ++t) {\n                            ++supW[cid(line, c)][w.ch[t]];\n                            if (w.len >= 7) ++supLongW[cid(line, c)][w.ch[t]];\n                            if (++c == N) c = 0;\n                        }\n                    } else {\n                        int r = st;\n                        for (int t = 0; t < w.len; ++t) {\n                            ++supW[cid(r, line)][w.ch[t]];\n                            if (w.len >= 7) ++supLongW[cid(r, line)][w.ch[t]];\n                            if (++r == N) r = 0;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < CELLS; ++i) {\n        for (int c = 0; c < SIG; ++c) {\n            cellByChar[i][c].reserve(max(1, supW[i][c]));\n        }\n    }\n\n    for (int pid = 0; pid < (int)places.size(); ++pid) {\n        const Place& p = places[pid];\n        const Word& w = words[p.sid];\n        if (p.ori == 0) {\n            int c = p.st;\n            int base = p.line * N;\n            for (int t = 0; t < p.len; ++t) {\n                cellByChar[base + c][w.ch[t]].push_back(pid);\n                if (++c == N) c = 0;\n            }\n        } else {\n            int r = p.st;\n            int col = p.line;\n            for (int t = 0; t < p.len; ++t) {\n                cellByChar[cid(r, col)][w.ch[t]].push_back(pid);\n                if (++r == N) r = 0;\n            }\n        }\n    }\n\n    for (int i = 0; i < CELLS; ++i) {\n        array<pair<int, int>, SIG> arr;\n        for (int c = 0; c < SIG; ++c) arr[c] = {supW[i][c], c};\n        sort(arr.begin(), arr.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n        for (int c = 0; c < SIG; ++c) supportOrder[i][c] = arr[c].second;\n        int gap = arr[0].first - arr[1].first;\n        if (i == 0) {\n            uncertaintyOrder.assign(CELLS, 0);\n        }\n        uncertaintyOrder[i] = i;\n    }\n\n    vector<int> gapVal(CELLS);\n    for (int i = 0; i < CELLS; ++i) {\n        array<pair<int, int>, SIG> arr;\n        for (int c = 0; c < SIG; ++c) arr[c] = {supW[i][c], c};\n        sort(arr.begin(), arr.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n        gapVal[i] = arr[0].first - arr[1].first;\n    }\n    sort(uncertaintyOrder.begin(), uncertaintyOrder.end(), [&](int a, int b) {\n        if (gapVal[a] != gapVal[b]) return gapVal[a] < gapVal[b];\n        return a < b;\n    });\n\n    Board supportBoard = makeBoardFromWeighted(supW, supLongW, 0);\n    Board comboBoard = makeBoardFromWeighted(supW, supLongW, 3);\n    Board longBoard = makeBoardFromWeighted(supLongW, supW, 0);\n\n    board = supportBoard;\n    recomputeAll(board);\n\n    State bestState = curState;\n    Board bestBoard = board;\n\n    auto saveBest = [&]() {\n        if (betterState(curState, bestState)) {\n            bestState = curState;\n            bestBoard = board;\n        }\n    };\n\n    Board bestPrunedBoard;\n    bitset<CELLS> bestKeep;\n    int bestDots = -1;\n    bool havePruned = false;\n\n    auto tryPruneIfFull = [&]() {\n        if (curState.sat != M) return;\n        Board outBoard;\n        bitset<CELLS> outKeep;\n        int dots = pruneCurrentBoard(outBoard, outKeep);\n        if (dots >= 0 && dots > bestDots) {\n            bestDots = dots;\n            bestPrunedBoard = outBoard;\n            bestKeep = outKeep;\n            havePruned = true;\n        }\n    };\n\n    int restarts = 0;\n    while (elapsed() < 2.85 && restarts < 5) {\n        Board start;\n        if (restarts == 0) {\n            start = makeSeededBoard(supportBoard, 0, 12);\n        } else if (restarts == 1) {\n            start = makeSeededBoard(comboBoard, 1, 12);\n        } else if (restarts == 2) {\n            start = bestBoard;\n            mutateBoard(start, max(6, 18 - bestState.sat / 40));\n            start = makeSeededBoard(start, 2, 10);\n        } else if (restarts == 3) {\n            start = makeSeededBoard(longBoard, 3, 12);\n            mutateBoard(start, 10);\n        } else {\n            start = makeRandomBoard();\n            start = makeSeededBoard(start, 4, 12);\n        }\n\n        board = start;\n        recomputeAll(board);\n        saveBest();\n        tryPruneIfFull();\n        if (havePruned && elapsed() > 2.90) break;\n\n        if (curState.sat != M && elapsed() < 2.90) {\n            emStep(6, 0);\n            saveBest();\n            tryPruneIfFull();\n        }\n        if (curState.sat != M && elapsed() < 2.90) {\n            greedySweep(false);\n            saveBest();\n            recomputeAll(board); // keep state absolutely consistent before next phase\n            saveBest();\n            tryPruneIfFull();\n        }\n        if (curState.sat != M && elapsed() < 2.90) {\n            emStep(4, 1);\n            saveBest();\n            tryPruneIfFull();\n        }\n        if (curState.sat != M && elapsed() < 2.90) {\n            greedySweep(true);\n            saveBest();\n            recomputeAll(board);\n            saveBest();\n            tryPruneIfFull();\n        }\n\n        if (curState.sat != M && elapsed() < 2.75) {\n            Board kick = board;\n            mutateBoard(kick, bestState.sat < M / 2 ? 18 : 8);\n            board = kick;\n            recomputeAll(board);\n            saveBest();\n            if (curState.sat != M && elapsed() < 2.90) {\n                greedySweep(false);\n                saveBest();\n                recomputeAll(board);\n                saveBest();\n                tryPruneIfFull();\n            }\n        }\n\n        ++restarts;\n    }\n\n    if (bestState.sat == M && !havePruned) {\n        board = bestBoard;\n        recomputeAll(board);\n        Board outBoard;\n        bitset<CELLS> outKeep;\n        int dots = pruneCurrentBoard(outBoard, outKeep);\n        if (dots >= 0) {\n            bestPrunedBoard = outBoard;\n            bestKeep = outKeep;\n            bestDots = dots;\n            havePruned = true;\n        }\n    }\n\n    if (havePruned) {\n        outputBoard(bestPrunedBoard, &bestKeep);\n    } else {\n        outputBoard(bestBoard, nullptr);\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INF = (1LL << 60);\n\nstruct HSeg { int row, l, r; };\nstruct VSeg { int col, u, d; };\n\nstatic const int di[4] = {-1, 1, 0, 0};\nstatic const int dj[4] = {0, 0, -1, 1};\nstatic const char dc[4] = {'U', 'D', 'L', 'R'};\nstatic const int invd[4] = {1, 0, 3, 2};\n\nstruct Solver {\n    int N, si, sj, M, start;\n    vector<string> grid;\n    vector<int> wt, rowOf, colOf;\n    vector<char> road;\n    vector<int> hOf, vOf;\n    vector<vector<int>> hCells, vCells;\n    vector<HSeg> hsegs;\n    vector<VSeg> vsegs;\n    vector<vector<pair<int,int>>> adjCell, revAdjCell;\n\n    void read_input() {\n        cin >> N >> si >> sj;\n        grid.resize(N);\n        for (int i = 0; i < N; ++i) cin >> grid[i];\n\n        M = N * N;\n        start = si * N + sj;\n\n        wt.assign(M, 0);\n        rowOf.assign(M, 0);\n        colOf.assign(M, 0);\n        road.assign(M, 0);\n        hOf.assign(M, -1);\n        vOf.assign(M, -1);\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int id = i * N + j;\n                rowOf[id] = i;\n                colOf[id] = j;\n                if (grid[i][j] != '#') {\n                    road[id] = 1;\n                    wt[id] = grid[i][j] - '0';\n                }\n            }\n        }\n\n        adjCell.assign(M, {});\n        revAdjCell.assign(M, {});\n        for (int id = 0; id < M; ++id) {\n            if (!road[id]) continue;\n            int i = rowOf[id], j = colOf[id];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int to = ni * N + nj;\n                if (!road[to]) continue;\n                adjCell[id].push_back({to, wt[to]});\n                revAdjCell[to].push_back({id, wt[id]});\n            }\n        }\n\n        // Horizontal segments on even rows\n        for (int i = 0; i < N; i += 2) {\n            int j = 0;\n            while (j < N) {\n                while (j < N && !road[i * N + j]) ++j;\n                if (j >= N) break;\n                int l = j;\n                vector<int> cells;\n                while (j < N && road[i * N + j]) {\n                    int id = i * N + j;\n                    cells.push_back(id);\n                    ++j;\n                }\n                int r = j - 1;\n                int sid = (int)hsegs.size();\n                hsegs.push_back({i, l, r});\n                hCells.push_back(cells);\n                for (int x : cells) hOf[x] = sid;\n            }\n        }\n\n        // Vertical segments on even cols\n        for (int j = 0; j < N; j += 2) {\n            int i = 0;\n            while (i < N) {\n                while (i < N && !road[i * N + j]) ++i;\n                if (i >= N) break;\n                int u = i;\n                vector<int> cells;\n                while (i < N && road[i * N + j]) {\n                    int id = i * N + j;\n                    cells.push_back(id);\n                    ++i;\n                }\n                int d = i - 1;\n                int sid = (int)vsegs.size();\n                vsegs.push_back({j, u, d});\n                vCells.push_back(cells);\n                for (int x : cells) vOf[x] = sid;\n            }\n        }\n    }\n\n    void dijkstraCells(int src, const vector<vector<pair<int,int>>>& g,\n                       vector<ll>& dist, vector<int>& parent) const {\n        int V = (int)g.size();\n        dist.assign(V, INF);\n        parent.assign(V, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[src] = 0;\n        parent[src] = src;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, w] : g[u]) {\n                ll nd = d + w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n\n    string reverseRoute(const string& s) const {\n        string t;\n        t.reserve(s.size());\n        for (int i = (int)s.size() - 1; i >= 0; --i) {\n            char c = s[i];\n            if (c == 'U') t.push_back('D');\n            else if (c == 'D') t.push_back('U');\n            else if (c == 'L') t.push_back('R');\n            else if (c == 'R') t.push_back('L');\n        }\n        return t;\n    }\n\n    pair<bool, ll> simulate(const string& s) const {\n        int ci = si, cj = sj;\n        vector<char> covH(hsegs.size(), 0), covV(vsegs.size(), 0);\n        int covered = 0;\n\n        auto cover = [&](int id) {\n            int h = hOf[id];\n            if (h != -1 && !covH[h]) {\n                covH[h] = 1;\n                ++covered;\n            }\n            int v = vOf[id];\n            if (v != -1 && !covV[v]) {\n                covV[v] = 1;\n                ++covered;\n            }\n        };\n\n        cover(start);\n        ll cost = 0;\n\n        for (char c : s) {\n            int d = -1;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            else return {false, 0};\n\n            int ni = ci + di[d], nj = cj + dj[d];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) return {false, 0};\n            int nid = ni * N + nj;\n            if (!road[nid]) return {false, 0};\n\n            ci = ni;\n            cj = nj;\n            cost += wt[nid];\n            cover(nid);\n        }\n\n        if (ci != si || cj != sj) return {false, 0};\n        if (covered != (int)hsegs.size() + (int)vsegs.size()) return {false, 0};\n        return {true, cost};\n    }\n\n    string buildGreedy() const {\n        // Corrected greedy: use exact return-cost from reverse graph.\n        const array<long double, 3> bonus   = {18.0L, 14.0L, 10.0L};\n        const array<long double, 3> retCoef = {0.05L, 0.10L, 0.18L};\n        const array<long double, 3> pickAlpha = {0.05L, 0.10L, 0.15L};\n\n        vector<ll> distBack;\n        vector<int> dummy;\n        dijkstraCells(start, revAdjCell, distBack, dummy);\n\n        auto returnCost = [&](int id) -> ll {\n            return distBack[id];\n        };\n\n        vector<char> covH(hsegs.size(), 0), covV(vsegs.size(), 0);\n        int coveredCnt = 0;\n        auto coverCell = [&](int id) {\n            int h = hOf[id];\n            if (h != -1 && !covH[h]) {\n                covH[h] = 1;\n                ++coveredCnt;\n            }\n            int v = vOf[id];\n            if (v != -1 && !covV[v]) {\n                covV[v] = 1;\n                ++coveredCnt;\n            }\n        };\n        coverCell(start);\n\n        vector<ll> dist;\n        vector<int> parent;\n        vector<int> seenH(hsegs.size(), 0), seenV(vsegs.size(), 0);\n        int stamp = 1;\n\n        int current = start;\n        string route;\n        route.reserve(40000);\n\n        auto appendPath = [&](const vector<int>& path) {\n            int prev = current;\n            for (int id : path) {\n                int pi = rowOf[prev], pj = colOf[prev];\n                int i = rowOf[id], j = colOf[id];\n                if (i == pi - 1 && j == pj) route.push_back('U');\n                else if (i == pi + 1 && j == pj) route.push_back('D');\n                else if (i == pi && j == pj - 1) route.push_back('L');\n                else if (i == pi && j == pj + 1) route.push_back('R');\n                coverCell(id);\n                prev = id;\n            }\n            current = prev;\n        };\n\n        int totalSeg = (int)hsegs.size() + (int)vsegs.size();\n        vector<int> candidates, bestPrefix, tmpPath;\n        vector<int> candMark(M, 0);\n        int candStamp = 1;\n\n        while (coveredCnt < totalSeg) {\n            dijkstraCells(current, adjCell, dist, parent);\n\n            int rem = totalSeg - coveredCnt;\n            int phase = (rem * 3 > totalSeg * 2 ? 0 : (rem * 3 > totalSeg ? 1 : 2));\n\n            candidates.clear();\n            ++candStamp;\n\n            auto addCand = [&](int id) {\n                if (id < 0 || id >= M) return;\n                if (!road[id]) return;\n                if (candMark[id] == candStamp) return;\n                candMark[id] = candStamp;\n                candidates.push_back(id);\n            };\n\n            auto considerCells = [&](const vector<int>& cells) {\n                if (cells.empty()) return;\n                int bestDistCell = -1, bestTradeCell = -1;\n                ll bestDist = INF;\n                long double bestTrade = 1e100L;\n\n                for (int id : cells) {\n                    if (dist[id] >= INF / 2) continue;\n                    if (bestDistCell == -1 || dist[id] < bestDist ||\n                        (dist[id] == bestDist && returnCost(id) < returnCost(bestDistCell))) {\n                        bestDist = dist[id];\n                        bestDistCell = id;\n                    }\n                    long double trade = (long double)dist[id] + pickAlpha[phase] * (long double)returnCost(id);\n                    if (bestTradeCell == -1 || trade < bestTrade - 1e-12L ||\n                        (fabsl(trade - bestTrade) <= 1e-12L && dist[id] < dist[bestTradeCell])) {\n                        bestTrade = trade;\n                        bestTradeCell = id;\n                    }\n                }\n\n                if (bestDistCell != -1) addCand(bestDistCell);\n                if (bestTradeCell != -1) addCand(bestTradeCell);\n                addCand(cells[(int)cells.size() / 2]);\n            };\n\n            for (int i = 0; i < (int)hsegs.size(); ++i) if (!covH[i]) considerCells(hCells[i]);\n            for (int i = 0; i < (int)vsegs.size(); ++i) if (!covV[i]) considerCells(vCells[i]);\n\n            if (candidates.empty()) break;\n\n            long double bestScore = -1e100L;\n            int bestGain = -1;\n            ll bestPrefixCost = INF;\n            ll bestReturn = INF;\n            bestPrefix.clear();\n\n            for (int cand : candidates) {\n                if (dist[cand] >= INF / 2) continue;\n\n                tmpPath.clear();\n                int x = cand;\n                bool ok = true;\n                while (x != current) {\n                    if (x < 0 || x >= M || parent[x] == -1) {\n                        ok = false;\n                        break;\n                    }\n                    tmpPath.push_back(x);\n                    x = parent[x];\n                }\n                if (!ok || tmpPath.empty()) continue;\n                reverse(tmpPath.begin(), tmpPath.end());\n\n                ++stamp;\n                ll prefCost = 0;\n                int gain = 0;\n                int lastPos = -1;\n                ll lastPrefixCost = 0;\n                int lastEnd = -1;\n\n                for (int pos = 0; pos < (int)tmpPath.size(); ++pos) {\n                    int id = tmpPath[pos];\n                    prefCost += wt[id];\n\n                    int add = 0;\n                    int h = hOf[id];\n                    if (h != -1 && !covH[h] && seenH[h] != stamp) {\n                        seenH[h] = stamp;\n                        ++add;\n                    }\n                    int v = vOf[id];\n                    if (v != -1 && !covV[v] && seenV[v] != stamp) {\n                        seenV[v] = stamp;\n                        ++add;\n                    }\n                    if (add) {\n                        gain += add;\n                        lastPos = pos;\n                        lastPrefixCost = prefCost;\n                        lastEnd = id;\n                    }\n                }\n\n                if (gain == 0) continue;\n\n                long double score = bonus[phase] * (long double)gain\n                                  - (long double)lastPrefixCost\n                                  - retCoef[phase] * (long double)returnCost(lastEnd);\n\n                if (score > bestScore + 1e-12L ||\n                    (fabsl(score - bestScore) <= 1e-12L &&\n                     (gain > bestGain ||\n                      (gain == bestGain && (lastPrefixCost < bestPrefixCost ||\n                                            (lastPrefixCost == bestPrefixCost &&\n                                             returnCost(lastEnd) < bestReturn)))))) {\n                    bestScore = score;\n                    bestGain = gain;\n                    bestPrefixCost = lastPrefixCost;\n                    bestReturn = returnCost(lastEnd);\n                    bestPrefix.assign(tmpPath.begin(), tmpPath.begin() + lastPos + 1);\n                }\n            }\n\n            if (bestPrefix.empty()) {\n                bool found = false;\n                for (int cand : candidates) {\n                    tmpPath.clear();\n                    int x = cand;\n                    bool ok = true;\n                    while (x != current) {\n                        if (x < 0 || x >= M || parent[x] == -1) {\n                            ok = false;\n                            break;\n                        }\n                        tmpPath.push_back(x);\n                        x = parent[x];\n                    }\n                    if (ok && !tmpPath.empty()) {\n                        reverse(tmpPath.begin(), tmpPath.end());\n                        bestPrefix = tmpPath;\n                        found = true;\n                        break;\n                    }\n                }\n                if (!found) break;\n            }\n\n            appendPath(bestPrefix);\n        }\n\n        if (current != start) {\n            dijkstraCells(current, adjCell, dist, parent);\n            vector<int> back;\n            int x = start;\n            while (x != current) {\n                if (x < 0 || x >= M || parent[x] == -1) {\n                    back.clear();\n                    break;\n                }\n                back.push_back(x);\n                x = parent[x];\n            }\n            if (!back.empty()) {\n                reverse(back.begin(), back.end());\n                appendPath(back);\n            }\n        }\n\n        return route;\n    }\n\n    string buildPostman() const {\n        struct Edge {\n            int u, v;\n            int cost;\n            string moves;\n        };\n\n        vector<int> deg(M, 0);\n        for (int id = 0; id < M; ++id) if (road[id]) deg[id] = (int)adjCell[id].size();\n\n        vector<char> isNode(M, 0);\n        vector<int> nodeCells;\n        for (int id = 0; id < M; ++id) {\n            if (!road[id]) continue;\n            bool node = false;\n            if (id == start) node = true;\n            else if (deg[id] != 2) node = true;\n            else {\n                int a = adjCell[id][0].first;\n                int b = adjCell[id][1].first;\n                if (!(rowOf[a] == rowOf[b] || colOf[a] == colOf[b])) node = true;\n            }\n            if (node) {\n                isNode[id] = 1;\n                nodeCells.push_back(id);\n            }\n        }\n\n        vector<int> nodeId(M, -1);\n        for (int i = 0; i < (int)nodeCells.size(); ++i) nodeId[nodeCells[i]] = i;\n        int V = (int)nodeCells.size();\n\n        auto step = [&](int id, int d) -> int {\n            int ni = rowOf[id] + di[d];\n            int nj = colOf[id] + dj[d];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) return -1;\n            return ni * N + nj;\n        };\n\n        vector<array<char, 4>> usedStep(M);\n        for (auto &a : usedStep) a.fill(0);\n\n        vector<Edge> edges;\n        vector<vector<pair<int,int>>> g(V);\n\n        for (int s : nodeCells) {\n            for (int d = 0; d < 4; ++d) {\n                int nxt = step(s, d);\n                if (nxt < 0 || !road[nxt] || usedStep[s][d]) continue;\n\n                int cur = s;\n                int prev = s;\n                int dir = d;\n                int cell = nxt;\n                int cost = 0;\n                string moves;\n\n                while (true) {\n                    usedStep[cur][dir] = 1;\n                    usedStep[cell][invd[dir]] = 1;\n\n                    moves.push_back(dc[dir]);\n                    cost += wt[cell];\n\n                    prev = cur;\n                    cur = cell;\n                    if (isNode[cur]) break;\n\n                    int nd = -1, nc = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int t = step(cur, d2);\n                        if (t < 0 || !road[t] || t == prev) continue;\n                        nd = d2;\n                        nc = t;\n                        break;\n                    }\n                    if (nd == -1) break;\n                    dir = nd;\n                    cell = nc;\n                }\n\n                int a = nodeId[s];\n                int b = nodeId[cur];\n                int eid = (int)edges.size();\n                edges.push_back({a, b, cost, moves});\n                if (a == b) {\n                    g[a].push_back({b, eid});\n                    g[a].push_back({b, eid});\n                } else {\n                    g[a].push_back({b, eid});\n                    g[b].push_back({a, eid});\n                }\n            }\n        }\n\n        int K = (int)nodeCells.size();\n        vector<int> odd;\n        for (int i = 0; i < K; ++i) {\n            if ((int)g[i].size() % 2 == 1) odd.push_back(i);\n        }\n        int O = (int)odd.size();\n\n        vector<vector<ll>> dmat(O, vector<ll>(O, INF));\n        vector<vector<int>> parV(O, vector<int>(K, -1));\n        vector<vector<int>> parE(O, vector<int>(K, -1));\n\n        auto dijkstraNode = [&](int src, vector<ll>& dist, vector<int>& pV, vector<int>& pE) {\n            dist.assign(K, INF);\n            pV.assign(K, -1);\n            pE.assign(K, -1);\n            priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n            dist[src] = 0;\n            pV[src] = src;\n            pq.push({0, src});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                if (d != dist[u]) continue;\n                for (auto [v, eid] : g[u]) {\n                    ll nd = d + edges[eid].cost;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        pV[v] = u;\n                        pE[v] = eid;\n                        pq.push({nd, v});\n                    }\n                }\n            }\n        };\n\n        for (int i = 0; i < O; ++i) {\n            vector<ll> dist;\n            dijkstraNode(odd[i], dist, parV[i], parE[i]);\n            for (int j = 0; j < O; ++j) dmat[i][j] = dist[odd[j]];\n        }\n\n        auto totalPairCost = [&](const vector<pair<int,int>>& ps) -> ll {\n            ll sum = 0;\n            for (auto [a, b] : ps) sum += dmat[a][b];\n            return sum;\n        };\n\n        auto makePairsExact = [&]() -> vector<pair<int,int>> {\n            int full = (1 << O) - 1;\n            vector<ll> dp(1 << O, INF);\n            vector<int> preMask(1 << O, -1), pickI(1 << O, -1), pickJ(1 << O, -1);\n            dp[0] = 0;\n            for (int mask = 0; mask <= full; ++mask) {\n                if (dp[mask] >= INF / 2) continue;\n                int i = 0;\n                while (i < O && (mask & (1 << i))) ++i;\n                if (i == O) continue;\n                for (int j = i + 1; j < O; ++j) {\n                    if (mask & (1 << j)) continue;\n                    int nm = mask | (1 << i) | (1 << j);\n                    ll nd = dp[mask] + dmat[i][j];\n                    if (nd < dp[nm]) {\n                        dp[nm] = nd;\n                        preMask[nm] = mask;\n                        pickI[nm] = i;\n                        pickJ[nm] = j;\n                    }\n                }\n            }\n            vector<pair<int,int>> ps;\n            int mask = full;\n            while (mask) {\n                int i = pickI[mask], j = pickJ[mask];\n                if (i < 0 || j < 0) break;\n                ps.push_back({i, j});\n                mask = preMask[mask];\n            }\n            return ps;\n        };\n\n        auto makePairsGreedy = [&]() -> vector<pair<int,int>> {\n            vector<char> used(O, 0);\n            vector<pair<int,int>> ps;\n            while (true) {\n                ll best = INF;\n                int bi = -1, bj = -1;\n                for (int i = 0; i < O; ++i) if (!used[i]) {\n                    for (int j = i + 1; j < O; ++j) if (!used[j]) {\n                        if (dmat[i][j] < best) {\n                            best = dmat[i][j];\n                            bi = i;\n                            bj = j;\n                        }\n                    }\n                }\n                if (bi == -1) break;\n                used[bi] = used[bj] = 1;\n                ps.push_back({bi, bj});\n            }\n            return ps;\n        };\n\n        vector<pair<int,int>> bestPairs;\n        ll bestCost = INF;\n\n        if (O == 0) {\n            bestPairs.clear();\n            bestCost = 0;\n        } else if (O <= 20) {\n            bestPairs = makePairsExact();\n            bestCost = totalPairCost(bestPairs);\n        } else {\n            // Several simple pairing orders.\n            vector<int> ord(O);\n            iota(ord.begin(), ord.end(), 0);\n\n            vector<vector<int>> orders;\n            orders.push_back(ord);\n\n            auto rev = ord;\n            reverse(rev.begin(), rev.end());\n            orders.push_back(rev);\n\n            auto shuf = ord;\n            mt19937 rng(712367 + N * 10007 + si * 1009 + sj * 9176);\n            shuffle(shuf.begin(), shuf.end(), rng);\n            orders.push_back(shuf);\n\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                ll sa = 0, sb = 0;\n                for (int t = 0; t < O; ++t) {\n                    if (a != t) sa += min(dmat[a][t], (ll)1e9);\n                    if (b != t) sb += min(dmat[b][t], (ll)1e9);\n                }\n                return sa < sb;\n            });\n            orders.push_back(ord);\n\n            for (auto o : orders) {\n                vector<char> used(O, 0);\n                vector<pair<int,int>> ps;\n                for (int x : o) {\n                    if (used[x]) continue;\n                    used[x] = 1;\n                    int bestY = -1;\n                    ll best = INF;\n                    for (int y = 0; y < O; ++y) {\n                        if (used[y] || y == x) continue;\n                        if (dmat[x][y] < best) {\n                            best = dmat[x][y];\n                            bestY = y;\n                        }\n                    }\n                    if (bestY != -1) {\n                        used[bestY] = 1;\n                        ps.push_back({x, bestY});\n                    }\n                }\n                ll c = totalPairCost(ps);\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestPairs = ps;\n                }\n            }\n\n            if (bestPairs.empty()) bestPairs = makePairsGreedy();\n        }\n\n        vector<int> dup(edges.size(), 0);\n        for (auto [a, b] : bestPairs) {\n            if (a < 0 || b < 0) continue;\n            int v = odd[b];\n            while (v != odd[a]) {\n                int eid = parE[a][v];\n                if (eid < 0) break;\n                dup[eid]++;\n                v = parV[a][v];\n            }\n        }\n\n        struct UseEdge {\n            int u, v, orig;\n        };\n\n        vector<UseEdge> uses;\n        vector<vector<pair<int,int>>> mg(K);\n\n        for (int eid = 0; eid < (int)edges.size(); ++eid) {\n            int cnt = 1 + dup[eid];\n            for (int k = 0; k < cnt; ++k) {\n                int uid = (int)uses.size();\n                uses.push_back({edges[eid].u, edges[eid].v, eid});\n                if (edges[eid].u == edges[eid].v) {\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                } else {\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                    mg[edges[eid].v].push_back({edges[eid].u, uid});\n                }\n            }\n        }\n\n        if (start < 0 || start >= M || nodeId[start] < 0) return \"\";\n\n        vector<int> it(K, 0), stV, stE, stRev;\n        vector<char> usedUse(uses.size(), 0);\n        vector<pair<int,int>> circuit;\n\n        stV.push_back(nodeId[start]);\n\n        while (!stV.empty()) {\n            int v = stV.back();\n            auto &adj = mg[v];\n            while (it[v] < (int)adj.size() && usedUse[adj[it[v]].second]) ++it[v];\n            if (it[v] == (int)adj.size()) {\n                stV.pop_back();\n                if (!stE.empty()) {\n                    circuit.push_back({stE.back(), stRev.back()});\n                    stE.pop_back();\n                    stRev.pop_back();\n                }\n            } else {\n                auto [to, uid] = adj[it[v]++];\n                if (usedUse[uid]) continue;\n                usedUse[uid] = 1;\n                bool rev = (v != uses[uid].u);\n                stV.push_back(to);\n                stE.push_back(uid);\n                stRev.push_back(rev ? 1 : 0);\n            }\n        }\n\n        reverse(circuit.begin(), circuit.end());\n\n        string route;\n        route.reserve(40000);\n        auto invertMove = [&](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        for (auto [uid, rev] : circuit) {\n            const auto &e = edges[uses[uid].orig];\n            if (!rev) {\n                route += e.moves;\n            } else {\n                for (int i = (int)e.moves.size() - 1; i >= 0; --i) {\n                    route.push_back(invertMove(e.moves[i]));\n                }\n            }\n        }\n\n        return route;\n    }\n\n    string buildSegmentTSP() const {\n        // Valid anchored route: start + chosen representative of each uncovered segment.\n        vector<ll> distStartFwd, distStartBack;\n        vector<int> dummy;\n        dijkstraCells(start, adjCell, distStartFwd, dummy);\n        dijkstraCells(start, revAdjCell, distStartBack, dummy);\n\n        vector<int> nodeCell;\n        vector<int> nodeWeight;\n        vector<int> cellToNode(M, -1);\n\n        nodeCell.push_back(start);\n        nodeWeight.push_back(0);\n        cellToNode[start] = 0;\n\n        auto chooseRep = [&](const vector<int>& cells) -> int {\n            int mid = (int)cells.size() / 2;\n            int best = cells[0];\n            auto key = [&](int id) {\n                int coverCnt = (hOf[id] != -1) + (vOf[id] != -1);\n                ll roundTrip = distStartFwd[id] + distStartBack[id];\n                ll fromStart = distStartFwd[id];\n                int midDist = abs((int)(lower_bound(cells.begin(), cells.end(), id) - cells.begin()) - mid);\n                return tuple<int, ll, ll, int>(-coverCnt, roundTrip, fromStart, id);\n            };\n            // Since cells are not sorted by ID meaningfully, use a direct scan with tie-breaking.\n            best = cells[0];\n            auto bestKey = tuple<int, ll, ll, int>(-( (hOf[best] != -1) + (vOf[best] != -1) ),\n                                                   distStartFwd[best] + distStartBack[best],\n                                                   distStartFwd[best],\n                                                   best);\n            for (int id : cells) {\n                auto k = tuple<int, ll, ll, int>(-( (hOf[id] != -1) + (vOf[id] != -1) ),\n                                                 distStartFwd[id] + distStartBack[id],\n                                                 distStartFwd[id],\n                                                 id);\n                if (k < bestKey) {\n                    bestKey = k;\n                    best = id;\n                }\n            }\n            return best;\n        };\n\n        // Add a representative for each segment not already covered by the start.\n        for (int i = 0; i < (int)hsegs.size(); ++i) {\n            if (hOf[start] == i) continue;\n            int rep = chooseRep(hCells[i]);\n            if (cellToNode[rep] == -1) {\n                cellToNode[rep] = (int)nodeCell.size();\n                nodeCell.push_back(rep);\n                nodeWeight.push_back(0);\n            }\n            nodeWeight[cellToNode[rep]]++;\n        }\n        for (int i = 0; i < (int)vsegs.size(); ++i) {\n            if (vOf[start] == i) continue;\n            int rep = chooseRep(vCells[i]);\n            if (cellToNode[rep] == -1) {\n                cellToNode[rep] = (int)nodeCell.size();\n                nodeCell.push_back(rep);\n                nodeWeight.push_back(0);\n            }\n            nodeWeight[cellToNode[rep]]++;\n        }\n\n        int n = (int)nodeCell.size();\n        if (n == 1) return \"\";\n\n        // All-pairs shortest path between chosen nodes.\n        vector<vector<ll>> D(n, vector<ll>(n, INF));\n        vector<ll> dist;\n        vector<int> parent;\n        for (int i = 0; i < n; ++i) {\n            dijkstraCells(nodeCell[i], adjCell, dist, parent);\n            for (int j = 0; j < n; ++j) D[i][j] = dist[nodeCell[j]];\n        }\n\n        auto cycleCost = [&](const vector<int>& ord) -> ll {\n            ll s = 0;\n            for (int i = 0; i + 1 < (int)ord.size(); ++i) s += D[ord[i]][ord[i + 1]];\n            return s;\n        };\n\n        auto buildNN = [&]() {\n            vector<int> ord;\n            vector<char> used(n, 0);\n            ord.push_back(0);\n            used[0] = 1;\n            int cur = 0;\n            while ((int)ord.size() < n) {\n                int best = -1;\n                long double bestVal = 1e100L;\n                for (int x = 1; x < n; ++x) if (!used[x]) {\n                    long double val = (long double)D[cur][x]\n                                    + 0.12L * (long double)D[x][0]\n                                    - 0.20L * (long double)nodeWeight[x];\n                    if (val < bestVal) {\n                        bestVal = val;\n                        best = x;\n                    }\n                }\n                used[best] = 1;\n                ord.push_back(best);\n                cur = best;\n            }\n            ord.push_back(0);\n            return ord;\n        };\n\n        auto buildInsertion = [&](bool farthestSeed) {\n            vector<int> ord;\n            vector<char> used(n, 0);\n            ord = {0};\n            used[0] = 1;\n\n            int seed = -1;\n            long double seedVal = farthestSeed ? -1e100L : 1e100L;\n            for (int x = 1; x < n; ++x) {\n                long double val = (long double)D[0][x] + (long double)D[x][0]\n                                - 0.20L * (long double)nodeWeight[x];\n                if ((farthestSeed && val > seedVal) || (!farthestSeed && val < seedVal)) {\n                    seedVal = val;\n                    seed = x;\n                }\n            }\n            ord.push_back(seed);\n            ord.push_back(0);\n            used[seed] = 1;\n\n            while ((int)ord.size() < n + 1) {\n                int choose = -1;\n                int choosePos = -1;\n                long double bestVal = 1e100L;\n                for (int x = 1; x < n; ++x) if (!used[x]) {\n                    for (int p = 1; p < (int)ord.size(); ++p) {\n                        ll delta = D[ord[p - 1]][x] + D[x][ord[p]] - D[ord[p - 1]][ord[p]];\n                        long double val = (long double)delta - 0.15L * (long double)nodeWeight[x];\n                        if (val < bestVal) {\n                            bestVal = val;\n                            choose = x;\n                            choosePos = p;\n                        }\n                    }\n                }\n                ord.insert(ord.begin() + choosePos, choose);\n                used[choose] = 1;\n            }\n            return ord;\n        };\n\n        vector<vector<int>> orders;\n        orders.push_back(buildNN());\n        orders.push_back(buildInsertion(false));\n        orders.push_back(buildInsertion(true));\n\n        vector<int> byWeight(n);\n        iota(byWeight.begin(), byWeight.end(), 0);\n        sort(byWeight.begin() + 1, byWeight.end(), [&](int a, int b) {\n            if (nodeWeight[a] != nodeWeight[b]) return nodeWeight[a] > nodeWeight[b];\n            ll ta = D[0][a] + D[a][0];\n            ll tb = D[0][b] + D[b][0];\n            return ta < tb;\n        });\n        byWeight.push_back(0);\n        orders.push_back(byWeight);\n\n        vector<int> bestOrd = orders[0];\n        ll bestCost = cycleCost(bestOrd);\n        for (auto &ord : orders) {\n            ll c = cycleCost(ord);\n            if (c < bestCost) {\n                bestCost = c;\n                bestOrd = ord;\n            }\n        }\n\n        // Reconstruct actual route from the chosen order.\n        string ans;\n        ans.reserve(40000);\n\n        auto appendPath = [&](int srcCell, int dstCell) {\n            if (srcCell == dstCell) return;\n            vector<ll> dist2;\n            vector<int> par2;\n            dijkstraCells(srcCell, adjCell, dist2, par2);\n\n            vector<int> path;\n            int x = dstCell;\n            while (x != srcCell) {\n                if (x < 0 || x >= M || par2[x] == -1) {\n                    path.clear();\n                    break;\n                }\n                path.push_back(x);\n                x = par2[x];\n            }\n            if (path.empty()) return;\n            reverse(path.begin(), path.end());\n\n            int prev = srcCell;\n            for (int id : path) {\n                int pi = rowOf[prev], pj = colOf[prev];\n                int i = rowOf[id], j = colOf[id];\n                if (i == pi - 1 && j == pj) ans.push_back('U');\n                else if (i == pi + 1 && j == pj) ans.push_back('D');\n                else if (i == pi && j == pj - 1) ans.push_back('L');\n                else if (i == pi && j == pj + 1) ans.push_back('R');\n                prev = id;\n            }\n        };\n\n        for (int i = 0; i + 1 < (int)bestOrd.size(); ++i) {\n            appendPath(nodeCell[bestOrd[i]], nodeCell[bestOrd[i + 1]]);\n        }\n\n        return ans;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.read_input();\n\n    vector<string> candidates;\n\n    string g = solver.buildGreedy();\n    candidates.push_back(g);\n    candidates.push_back(solver.reverseRoute(g));\n\n    string p = solver.buildPostman();\n    candidates.push_back(p);\n    candidates.push_back(solver.reverseRoute(p));\n\n    string t = solver.buildSegmentTSP();\n    candidates.push_back(t);\n    candidates.push_back(solver.reverseRoute(t));\n\n    string best;\n    ll bestCost = INF;\n    size_t bestLen = numeric_limits<size_t>::max();\n\n    for (const auto& s : candidates) {\n        auto [ok, cost] = solver.simulate(s);\n        if (!ok) continue;\n        if (cost < bestCost || (cost == bestCost && s.size() < bestLen)) {\n            bestCost = cost;\n            bestLen = s.size();\n            best = s;\n        }\n    }\n\n    if (best.empty() && !candidates.empty()) best = candidates[0];\n    cout << best << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskNode {\n    long long pr;\n    int id;\n};\n\nstruct TaskCmp {\n    bool operator()(const TaskNode& a, const TaskNode& b) const {\n        if (a.pr != b.pr) return a.pr < b.pr; // max-heap by priority\n        return a.id > b.id;                  // smaller id first on tie\n    }\n};\n\nstatic const double INIT_SKILL = 5.0;\n\nvector<int> hungarian_min_cost(const vector<vector<double>>& a) {\n    int n = (int)a.size();\n    const double INF = 1e100;\n    vector<double> u(n + 1, 0.0), v(n + 1, 0.0), minv(n + 1);\n    vector<int> p(n + 1, 0), way(n + 1, 0);\n\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        fill(minv.begin(), minv.end(), INF);\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            double delta = INF;\n            int j1 = 0;\n\n            for (int j = 1; j <= n; ++j) {\n                if (used[j]) continue;\n                double cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n\n            for (int j = 0; j <= n; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    vector<int> ans(n, -1);\n    for (int j = 1; j <= n; ++j) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<vector<int>> d(N, vector<int>(K));\n    vector<long long> sumd(N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            cin >> d[i][k];\n            sumd[i] += d[i][k];\n        }\n    }\n\n    vector<vector<int>> succ(N);\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Weighted criticality: own difficulty + longest downstream chain difficulty.\n    vector<long long> workRemain(N, 0), height(N, 0);\n    for (int i = N - 1; i >= 0; --i) {\n        long long bestWork = 0;\n        long long bestH = 0;\n        for (int v : succ[i]) {\n            bestWork = max(bestWork, workRemain[v]);\n            bestH = max(bestH, height[v]);\n        }\n        workRemain[i] = sumd[i] + bestWork;\n        height[i] = 1 + bestH;\n    }\n\n    vector<long long> priority(N, 0);\n    for (int i = 0; i < N; ++i) {\n        priority[i] = workRemain[i] * 1000LL + height[i];\n    }\n\n    priority_queue<TaskNode, vector<TaskNode>, TaskCmp> pq;\n    for (int i = 0; i < N; ++i) {\n        if (indeg[i] == 0) pq.push({priority[i], i});\n    }\n\n    vector<int> busyTask(M, -1);\n    vector<int> startDay(M, -1);\n    vector<int> taskStatus(N, 0); // 0=not started, 1=started, 2=done\n    vector<vector<double>> skill(M, vector<double>(K, INIT_SKILL));\n    vector<int> obsCnt(M, 0);\n\n    auto predict_duration = [&](int mem, int task) -> double {\n        double w = 0.0;\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill[mem][k]) {\n                w += (double)d[task][k] - skill[mem][k];\n            }\n        }\n        return max(1.0, w);\n    };\n\n    auto update_skill = [&](int mem, int task, int dur) {\n        double w = 0.0;\n        vector<double> gap(K, 0.0);\n        for (int k = 0; k < K; ++k) {\n            if (d[task][k] > skill[mem][k]) {\n                gap[k] = (double)d[task][k] - skill[mem][k];\n                w += gap[k];\n            }\n        }\n\n        double pred = max(1.0, w);\n        double err = (double)dur - pred;\n        err = max(-4.0, min(4.0, err));\n\n        double eta = 0.5 / sqrt((double)obsCnt[mem] + 1.0);\n\n        if (w > 1e-9) {\n            for (int k = 0; k < K; ++k) {\n                if (gap[k] <= 0.0) continue;\n                skill[mem][k] -= eta * err * (gap[k] / w);\n                if (skill[mem][k] < 0.0) skill[mem][k] = 0.0;\n                if (skill[mem][k] > 100.0) skill[mem][k] = 100.0;\n            }\n        } else if (err > 0.0) {\n            // If predicted exactly 1, but actual duration was longer, lower all skills slightly.\n            double dec = eta * err / max(1, K);\n            for (int k = 0; k < K; ++k) {\n                skill[mem][k] = max(0.0, skill[mem][k] - dec);\n            }\n        }\n\n        obsCnt[mem]++;\n    };\n\n    int day = 1;\n    while (true) {\n        vector<int> freeMembers;\n        freeMembers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (busyTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        int freeCount = (int)freeMembers.size();\n        int take = min(freeCount, (int)pq.size());\n\n        vector<int> selected;\n        selected.reserve(take);\n        for (int t = 0; t < take; ++t) {\n            selected.push_back(pq.top().id);\n            pq.pop();\n        }\n\n        vector<pair<int,int>> outPairs;\n\n        if (freeCount > 0 && !selected.empty()) {\n            int n = freeCount;\n            int L = (int)selected.size();\n\n            vector<vector<double>> cost(n, vector<double>(n, 0.0));\n            for (int r = 0; r < n; ++r) {\n                int mem = freeMembers[r];\n                for (int c = 0; c < L; ++c) {\n                    cost[r][c] = predict_duration(mem, selected[c]);\n                }\n                for (int c = L; c < n; ++c) {\n                    cost[r][c] = 0.0; // dummy task\n                }\n            }\n\n            vector<int> assign = hungarian_min_cost(cost);\n\n            for (int r = 0; r < n; ++r) {\n                int c = assign[r];\n                if (c >= 0 && c < L) {\n                    int mem = freeMembers[r];\n                    int task = selected[c];\n                    outPairs.push_back({mem, task});\n                    busyTask[mem] = task;\n                    startDay[mem] = day;\n                    taskStatus[task] = 1;\n                }\n            }\n        }\n\n        cout << outPairs.size();\n        for (auto &p : outPairs) {\n            cout << ' ' << (p.first + 1) << ' ' << (p.second + 1);\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        vector<int> finished(cnt);\n        for (int i = 0; i < cnt; ++i) cin >> finished[i];\n\n        for (int mem1 : finished) {\n            int mem = mem1 - 1;\n            int task = busyTask[mem];\n            if (task < 0) continue;\n\n            int dur = day - startDay[mem] + 1;\n            update_skill(mem, task, dur);\n\n            busyTask[mem] = -1;\n            startDay[mem] = -1;\n            taskStatus[task] = 2;\n\n            for (int v : succ[task]) {\n                if (--indeg[v] == 0) {\n                    pq.push({priority[v], v});\n                }\n            }\n        }\n\n        day++;\n    }\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int N = 1000;\nstatic constexpr ll INFLL = (1LL << 60);\n\nstruct Pt {\n    int x, y;\n};\n\nstruct Order {\n    Pt p, q;\n    ll pq, op, oq;\n    ll mx2, my2;\n};\n\nstruct Event {\n    int id;\n    int type; // 0 = pickup, 1 = delivery\n};\n\nstruct InsInfo {\n    ll best = INFLL;\n    ll second = INFLL;\n    int i = 0, j = 0;\n    bool same = true;\n};\n\nstruct State {\n    ll cost = INFLL;\n    vector<Event> seq;\n    array<char, N> used{};\n};\n\nstruct Cand {\n    vector<int> sel;\n    int scoreId = -1;\n    Pt anchor{400, 400};\n    ll proxy = 0;\n    ll quickCost = INFLL;\n};\n\nstatic constexpr Pt OFFICE{400, 400};\n\nvector<Order> ord(N);\nvector<vector<ll>> scoreVecs;\nvector<Pt> scoreAnchors;\n\nstatic chrono::steady_clock::time_point gStart;\nstatic inline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - gStart).count();\n}\n\nstatic inline ll absl(ll x) { return x >= 0 ? x : -x; }\nstatic inline ll md(const Pt& a, const Pt& b) {\n    return absl((ll)a.x - b.x) + absl((ll)a.y - b.y);\n}\nstatic inline Pt pointOf(const Event& e) {\n    return e.type == 0 ? ord[e.id].p : ord[e.id].q;\n}\nstatic inline ll directCost(int id) {\n    return ord[id].op + ord[id].pq + ord[id].oq;\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\nstatic vector<Pt> buildPts(const vector<Event>& seq) {\n    vector<Pt> pts;\n    pts.reserve(seq.size() + 2);\n    pts.push_back(OFFICE);\n    for (const auto& e : seq) pts.push_back(pointOf(e));\n    pts.push_back(OFFICE);\n    return pts;\n}\n\nstatic ll routeCostPts(const vector<Pt>& pts) {\n    ll c = 0;\n    for (int i = 0; i + 1 < (int)pts.size(); ++i) c += md(pts[i], pts[i + 1]);\n    return c;\n}\n\nstatic ll seqCost(const vector<Event>& seq) {\n    return routeCostPts(buildPts(seq));\n}\n\nstatic InsInfo bestInsertPts(const vector<Pt>& pts, int id) {\n    int m = (int)pts.size() - 2;\n    const Pt& P = ord[id].p;\n    const Pt& Q = ord[id].q;\n\n    InsInfo res;\n    for (int i = 0; i <= m; ++i) {\n        ll e0 = md(pts[i], pts[i + 1]);\n\n        ll sameDelta = md(pts[i], P) + ord[id].pq + md(Q, pts[i + 1]) - e0;\n        if (sameDelta < res.best) {\n            res.second = res.best;\n            res.best = sameDelta;\n            res.i = i;\n            res.j = i;\n            res.same = true;\n        } else if (sameDelta < res.second) {\n            res.second = sameDelta;\n        }\n\n        ll left = md(pts[i], P) + md(P, pts[i + 1]) - e0;\n        for (int j = i + 1; j <= m; ++j) {\n            ll e1 = md(pts[j], pts[j + 1]);\n            ll delta = left + md(pts[j], Q) + md(Q, pts[j + 1]) - e1;\n            if (delta < res.best) {\n                res.second = res.best;\n                res.best = delta;\n                res.i = i;\n                res.j = j;\n                res.same = false;\n            } else if (delta < res.second) {\n                res.second = delta;\n            }\n        }\n    }\n    return res;\n}\n\nstatic void applyInsert(vector<Event>& seq, const InsInfo& ins, int id) {\n    seq.insert(seq.begin() + ins.i, Event{id, 0});\n    if (ins.same) {\n        seq.insert(seq.begin() + ins.i + 1, Event{id, 1});\n    } else {\n        seq.insert(seq.begin() + ins.j + 1, Event{id, 1});\n    }\n}\n\nstatic vector<Event> removeOrderSeq(const vector<Event>& seq, int id) {\n    vector<Event> res;\n    res.reserve(seq.size() - 2);\n    for (const auto& e : seq) if (e.id != id) res.push_back(e);\n    return res;\n}\n\nstatic vector<int> selectedIds(const array<char, N>& used) {\n    vector<int> ids;\n    for (int i = 0; i < N; ++i) if (used[i]) ids.push_back(i);\n    return ids;\n}\n\nstatic vector<int> selectTop50(const vector<ll>& score) {\n    vector<int> ids(N);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int a, int b) {\n        if (score[a] != score[b]) return score[a] < score[b];\n        return a < b;\n    });\n    ids.resize(50);\n    sort(ids.begin(), ids.end());\n    return ids;\n}\n\nstatic string keyOfSel(const vector<int>& sel) {\n    string s;\n    s.reserve(sel.size() * 6);\n    for (int x : sel) {\n        s += to_string(x);\n        s.push_back(',');\n    }\n    return s;\n}\n\nstatic vector<int> orderByScore(const vector<int>& sel, int sid, bool desc) {\n    vector<int> ords = sel;\n    const auto& sc = scoreVecs[sid];\n    sort(ords.begin(), ords.end(), [&](int a, int b) {\n        if (sc[a] != sc[b]) return desc ? (sc[a] > sc[b]) : (sc[a] < sc[b]);\n        return a < b;\n    });\n    return ords;\n}\n\nstatic vector<int> orderByPQ(const vector<int>& sel, bool desc) {\n    vector<int> ords = sel;\n    sort(ords.begin(), ords.end(), [&](int a, int b) {\n        if (ord[a].pq != ord[b].pq) return desc ? (ord[a].pq > ord[b].pq) : (ord[a].pq < ord[b].pq);\n        return a < b;\n    });\n    return ords;\n}\n\nstatic vector<int> orderByAngle(const vector<int>& sel, Pt anchor) {\n    vector<pair<double,int>> tmp;\n    tmp.reserve(sel.size());\n    for (int id : sel) {\n        double x = (double)ord[id].mx2 * 0.5 - anchor.x;\n        double y = (double)ord[id].my2 * 0.5 - anchor.y;\n        tmp.push_back({atan2(y, x), id});\n    }\n    sort(tmp.begin(), tmp.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n    vector<int> ords;\n    ords.reserve(sel.size());\n    for (auto& t : tmp) ords.push_back(t.second);\n    return ords;\n}\n\nstatic State buildInsertionState(const vector<int>& sel, const vector<int>& order) {\n    State st;\n    st.used.fill(0);\n    for (int id : sel) st.used[id] = 1;\n\n    st.seq.clear();\n    st.seq.reserve(100);\n\n    for (int id : order) {\n        vector<Pt> pts = buildPts(st.seq);\n        InsInfo ins = bestInsertPts(pts, id);\n        applyInsert(st.seq, ins, id);\n    }\n    st.cost = seqCost(st.seq);\n    return st;\n}\n\nstatic State buildRegretState(const vector<int>& sel, int startMode, uint64_t seed) {\n    State st;\n    st.used.fill(0);\n    for (int id : sel) st.used[id] = 1;\n\n    vector<int> rem = sel;\n    vector<pair<ll,int>> d;\n    d.reserve(rem.size());\n    for (int id : rem) d.push_back({directCost(id), id});\n    sort(d.begin(), d.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n\n    int first = d[0].second;\n    if (startMode == 1) {\n        int k = min(8, (int)d.size());\n        uint64_t r = splitmix64(seed);\n        first = d[r % k].second;\n    }\n\n    st.seq.push_back({first, 0});\n    st.seq.push_back({first, 1});\n    st.cost = directCost(first);\n\n    rem.erase(find(rem.begin(), rem.end(), first));\n\n    while (!rem.empty()) {\n        vector<Pt> pts = buildPts(st.seq);\n\n        ll bestReg = -INFLL;\n        ll bestDelta = INFLL;\n        ll bestDirect = INFLL;\n        int choose = -1;\n        InsInfo chooseIns;\n\n        for (int id : rem) {\n            InsInfo ins = bestInsertPts(pts, id);\n            ll sec = (ins.second >= INFLL / 4 ? INFLL / 4 : ins.second);\n            ll reg = sec - ins.best;\n            ll dir = directCost(id);\n            if (reg > bestReg ||\n                (reg == bestReg && (ins.best < bestDelta ||\n                 (ins.best == bestDelta && dir < bestDirect)))) {\n                bestReg = reg;\n                bestDelta = ins.best;\n                bestDirect = dir;\n                choose = id;\n                chooseIns = ins;\n            }\n        }\n\n        applyInsert(st.seq, chooseIns, choose);\n        st.cost += chooseIns.best;\n        rem.erase(find(rem.begin(), rem.end(), choose));\n    }\n\n    st.cost = seqCost(st.seq);\n    return st;\n}\n\nstatic void optimizeAdj(State& st) {\n    for (int iter = 0; iter < 50; ++iter) {\n        bool improved = false;\n        int m = (int)st.seq.size();\n        for (int i = 0; i + 1 < m; ++i) {\n            if (st.seq[i].id == st.seq[i + 1].id) continue;\n            Pt prev = (i == 0 ? OFFICE : pointOf(st.seq[i - 1]));\n            Pt a = pointOf(st.seq[i]);\n            Pt b = pointOf(st.seq[i + 1]);\n            Pt nxt = (i + 2 == m ? OFFICE : pointOf(st.seq[i + 2]));\n\n            ll before = md(prev, a) + md(a, b) + md(b, nxt);\n            ll after  = md(prev, b) + md(b, a) + md(a, nxt);\n\n            if (after < before) {\n                swap(st.seq[i], st.seq[i + 1]);\n                st.cost += after - before;\n                improved = true;\n                break;\n            }\n        }\n        if (!improved) break;\n    }\n}\n\nstatic bool pairBestImprove(State& st) {\n    vector<int> ids = selectedIds(st.used);\n    ll bestCost = st.cost;\n    int bestId = -1;\n    InsInfo bestIns;\n    vector<Event> bestReduced;\n\n    for (int id : ids) {\n        vector<Event> reduced = removeOrderSeq(st.seq, id);\n        vector<Pt> pts = buildPts(reduced);\n        ll redCost = routeCostPts(pts);\n        InsInfo ins = bestInsertPts(pts, id);\n        ll nc = redCost + ins.best;\n        if (nc < bestCost) {\n            bestCost = nc;\n            bestId = id;\n            bestIns = ins;\n            bestReduced = std::move(reduced);\n        }\n    }\n\n    if (bestId == -1) return false;\n\n    st.seq = std::move(bestReduced);\n    applyInsert(st.seq, bestIns, bestId);\n    st.cost = bestCost;\n    return true;\n}\n\nstatic vector<int> buildPool(const vector<vector<int>>& rankLists,\n                             const vector<int>& rankIds,\n                             const array<char, N>& used,\n                             int perLimit,\n                             int maxSize) {\n    vector<int> pool;\n    pool.reserve(maxSize);\n    array<char, N> seen{};\n    seen.fill(0);\n\n    for (int rid : rankIds) {\n        int cnt = 0;\n        for (int id : rankLists[rid]) {\n            if (used[id] || seen[id]) continue;\n            seen[id] = 1;\n            pool.push_back(id);\n            if (++cnt == perLimit) break;\n        }\n    }\n\n    if ((int)pool.size() > maxSize) pool.resize(maxSize);\n    return pool;\n}\n\nstatic bool swapBestImprove(State& st,\n                            const vector<vector<int>>& rankLists,\n                            const vector<int>& rankIds) {\n    vector<int> ids = selectedIds(st.used);\n    vector<pair<ll,int>> gain;\n    gain.reserve(ids.size());\n\n    for (int id : ids) {\n        vector<Event> reduced = removeOrderSeq(st.seq, id);\n        ll redCost = seqCost(reduced);\n        gain.push_back({st.cost - redCost, id});\n    }\n\n    sort(gain.begin(), gain.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    vector<int> pool = buildPool(rankLists, rankIds, st.used, 20, 40);\n    if (pool.empty()) return false;\n\n    int Kremove = min(10, (int)gain.size());\n    int Kadd = min(30, (int)pool.size());\n\n    ll bestCost = st.cost;\n    int bestRem = -1, bestAdd = -1;\n    InsInfo bestIns;\n    vector<Event> bestReduced;\n\n    for (int t = 0; t < Kremove; ++t) {\n        int remId = gain[t].second;\n        vector<Event> reduced = removeOrderSeq(st.seq, remId);\n        vector<Pt> pts = buildPts(reduced);\n        ll redCost = routeCostPts(pts);\n\n        for (int k = 0; k < Kadd; ++k) {\n            int addId = pool[k];\n            if (st.used[addId]) continue;\n            InsInfo ins = bestInsertPts(pts, addId);\n            ll nc = redCost + ins.best;\n            if (nc < bestCost) {\n                bestCost = nc;\n                bestRem = remId;\n                bestAdd = addId;\n                bestIns = ins;\n                bestReduced = reduced;\n            }\n        }\n    }\n\n    if (bestRem == -1) return false;\n\n    st.seq = std::move(bestReduced);\n    applyInsert(st.seq, bestIns, bestAdd);\n    st.used[bestRem] = 0;\n    st.used[bestAdd] = 1;\n    st.cost = bestCost;\n    return true;\n}\n\nstatic void fullImprove(State& st,\n                        const vector<vector<int>>& rankLists,\n                        const vector<int>& rankIds) {\n    optimizeAdj(st);\n\n    for (int round = 0; round < 3; ++round) {\n        if (elapsed() > 1.85) break;\n        bool changed = false;\n\n        for (int t = 0; t < 8; ++t) {\n            if (elapsed() > 1.85) break;\n            if (!pairBestImprove(st)) break;\n            changed = true;\n            optimizeAdj(st);\n        }\n\n        for (int t = 0; t < 3; ++t) {\n            if (elapsed() > 1.85) break;\n            if (!swapBestImprove(st, rankLists, rankIds)) break;\n            changed = true;\n            optimizeAdj(st);\n\n            for (int r = 0; r < 5; ++r) {\n                if (elapsed() > 1.85) break;\n                if (!pairBestImprove(st)) break;\n                changed = true;\n                optimizeAdj(st);\n            }\n        }\n\n        optimizeAdj(st);\n        if (!changed) break;\n    }\n\n    st.cost = seqCost(st.seq);\n}\n\nstatic ll quickEvalCandidate(const Cand& c) {\n    vector<int> ord1 = orderByScore(c.sel, c.scoreId, true);\n    vector<int> ord2 = orderByPQ(c.sel, true);\n    State s1 = buildInsertionState(c.sel, ord1);\n    State s2 = buildInsertionState(c.sel, ord2);\n    return min(s1.cost, s2.cost);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    gStart = chrono::steady_clock::now();\n\n    for (int i = 0; i < N; ++i) {\n        cin >> ord[i].p.x >> ord[i].p.y >> ord[i].q.x >> ord[i].q.y;\n        ord[i].pq = md(ord[i].p, ord[i].q);\n        ord[i].op = md(ord[i].p, OFFICE);\n        ord[i].oq = md(ord[i].q, OFFICE);\n        ord[i].mx2 = ord[i].p.x + ord[i].q.x;\n        ord[i].my2 = ord[i].p.y + ord[i].q.y;\n    }\n\n    vector<Pt> anchors;\n    for (int x : {0, 200, 400, 600, 800}) {\n        for (int y : {0, 200, 400, 600, 800}) {\n            anchors.push_back({x, y});\n        }\n    }\n\n    mt19937_64 rng(712367821ULL);\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    for (int k = 0; k < 12; ++k) {\n        int id = perm[k];\n        anchors.push_back({\n            (ord[id].p.x + ord[id].q.x) / 2,\n            (ord[id].p.y + ord[id].q.y) / 2\n        });\n    }\n\n    auto addScoreVec = [&](vector<ll>&& sc, Pt anchor) -> int {\n        scoreVecs.push_back(std::move(sc));\n        scoreAnchors.push_back(anchor);\n        return (int)scoreVecs.size() - 1;\n    };\n\n    // Anchor-based score vectors\n    for (const auto& a : anchors) {\n        for (ll lam : {0LL, 1LL, 3LL}) {\n            vector<ll> s0(N), s1(N), s2(N);\n            for (int i = 0; i < N; ++i) {\n                ll dp = md(ord[i].p, a);\n                ll dq = md(ord[i].q, a);\n                ll mid = absl(ord[i].mx2 - 2LL * a.x) + absl(ord[i].my2 - 2LL * a.y);\n                s0[i] = mid + lam * ord[i].pq;\n                s1[i] = max(dp, dq) + lam * ord[i].pq;\n                s2[i] = dp + dq + 2LL * lam * ord[i].pq;\n            }\n            addScoreVec(std::move(s0), a);\n            addScoreVec(std::move(s1), a);\n            addScoreVec(std::move(s2), a);\n        }\n    }\n\n    // Global score vectors\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = ord[i].op + ord[i].oq + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = max(ord[i].op, ord[i].oq) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = absl(ord[i].mx2 - 800) + absl(ord[i].my2 - 800) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = absl(ord[i].mx2 - ord[i].my2) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = absl(ord[i].mx2 + ord[i].my2 - 1600) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = min(ord[i].op, ord[i].oq) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n\n    int S = (int)scoreVecs.size();\n\n    // Build rank lists for swap pool.\n    vector<vector<int>> rankLists(S);\n    for (int sid = 0; sid < S; ++sid) {\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        sort(ids.begin(), ids.end(), [&](int a, int b) {\n            if (scoreVecs[sid][a] != scoreVecs[sid][b]) return scoreVecs[sid][a] < scoreVecs[sid][b];\n            return a < b;\n        });\n        rankLists[sid] = std::move(ids);\n    }\n\n    // Candidate generation.\n    vector<Cand> cands;\n    unordered_set<string> seen;\n    seen.reserve(256);\n\n    for (int sid = 0; sid < S; ++sid) {\n        vector<int> sel = selectTop50(scoreVecs[sid]);\n        string key = keyOfSel(sel);\n        if (seen.insert(key).second) {\n            ll proxy = 0;\n            for (int id : sel) proxy += scoreVecs[sid][id];\n            cands.push_back({sel, sid, scoreAnchors[sid], proxy, INFLL});\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.proxy != b.proxy) return a.proxy < b.proxy;\n        return a.scoreId < b.scoreId;\n    });\n    if ((int)cands.size() > 100) cands.resize(100);\n\n    // Quick evaluation.\n    for (auto& c : cands) {\n        if (elapsed() > 1.85) break;\n        c.quickCost = quickEvalCandidate(c);\n    }\n\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.quickCost != b.quickCost) return a.quickCost < b.quickCost;\n        return a.scoreId < b.scoreId;\n    });\n\n    int REFINE = min(5, (int)cands.size());\n    State globalBest;\n    globalBest.cost = INFLL;\n\n    for (int i = 0; i < REFINE; ++i) {\n        if (elapsed() > 1.85) break;\n        const Cand& c = cands[i];\n\n        vector<int> rankIds = {c.scoreId, S - 7, S - 6, S - 5, S - 4, S - 3, S - 2, S - 1};\n        sort(rankIds.begin(), rankIds.end());\n        rankIds.erase(unique(rankIds.begin(), rankIds.end()), rankIds.end());\n\n        vector<State> vars;\n        vars.reserve(5);\n        vars.push_back(buildInsertionState(c.sel, orderByScore(c.sel, c.scoreId, true)));\n        vars.push_back(buildInsertionState(c.sel, orderByScore(c.sel, c.scoreId, false)));\n        vars.push_back(buildInsertionState(c.sel, orderByPQ(c.sel, true)));\n        vars.push_back(buildInsertionState(c.sel, orderByAngle(c.sel, c.anchor)));\n        vars.push_back(buildRegretState(c.sel, 0, splitmix64(123456789ULL ^ (uint64_t)c.scoreId * 1000003ULL)));\n\n        sort(vars.begin(), vars.end(), [&](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        for (int k = 0; k < (int)vars.size() && k < 2; ++k) {\n            if (elapsed() > 1.85) break;\n            State st = vars[k];\n            fullImprove(st, rankLists, rankIds);\n            if (st.cost < globalBest.cost) globalBest = std::move(st);\n        }\n    }\n\n    // Fallback.\n    if (globalBest.cost == INFLL && !cands.empty()) {\n        const Cand& c = cands[0];\n        globalBest = buildInsertionState(c.sel, orderByScore(c.sel, c.scoreId, true));\n        globalBest.cost = seqCost(globalBest.seq);\n    }\n\n    vector<int> chosen = selectedIds(globalBest.used);\n    sort(chosen.begin(), chosen.end());\n\n    vector<Pt> pts = buildPts(globalBest.seq);\n\n    cout << 50;\n    for (int id : chosen) cout << ' ' << (id + 1);\n    cout << '\\n';\n\n    cout << pts.size();\n    for (const auto& p : pts) cout << ' ' << p.x << ' ' << p.y;\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        iota(p.begin(), p.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstatic inline int rounded_dist(int x1, int y1, int x2, int y2) {\n    long long dx = (long long)x1 - x2;\n    long long dy = (long long)y1 - y2;\n    long long s = dx * dx + dy * dy;\n    return (int)llround(sqrt((long double)s));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        edges[i].d = rounded_dist(\n            x[edges[i].u], y[edges[i].u],\n            x[edges[i].v], y[edges[i].v]\n        );\n    }\n\n    // Build the backbone tree by Kruskal on d.\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (edges[a].d != edges[b].d) return edges[a].d < edges[b].d;\n        return a < b;\n    });\n\n    vector<char> is_base(M, 0);\n    DSU dsu_build(N);\n    int base_cnt = 0;\n    for (int id : ord) {\n        if (dsu_build.unite(edges[id].u, edges[id].v)) {\n            is_base[id] = 1;\n            ++base_cnt;\n        }\n    }\n\n    // Tree structure of the backbone.\n    vector<vector<pair<int,int>>> g(N);\n    for (int id = 0; id < M; ++id) {\n        if (!is_base[id]) continue;\n        int u = edges[id].u, v = edges[id].v;\n        g[u].push_back({v, id});\n        g[v].push_back({u, id});\n    }\n\n    vector<int> parent(N, -1), depth(N, 0), pedge(N, -1);\n    {\n        stack<int> st;\n        st.push(0);\n        parent[0] = 0;\n        while (!st.empty()) {\n            int v = st.top();\n            st.pop();\n            for (auto [to, id] : g[v]) {\n                if (to == parent[v]) continue;\n                parent[to] = v;\n                depth[to] = depth[v] + 1;\n                pedge[to] = id;\n                st.push(to);\n            }\n        }\n    }\n\n    DSU dsu(N);\n    vector<char> base_seen(M, 0);\n\n    int seen_base_cnt = 0;\n    int extra_cnt = 0;\n    constexpr int EXTRA_LIMIT = 120;\n\n    auto evaluate_path = [&](int u, int v) {\n        int best_d = -1;\n        int best_id = -1;\n        int cnt_future = 0;\n\n        auto consider_edge = [&](int id) {\n            if (id < 0) return;\n            if (!base_seen[id]) {\n                ++cnt_future;\n                if (edges[id].d > best_d) {\n                    best_d = edges[id].d;\n                    best_id = id;\n                }\n            }\n        };\n\n        while (depth[u] > depth[v]) {\n            consider_edge(pedge[u]);\n            u = parent[u];\n        }\n        while (depth[v] > depth[u]) {\n            consider_edge(pedge[v]);\n            v = parent[v];\n        }\n        while (u != v) {\n            consider_edge(pedge[u]);\n            consider_edge(pedge[v]);\n            u = parent[u];\n            v = parent[v];\n        }\n        return tuple<int,int,int>(best_d, best_id, cnt_future);\n    };\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n\n        bool take = false;\n\n        if (is_base[i]) {\n            base_seen[i] = 1;\n            ++seen_base_cnt;\n\n            // Always keep backbone edges if they still connect components.\n            if (dsu.unite(edges[i].u, edges[i].v)) {\n                take = true;\n            }\n        } else {\n            // Conservative extra-edge policy.\n            if (extra_cnt < EXTRA_LIMIT && seen_base_cnt < base_cnt) {\n                if (dsu.find(edges[i].u) != dsu.find(edges[i].v)) {\n                    auto [best_d, best_id, cnt_future] = evaluate_path(edges[i].u, edges[i].v);\n\n                    // Only consider if there is still a future backbone edge on the path.\n                    if (best_d >= 30 && best_id != -1) {\n                        double thr = 1.10\n                                   + 0.02 * min(cnt_future, 5)\n                                   + 0.04 * (double)(base_cnt - seen_base_cnt) / base_cnt;\n\n                        if (best_d >= 50)  thr += 0.03;\n                        if (best_d >= 100) thr += 0.04;\n                        if (best_d >= 200) thr += 0.04;\n                        thr = min(thr, 1.38);\n\n                        if ((double)l <= thr * (double)best_d) {\n                            if (dsu.unite(edges[i].u, edges[i].v)) {\n                                take = true;\n                                ++extra_cnt;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        cout << (take ? 1 : 0) << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstatic const int B = 30;\n\nstruct Candidate {\n    bool horizontal;\n    int line;       // row if horizontal, column if vertical\n    int side;       // -1 or +1\n    int variant;    // segment partition variant\n    int area = 0;\n    int petCount = 0;\n    int nearRisk = 0;\n    int prepTurns = 0;\n    long double score = -1e100L;\n    vector<pair<int,int>> segs; // intervals [l, r] on the barrier line\n};\n\nstatic inline int manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nstatic inline int clampi(int v, int l, int r) {\n    return max(l, min(r, v));\n}\n\nstatic bool feasibleMatching(\n    const vector<vector<int>>& cost,\n    int T,\n    vector<int>& matchHumanToSeg\n) {\n    int n = (int)cost.size();\n    vector<int> matchSegToHuman(n, -1);\n\n    function<bool(int, vector<int>&)> dfs = [&](int h, vector<int>& seen) -> bool {\n        for (int s = 0; s < n; ++s) {\n            if (cost[h][s] > T || seen[s]) continue;\n            seen[s] = 1;\n            if (matchSegToHuman[s] == -1 || dfs(matchSegToHuman[s], seen)) {\n                matchSegToHuman[s] = h;\n                return true;\n            }\n        }\n        return false;\n    };\n\n    for (int h = 0; h < n; ++h) {\n        vector<int> seen(n, 0);\n        if (!dfs(h, seen)) return false;\n    }\n\n    matchHumanToSeg.assign(n, -1);\n    for (int s = 0; s < n; ++s) {\n        matchHumanToSeg[matchSegToHuman[s]] = s;\n    }\n    return true;\n}\n\nstatic int minmaxMatching(\n    const vector<vector<int>>& cost,\n    vector<int>& matchHumanToSeg\n) {\n    int n = (int)cost.size();\n    int lo = 0, hi = 60;\n    while (lo < hi) {\n        int mid = (lo + hi) / 2;\n        vector<int> tmp;\n        if (feasibleMatching(cost, mid, tmp)) hi = mid;\n        else lo = mid + 1;\n    }\n    feasibleMatching(cost, lo, matchHumanToSeg);\n    return lo;\n}\n\nstatic vector<pair<int,int>> buildSegments(int M, int variant) {\n    int L = 30;\n    int base = L / M, rem = L % M;\n    vector<int> len(M, base);\n\n    if (variant == 0) {\n        for (int i = 0; i < rem; ++i) len[i]++;\n    } else if (variant == 1) {\n        for (int i = M - rem; i < M; ++i) len[i]++;\n    } else {\n        int st = (M - rem) / 2;\n        for (int i = 0; i < rem; ++i) len[st + i]++;\n    }\n\n    vector<pair<int,int>> segs;\n    int cur = 1;\n    for (int i = 0; i < M; ++i) {\n        segs.push_back({cur, cur + len[i] - 1});\n        cur += len[i];\n    }\n    return segs;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Point> pets(N);\n    vector<int> ptype(N);\n    vector<vector<int>> petOcc(B + 1, vector<int>(B + 1, 0));\n\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> ptype[i];\n        petOcc[pets[i].x][pets[i].y]++;\n    }\n\n    int M;\n    cin >> M;\n    vector<Point> humans(M);\n    for (int i = 0; i < M; ++i) cin >> humans[i].x >> humans[i].y;\n\n    vector<vector<int>> ps(B + 1, vector<int>(B + 1, 0));\n    for (int i = 1; i <= B; ++i) {\n        for (int j = 1; j <= B; ++j) {\n            ps[i][j] = petOcc[i][j] + ps[i - 1][j] + ps[i][j - 1] - ps[i - 1][j - 1];\n        }\n    }\n\n    auto sumRect = [&](int r1, int c1, int r2, int c2) -> int {\n        r1 = clampi(r1, 1, B);\n        c1 = clampi(c1, 1, B);\n        r2 = clampi(r2, 1, B);\n        c2 = clampi(c2, 1, B);\n        if (r1 > r2 || c1 > c2) return 0;\n        return ps[r2][c2] - ps[r1 - 1][c2] - ps[r2][c1 - 1] + ps[r1 - 1][c1 - 1];\n    };\n\n    auto buildCostMatrix = [&](bool horizontal, int line, int side, const vector<pair<int,int>>& segs) {\n        int n = M;\n        vector<vector<int>> cost(n, vector<int>(n, 0));\n        int sideCoord = line + side;\n\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                auto [l, r] = segs[j];\n                int d = 0;\n                if (horizontal) {\n                    d = abs(humans[i].x - sideCoord) + min(abs(humans[i].y - l), abs(humans[i].y - r));\n                } else {\n                    d = abs(humans[i].y - sideCoord) + min(abs(humans[i].x - l), abs(humans[i].x - r));\n                }\n                cost[i][j] = d;\n            }\n        }\n        return cost;\n    };\n\n    auto evaluate = [&](bool horizontal, int line, int side, int variant) -> optional<Candidate> {\n        Candidate cand;\n        cand.horizontal = horizontal;\n        cand.line = line;\n        cand.side = side;\n        cand.variant = variant;\n\n        // Final reachable region\n        if (horizontal) {\n            if (side == -1) {\n                cand.area = (line - 1) * B;\n                cand.petCount = sumRect(1, 1, line - 1, B);\n            } else {\n                cand.area = (B - line) * B;\n                cand.petCount = sumRect(line + 1, 1, B, B);\n            }\n        } else {\n            if (side == -1) {\n                cand.area = (line - 1) * B;\n                cand.petCount = sumRect(1, 1, B, line - 1);\n            } else {\n                cand.area = (B - line) * B;\n                cand.petCount = sumRect(1, line + 1, B, B);\n            }\n        }\n\n        if (cand.area <= 0) return nullopt;\n\n        // Risk near the barrier line itself\n        int risk = 0;\n        for (auto &p : pets) {\n            int d = horizontal ? abs(p.x - line) : abs(p.y - line);\n            if (d <= 2) risk += (3 - d); // d=0 -> 3, d=1 -> 2, d=2 -> 1\n        }\n        cand.nearRisk = risk;\n\n        cand.segs = buildSegments(M, variant);\n\n        // Build cost matrix and estimate prep time by min-max matching\n        auto cost = buildCostMatrix(horizontal, line, side, cand.segs);\n        vector<int> matchHumanToSeg;\n        cand.prepTurns = minmaxMatching(cost, matchHumanToSeg);\n\n        long double raw = (long double)cand.area * exp2l(-(long double)cand.petCount);\n        long double timeFactor = expl(-0.02L * (long double)cand.prepTurns);\n        long double riskFactor = 1.0L / (1.0L + 0.15L * (long double)cand.nearRisk);\n        cand.score = raw * timeFactor * riskFactor;\n\n        return cand;\n    };\n\n    optional<Candidate> best;\n\n    auto better = [&](const Candidate& a, const Candidate& b) {\n        const long double EPS = 1e-15L;\n        if (fabsl(a.score - b.score) > EPS) return a.score > b.score;\n        if (a.prepTurns != b.prepTurns) return a.prepTurns < b.prepTurns;\n        if (a.nearRisk != b.nearRisk) return a.nearRisk < b.nearRisk;\n        if (a.petCount != b.petCount) return a.petCount < b.petCount;\n        return a.area > b.area;\n    };\n\n    for (int line = 2; line <= 29; ++line) {\n        for (int side : {-1, +1}) {\n            for (int variant = 0; variant < 3; ++variant) {\n                auto cand = evaluate(true, line, side, variant);\n                if (!cand) continue;\n                if (!best || better(*cand, *best)) best = *cand;\n            }\n        }\n    }\n    for (int line = 2; line <= 29; ++line) {\n        for (int side : {-1, +1}) {\n            for (int variant = 0; variant < 3; ++variant) {\n                auto cand = evaluate(false, line, side, variant);\n                if (!cand) continue;\n                if (!best || better(*cand, *best)) best = *cand;\n            }\n        }\n    }\n\n    if (!best) {\n        for (int turn = 0; turn < 300; ++turn) {\n            cout << string(M, '.') << '\\n' << flush;\n            for (int i = 0; i < N; ++i) {\n                string s;\n                cin >> s;\n            }\n        }\n        return 0;\n    }\n\n    Candidate cand = *best;\n    int sideCoord = cand.line + cand.side;\n\n    // Recompute assignment for chosen candidate\n    auto cost = buildCostMatrix(cand.horizontal, cand.line, cand.side, cand.segs);\n    vector<int> matchHumanToSeg;\n    minmaxMatching(cost, matchHumanToSeg);\n\n    struct Builder {\n        int seg = -1;\n        Point start{};\n        Point pos{};\n        int cur = 0;       // current column (horizontal) or row (vertical)\n        int l = 0, r = 0;\n        int dir = 0;       // +1 or -1\n        bool horizontal = true;\n        bool needWall = true;\n        bool done = false;\n        int built = 0;\n    };\n\n    vector<Builder> builders(M);\n    for (int h = 0; h < M; ++h) {\n        int s = matchHumanToSeg[h];\n        auto [l, r] = cand.segs[s];\n        int dL, dR;\n        if (cand.horizontal) {\n            dL = abs(humans[h].x - sideCoord) + abs(humans[h].y - l);\n            dR = abs(humans[h].x - sideCoord) + abs(humans[h].y - r);\n            builders[h].horizontal = true;\n            builders[h].l = l;\n            builders[h].r = r;\n            if (dL <= dR) {\n                builders[h].start = {sideCoord, l};\n                builders[h].pos = builders[h].start;\n                builders[h].cur = l;\n                builders[h].dir = +1;\n            } else {\n                builders[h].start = {sideCoord, r};\n                builders[h].pos = builders[h].start;\n                builders[h].cur = r;\n                builders[h].dir = -1;\n            }\n        } else {\n            dL = abs(humans[h].x - l) + abs(humans[h].y - sideCoord);\n            dR = abs(humans[h].x - r) + abs(humans[h].y - sideCoord);\n            builders[h].horizontal = false;\n            builders[h].l = l;\n            builders[h].r = r;\n            if (dL <= dR) {\n                builders[h].start = {l, sideCoord};\n                builders[h].pos = builders[h].start;\n                builders[h].cur = l;\n                builders[h].dir = +1;\n            } else {\n                builders[h].start = {r, sideCoord};\n                builders[h].pos = builders[h].start;\n                builders[h].cur = r;\n                builders[h].dir = -1;\n            }\n        }\n    }\n\n    vector<Point> curHumans = humans;\n    vector<vector<int>> humanOcc(B + 1, vector<int>(B + 1, 0));\n\n    auto rebuildHumanOcc = [&]() {\n        for (int i = 1; i <= B; ++i) fill(humanOcc[i].begin(), humanOcc[i].end(), 0);\n        for (auto &p : curHumans) humanOcc[p.x][p.y]++;\n    };\n    rebuildHumanOcc();\n\n    auto inBoard = [&](int x, int y) -> bool {\n        return 1 <= x && x <= B && 1 <= y && y <= B;\n    };\n\n    auto safeToWall = [&](const Point& q) -> bool {\n        if (!inBoard(q.x, q.y)) return false;\n        if (humanOcc[q.x][q.y] > 0) return false;\n        if (petOcc[q.x][q.y] > 0) return false;\n        static int dx[4] = {-1, 1, 0, 0};\n        static int dy[4] = {0, 0, -1, 1};\n        for (int dir = 0; dir < 4; ++dir) {\n            int nx = q.x + dx[dir], ny = q.y + dy[dir];\n            if (inBoard(nx, ny) && petOcc[nx][ny] > 0) return false;\n        }\n        return true;\n    };\n\n    auto moveToward = [&](Point& p, const Point& t) -> char {\n        if (p.x < t.x) { ++p.x; return 'D'; }\n        if (p.x > t.x) { --p.x; return 'U'; }\n        if (p.y < t.y) { ++p.y; return 'R'; }\n        if (p.y > t.y) { --p.y; return 'L'; }\n        return '.';\n    };\n\n    for (int turn = 0; turn < 300; ++turn) {\n        string out(M, '.');\n        vector<Point> nextHumans = curHumans;\n\n        if (turn < cand.prepTurns) {\n            // Travel phase: move everyone to the assigned segment endpoint.\n            for (int i = 0; i < M; ++i) {\n                out[i] = moveToward(nextHumans[i], builders[i].start);\n            }\n        } else {\n            // Build phase: each human builds its own segment.\n            for (int i = 0; i < M; ++i) {\n                if (builders[i].done) {\n                    out[i] = '.';\n                    continue;\n                }\n\n                if (builders[i].needWall) {\n                    Point q;\n                    if (cand.horizontal) q = {cand.line, builders[i].cur};\n                    else q = {builders[i].cur, cand.line};\n\n                    if (safeToWall(q)) {\n                        out[i] = cand.horizontal\n                            ? (cand.side == -1 ? 'd' : 'u')\n                            : (cand.side == -1 ? 'r' : 'l');\n                        builders[i].built++;\n                        if (builders[i].built >= (builders[i].r - builders[i].l + 1)) {\n                            builders[i].done = true;\n                        } else {\n                            builders[i].needWall = false;\n                        }\n                    } else {\n                        out[i] = '.';\n                    }\n                } else {\n                    out[i] = cand.horizontal\n                        ? (builders[i].dir == +1 ? 'R' : 'L')\n                        : (builders[i].dir == +1 ? 'D' : 'U');\n                    if (cand.horizontal) nextHumans[i].y += builders[i].dir;\n                    else nextHumans[i].x += builders[i].dir;\n                    builders[i].cur += builders[i].dir;\n                    builders[i].needWall = true;\n                }\n            }\n        }\n\n        cout << out << '\\n' << flush;\n\n        curHumans = nextHumans;\n        rebuildHumanOcc();\n\n        vector<string> mv(N);\n        for (int i = 0; i < N; ++i) cin >> mv[i];\n\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].x, y = pets[i].y;\n            for (char ch : mv[i]) {\n                if (ch == 'U') --x;\n                else if (ch == 'D') ++x;\n                else if (ch == 'L') --y;\n                else if (ch == 'R') ++y;\n            }\n            pets[i] = {x, y};\n        }\n\n        for (int i = 1; i <= B; ++i) fill(petOcc[i].begin(), petOcc[i].end(), 0);\n        for (auto &p : pets) petOcc[p.x][p.y]++;\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int MAXL = 200;\nstatic constexpr double P_INF = 1e100;\n\nint si, sj, ti, tj;\ndouble p, qprob;\nvector<string> hwall(20), vwall(19);\n\nint startPos, goalPos;\nint moveTo[4][N];\nint distGoal[N];\nint c2d[256];\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\ninline int id(int i, int j) { return i * W + j; }\n\nbool open_move(int pos, int dir) {\n    int i = pos / W, j = pos % W;\n    if (dir == 0) return i > 0 && vwall[i - 1][j] == '0';\n    if (dir == 1) return i + 1 < H && vwall[i][j] == '0';\n    if (dir == 2) return j > 0 && hwall[i][j - 1] == '0';\n    if (dir == 3) return j + 1 < W && hwall[i][j] == '0';\n    return false;\n}\n\nstruct State {\n    array<double, N> prob{};\n    double score = 0.0;\n    double bound = 0.0;\n    int len = 0;\n    string s;\n};\n\ndouble computeBound(const State& st) {\n    double pot = 0.0;\n    for (int pos = 0; pos < N; ++pos) {\n        if (pos == goalPos) continue;\n        double pr = st.prob[pos];\n        if (pr == 0.0) continue;\n        double rem = 401.0 - st.len - distGoal[pos];\n        if (rem > 0.0) pot += pr * rem;\n    }\n    return st.score + pot;\n}\n\nState makeInitialState() {\n    State st;\n    st.prob.fill(0.0);\n    st.prob[startPos] = 1.0;\n    st.score = 0.0;\n    st.len = 0;\n    st.s.clear();\n    st.bound = computeBound(st);\n    return st;\n}\n\nbool uselessDir(const State& st, int dir) {\n    for (int pos = 0; pos < N; ++pos) {\n        double pr = st.prob[pos];\n        if (pr == 0.0) continue;\n        if (pos == goalPos) continue;\n        if (moveTo[dir][pos] != pos) return false;\n    }\n    return true;\n}\n\nState advanceState(const State& st, int dir) {\n    State ch;\n    ch.prob.fill(0.0);\n    ch.score = st.score;\n    ch.len = st.len + 1;\n    ch.s = st.s;\n    ch.s.push_back(dch[dir]);\n\n    double reward = 401.0 - ch.len;\n\n    for (int pos = 0; pos < N; ++pos) {\n        double pr = st.prob[pos];\n        if (pr == 0.0) continue;\n\n        if (pos == goalPos) {\n            ch.prob[goalPos] += pr;\n            continue;\n        }\n\n        double stay = pr * p;\n        double mv = pr * qprob;\n        ch.prob[pos] += stay;\n\n        int np = moveTo[dir][pos];\n        if (np == goalPos) {\n            ch.score += mv * reward;\n            ch.prob[goalPos] += mv;\n        } else {\n            ch.prob[np] += mv;\n        }\n    }\n\n    ch.bound = computeBound(ch);\n    return ch;\n}\n\nState simulateApprox(const string& s) {\n    State st = makeInitialState();\n    for (char c : s) {\n        int d = c2d[(unsigned char)c];\n        if (d < 0) continue;\n        st = advanceState(st, d);\n    }\n    return st;\n}\n\ndouble evalExact(const string& s) {\n    array<double, N> cur{}, nxt{};\n    cur.fill(0.0);\n    nxt.fill(0.0);\n    cur[startPos] = 1.0;\n\n    double score = 0.0;\n\n    for (int t = 0; t < (int)s.size(); ++t) {\n        if (cur[goalPos] >= 1.0 - 1e-15) break;\n\n        nxt.fill(0.0);\n        int dir = c2d[(unsigned char)s[t]];\n        if (dir < 0) return 0.0;\n\n        double reward = 401.0 - (t + 1);\n\n        for (int pos = 0; pos < N; ++pos) {\n            double pr = cur[pos];\n            if (pr == 0.0) continue;\n\n            if (pos == goalPos) {\n                nxt[goalPos] += pr;\n                continue;\n            }\n\n            double stay = pr * p;\n            double mv = pr * qprob;\n\n            nxt[pos] += stay;\n\n            int np = moveTo[dir][pos];\n            if (np == goalPos) {\n                score += mv * reward;\n                nxt[goalPos] += mv;\n            } else {\n                nxt[np] += mv;\n            }\n        }\n\n        cur.swap(nxt);\n    }\n\n    return score;\n}\n\nstring bfsShortestPath() {\n    vector<int> dist(N, -1), par(N, -1);\n    vector<char> pch(N, '?');\n    queue<int> q;\n    dist[startPos] = 0;\n    q.push(startPos);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == goalPos) break;\n        for (int d = 0; d < 4; ++d) {\n            int nv = moveTo[d][v];\n            if (nv == v) continue;\n            if (dist[nv] != -1) continue;\n            dist[nv] = dist[v] + 1;\n            par[nv] = v;\n            pch[nv] = dch[d];\n            q.push(nv);\n        }\n    }\n\n    if (dist[goalPos] == -1) return \"\";\n    string s;\n    for (int cur = goalPos; cur != startPos; cur = par[cur]) s.push_back(pch[cur]);\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstring bfsMonotoneDR() {\n    vector<int> dist(N, -1), par(N, -1);\n    vector<char> pch(N, '?');\n    queue<int> q;\n    dist[startPos] = 0;\n    q.push(startPos);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == goalPos) break;\n        for (int d : {1, 3}) {\n            int nv = moveTo[d][v];\n            if (nv == v) continue;\n            if (dist[nv] != -1) continue;\n            dist[nv] = dist[v] + 1;\n            par[nv] = v;\n            pch[nv] = dch[d];\n            q.push(nv);\n        }\n    }\n\n    if (dist[goalPos] == -1) return \"\";\n    string s;\n    for (int cur = goalPos; cur != startPos; cur = par[cur]) s.push_back(pch[cur]);\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstring directLShape(bool rowThenCol) {\n    string s;\n    if (rowThenCol) {\n        // D... then R...\n        for (int i = si; i < ti; ++i) if (vwall[i][sj] == '1') return \"\";\n        for (int j = sj; j < tj; ++j) if (hwall[ti][j] == '1') return \"\";\n        s.append(ti - si, 'D');\n        s.append(tj - sj, 'R');\n    } else {\n        // R... then D...\n        for (int j = sj; j < tj; ++j) if (hwall[si][j] == '1') return \"\";\n        for (int i = si; i < ti; ++i) if (vwall[i][tj] == '1') return \"\";\n        s.append(tj - sj, 'R');\n        s.append(ti - si, 'D');\n    }\n    return s;\n}\n\nstring dijkstraTurnPenalty(int turnPenalty) {\n    const long long INF = (1LL << 60);\n    int S = N * 5;\n    vector<long long> dist(S, INF);\n    vector<int> par(S, -1);\n    vector<char> pch(S, '?');\n\n    auto sid = [&](int pos, int prev) { return pos * 5 + prev; };\n\n    int st = sid(startPos, 4);\n    dist[st] = 0;\n\n    using P = pair<long long, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    pq.push({0, st});\n\n    while (!pq.empty()) {\n        auto [cd, cur] = pq.top();\n        pq.pop();\n        if (cd != dist[cur]) continue;\n\n        int pos = cur / 5;\n        int prev = cur % 5;\n\n        for (int d = 0; d < 4; ++d) {\n            int np = moveTo[d][pos];\n            if (np == pos) continue;\n            long long nd = cd + 1 + ((prev != 4 && prev != d) ? turnPenalty : 0);\n            int ns = sid(np, d);\n            if (nd < dist[ns]) {\n                dist[ns] = nd;\n                par[ns] = cur;\n                pch[ns] = dch[d];\n                pq.push({nd, ns});\n            }\n        }\n    }\n\n    int best = -1;\n    long long bestd = INF;\n    for (int prev = 0; prev < 4; ++prev) {\n        int gs = sid(goalPos, prev);\n        if (dist[gs] < bestd) {\n            bestd = dist[gs];\n            best = gs;\n        }\n    }\n    if (best == -1 || bestd == INF) return \"\";\n\n    string s;\n    for (int cur = best; cur != st; cur = par[cur]) s.push_back(pch[cur]);\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstring greedyBoundTemplate() {\n    State cur = makeInitialState();\n    string s;\n    s.reserve(MAXL);\n\n    for (int step = 0; step < MAXL; ++step) {\n        int bestDir = -1;\n        State bestCh;\n\n        for (int d = 0; d < 4; ++d) {\n            if (uselessDir(cur, d)) continue;\n            State ch = advanceState(cur, d);\n            if (bestDir == -1 ||\n                ch.bound > bestCh.bound ||\n                (ch.bound == bestCh.bound && ch.score > bestCh.score)) {\n                bestDir = d;\n                bestCh = std::move(ch);\n            }\n        }\n\n        if (bestDir == -1) break;\n        if (bestCh.bound <= cur.score + 1e-12) break;\n\n        s.push_back(dch[bestDir]);\n        cur = std::move(bestCh);\n    }\n\n    return s;\n}\n\nvoid addPrefixes(vector<string>& seeds, const string& raw) {\n    if (raw.empty()) return;\n    string s = raw;\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n\n    vector<int> cuts;\n    int L = (int)s.size();\n    for (int c : {10, 20, 40, 80, L}) {\n        if (c > 0) cuts.push_back(min(c, L));\n    }\n    sort(cuts.begin(), cuts.end());\n    cuts.erase(unique(cuts.begin(), cuts.end()), cuts.end());\n\n    for (int c : cuts) seeds.push_back(s.substr(0, c));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj >> ti >> tj >> p;\n    qprob = 1.0 - p;\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    startPos = id(si, sj);\n    goalPos = id(ti, tj);\n\n    for (int i = 0; i < 256; ++i) c2d[i] = -1;\n    c2d[(unsigned char)'U'] = 0;\n    c2d[(unsigned char)'D'] = 1;\n    c2d[(unsigned char)'L'] = 2;\n    c2d[(unsigned char)'R'] = 3;\n\n    for (int pos = 0; pos < N; ++pos) {\n        for (int d = 0; d < 4; ++d) {\n            moveTo[d][pos] = open_move(pos, d) ? (\n                [&]() {\n                    int i = pos / W, j = pos % W;\n                    if (d == 0) return id(i - 1, j);\n                    if (d == 1) return id(i + 1, j);\n                    if (d == 2) return id(i, j - 1);\n                    return id(i, j + 1);\n                }()\n            ) : pos;\n        }\n    }\n\n    // Shortest distances from every cell to goal.\n    {\n        fill(distGoal, distGoal + N, -1);\n        queue<int> q;\n        distGoal[goalPos] = 0;\n        q.push(goalPos);\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nv = moveTo[d][v];\n                if (nv == v) continue;\n                if (distGoal[nv] != -1) continue;\n                distGoal[nv] = distGoal[v] + 1;\n                q.push(nv);\n            }\n        }\n    }\n\n    vector<string> rawTemplates;\n    rawTemplates.reserve(16);\n\n    // Baselines\n    rawTemplates.push_back(bfsShortestPath());\n    rawTemplates.push_back(bfsMonotoneDR());\n    rawTemplates.push_back(directLShape(true));\n    rawTemplates.push_back(directLShape(false));\n    rawTemplates.push_back(greedyBoundTemplate());\n\n    for (int pen : {1, 4, 16, 64, 256}) {\n        rawTemplates.push_back(dijkstraTurnPenalty(pen));\n    }\n\n    // Build seed strings with prefixes.\n    vector<string> seedStrings;\n    seedStrings.reserve(128);\n    seedStrings.push_back(\"\"); // empty seed\n    for (const string& t : rawTemplates) addPrefixes(seedStrings, t);\n\n    sort(seedStrings.begin(), seedStrings.end());\n    seedStrings.erase(unique(seedStrings.begin(), seedStrings.end()), seedStrings.end());\n\n    // Simulate seeds to initialize beam.\n    vector<State> beam;\n    beam.reserve(seedStrings.size());\n    for (const string& s : seedStrings) {\n        State st = simulateApprox(s);\n        beam.push_back(std::move(st));\n    }\n\n    auto cmpBound = [](const State& a, const State& b) {\n        if (a.bound != b.bound) return a.bound > b.bound;\n        if (a.score != b.score) return a.score > b.score;\n        return a.len < b.len;\n    };\n\n    const int BEAM = 80;\n\n    // Keep an exact candidate pool as strings.\n    vector<string> pool;\n    pool.reserve(800);\n    for (const string& s : seedStrings) pool.push_back(s);\n\n    string bestApproxScoreStr = \"\";\n    double bestApproxScoreVal = -1e100;\n    string bestApproxBoundStr = \"\";\n    double bestApproxBoundVal = -1e100;\n\n    // Initialize best approx with seeds.\n    for (const State& st : beam) {\n        if (st.score > bestApproxScoreVal) {\n            bestApproxScoreVal = st.score;\n            bestApproxScoreStr = st.s;\n        }\n        if (st.bound > bestApproxBoundVal) {\n            bestApproxBoundVal = st.bound;\n            bestApproxBoundStr = st.s;\n        }\n    }\n\n    // Beam search over prefixes.\n    for (int iter = 0; iter < MAXL; ++iter) {\n        vector<State> cand;\n        cand.reserve(beam.size() * 4);\n\n        for (const State& st : beam) {\n            if (st.len >= MAXL) continue;\n            if (st.bound <= st.score + 1e-12) continue; // no future improvement possible\n\n            for (int d = 0; d < 4; ++d) {\n                if (uselessDir(st, d)) continue;\n                State ch = advanceState(st, d);\n\n                if (ch.score > bestApproxScoreVal) {\n                    bestApproxScoreVal = ch.score;\n                    bestApproxScoreStr = ch.s;\n                }\n                if (ch.bound > bestApproxBoundVal) {\n                    bestApproxBoundVal = ch.bound;\n                    bestApproxBoundStr = ch.s;\n                }\n\n                cand.push_back(std::move(ch));\n            }\n        }\n\n        if (cand.empty()) break;\n\n        int bestScoreIdx = 0, bestBoundIdx = 0;\n        for (int i = 1; i < (int)cand.size(); ++i) {\n            if (cand[i].score > cand[bestScoreIdx].score ||\n                (cand[i].score == cand[bestScoreIdx].score && cand[i].bound > cand[bestScoreIdx].bound)) {\n                bestScoreIdx = i;\n            }\n            if (cand[i].bound > cand[bestBoundIdx].bound ||\n                (cand[i].bound == cand[bestBoundIdx].bound && cand[i].score > cand[bestBoundIdx].score)) {\n                bestBoundIdx = i;\n            }\n        }\n        pool.push_back(cand[bestScoreIdx].s);\n        pool.push_back(cand[bestBoundIdx].s);\n\n        if ((int)cand.size() > BEAM) {\n            nth_element(cand.begin(), cand.begin() + BEAM, cand.end(), cmpBound);\n            cand.resize(BEAM);\n        }\n\n        beam = std::move(cand);\n    }\n\n    // Add final beam states and global best approximate strings.\n    for (const State& st : beam) pool.push_back(st.s);\n    pool.push_back(bestApproxScoreStr);\n    pool.push_back(bestApproxBoundStr);\n\n    sort(pool.begin(), pool.end());\n    pool.erase(unique(pool.begin(), pool.end()), pool.end());\n\n    // Exact evaluation of pooled candidates.\n    string answer = \"\";\n    double bestExact = -1.0;\n    for (const string& s : pool) {\n        double sc = evalExact(s);\n        if (sc > bestExact) {\n            bestExact = sc;\n            answer = s;\n        }\n    }\n\n    if (answer.empty()) {\n        // Safety fallback.\n        answer = bfsShortestPath();\n        if ((int)answer.size() > MAXL) answer.resize(MAXL);\n    }\n\n    cout << answer << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int S = N * N;\nstatic constexpr int ST = S * 4;\n\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\nint baseTo[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1},\n};\n\nint nxtDir[8][4][4]; // nxtDir[t][rot][entry_dir] -> exit_dir, or -1\n\nusing RotArr = array<uint8_t, S>;\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 EvalResult {\n    long long score = -1;\n    int cycles = 0;\n    int l1 = 0, l2 = 0;\n    vector<int> hotCells;\n};\n\nint rotCorner[8][4];\nint rotPair[8][2];\n\nstatic inline bool better(const EvalResult& a, const EvalResult& b) {\n    if (a.score != b.score) return a.score > b.score;\n    if (a.cycles != b.cycles) return a.cycles > b.cycles;\n    if (a.l1 + a.l2 != b.l1 + b.l2) return a.l1 + a.l2 > b.l1 + b.l2;\n    if (a.l1 != b.l1) return a.l1 > b.l1;\n    return a.l2 > b.l2;\n}\n\nstatic inline void apply_sym(int sym, int i, int j, int& u, int& v) {\n    switch (sym) {\n        case 0: u = i; v = j; break;\n        case 1: u = i; v = N - 1 - j; break;\n        case 2: u = N - 1 - i; v = j; break;\n        case 3: u = N - 1 - i; v = N - 1 - j; break;\n        case 4: u = j; v = i; break;\n        case 5: u = j; v = N - 1 - i; break;\n        case 6: u = N - 1 - j; v = i; break;\n        case 7: u = N - 1 - j; v = N - 1 - i; break;\n    }\n}\n\nstatic inline int pattern_value(int pid, int u, int v, uint64_t seed) {\n    switch (pid) {\n        case 0: return u + v;\n        case 1: return u - v + 29;\n        case 2: return ((u & 1) << 1) | (v & 1);                 // 2x2 checkerboard\n        case 3: return (u / 2) * 4 + (v / 2);                    // 2x2 coarse\n        case 4: return (u / 3) * 4 + (v / 3);                    // 3x3 coarse\n        case 5: return min(min(u, 29 - u), min(v, 29 - v));      // border distance\n        case 6: return abs(u - 15) + abs(v - 15);                // center distance\n        case 7: return (int)(splitmix64(seed + (uint64_t)u * 10007ULL + (uint64_t)v * 10009ULL) & 1023ULL);\n    }\n    return u + v;\n}\n\nEvalResult evaluate(const RotArr& rot, const array<int, S>& tile) {\n    static int succ[ST];\n    static uint8_t vis[ST];\n    static int pos[ST];\n    static uint8_t mark[S];\n\n    memset(vis, 0, sizeof(vis));\n    memset(mark, 0, sizeof(mark));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int base = (i * N + j) * 4;\n            int t = tile[i * N + j];\n            int r = rot[i * N + j];\n            for (int d = 0; d < 4; ++d) {\n                int d2 = nxtDir[t][r][d];\n                if (d2 < 0) {\n                    succ[base + d] = -1;\n                    continue;\n                }\n                int ni = i + di[d2];\n                int nj = j + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    succ[base + d] = -1;\n                    continue;\n                }\n                int nd = (d2 + 2) & 3;\n                succ[base + d] = (ni * N + nj) * 4 + nd;\n            }\n        }\n    }\n\n    vector<int> lens;\n    vector<vector<int>> cycStates;\n    vector<int> st;\n    st.reserve(ST);\n    lens.reserve(1024);\n    cycStates.reserve(1024);\n\n    for (int s = 0; s < ST; ++s) {\n        if (vis[s]) continue;\n        int cur = s;\n        st.clear();\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;\n            pos[cur] = (int)st.size();\n            st.push_back(cur);\n            cur = succ[cur];\n        }\n        if (cur != -1 && vis[cur] == 1) {\n            vector<int> cyc(st.begin() + pos[cur], st.end());\n            lens.push_back((int)cyc.size());\n            cycStates.push_back(move(cyc));\n        }\n        for (int v : st) vis[v] = 2;\n    }\n\n    EvalResult res;\n    res.cycles = (int)lens.size();\n    if (res.cycles >= 1) {\n        vector<int> ord(res.cycles);\n        iota(ord.begin(), ord.end(), 0);\n        int top = min(4, res.cycles);\n        partial_sort(ord.begin(), ord.begin() + top, ord.end(), [&](int a, int b) {\n            if (lens[a] != lens[b]) return lens[a] > lens[b];\n            return a < b;\n        });\n\n        res.l1 = lens[ord[0]];\n        if (res.cycles >= 2) res.l2 = lens[ord[1]];\n        res.score = (res.cycles >= 2 ? 1LL * res.l1 * res.l2 : 0LL);\n\n        auto add_hot = [&](int cell) {\n            if (cell < 0 || cell >= S) return;\n            mark[cell] = 1;\n            int i = cell / N, j = cell % N;\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) mark[ni * N + nj] = 1;\n            }\n        };\n\n        for (int k = 0; k < top; ++k) {\n            for (int stid : cycStates[ord[k]]) {\n                add_hot(stid / 4);\n            }\n        }\n\n        for (int i = 0; i < S; ++i) if (mark[i]) res.hotCells.push_back(i);\n    }\n\n    return res;\n}\n\nRotArr make_candidate(const array<int, S>& tile, int pid, int sym, int mode, uint64_t seed) {\n    RotArr rot{};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u, v;\n            apply_sym(sym, i, j, u, v);\n            int x = pattern_value(pid, u, v, seed);\n            int t = tile[i * N + j];\n\n            if (t <= 3) {\n                int kind;\n                if (mode == 0) kind = x & 3;\n                else kind = (x ^ (x >> 1)) & 3;\n                int r = rotCorner[t][kind];\n                if (r < 0) r = 0;\n                rot[i * N + j] = (uint8_t)r;\n            } else {\n                int kind;\n                if (mode == 0) kind = x & 1;\n                else kind = (x ^ (x >> 1)) & 1;\n                int r = rotPair[t][kind];\n                if (r < 0) r = 0;\n                rot[i * N + j] = (uint8_t)r;\n            }\n        }\n    }\n    return rot;\n}\n\nstatic inline int pick_cell(const vector<int>& hot, mt19937_64& rng) {\n    if (!hot.empty() && (rng() % 100) < 75) return hot[rng() % hot.size()];\n    return (int)(rng() % S);\n}\n\nbool try_best_cell(RotArr& cur, EvalResult& curEv, const array<int, S>& tile, int cell) {\n    uint8_t old = cur[cell];\n    uint8_t bestR = old;\n    EvalResult bestEv = curEv;\n\n    for (int r = 0; r < 4; ++r) {\n        if (r == old) continue;\n        cur[cell] = (uint8_t)r;\n        EvalResult ev = evaluate(cur, tile);\n        if (better(ev, bestEv)) {\n            bestEv = move(ev);\n            bestR = (uint8_t)r;\n        }\n    }\n\n    cur[cell] = bestR;\n    if (bestR != old) {\n        curEv = move(bestEv);\n        return true;\n    }\n    return false;\n}\n\nbool try_best_block(RotArr& cur, EvalResult& curEv, const array<int, S>& tile, int bi, int bj, mt19937_64& rng) {\n    RotArr bak = cur;\n    EvalResult bakEv = curEv;\n\n    array<int, 4> cells = {\n        bi * N + bj,\n        bi * N + (bj + 1),\n        (bi + 1) * N + bj,\n        (bi + 1) * N + (bj + 1)\n    };\n\n    bool changed = false;\n    for (int pass = 0; pass < 2; ++pass) {\n        shuffle(cells.begin(), cells.end(), rng);\n        for (int c : cells) {\n            changed |= try_best_cell(cur, curEv, tile, c);\n        }\n    }\n\n    if (!better(curEv, bakEv)) {\n        cur = bak;\n        curEv = bakEv;\n        return false;\n    }\n    return changed;\n}\n\nvoid local_search(RotArr& cur, EvalResult& curEv, const array<int, S>& tile,\n                  RotArr& globalBestRot, EvalResult& globalBestEv,\n                  chrono::steady_clock::time_point deadline, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    auto update_global = [&]() {\n        if (better(curEv, globalBestEv)) {\n            globalBestEv = curEv;\n            globalBestRot = cur;\n        }\n    };\n\n    // Initial greedy sweep on hot cells.\n    {\n        vector<int> ord = curEv.hotCells;\n        shuffle(ord.begin(), ord.end(), rng);\n        int lim = min<int>(60, ord.size());\n        for (int i = 0; i < lim; ++i) {\n            if (chrono::steady_clock::now() >= deadline) return;\n            try_best_cell(cur, curEv, tile, ord[i]);\n            update_global();\n        }\n    }\n\n    int stagnation = 0;\n    while (chrono::steady_clock::now() < deadline) {\n        if (stagnation > 150) {\n            // Restart from the best-known solution with a small random shake.\n            cur = globalBestRot;\n            curEv = globalBestEv;\n\n            for (int k = 0; k < 5; ++k) {\n                int c = (int)(rng() % S);\n                cur[c] = (uint8_t)(rng() & 3);\n            }\n            curEv = evaluate(cur, tile);\n            update_global();\n\n            stagnation = 0;\n            continue;\n        }\n\n        int mode = (int)(rng() % 100);\n        bool moved = false;\n\n        if (mode < 62) {\n            int cell = pick_cell(curEv.hotCells, rng);\n            moved = try_best_cell(cur, curEv, tile, cell);\n        } else if (mode < 90) {\n            int cell = pick_cell(curEv.hotCells, rng);\n            int i = cell / N, j = cell % N;\n            int bi = max(0, min(i - 1, N - 2));\n            int bj = max(0, min(j - 1, N - 2));\n            moved = try_best_block(cur, curEv, tile, bi, bj, rng);\n        } else {\n            // Random shake; accept sometimes even if worse to escape local minima.\n            RotArr bak = cur;\n            EvalResult bakEv = curEv;\n\n            if (!curEv.hotCells.empty() && (rng() % 100) < 70) {\n                int cell = curEv.hotCells[rng() % curEv.hotCells.size()];\n                int i = cell / N, j = cell % N;\n                int bi = max(0, min(i - 1, N - 2));\n                int bj = max(0, min(j - 1, N - 2));\n                for (int di2 = 0; di2 < 2; ++di2) {\n                    for (int dj2 = 0; dj2 < 2; ++dj2) {\n                        int c = (bi + di2) * N + (bj + dj2);\n                        cur[c] = (uint8_t)(rng() & 3);\n                    }\n                }\n            } else {\n                for (int k = 0; k < 4; ++k) {\n                    int c = (int)(rng() % S);\n                    cur[c] = (uint8_t)(rng() & 3);\n                }\n            }\n\n            curEv = evaluate(cur, tile);\n            if (better(curEv, bakEv) || (rng() % 250 == 0)) {\n                moved = true;\n            } else {\n                cur = bak;\n                curEv = bakEv;\n            }\n        }\n\n        update_global();\n        if (moved) stagnation = 0;\n        else ++stagnation;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    array<int, S> tile{};\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) tile[i * N + j] = s[j] - '0';\n    }\n\n    // Precompute rotations for each tile type / desired kind.\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            for (int d = 0; d < 4; ++d) {\n                int bd = (d + r) & 3; // world dir -> base dir\n                int be = baseTo[t][bd];\n                if (be < 0) nxtDir[t][r][d] = -1;\n                else nxtDir[t][r][d] = (be - r + 4) & 3;\n            }\n        }\n    }\n\n    for (int t = 0; t < 8; ++t) {\n        for (int k = 0; k < 4; ++k) rotCorner[t][k] = -1;\n        for (int k = 0; k < 2; ++k) rotPair[t][k] = -1;\n    }\n\n    auto corner_kind = [&](int a, int b) -> int {\n        if (a > b) swap(a, b);\n        if (a == 0 && b == 1) return 0; // left-up\n        if (a == 1 && b == 2) return 1; // up-right\n        if (a == 2 && b == 3) return 2; // right-down\n        if (a == 0 && b == 3) return 3; // left-down\n        return -1;\n    };\n    auto straight_kind = [&](int a, int b) -> int {\n        if (a > b) swap(a, b);\n        if (a == 0 && b == 2) return 0; // horizontal\n        if (a == 1 && b == 3) return 1; // vertical\n        return -1;\n    };\n\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            vector<pair<int,int>> prs;\n            for (int d = 0; d < 4; ++d) {\n                int e = nxtDir[t][r][d];\n                if (e != -1 && d < e) prs.push_back({d, e});\n            }\n            sort(prs.begin(), prs.end());\n\n            if (t <= 3 && prs.size() == 1) {\n                int k = corner_kind(prs[0].first, prs[0].second);\n                if (k >= 0 && rotCorner[t][k] == -1) rotCorner[t][k] = r;\n            } else if (t <= 5 && prs.size() == 2) {\n                int a = corner_kind(prs[0].first, prs[0].second);\n                int b = corner_kind(prs[1].first, prs[1].second);\n                if ((a == 0 && b == 2) || (a == 2 && b == 0)) {\n                    if (rotPair[t][0] == -1) rotPair[t][0] = r;\n                }\n                if ((a == 3 && b == 1) || (a == 1 && b == 3)) {\n                    if (rotPair[t][1] == -1) rotPair[t][1] = r;\n                }\n            } else if (t >= 6 && prs.size() == 1) {\n                int k = straight_kind(prs[0].first, prs[0].second);\n                if (k >= 0 && rotPair[t][k] == -1) rotPair[t][k] = r;\n            }\n        }\n    }\n\n    auto start = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85;\n\n    struct Node {\n        EvalResult ev;\n        RotArr rot;\n    };\n\n    vector<Node> nodes;\n    nodes.reserve(128);\n\n    // Diverse structured candidates.\n    for (int pid = 0; pid < 8; ++pid) {\n        for (int sym = 0; sym < 8; ++sym) {\n            for (int mode = 0; mode < 2; ++mode) {\n                uint64_t seed = splitmix64(0x123456789abcdef0ULL ^ (uint64_t)pid * 0x9e3779b97f4a7c15ULL ^\n                                           (uint64_t)sym * 0xbf58476d1ce4e5b9ULL ^ (uint64_t)mode * 0x94d049bb133111ebULL);\n                RotArr cand = make_candidate(tile, pid, sym, mode, seed);\n                EvalResult ev = evaluate(cand, tile);\n                nodes.push_back(Node{move(ev), move(cand)});\n            }\n        }\n    }\n\n    sort(nodes.begin(), nodes.end(), [&](const Node& a, const Node& b) {\n        return better(a.ev, b.ev);\n    });\n\n    RotArr globalBestRot = nodes.front().rot;\n    EvalResult globalBestEv = nodes.front().ev;\n\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    // Refine the top few candidates within remaining time.\n    int use = min<int>(3, nodes.size());\n    for (int k = 0; k < use; ++k) {\n        double rem = TIME_LIMIT - elapsed();\n        if (rem <= 0.01) break;\n        double slice = rem / (use - k);\n        auto deadline = chrono::steady_clock::now() +\n                        chrono::duration_cast<chrono::steady_clock::duration>(chrono::duration<double>(slice));\n\n        RotArr cur = nodes[k].rot;\n        EvalResult curEv = nodes[k].ev;\n\n        local_search(cur, curEv, tile, globalBestRot, globalBestEv, deadline,\n                     splitmix64(0xabcdef0123456789ULL ^ (uint64_t)k * 0x9e3779b97f4a7c15ULL));\n\n        if (better(curEv, globalBestEv)) {\n            globalBestEv = curEv;\n            globalBestRot = cur;\n        }\n        if (elapsed() > TIME_LIMIT) break;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << int(globalBestRot[i * N + j]);\n        }\n    }\n    cout << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100;\n\nstruct EvalRes {\n    int exact = 0;    // largest tree component size\n    int near = 0;     // almost-tree component potential\n    int largest = 0;  // largest connected component size\n    int goodDeg = 0;  // degree matches tile degree\n    int diffDeg = 0;  // sum of abs(deg - need)\n    int shape = 0;    // border/center heuristic\n};\n\nstruct Node {\n    array<uint8_t, MAXC> bd{};\n    int blank = -1;\n    uint64_t hash = 0;\n    EvalRes ev;\n    int parent = -1;\n    char move = '?';\n    int depth = 0; // depth from the start of this search\n};\n\nstruct SearchResult {\n    string path; // path from the original root, if used by caller\n    Node end;\n    long long score = 0;\n};\n\nint N, T;\nint cells, fullV;\n\nint adjPos[MAXC][4];\nuint64_t zob[MAXC][16];\nint pcnt[16];\nint shapeW[5][5];\n\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\nchrono::steady_clock::time_point gStart;\ndouble gDeadline = 2.85;\n\ninline double elapsedSec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - gStart).count();\n}\n\ninline int parseHex(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + (c - 'a');\n}\n\ninline bool vecGreater(const array<int, 6>& a, const array<int, 6>& b) {\n    for (int i = 0; i < 6; ++i) {\n        if (a[i] != b[i]) return a[i] > b[i];\n    }\n    return false;\n}\n\ninline array<int, 6> modeKey(const EvalRes& e, int mode) {\n    if (mode == 0) {\n        return {e.exact, e.near, e.goodDeg, -e.diffDeg, e.shape, e.largest};\n    } else if (mode == 1) {\n        return {e.exact, e.shape, e.goodDeg, e.near, -e.diffDeg, e.largest};\n    } else {\n        return {e.exact, e.goodDeg, e.near, e.shape, -e.diffDeg, e.largest};\n    }\n}\n\ninline array<int, 6> partialKey(const EvalRes& e) {\n    return {e.exact, e.near, e.goodDeg, e.shape, -e.diffDeg, e.largest};\n}\n\ninline bool betterEvalMode(const EvalRes& a, const EvalRes& b, int mode) {\n    return vecGreater(modeKey(a, mode), modeKey(b, mode));\n}\n\ninline bool betterPartialScore(const EvalRes& a, const EvalRes& b) {\n    // Compare by actual judge score for partial states (depends only on exact).\n    if (a.exact != b.exact) return a.exact > b.exact;\n    return vecGreater(partialKey(a), partialKey(b));\n}\n\ninline long long partialScore(int exact) {\n    return (500000LL * exact + fullV / 2) / fullV;\n}\n\ninline long long fullScore(int totalLen) {\n    return llround(500000.0L * (2.0L - (long double)totalLen / (long double)T));\n}\n\ninline long long actualScore(const Node& n, int prefixLen) {\n    if (n.ev.exact == fullV) {\n        return fullScore(prefixLen + n.depth);\n    }\n    return partialScore(n.ev.exact);\n}\n\nEvalRes evaluate(const array<uint8_t, MAXC>& bd) {\n    int id[MAXC];\n    int V = 0;\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] != 0) id[i] = V++;\n        else id[i] = -1;\n    }\n\n    int deg[MAXC] = {};\n    int adj[MAXC][4];\n    int shape = 0;\n    int E = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int m = bd[idx];\n            if (!m) continue;\n\n            int ring = min(min(i, j), min(N - 1 - i, N - 1 - j));\n            if (ring > 4) ring = 4;\n            int need = pcnt[m];\n            int desired = min(4, ring + 1);\n            shape += shapeW[need][ring];\n\n            if (j + 1 < N) {\n                int idx2 = idx + 1;\n                int m2 = bd[idx2];\n                if (m2 && (m & 4) && (m2 & 1)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n            if (i + 1 < N) {\n                int idx2 = idx + N;\n                int m2 = bd[idx2];\n                if (m2 && (m & 8) && (m2 & 2)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n        }\n    }\n\n    bool vis[MAXC] = {};\n    int q[MAXC];\n\n    EvalRes res;\n    for (int s = 0; s < V; ++s) {\n        if (vis[s]) continue;\n\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n\n        int cnt = 0;\n        int sumdeg = 0;\n\n        while (head < tail) {\n            int x = q[head++];\n            ++cnt;\n            sumdeg += deg[x];\n            for (int k = 0; k < deg[x]; ++k) {\n                int y = adj[x][k];\n                if (!vis[y]) {\n                    vis[y] = true;\n                    q[tail++] = y;\n                }\n            }\n        }\n\n        int edges = sumdeg / 2;\n        int excess = edges - cnt + 1; // cycle rank of the component\n        res.largest = max(res.largest, cnt);\n        res.near = max(res.near, cnt - 2 * excess);\n        if (excess == 0) res.exact = max(res.exact, cnt);\n    }\n\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] == 0) continue;\n        res.goodDeg += 0; // placeholder, filled below\n    }\n\n    // Recompute degrees for local consistency metrics.\n    // (We keep this separate for clarity and because the board is tiny.)\n    memset(deg, 0, sizeof(deg));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int m = bd[idx];\n            if (!m) continue;\n            if (j + 1 < N) {\n                int idx2 = idx + 1;\n                int m2 = bd[idx2];\n                if (m2 && (m & 4) && (m2 & 1)) {\n                    ++deg[id[idx]];\n                    ++deg[id[idx2]];\n                }\n            }\n            if (i + 1 < N) {\n                int idx2 = idx + N;\n                int m2 = bd[idx2];\n                if (m2 && (m & 8) && (m2 & 2)) {\n                    ++deg[id[idx]];\n                    ++deg[id[idx2]];\n                }\n            }\n        }\n    }\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] == 0) continue;\n        int need = pcnt[bd[i]];\n        int d = deg[id[i]];\n        if (d == need) ++res.goodDeg;\n        res.diffDeg += abs(d - need);\n    }\n\n    res.shape = shape;\n    return res;\n}\n\nNode applyMove(const Node& cur, int dir, int parentId) {\n    Node nxt = cur;\n    int a = cur.blank;\n    int b = adjPos[a][dir];\n    uint8_t x = nxt.bd[a];\n    uint8_t y = nxt.bd[b];\n    nxt.hash ^= zob[a][x] ^ zob[a][y] ^ zob[b][y] ^ zob[b][x];\n    swap(nxt.bd[a], nxt.bd[b]);\n    nxt.blank = b;\n    nxt.parent = parentId;\n    nxt.move = dirChar[dir];\n    nxt.depth = cur.depth + 1;\n    nxt.ev = evaluate(nxt.bd);\n    return nxt;\n}\n\nstring buildPath(const vector<Node>& nodes, int id) {\n    string s;\n    while (id != -1 && nodes[id].parent != -1) {\n        s.push_back(nodes[id].move);\n        id = nodes[id].parent;\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstruct Cand {\n    int id;\n    array<int, 6> key;\n    array<int, 6> self;\n    uint32_t noise;\n};\n\nbool betterCand(const Cand& a, const Cand& b) {\n    if (vecGreater(a.key, b.key)) return true;\n    if (vecGreater(b.key, a.key)) return false;\n    if (vecGreater(a.self, b.self)) return true;\n    if (vecGreater(b.self, a.self)) return false;\n    return a.noise > b.noise;\n}\n\nSearchResult searchBeam(const Node& start, int prefixLen, int mode, int beamWidth, int depthLimit, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    vector<Node> nodes;\n    nodes.reserve((size_t)beamWidth * (size_t)depthLimit * 4 + 64);\n\n    Node root = start;\n    root.parent = -1;\n    root.move = '?';\n    root.depth = 0;\n    nodes.push_back(root);\n\n    vector<int> layer = {0};\n\n    unordered_set<uint64_t> seen;\n    seen.reserve((size_t)beamWidth * (size_t)depthLimit * 6 + 64);\n    seen.insert(root.hash);\n\n    int bestId = 0;\n    long long bestScore = actualScore(nodes[0], prefixLen);\n    array<int, 6> bestHeu = modeKey(nodes[0].ev, mode);\n\n    for (int depth = 0; depth < depthLimit; ++depth) {\n        if ((depth & 3) == 0 && elapsedSec() > gDeadline) break;\n\n        unordered_map<uint64_t, Cand> bestMap;\n        bestMap.reserve(layer.size() * 4 + 32);\n\n        int generated = 0;\n\n        for (int pid : layer) {\n            const Node cur = nodes[pid];\n\n            for (int dir = 0; dir < 4; ++dir) {\n                int nb = adjPos[cur.blank][dir];\n                if (nb == -1) continue;\n\n                Node child = applyMove(cur, dir, pid);\n                if (seen.count(child.hash)) continue;\n                seen.insert(child.hash);\n\n                int childId = (int)nodes.size();\n                nodes.push_back(child);\n\n                long long scChild = actualScore(nodes[childId], prefixLen);\n                array<int, 6> heuChild = modeKey(nodes[childId].ev, mode);\n\n                if (scChild > bestScore || (scChild == bestScore && vecGreater(heuChild, bestHeu))) {\n                    bestScore = scChild;\n                    bestId = childId;\n                    bestHeu = heuChild;\n                }\n\n                array<int, 6> bestKey = heuChild;\n\n                // One-step lookahead for ranking and possibly better actual-score samples.\n                for (int ndir = 0; ndir < 4; ++ndir) {\n                    int nnb = adjPos[child.blank][ndir];\n                    if (nnb == -1) continue;\n                    if (nnb == cur.blank) continue; // immediate backtrack\n\n                    Node grand = applyMove(child, ndir, childId);\n                    if (seen.count(grand.hash)) continue;\n\n                    array<int, 6> heuGrand = modeKey(grand.ev, mode);\n                    if (vecGreater(heuGrand, bestKey)) bestKey = heuGrand;\n\n                    long long scGrand = actualScore(grand, prefixLen);\n                    if (scGrand > bestScore || (scGrand == bestScore && vecGreater(heuGrand, bestHeu))) {\n                        int gid = (int)nodes.size();\n                        nodes.push_back(grand);\n                        bestScore = scGrand;\n                        bestId = gid;\n                        bestHeu = heuGrand;\n                    }\n                }\n\n                Cand cand{childId, bestKey, heuChild, (uint32_t)rng()};\n                auto it = bestMap.find(child.hash);\n                if (it == bestMap.end() || betterCand(cand, it->second)) {\n                    bestMap[child.hash] = cand;\n                }\n\n                ++generated;\n                if ((generated & 31) == 0 && elapsedSec() > gDeadline) break;\n            }\n\n            if (elapsedSec() > gDeadline) break;\n        }\n\n        if (bestMap.empty()) break;\n\n        vector<Cand> candVec;\n        candVec.reserve(bestMap.size());\n        for (auto& kv : bestMap) candVec.push_back(kv.second);\n\n        sort(candVec.begin(), candVec.end(), [](const Cand& a, const Cand& b) {\n            return betterCand(a, b);\n        });\n\n        if ((int)candVec.size() > beamWidth) candVec.resize(beamWidth);\n\n        layer.clear();\n        layer.reserve(candVec.size());\n        for (const auto& c : candVec) {\n            layer.push_back(c.id);\n        }\n    }\n\n    SearchResult res;\n    res.end = nodes[bestId];\n    res.path = buildPath(nodes, bestId);\n    res.score = bestScore;\n    return res;\n}\n\nSearchResult searchGreedy(const Node& start, int prefixLen, int mode, int maxSteps, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    Node cur = start;\n    cur.parent = -1;\n    cur.move = '?';\n    cur.depth = 0;\n\n    string path;\n    string bestPath;\n    Node best = cur;\n    long long bestScore = actualScore(cur, prefixLen);\n    array<int, 6> bestHeu = modeKey(cur.ev, mode);\n\n    unordered_set<uint64_t> seen;\n    seen.reserve((size_t)maxSteps * 4 + 32);\n    seen.insert(cur.hash);\n\n    int stagnation = 0;\n\n    for (int step = 0; step < maxSteps; ++step) {\n        if ((step & 7) == 0 && elapsedSec() > gDeadline) break;\n\n        struct GCand {\n            int dir;\n            Node st;\n            array<int, 6> key;\n            array<int, 6> self;\n            uint32_t noise;\n        };\n\n        vector<GCand> cands;\n        cands.reserve(4);\n\n        for (int dir = 0; dir < 4; ++dir) {\n            int nb = adjPos[cur.blank][dir];\n            if (nb == -1) continue;\n\n            Node child = applyMove(cur, dir, -1);\n            if (seen.count(child.hash)) continue;\n\n            array<int, 6> selfKey = modeKey(child.ev, mode);\n            array<int, 6> bestKey = selfKey;\n\n            for (int ndir = 0; ndir < 4; ++ndir) {\n                int nnb = adjPos[child.blank][ndir];\n                if (nnb == -1) continue;\n                if (nnb == cur.blank) continue;\n\n                Node grand = applyMove(child, ndir, -1);\n                if (seen.count(grand.hash)) continue;\n                array<int, 6> gk = modeKey(grand.ev, mode);\n                if (vecGreater(gk, bestKey)) bestKey = gk;\n            }\n\n            cands.push_back({dir, child, bestKey, selfKey, (uint32_t)rng()});\n        }\n\n        if (cands.empty()) break;\n\n        sort(cands.begin(), cands.end(), [](const GCand& a, const GCand& b) {\n            if (vecGreater(a.key, b.key)) return true;\n            if (vecGreater(b.key, a.key)) return false;\n            if (vecGreater(a.self, b.self)) return true;\n            if (vecGreater(b.self, a.self)) return false;\n            return a.noise > b.noise;\n        });\n\n        int pick = 0;\n        if ((int)cands.size() >= 2) {\n            uint32_t r = (uint32_t)rng();\n            if (r % 100 < 18) pick = 1;\n            if ((int)cands.size() >= 3 && r % 100 < 7) pick = 2;\n        }\n\n        cur = cands[pick].st;\n        path.push_back(dirChar[cands[pick].dir]);\n        seen.insert(cur.hash);\n\n        long long sc = actualScore(cur, prefixLen);\n        array<int, 6> heu = modeKey(cur.ev, mode);\n        if (sc > bestScore || (sc == bestScore && vecGreater(heu, bestHeu))) {\n            bestScore = sc;\n            best = cur;\n            bestPath = path;\n            bestHeu = heu;\n            stagnation = 0;\n        } else {\n            ++stagnation;\n        }\n\n        if (cur.ev.exact == fullV) {\n            // A full tree is valuable; continue only if it is still improving score.\n            long long fullSc = actualScore(cur, prefixLen);\n            if (fullSc >= bestScore) {\n                bestScore = fullSc;\n                best = cur;\n                bestPath = path;\n                bestHeu = heu;\n            }\n        }\n\n        if (stagnation > 50) break;\n    }\n\n    SearchResult res;\n    res.end = best;\n    res.path = bestPath;\n    res.score = bestScore;\n    return res;\n}\n\nstruct FinalCand {\n    string path;\n    Node end;\n    long long score;\n};\n\nbool betterFinal(const FinalCand& a, const FinalCand& b) {\n    if (a.score != b.score) return a.score > b.score;\n    if (a.end.ev.exact == fullV && b.end.ev.exact == fullV && a.path.size() != b.path.size()) {\n        return a.path.size() < b.path.size();\n    }\n    return a.path.size() < b.path.size();\n}\n\nuint64_t splitmix64(uint64_t& x) {\n    x += 0x9e3779b97f4a7c15ULL;\n    uint64_t z = x;\n    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n    z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n    return z ^ (z >> 31);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    cells = N * N;\n    fullV = cells - 1;\n\n    vector<string> s(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n\n    for (int i = 0; i < 16; ++i) {\n        pcnt[i] = __builtin_popcount((unsigned)i);\n    }\n\n    // Mild shape heuristic: leaves on border, higher degree toward center.\n    for (int need = 1; need <= 4; ++need) {\n        for (int ring = 0; ring <= 4; ++ring) {\n            int desired = min(4, ring + 1);\n            shapeW[need][ring] = 8 - 2 * abs(need - desired);\n        }\n    }\n\n    Node root;\n    int blankPos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int v = parseHex(s[i][j]);\n            root.bd[idx] = (uint8_t)v;\n            if (v == 0) blankPos = idx;\n        }\n    }\n    root.blank = blankPos;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            adjPos[idx][0] = (i > 0 ? idx - N : -1);\n            adjPos[idx][1] = (i + 1 < N ? idx + N : -1);\n            adjPos[idx][2] = (j > 0 ? idx - 1 : -1);\n            adjPos[idx][3] = (j + 1 < N ? idx + 1 : -1);\n        }\n    }\n\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    uint64_t sm = seed ^ 0x123456789abcdef0ULL;\n    for (int i = 0; i < cells; ++i) {\n        for (int v = 0; v < 16; ++v) {\n            zob[i][v] = splitmix64(sm);\n        }\n    }\n\n    root.hash = 0;\n    for (int i = 0; i < cells; ++i) root.hash ^= zob[i][root.bd[i]];\n    root.ev = evaluate(root.bd);\n    root.parent = -1;\n    root.move = '?';\n    root.depth = 0;\n\n    gStart = chrono::steady_clock::now();\n    gDeadline = 2.85;\n\n    vector<FinalCand> finals;\n\n    auto addCand = [&](const SearchResult& r) {\n        finals.push_back({r.path, r.end, r.score});\n    };\n\n    // Stage 1: several diverse searches from the root.\n    {\n        int rootDepth = min(80, T);\n        int rootBeam = 120;\n        int rootGreedy = min(80, T);\n\n        uint64_t s1 = splitmix64(sm);\n        uint64_t s2 = splitmix64(sm);\n        uint64_t s3 = splitmix64(sm);\n        uint64_t s4 = splitmix64(sm);\n\n        SearchResult r1 = searchBeam(root, 0, 0, rootBeam, rootDepth, s1);\n        SearchResult r2 = searchBeam(root, 0, 1, rootBeam, rootDepth, s2);\n        SearchResult r3 = searchBeam(root, 0, 2, rootBeam, rootDepth, s3);\n        SearchResult r4 = searchGreedy(root, 0, 2, rootGreedy, s4);\n\n        addCand(r1);\n        addCand(r2);\n        addCand(r3);\n        addCand(r4);\n\n        if (elapsedSec() < gDeadline) {\n            vector<SearchResult> roots = {r1, r2, r3, r4};\n\n            // Pick promising partial states for refinement:\n            // sort by actual score (which is already path-aware for full states),\n            // then by remaining budget, then by heuristic quality.\n            struct Pick {\n                SearchResult r;\n                int remaining;\n                array<int, 6> pk;\n            };\n            vector<Pick> picks;\n            for (auto& rr : roots) {\n                if (rr.end.ev.exact == fullV) continue; // already full; keep as final candidate\n                int rem = T - (int)rr.path.size();\n                if (rem <= 0) continue;\n                picks.push_back({rr, rem, partialKey(rr.end.ev)});\n            }\n\n            sort(picks.begin(), picks.end(), [&](const Pick& a, const Pick& b) {\n                if (a.r.score != b.r.score) return a.r.score > b.r.score;\n                if (a.remaining != b.remaining) return a.remaining > b.remaining;\n                if (vecGreater(a.pk, b.pk)) return true;\n                if (vecGreater(b.pk, a.pk)) return false;\n                return a.r.path.size() < b.r.path.size();\n            });\n\n            vector<Pick> uniq;\n            unordered_set<uint64_t> used;\n            used.reserve(8);\n            for (auto& p : picks) {\n                if (used.insert(p.r.end.hash).second) uniq.push_back(p);\n                if ((int)uniq.size() >= 2) break;\n            }\n\n            if (!uniq.empty() && elapsedSec() < gDeadline) {\n                auto doRefine = [&](const Pick& p, int mode, int beamWidth, int depthCap, uint64_t seedX) {\n                    int rem = T - (int)p.r.path.size();\n                    if (rem <= 0) return;\n                    int lim = min(depthCap, rem);\n                    SearchResult ext = searchBeam(p.r.end, (int)p.r.path.size(), mode, beamWidth, lim, seedX);\n                    FinalCand fc;\n                    fc.path = p.r.path + ext.path;\n                    fc.end = ext.end;\n                    fc.score = ext.score;\n                    addCand(ext); // ext.score already includes prefixLen inside the search\n                    finals.push_back(fc);\n                };\n\n                // Refine the best candidate with both beam and greedy.\n                {\n                    const auto& p = uniq[0];\n                    uint64_t sa = splitmix64(sm);\n                    uint64_t sb = splitmix64(sm);\n                    int rem = T - (int)p.r.path.size();\n                    if (rem > 0) {\n                        int lim = min(160, rem);\n                        SearchResult ext1 = searchBeam(p.r.end, (int)p.r.path.size(), 0, 160, lim, sa);\n                        FinalCand fc1{p.r.path + ext1.path, ext1.end, ext1.score};\n                        finals.push_back(fc1);\n\n                        SearchResult ext2 = searchGreedy(p.r.end, (int)p.r.path.size(), 1, min(160, rem), sb);\n                        FinalCand fc2{p.r.path + ext2.path, ext2.end, ext2.score};\n                        finals.push_back(fc2);\n                    }\n                }\n\n                if (uniq.size() >= 2 && elapsedSec() < gDeadline) {\n                    const auto& p = uniq[1];\n                    uint64_t sc = splitmix64(sm);\n                    int rem = T - (int)p.r.path.size();\n                    if (rem > 0) {\n                        int lim = min(160, rem);\n                        SearchResult ext = searchBeam(p.r.end, (int)p.r.path.size(), 1, 160, lim, sc);\n                        FinalCand fc{p.r.path + ext.path, ext.end, ext.score};\n                        finals.push_back(fc);\n                    }\n                }\n            }\n        }\n    }\n\n    // Choose the best final candidate by the judge score.\n    if (finals.empty()) {\n        cout << '\\n';\n        return 0;\n    }\n\n    FinalCand best = finals[0];\n    for (int i = 1; i < (int)finals.size(); ++i) {\n        if (betterFinal(finals[i], best)) best = finals[i];\n    }\n\n    if ((int)best.path.size() > T) {\n        // Safety fallback: should not happen, but keep output legal.\n        best.path.resize(T);\n    }\n\n    cout << best.path << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ld = long double;\n\nstatic const ld PI = acosl(-1.0L);\nstatic const int MAXS = 101;       // strips = cuts + 1\nstatic const int MAXPROD = 50000;   // enough for our candidates\n\nint N, K;\narray<int, 11> A{};\nvector<int> X, Y;\n\nstruct Partition {\n    bool ok = false;\n    vector<ll> cuts;   // c values for a*x + b*y = c\n    vector<int> bin;   // bin index for each point\n};\n\nstruct Family {\n    int a = 0, b = 0;  // primitive normal vector\n    ld ang = 0;\n    vector<ll> sortedVals;\n    vector<int> ord;\n\n    vector<ll> cutVals;  // valid integer cut positions\n    vector<int> leftCnt; // #points with projection < cutVals[i]\n\n    vector<Partition> cache;\n    vector<char> built;\n\n    Family() : cache(MAXS + 1), built(MAXS + 1, 0) {}\n};\n\nstruct Candidate {\n    int score = -1;\n    int cuts = INT_MAX;\n    vector<int> fams;\n    vector<int> strips;\n};\n\nvector<Family> families;\nCandidate bestCand;\nint totalA = 0;\n\npair<int,int> canon(int a, int b) {\n    if (a == 0 && b == 0) return {0, 0};\n    int g = std::gcd(abs(a), abs(b));\n    a /= g;\n    b /= g;\n    if (b < 0 || (b == 0 && a < 0)) {\n        a = -a;\n        b = -b;\n    }\n    return {a, b};\n}\n\nll egcdPos(ll a, ll b, ll& x, ll& y) {\n    if (b == 0) {\n        x = 1;\n        y = 0;\n        return a;\n    }\n    ll x1, y1;\n    ll g = egcdPos(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\nstruct LineOut {\n    ll x1, y1, x2, y2;\n};\n\nLineOut makeLine(int a, int b, ll c) {\n    // Solve a*x + b*y = c with integer coordinates\n    ll aa = llabs((ll)a), bb = llabs((ll)b);\n    ll x, y;\n    egcdPos(aa, bb, x, y); // aa*x + bb*y = 1\n\n    if (a < 0) x = -x;\n    if (b < 0) y = -y;\n\n    x *= c;\n    y *= c;\n\n    // Direction vector on the line is (b, -a)\n    return {x, y, x + b, y - a};\n}\n\nFamily buildFamily(int a, int b) {\n    Family F;\n    F.a = a;\n    F.b = b;\n    F.ang = atan2l((ld)b, (ld)a);\n    if (F.ang < 0) F.ang += PI;\n\n    vector<ll> proj(N);\n    F.ord.resize(N);\n    for (int i = 0; i < N; i++) {\n        proj[i] = 1LL * a * X[i] + 1LL * b * Y[i];\n        F.ord[i] = i;\n    }\n\n    sort(F.ord.begin(), F.ord.end(), [&](int i, int j) {\n        if (proj[i] != proj[j]) return proj[i] < proj[j];\n        return i < j;\n    });\n\n    F.sortedVals.resize(N);\n    for (int i = 0; i < N; i++) F.sortedVals[i] = proj[F.ord[i]];\n\n    vector<ll> uniq;\n    vector<int> cnt;\n    for (ll v : F.sortedVals) {\n        if (uniq.empty() || uniq.back() != v) {\n            uniq.push_back(v);\n            cnt.push_back(1);\n        } else {\n            cnt.back()++;\n        }\n    }\n\n    vector<int> pref(cnt.size() + 1, 0);\n    for (int i = 0; i < (int)cnt.size(); i++) pref[i + 1] = pref[i] + cnt[i];\n\n    for (int k = 0; k + 1 < (int)uniq.size(); k++) {\n        if (uniq[k + 1] - uniq[k] >= 2) {\n            F.cutVals.push_back(uniq[k] + 1);   // any integer inside the gap\n            F.leftCnt.push_back(pref[k + 1]);   // #points left of this cut\n        }\n    }\n\n    return F;\n}\n\nPartition buildPartition(const Family& F, int s) {\n    Partition res;\n    if (s < 1 || s > MAXS) return res;\n\n    if (s == 1) {\n        res.ok = true;\n        res.bin.assign(N, 0);\n        return res;\n    }\n\n    int gaps = (int)F.cutVals.size();\n    if (gaps < s - 1) return res;\n\n    vector<ll> cuts;\n    cuts.reserve(s - 1);\n\n    int start = 0;\n    for (int j = 1; j <= s - 1; j++) {\n        int lo = start;\n        int hi = gaps - 1 - ((s - 1) - j);\n        if (lo > hi) return res;\n\n        ll target = (1LL * j * N + s / 2) / s; // rounded quantile\n\n        auto it = lower_bound(F.leftCnt.begin() + lo, F.leftCnt.begin() + hi + 1, target);\n        int idx;\n        if (it == F.leftCnt.begin() + lo) {\n            idx = lo;\n        } else if (it == F.leftCnt.begin() + hi + 1) {\n            idx = hi;\n        } else {\n            int p = (int)(it - F.leftCnt.begin());\n            ll d0 = llabs((ll)F.leftCnt[p - 1] - target);\n            ll d1 = llabs((ll)F.leftCnt[p] - target);\n            idx = (d0 <= d1 ? p - 1 : p);\n        }\n\n        cuts.push_back(F.cutVals[idx]);\n        start = idx + 1;\n    }\n\n    res.bin.assign(N, 0);\n    int ptr = 0;\n    for (int j = 0; j < s - 1; j++) {\n        while (ptr < N && F.sortedVals[ptr] < cuts[j]) {\n            res.bin[F.ord[ptr]] = j;\n            ptr++;\n        }\n    }\n    while (ptr < N) {\n        res.bin[F.ord[ptr]] = s - 1;\n        ptr++;\n    }\n\n    res.ok = true;\n    res.cuts = std::move(cuts);\n    return res;\n}\n\nPartition& getPartition(int fid, int s) {\n    Family& F = families[fid];\n    if (!F.built[s]) {\n        F.cache[s] = buildPartition(F, s);\n        F.built[s] = 1;\n    }\n    return F.cache[s];\n}\n\nbool better(const Candidate& a, const Candidate& b) {\n    if (a.score != b.score) return a.score > b.score;\n    return a.cuts < b.cuts;\n}\n\nvoid consider(const Candidate& cand) {\n    if (cand.score < 0) return;\n    if (better(cand, bestCand)) bestCand = cand;\n}\n\nCandidate evaluateCandidate(const vector<int>& fams, const vector<int>& strips) {\n    Candidate res;\n    int t = (int)fams.size();\n\n    ll prod = 1;\n    int cuts = 0;\n    for (int s : strips) {\n        if (s < 1 || s > MAXS) return res;\n        cuts += s - 1;\n        if (cuts > K) return res;\n        if (prod > MAXPROD / s) return res;\n        prod *= s;\n    }\n    if (prod > MAXPROD) return res;\n\n    vector<const Partition*> parts(t);\n    for (int i = 0; i < t; i++) {\n        Partition& p = getPartition(fams[i], strips[i]);\n        if (!p.ok) return res;\n        parts[i] = &p;\n    }\n\n    static int cell[MAXPROD + 5];\n    fill(cell, cell + (int)prod, 0);\n\n    vector<int> mul(t, 1);\n    for (int i = t - 2; i >= 0; i--) {\n        mul[i] = mul[i + 1] * strips[i + 1];\n    }\n\n    for (int i = 0; i < N; i++) {\n        int id = 0;\n        for (int j = 0; j < t; j++) {\n            id += parts[j]->bin[i] * mul[j];\n        }\n        cell[id]++;\n    }\n\n    int hist[11] = {};\n    for (int i = 0; i < (int)prod; i++) {\n        int v = cell[i];\n        if (1 <= v && v <= 10) hist[v]++;\n    }\n\n    int score = 0;\n    for (int d = 1; d <= 10; d++) score += min(A[d], hist[d]);\n\n    res.score = score;\n    res.cuts = cuts;\n    res.fams = fams;\n    res.strips = strips;\n    return res;\n}\n\nll maxProduct(int t) {\n    int q = K / t;\n    int r = K % t;\n    ll prod = 1;\n    for (int i = 0; i < t; i++) {\n        int cuts = q + (i < r ? 1 : 0);\n        prod *= (cuts + 1);\n    }\n    return prod;\n}\n\nvector<int> buildTargets(ll cap, int keepProxy, const vector<pair<ld,int>>& proxies) {\n    vector<int> res;\n    set<int> seen;\n\n    auto add = [&](ll x) {\n        if (x < 1) x = 1;\n        if (x > cap) x = cap;\n        int v = (int)x;\n        if (seen.insert(v).second) res.push_back(v);\n    };\n\n    for (int i = 0; i < (int)proxies.size() && i < keepProxy; i++) add(proxies[i].second);\n    add(totalA);\n    add(N / 2);\n    add(N / 3);\n    add(cap);\n\n    return res;\n}\n\nCandidate refineCandidate(Candidate cur) {\n    for (int iter = 0; iter < 2; iter++) {\n        Candidate bestLocal = cur;\n        int t = (int)cur.strips.size();\n\n        auto test = [&](const vector<int>& s) {\n            Candidate cand = evaluateCandidate(cur.fams, s);\n            if (better(cand, bestLocal)) bestLocal = std::move(cand);\n        };\n\n        for (int i = 0; i < t; i++) {\n            if (cur.strips[i] > 1) {\n                auto s = cur.strips;\n                s[i]--;\n                test(s);\n            }\n            if (cur.strips[i] < MAXS) {\n                auto s = cur.strips;\n                s[i]++;\n                test(s);\n            }\n        }\n\n        for (int i = 0; i < t; i++) {\n            for (int j = i + 1; j < t; j++) {\n                if (cur.strips[i] > 1 && cur.strips[j] < MAXS) {\n                    auto s = cur.strips;\n                    s[i]--;\n                    s[j]++;\n                    test(s);\n                }\n                if (cur.strips[i] < MAXS && cur.strips[j] > 1) {\n                    auto s = cur.strips;\n                    s[i]++;\n                    s[j]--;\n                    test(s);\n                }\n            }\n        }\n\n        if (better(bestLocal, cur)) cur = std::move(bestLocal);\n        else break;\n    }\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> A[d];\n        totalA += A[d];\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    // Build a set of candidate primitive normals.\n    const int B = 12;\n    set<pair<int,int>> seen;\n    vector<pair<int,int>> normals;\n\n    auto addNormal = [&](int a, int b) {\n        auto p = canon(a, b);\n        if (p.first == 0 && p.second == 0) return;\n        if (seen.insert(p).second) normals.push_back(p);\n    };\n\n    for (int a = -B; a <= B; a++) {\n        for (int b = -B; b <= B; b++) {\n            if (a == 0 && b == 0) continue;\n            if (std::gcd(abs(a), abs(b)) != 1) continue;\n            addNormal(a, b);\n        }\n    }\n\n    // Extra PCA-derived direction.\n    long double mx = 0, my = 0;\n    for (int i = 0; i < N; i++) {\n        mx += X[i];\n        my += Y[i];\n    }\n    mx /= N;\n    my /= N;\n\n    long double cxx = 0, cyy = 0, cxy = 0;\n    for (int i = 0; i < N; i++) {\n        long double dx = X[i] - mx;\n        long double dy = Y[i] - my;\n        cxx += dx * dx;\n        cyy += dy * dy;\n        cxy += dx * dy;\n    }\n    long double theta = 0.5L * atan2l(2.0L * cxy, cxx - cyy);\n    int pa = (int)llround(cosl(theta) * 12.0L);\n    int pb = (int)llround(sinl(theta) * 12.0L);\n    if (pa == 0 && pb == 0) pa = 1;\n    addNormal(pa, pb);\n\n    sort(normals.begin(), normals.end(), [&](auto& p1, auto& p2) {\n        ld a1 = atan2l((ld)p1.second, (ld)p1.first);\n        ld a2 = atan2l((ld)p2.second, (ld)p2.first);\n        if (a1 < 0) a1 += PI;\n        if (a2 < 0) a2 += PI;\n        if (a1 != a2) return a1 < a2;\n        return p1 < p2;\n    });\n\n    families.reserve(normals.size());\n    for (auto [a, b] : normals) {\n        families.push_back(buildFamily(a, b));\n    }\n\n    int M = (int)families.size();\n\n    // Precompute proxy values for Poisson-like target piece counts.\n    array<ll, 11> fact{};\n    fact[0] = 1;\n    for (int i = 1; i <= 10; i++) fact[i] = fact[i - 1] * i;\n\n    vector<pair<ld,int>> proxies;\n    for (ld lam = 0.5L; lam <= 12.0L + 1e-12L; lam += 0.1L) {\n        ld m = (ld)N / lam;\n        ld e = expl(-lam);\n        ld p = 1.0L;\n        ld proxy = 0.0L;\n        for (int d = 1; d <= 10; d++) {\n            p *= lam;\n            ld expect = m * e * p / (ld)fact[d];\n            proxy += min((ld)A[d], expect);\n        }\n        proxies.push_back({proxy, (int)llround(m)});\n    }\n    sort(proxies.begin(), proxies.end(), [&](auto& x, auto& y) {\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n\n    ll cap2 = maxProduct(2);\n    ll cap3 = maxProduct(3);\n    vector<int> targets2 = buildTargets(cap2, 5, proxies);\n    vector<int> targets3 = buildTargets(cap3, 5, proxies);\n\n    // Single-family search.\n    vector<Candidate> bestSingle(M);\n    Candidate globalBestSingle;\n    vector<int> singleCounts = {\n        1,2,3,4,5,6,7,8,9,10,\n        12,14,15,16,18,20,24,25,30,36,\n        40,45,50,60,70,80,90,100,101\n    };\n\n    for (int fid = 0; fid < M; fid++) {\n        Candidate bestLocal;\n        for (int s : singleCounts) {\n            Candidate cand = evaluateCandidate(vector<int>{fid}, vector<int>{s});\n            if (better(cand, bestLocal)) bestLocal = cand;\n        }\n        bestSingle[fid] = bestLocal;\n        consider(bestLocal);\n    }\n\n    // Select a small diverse set of good orientations.\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (bestSingle[i].score != bestSingle[j].score) return bestSingle[i].score > bestSingle[j].score;\n        return families[i].ang < families[j].ang;\n    });\n\n    const int SEL = 7;\n    vector<int> selected;\n    vector<int> binBest(SEL, -1);\n    vector<char> used(M, 0);\n\n    auto angleBin = [&](int fid) {\n        int b = (int)(families[fid].ang * SEL / PI);\n        if (b < 0) b = 0;\n        if (b >= SEL) b = SEL - 1;\n        return b;\n    };\n\n    for (int fid : order) {\n        int b = angleBin(fid);\n        if (binBest[b] == -1) binBest[b] = fid;\n    }\n    for (int b = 0; b < SEL; b++) {\n        if (binBest[b] != -1) {\n            selected.push_back(binBest[b]);\n            used[binBest[b]] = 1;\n        }\n    }\n    for (int fid : order) {\n        if ((int)selected.size() >= SEL) break;\n        if (!used[fid]) {\n            selected.push_back(fid);\n            used[fid] = 1;\n        }\n    }\n    sort(selected.begin(), selected.end(), [&](int i, int j) {\n        if (bestSingle[i].score != bestSingle[j].score) return bestSingle[i].score > bestSingle[j].score;\n        return families[i].ang < families[j].ang;\n    });\n\n    // Pair-family search.\n    vector<int> specialR = {1,2,3,4,5,6,8,10,12,15,20,25};\n    for (int ii = 0; ii < (int)selected.size(); ii++) {\n        for (int jj = ii + 1; jj < (int)selected.size(); jj++) {\n            int fi = selected[ii], fj = selected[jj];\n\n            for (int T : targets2) {\n                set<int> rs;\n                for (int r : specialR) if (1 <= r && r <= MAXS) rs.insert(r);\n                int root = max(1, (int)llround(sqrt((ld)T)));\n                for (int r = max(1, root - 3); r <= min(MAXS, root + 3); r++) rs.insert(r);\n\n                for (int r : rs) {\n                    int c0 = max(1, (int)llround((ld)T / r));\n                    for (int dc = -1; dc <= 1; dc++) {\n                        int c = c0 + dc;\n                        if (c < 1 || c > MAXS) continue;\n                        if (r + c - 2 > K) continue;\n\n                        consider(evaluateCandidate(vector<int>{fi, fj}, vector<int>{r, c}));\n                        consider(evaluateCandidate(vector<int>{fi, fj}, vector<int>{c, r}));\n                    }\n                }\n            }\n        }\n    }\n\n    // Triple-family search.\n    for (int i = 0; i < (int)selected.size(); i++) {\n        for (int j = i + 1; j < (int)selected.size(); j++) {\n            for (int k = j + 1; k < (int)selected.size(); k++) {\n                int f1 = selected[i], f2 = selected[j], f3 = selected[k];\n\n                for (int T : targets3) {\n                    int root = max(1, (int)llround(cbrtl((ld)T)));\n                    for (int s = max(1, root - 1); s <= min(MAXS, root + 1); s++) {\n                        vector<int> base = {s, s, s};\n                        if ((s - 1) * 3 > K) continue;\n\n                        consider(evaluateCandidate(vector<int>{f1, f2, f3}, base));\n\n                        if (s > 1) {\n                            for (int idx = 0; idx < 3; idx++) {\n                                vector<int> t = base;\n                                t[idx]--;\n                                consider(evaluateCandidate(vector<int>{f1, f2, f3}, t));\n                            }\n                        }\n                        if (s < MAXS) {\n                            for (int idx = 0; idx < 3; idx++) {\n                                vector<int> t = base;\n                                t[idx]++;\n                                consider(evaluateCandidate(vector<int>{f1, f2, f3}, t));\n                            }\n                        }\n\n                        if (s > 1 && s < MAXS) {\n                            for (int a = 0; a < 3; a++) {\n                                for (int b = 0; b < 3; b++) if (a != b) {\n                                    vector<int> t = base;\n                                    t[a]++;\n                                    t[b]--;\n                                    consider(evaluateCandidate(vector<int>{f1, f2, f3}, t));\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    if (bestCand.score < 0) {\n        bestCand = bestSingle[order[0]];\n    }\n\n    bestCand = refineCandidate(bestCand);\n\n    // Output lines\n    cout << bestCand.cuts << '\\n';\n    for (int idx = 0; idx < (int)bestCand.fams.size(); idx++) {\n        int fid = bestCand.fams[idx];\n        int s = bestCand.strips[idx];\n        const Family& F = families[fid];\n        Partition& P = getPartition(fid, s);\n\n        for (ll c : P.cuts) {\n            LineOut L = makeLine(F.a, F.b, c);\n            cout << L.x1 << ' ' << L.y1 << ' ' << L.x2 << ' ' << L.y2 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cand {\n    array<uint16_t, 4> c{};\n    array<uint16_t, 64> bd{};\n    array<uint16_t, 64> sg{};\n    uint8_t bdLen = 0;\n    uint8_t sgLen = 0;\n    int perim = 0;\n};\n\nstruct Op {\n    array<int, 8> a{};\n};\n\nstruct Node {\n    long long score;\n    int ver;\n    int cid;\n    bool operator<(const Node& other) const {\n        return score < other.score;\n    }\n};\n\nstruct Params {\n    long long A, B, C, D;\n    uint64_t seed;\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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto t0 = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - t0).count();\n    };\n\n    int N, M;\n    cin >> N >> M;\n\n    const int V = N * N;\n    const long long C = (N - 1) / 2;\n\n    auto pid = [&](int x, int y) -> int { return x * N + y; };\n\n    vector<long long> wt(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            long long dx = x - C, dy = y - C;\n            wt[pid(x, y)] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    vector<uint8_t> initOcc(V, 0);\n    vector<int> initIds;\n    long long initSum = 0;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        int p = pid(x, y);\n        if (!initOcc[p]) {\n            initOcc[p] = 1;\n            initIds.push_back(p);\n            initSum += wt[p];\n        }\n    }\n\n    // Prefix sums for initial occupied dots\n    vector<vector<int>> rowPref(N, vector<int>(N + 1, 0));\n    vector<vector<int>> colPref(N, vector<int>(N + 1, 0));\n    for (int y = 0; y < N; ++y) {\n        for (int x = 0; x < N; ++x) {\n            rowPref[y][x + 1] = rowPref[y][x] + initOcc[pid(x, y)];\n        }\n    }\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            colPref[x][y + 1] = colPref[x][y] + initOcc[pid(x, y)];\n        }\n    }\n\n    int D = 2 * N - 1;\n    vector<int> diag1Start(D), diag2Start(D);\n    vector<vector<int>> diag1Pref(D), diag2Pref(D);\n\n    for (int diff = -(N - 1); diff <= N - 1; ++diff) {\n        int idx = diff + (N - 1);\n        int sx = max(0, diff);\n        int len = N - abs(diff);\n        diag1Start[idx] = sx;\n        diag1Pref[idx].assign(len + 1, 0);\n        for (int i = 0; i < len; ++i) {\n            int x = sx + i;\n            int y = x - diff;\n            diag1Pref[idx][i + 1] = diag1Pref[idx][i] + initOcc[pid(x, y)];\n        }\n    }\n    for (int s = 0; s <= 2 * N - 2; ++s) {\n        int sx = max(0, s - (N - 1));\n        int ex = min(N - 1, s);\n        int len = ex - sx + 1;\n        diag2Start[s] = sx;\n        diag2Pref[s].assign(len + 1, 0);\n        for (int i = 0; i < len; ++i) {\n            int x = sx + i;\n            int y = s - x;\n            diag2Pref[s][i + 1] = diag2Pref[s][i] + initOcc[pid(x, y)];\n        }\n    }\n\n    auto rowCnt = [&](int y, int l, int r) -> int {\n        if (l > r) return 0;\n        return rowPref[y][r + 1] - rowPref[y][l];\n    };\n    auto colCnt = [&](int x, int l, int r) -> int {\n        if (l > r) return 0;\n        return colPref[x][r + 1] - colPref[x][l];\n    };\n    auto diag1Cnt = [&](int diff, int l, int r) -> int {\n        if (l > r) return 0;\n        int idx = diff + (N - 1);\n        int sx = diag1Start[idx];\n        return diag1Pref[idx][r - sx + 1] - diag1Pref[idx][l - sx];\n    };\n    auto diag2Cnt = [&](int s, int l, int r) -> int {\n        if (l > r) return 0;\n        int sx = diag2Start[s];\n        return diag2Pref[s][r - sx + 1] - diag2Pref[s][l - sx];\n    };\n\n    const int H = N * (N - 1);\n    const int DD = (N - 1) * (N - 1);\n    const int totalSeg = 2 * H + 2 * DD;\n\n    auto hid = [&](int x, int y) -> int { return y * (N - 1) + x; };\n    auto vid = [&](int x, int y) -> int { return H + x * (N - 1) + y; };\n    auto pdiag = [&](int x, int y) -> int { return 2 * H + y * (N - 1) + x; };\n    auto ndiag = [&](int x, int y) -> int { return 2 * H + DD + y * (N - 1) + x; };\n\n    vector<Cand> cands;\n    cands.reserve(1000000);\n\n    vector<uint8_t> initCnt;\n    vector<int> initReadyMiss;\n    vector<pair<int, int>> initReady; // (cid, missing point)\n\n    vector<vector<int>> cornerInc(V), boundaryInc(V), segInc(totalSeg);\n    vector<array<int, 4>> initBucket(V);\n    vector<int> initBdAliveCnt(V, 0);\n    for (int i = 0; i < V; ++i) initBucket[i] = {0, 0, 0, 0};\n\n    auto addCandidate = [&](Cand&& cd, uint8_t cnt, int missPoint) {\n        if (cnt == 4) return;\n        int cid = (int)cands.size();\n        cands.push_back(cd);\n        initCnt.push_back(cnt);\n        if (cnt == 3) {\n            initReadyMiss.push_back(missPoint);\n            initReady.emplace_back(cid, missPoint);\n        } else {\n            initReadyMiss.push_back(-1);\n        }\n\n        const Cand& c = cands.back();\n        for (int i = 0; i < 4; ++i) {\n            int p = c.c[i];\n            cornerInc[p].push_back(cid);\n            initBucket[p][cnt]++;\n        }\n        for (int i = 0; i < c.bdLen; ++i) {\n            int p = c.bd[i];\n            boundaryInc[p].push_back(cid);\n            initBdAliveCnt[p]++;\n        }\n        for (int i = 0; i < c.sgLen; ++i) {\n            segInc[c.sg[i]].push_back(cid);\n        }\n    };\n\n    auto tryAddAxis = [&](int x, int y, int w, int h) {\n        if (rowCnt(y, x + 1, x + w - 1) > 0) return;\n        if (rowCnt(y + h, x + 1, x + w - 1) > 0) return;\n        if (colCnt(x, y + 1, y + h - 1) > 0) return;\n        if (colCnt(x + w, y + 1, y + h - 1) > 0) return;\n\n        Cand cd;\n        cd.bdLen = cd.sgLen = 0;\n        cd.c = { (uint16_t)pid(x, y), (uint16_t)pid(x + w, y), (uint16_t)pid(x + w, y + h), (uint16_t)pid(x, y + h) };\n\n        int cnt = 0;\n        for (int i = 0; i < 4; ++i) cnt += initOcc[cd.c[i]];\n        if (cnt == 4) return;\n\n        for (int xx = x + 1; xx < x + w; ++xx) cd.bd[cd.bdLen++] = (uint16_t)pid(xx, y);\n        for (int yy = y + 1; yy < y + h; ++yy) cd.bd[cd.bdLen++] = (uint16_t)pid(x + w, yy);\n        for (int xx = x + w - 1; xx > x; --xx) cd.bd[cd.bdLen++] = (uint16_t)pid(xx, y + h);\n        for (int yy = y + h - 1; yy > y; --yy) cd.bd[cd.bdLen++] = (uint16_t)pid(x, yy);\n\n        for (int xx = x; xx < x + w; ++xx) cd.sg[cd.sgLen++] = (uint16_t)hid(xx, y);\n        for (int yy = y; yy < y + h; ++yy) cd.sg[cd.sgLen++] = (uint16_t)vid(x + w, yy);\n        for (int xx = x + w - 1; xx >= x; --xx) cd.sg[cd.sgLen++] = (uint16_t)hid(xx, y + h);\n        for (int yy = y + h - 1; yy >= y; --yy) cd.sg[cd.sgLen++] = (uint16_t)vid(x, yy);\n\n        cd.perim = cd.sgLen;\n        int miss = -1;\n        if (cnt == 3) {\n            for (int i = 0; i < 4; ++i) if (!initOcc[cd.c[i]]) miss = cd.c[i];\n        }\n        addCandidate(std::move(cd), (uint8_t)cnt, miss);\n    };\n\n    auto tryAddDiag = [&](int x, int y, int a, int b) {\n        int diff1 = x - y;\n        int diff2 = x - y + 2 * b;\n        int sum1 = x + y;\n        int sum2 = x + y + 2 * a;\n\n        if (diag1Cnt(diff1, x + 1, x + a - 1) > 0) return;\n        if (diag2Cnt(sum2, x + a + 1, x + a + b - 1) > 0) return;\n        if (diag2Cnt(sum1, x + 1, x + b - 1) > 0) return;\n        if (diag1Cnt(diff2, x + b + 1, x + a + b - 1) > 0) return;\n\n        Cand cd;\n        cd.bdLen = cd.sgLen = 0;\n        cd.c = { (uint16_t)pid(x, y),\n                 (uint16_t)pid(x + a, y + a),\n                 (uint16_t)pid(x + a + b, y + a - b),\n                 (uint16_t)pid(x + b, y - b) };\n\n        int cnt = 0;\n        for (int i = 0; i < 4; ++i) cnt += initOcc[cd.c[i]];\n        if (cnt == 4) return;\n\n        for (int t = 1; t < a; ++t) cd.bd[cd.bdLen++] = (uint16_t)pid(x + t, y + t);\n        for (int t = 1; t < b; ++t) cd.bd[cd.bdLen++] = (uint16_t)pid(x + a + t, y + a - t);\n        for (int t = 1; t < b; ++t) cd.bd[cd.bdLen++] = (uint16_t)pid(x + t, y - t);\n        for (int t = 1; t < a; ++t) cd.bd[cd.bdLen++] = (uint16_t)pid(x + b + t, y - b + t);\n\n        for (int t = 0; t < a; ++t) cd.sg[cd.sgLen++] = (uint16_t)pdiag(x + t, y + t);\n        for (int t = 0; t < b; ++t) cd.sg[cd.sgLen++] = (uint16_t)ndiag(x + a + t, y + a - t - 1);\n        for (int t = 0; t < a; ++t) cd.sg[cd.sgLen++] = (uint16_t)pdiag(x + b + t, y - b + t);\n        for (int t = 0; t < b; ++t) cd.sg[cd.sgLen++] = (uint16_t)ndiag(x + t, y - t - 1);\n\n        cd.perim = cd.sgLen;\n        int miss = -1;\n        if (cnt == 3) {\n            for (int i = 0; i < 4; ++i) if (!initOcc[cd.c[i]]) miss = cd.c[i];\n        }\n        addCandidate(std::move(cd), (uint8_t)cnt, miss);\n    };\n\n    // Balanced rectangles\n    const int BAL = 15;\n    const int THIN_MAX = 30;\n\n    for (int w = 1; w <= BAL; ++w) {\n        for (int h = 1; h <= BAL; ++h) {\n            for (int x = 0; x + w < N; ++x) {\n                for (int y = 0; y + h < N; ++y) {\n                    tryAddAxis(x, y, w, h);\n                }\n            }\n        }\n    }\n\n    // Thin long rectangles\n    for (int w = 1; w <= THIN_MAX; ++w) {\n        for (int h = 1; h <= THIN_MAX; ++h) {\n            if (w <= BAL && h <= BAL) continue;\n            if (min(w, h) > 2) continue;\n            for (int x = 0; x + w < N; ++x) {\n                for (int y = 0; y + h < N; ++y) {\n                    tryAddAxis(x, y, w, h);\n                }\n            }\n        }\n    }\n\n    // Balanced 45-degree rectangles\n    for (int a = 1; a <= BAL - 1; ++a) {\n        for (int b = 1; a + b <= BAL; ++b) {\n            for (int x = 0; x + a + b < N; ++x) {\n                for (int y = b; y + a < N; ++y) {\n                    tryAddDiag(x, y, a, b);\n                }\n            }\n        }\n    }\n\n    // Thin long 45-degree rectangles\n    for (int a = 1; a <= THIN_MAX - 1; ++a) {\n        for (int b = 1; a + b <= THIN_MAX; ++b) {\n            if (a + b <= BAL) continue;\n            if (min(a, b) > 2) continue;\n            for (int x = 0; x + a + b < N; ++x) {\n                for (int y = b; y + a < N; ++y) {\n                    tryAddDiag(x, y, a, b);\n                }\n            }\n        }\n    }\n\n    int Ccand = (int)cands.size();\n\n    auto simulate = [&](const Params& ps) -> pair<long long, vector<Op>> {\n        vector<array<int, 4>> bucket = initBucket;\n        vector<int> bdAliveCnt = initBdAliveCnt;\n        vector<uint8_t> occ = initOcc;\n        vector<uint8_t> cnt = initCnt;\n        vector<uint8_t> alive(Ccand, 1);\n        vector<int> readyMiss(Ccand, -1);\n        vector<int> ver(Ccand, 0);\n        vector<uint8_t> segUsed(totalSeg, 0);\n\n        vector<vector<int>> readyList(V);\n        vector<uint8_t> mark(V, 0);\n        vector<int> touched;\n        touched.reserve(1024);\n\n        auto touch = [&](int p) {\n            if (!occ[p] && !mark[p]) {\n                mark[p] = 1;\n                touched.push_back(p);\n            }\n        };\n\n        auto addContrib = [&](int cid, int k) {\n            const Cand& cd = cands[cid];\n            for (int i = 0; i < 4; ++i) {\n                int p = cd.c[i];\n                bucket[p][k]++;\n                touch(p);\n            }\n        };\n\n        auto removeContrib = [&](int cid, int k) {\n            const Cand& cd = cands[cid];\n            for (int i = 0; i < 4; ++i) {\n                int p = cd.c[i];\n                bucket[p][k]--;\n                touch(p);\n            }\n        };\n\n        auto killCandidate = [&](int cid) {\n            if (!alive[cid]) return;\n            int k = cnt[cid];\n            removeContrib(cid, k);\n            const Cand& cd = cands[cid];\n            for (int i = 0; i < cd.bdLen; ++i) {\n                int p = cd.bd[i];\n                --bdAliveCnt[p];\n                touch(p);\n            }\n            alive[cid] = 0;\n            readyMiss[cid] = -1;\n            cnt[cid] = 4;\n        };\n\n        auto scoreCand = [&](int cid, int miss) -> long long {\n            long long support = 8LL * bucket[miss][2] + 3LL * bucket[miss][1] + 1LL * bucket[miss][3];\n            long long s = ps.A * wt[miss] + ps.B * support - ps.C * bdAliveCnt[miss] - ps.D * cands[cid].perim;\n            uint64_t z = splitmix64((uint64_t)cid ^ ps.seed);\n            s += (long long)(z % 11) - 5;\n            return s;\n        };\n\n        priority_queue<Node> pq;\n\n        for (auto [cid, miss] : initReady) {\n            readyMiss[cid] = miss;\n            readyList[miss].push_back(cid);\n            ver[cid] = 1;\n            pq.push(Node{scoreCand(cid, miss), ver[cid], cid});\n        }\n\n        vector<Op> ops;\n        ops.reserve(200000);\n        long long curSum = initSum;\n\n        while (!pq.empty()) {\n            if (elapsed() > 4.7) break;\n\n            Node cur = pq.top();\n            pq.pop();\n\n            int cid = cur.cid;\n            if (cur.ver != ver[cid]) continue;\n            if (!alive[cid] || cnt[cid] != 3 || readyMiss[cid] < 0) continue;\n\n            int miss = readyMiss[cid];\n            if (occ[miss]) continue;\n\n            // Apply this rectangle\n            int missIdx = -1;\n            for (int i = 0; i < 4; ++i) if (cands[cid].c[i] == miss) missIdx = i;\n            if (missIdx < 0) continue; // safety\n\n            Op op;\n            for (int t = 0; t < 4; ++t) {\n                int p = cands[cid].c[(missIdx + t) & 3];\n                op.a[2 * t] = p / N;\n                op.a[2 * t + 1] = p % N;\n            }\n\n            ops.push_back(op);\n            curSum += wt[miss];\n\n            occ[miss] = 1;\n            killCandidate(cid);\n\n            // Candidates that contain the new point as a corner\n            for (int nid : cornerInc[miss]) {\n                if (!alive[nid]) continue;\n\n                int old = cnt[nid];\n                if (old == 3) {\n                    killCandidate(nid);\n                    continue;\n                }\n\n                removeContrib(nid, old);\n                ++cnt[nid];\n                addContrib(nid, cnt[nid]);\n\n                if (cnt[nid] == 3) {\n                    int mm = -1;\n                    for (int i = 0; i < 4; ++i) if (!occ[cands[nid].c[i]]) mm = cands[nid].c[i];\n                    readyMiss[nid] = mm;\n                    readyList[mm].push_back(nid);\n                }\n            }\n\n            // Candidates whose perimeter contains the new point\n            for (int nid : boundaryInc[miss]) {\n                if (alive[nid]) killCandidate(nid);\n            }\n\n            // Candidates sharing a segment with the chosen rectangle\n            const Cand& chosen = cands[cid];\n            for (int i = 0; i < chosen.sgLen; ++i) {\n                int s = chosen.sg[i];\n                if (segUsed[s]) continue;\n                segUsed[s] = 1;\n                for (int nid : segInc[s]) {\n                    if (alive[nid]) killCandidate(nid);\n                }\n            }\n\n            // Refresh all ready candidates whose missing point was affected\n            for (int p : touched) {\n                if (!occ[p]) {\n                    for (int nid : readyList[p]) {\n                        if (!alive[nid] || cnt[nid] != 3 || readyMiss[nid] != p) continue;\n                        ++ver[nid];\n                        pq.push(Node{scoreCand(nid, p), ver[nid], nid});\n                    }\n                }\n                mark[p] = 0;\n            }\n            touched.clear();\n        }\n\n        return {curSum, ops};\n    };\n\n    int simCount = 3;\n    if (Ccand > 950000) simCount = 2;\n    if (Ccand > 1300000) simCount = 1;\n    if (elapsed() > 3.8) simCount = min(simCount, 1);\n    else if (elapsed() > 2.8) simCount = min(simCount, 2);\n\n    vector<Params> variants = {\n        {1300,  90, 4, 10, 0x123456789abcdefULL},\n        {1000, 120, 5,  8, 0x223456789abcdefULL},\n        { 800, 160, 6,  6, 0x323456789abcdefULL}\n    };\n    if (simCount < (int)variants.size()) variants.resize(simCount);\n\n    long long bestSum = initSum;\n    vector<Op> bestOps;\n\n    for (int i = 0; i < simCount; ++i) {\n        if (elapsed() > 4.7) break;\n        auto [sum, ops] = simulate(variants[i]);\n        if (sum > bestSum || (sum == bestSum && ops.size() > bestOps.size())) {\n            bestSum = sum;\n            bestOps = move(ops);\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n    for (const auto& op : bestOps) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << op.a[i];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int CELLS = 100;\nstatic constexpr int COLORS = 3;\nstatic constexpr int EXACT_DEPTH = 4;\nstatic constexpr double DISCOUNT = 0.97;\n\nstruct Board {\n    array<uint8_t, CELLS> a{};\n};\n\nint F[CELLS];\nint tot[4];\nint prefCnt[CELLS + 1][4];\nint remainAfter[CELLS + 1][4];\ndouble futureWeight[CELLS + 1][4];\n\nint targetR[4], targetC[4];\nint targetDist[4][CELLS];\n\nint NB[CELLS][4];\nstatic constexpr char DIRS[4] = {'F', 'B', 'L', 'R'};\n\ninline void initNeighbors() {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            NB[id][0] = (r + 1 < N ? (r + 1) * N + c : -1); // down\n            NB[id][1] = (r - 1 >= 0 ? (r - 1) * N + c : -1); // up\n            NB[id][2] = (c + 1 < N ? r * N + (c + 1) : -1);   // right\n            NB[id][3] = (c - 1 >= 0 ? r * N + (c - 1) : -1);  // left\n        }\n    }\n}\n\ninline int kthEmpty(const Board& b, int p) {\n    for (int i = 0; i < CELLS; ++i) {\n        if (b.a[i] == 0) {\n            --p;\n            if (p == 0) return i;\n        }\n    }\n    return -1;\n}\n\ninline int collectEmpties(const Board& b, int empties[]) {\n    int ec = 0;\n    for (int i = 0; i < CELLS; ++i) {\n        if (b.a[i] == 0) empties[ec++] = i;\n    }\n    return ec;\n}\n\ninline Board tilt(const Board& b, char d) {\n    Board r{};\n    r.a.fill(0);\n\n    if (d == 'L') {\n        for (int row = 0; row < N; ++row) {\n            int w = 0;\n            int base = row * N;\n            for (int c = 0; c < N; ++c) {\n                uint8_t v = b.a[base + c];\n                if (v) r.a[base + w++] = v;\n            }\n        }\n    } else if (d == 'R') {\n        for (int row = 0; row < N; ++row) {\n            int w = N - 1;\n            int base = row * N;\n            for (int c = N - 1; c >= 0; --c) {\n                uint8_t v = b.a[base + c];\n                if (v) r.a[base + w--] = v;\n            }\n        }\n    } else if (d == 'F') {\n        for (int c = 0; c < N; ++c) {\n            int w = 0;\n            for (int row = 0; row < N; ++row) {\n                uint8_t v = b.a[row * N + c];\n                if (v) r.a[w++ * N + c] = v;\n            }\n        }\n    } else { // 'B'\n        for (int c = 0; c < N; ++c) {\n            int w = N - 1;\n            for (int row = N - 1; row >= 0; --row) {\n                uint8_t v = b.a[row * N + c];\n                if (v) r.a[w-- * N + c] = v;\n            }\n        }\n    }\n    return r;\n}\n\ninline long long exactScore(const Board& b) {\n    bool vis[CELLS] = {};\n    int q[CELLS];\n    long long ans = 0;\n\n    for (int s = 0; s < CELLS; ++s) {\n        if (b.a[s] == 0 || vis[s]) continue;\n        uint8_t col = b.a[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            ++sz;\n            for (int k = 0; k < 4; ++k) {\n                int to = NB[v][k];\n                if (to != -1 && !vis[to] && b.a[to] == col) {\n                    vis[to] = true;\n                    q[tail++] = to;\n                }\n            }\n        }\n\n        ans += 1LL * sz * sz;\n    }\n    return ans;\n}\n\nstruct Info {\n    long long sumSq = 0;\n    int top[4][3]{};       // top[color][0..2]\n    int compCnt[4]{};      // components per color\n    int compSizeCell[CELLS]{};\n    long long rowSq[4]{};\n    long long colSq[4]{};\n    long long distSum[4]{};\n    int bboxArea[4]{};\n    int adj = 0;\n};\n\ninline void updTop(int t[3], int x) {\n    if (x > t[0]) {\n        t[2] = t[1];\n        t[1] = t[0];\n        t[0] = x;\n    } else if (x > t[1]) {\n        t[2] = t[1];\n        t[1] = x;\n    } else if (x > t[2]) {\n        t[2] = x;\n    }\n}\n\ninline Info analyze(const Board& b) {\n    Info info{};\n    bool vis[CELLS] = {};\n    int q[CELLS];\n    int compCells[CELLS];\n    int rowCnt[4][N] = {};\n    int colCnt[4][N] = {};\n\n    int minR[4], maxR[4], minC[4], maxC[4];\n    for (int c = 1; c <= 3; ++c) {\n        minR[c] = minC[c] = N;\n        maxR[c] = maxC[c] = -1;\n    }\n\n    for (int s = 0; s < CELLS; ++s) {\n        if (b.a[s] == 0 || vis[s]) continue;\n        uint8_t col = b.a[s];\n        int head = 0, tail = 0, cc = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        ++info.compCnt[col];\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            compCells[cc++] = v;\n            ++sz;\n\n            int r = v / N, c = v % N;\n            rowCnt[col][r]++;\n            colCnt[col][c]++;\n            info.distSum[col] += targetDist[col][v];\n            minR[col] = min(minR[col], r);\n            maxR[col] = max(maxR[col], r);\n            minC[col] = min(minC[col], c);\n            maxC[col] = max(maxC[col], c);\n\n            for (int k = 0; k < 4; ++k) {\n                int to = NB[v][k];\n                if (to != -1 && !vis[to] && b.a[to] == col) {\n                    vis[to] = true;\n                    q[tail++] = to;\n                }\n            }\n        }\n\n        info.sumSq += 1LL * sz * sz;\n        updTop(info.top[col], sz);\n        for (int i = 0; i < cc; ++i) info.compSizeCell[compCells[i]] = sz;\n    }\n\n    for (int c = 1; c <= 3; ++c) {\n        long long rs = 0, cs = 0;\n        for (int i = 0; i < N; ++i) {\n            rs += 1LL * rowCnt[c][i] * rowCnt[c][i];\n            cs += 1LL * colCnt[c][i] * colCnt[c][i];\n        }\n        info.rowSq[c] = rs;\n        info.colSq[c] = cs;\n\n        if (info.compCnt[c] == 0) {\n            info.bboxArea[c] = 0;\n        } else {\n            int h = maxR[c] - minR[c] + 1;\n            int w = maxC[c] - minC[c] + 1;\n            info.bboxArea[c] = h * w;\n        }\n    }\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            if (b.a[id] == 0) continue;\n            if (c + 1 < N && b.a[id + 1] == b.a[id]) ++info.adj;\n            if (r + 1 < N && b.a[id + N] == b.a[id]) ++info.adj;\n        }\n    }\n\n    return info;\n}\n\ninline double heuristicFromInfo(const Info& info, int idx) {\n    double s = (double)info.sumSq;\n\n    for (int c = 1; c <= 3; ++c) {\n        double rem = remainAfter[idx][c] + 0.25 * futureWeight[idx][c];\n        double top = info.top[c][0] + 0.65 * info.top[c][1] + 0.35 * info.top[c][2];\n        double avgDist = info.distSum[c] / max(1, tot[c]);\n\n        double pot = 1.4 * top;\n        pot += 0.012 * (double)(info.rowSq[c] + info.colSq[c]);\n        pot -= 0.10 * avgDist;\n        pot -= 0.25 * info.compCnt[c];\n        pot -= 0.02 * info.bboxArea[c];\n\n        s += rem * pot;\n    }\n\n    s += 0.04 * info.adj;\n    return s;\n}\n\ninline int findMarkerPos(const Board& b) {\n    for (int i = 0; i < CELLS; ++i) if (b.a[i] == 4) return i;\n    return -1;\n}\n\ninline double markerBonus(const Info& info, int pos, int color, int idx) {\n    if (pos < 0) return 0.0;\n    int r = pos / N, c = pos % N;\n    double imp = futureWeight[idx][color] / max(1, tot[color]);\n    double dist = abs(r - targetR[color]) + abs(c - targetC[color]);\n    return (0.75 + 2.5 * imp) * (double)info.compSizeCell[pos] - 0.12 * dist;\n}\n\ndouble exactValue(const Board& state, int idx);\n\ndouble scoreCurrentCandidate(const Board& afterCurrentTilt, int nextIdx) {\n    int empties[CELLS];\n    int ec = collectEmpties(afterCurrentTilt, empties);\n\n    if (100 - nextIdx <= EXACT_DEPTH) {\n        return exactValue(afterCurrentTilt, nextIdx);\n    }\n\n    double sum = 0.0;\n    for (int i = 0; i < ec; ++i) {\n        int pos = empties[i];\n\n        Board real = afterCurrentTilt;\n        real.a[pos] = (uint8_t)F[nextIdx];\n\n        Board mark = afterCurrentTilt;\n        mark.a[pos] = 4;\n\n        double best = -1e100;\n        for (char d : DIRS) {\n            Board u = tilt(real, d);\n            Board m = tilt(mark, d);\n            int mp = findMarkerPos(m);\n\n            Info info = analyze(u);\n            double v = heuristicFromInfo(info, nextIdx + 1);\n            v += markerBonus(info, mp, F[nextIdx], nextIdx + 1);\n\n            if (v > best) best = v;\n        }\n        sum += best;\n    }\n\n    return sum / ec;\n}\n\ndouble exactValue(const Board& state, int idx) {\n    if (idx >= CELLS) return (double)exactScore(state);\n\n    if (idx == CELLS - 1) {\n        int empties[CELLS];\n        int ec = collectEmpties(state, empties);\n        double sum = 0.0;\n        for (int i = 0; i < ec; ++i) {\n            Board t = state;\n            t.a[empties[i]] = (uint8_t)F[idx];\n            sum += (double)exactScore(t);\n        }\n        return sum / ec;\n    }\n\n    int empties[CELLS];\n    int ec = collectEmpties(state, empties);\n    double sum = 0.0;\n\n    for (int i = 0; i < ec; ++i) {\n        Board t = state;\n        t.a[empties[i]] = (uint8_t)F[idx];\n\n        double best = -1e100;\n        for (char d : DIRS) {\n            Board u = tilt(t, d);\n            double v = exactValue(u, idx + 1);\n            if (v > best) best = v;\n        }\n        sum += best;\n    }\n\n    return sum / ec;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    initNeighbors();\n\n    for (int i = 0; i < CELLS; ++i) cin >> F[i];\n\n    for (int i = 0; i < CELLS; ++i) {\n        for (int c = 1; c <= 3; ++c) prefCnt[i + 1][c] = prefCnt[i][c];\n        prefCnt[i + 1][F[i]]++;\n    }\n    for (int i = 0; i <= CELLS; ++i) {\n        for (int c = 1; c <= 3; ++c) {\n            remainAfter[i][c] = prefCnt[CELLS][c] - prefCnt[i][c];\n        }\n    }\n\n    for (int c = 1; c <= 3; ++c) futureWeight[CELLS][c] = 0.0;\n    for (int i = CELLS - 1; i >= 0; --i) {\n        for (int c = 1; c <= 3; ++c) futureWeight[i][c] = futureWeight[i + 1][c] * DISCOUNT;\n        futureWeight[i][F[i]] += 1.0;\n    }\n\n    vector<pair<int,int>> ord;\n    for (int c = 1; c <= 3; ++c) ord.push_back({tot[c], c});\n    sort(ord.begin(), ord.end(), [](const auto& x, const auto& y) {\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n\n    int corners[3][2] = {{0, 0}, {0, 9}, {9, 0}};\n    for (int i = 0; i < 3; ++i) {\n        int color = ord[i].second;\n        targetR[color] = corners[i][0];\n        targetC[color] = corners[i][1];\n    }\n\n    for (int c = 1; c <= 3; ++c) {\n        for (int i = 0; i < CELLS; ++i) {\n            int r = i / N, col = i % N;\n            targetDist[c][i] = abs(r - targetR[c]) + abs(col - targetC[c]);\n        }\n    }\n\n    Board board{};\n\n    for (int t = 0; t < CELLS; ++t) {\n        int p;\n        cin >> p;\n\n        Board cur = board;\n        int pos = kthEmpty(cur, p);\n        cur.a[pos] = (uint8_t)F[t];\n\n        if (t == CELLS - 1) {\n            board = cur;\n            break;\n        }\n\n        int nextIdx = t + 1;\n        double bestScore = -1e100;\n        Board bestBoard = cur;\n        char bestDir = 'F';\n\n        for (char d : DIRS) {\n            Board real = tilt(cur, d);\n\n            double sc;\n            if (100 - nextIdx <= EXACT_DEPTH) {\n                sc = exactValue(real, nextIdx);\n            } else {\n                Info info = analyze(real);\n\n                Board mark = cur;\n                mark.a[pos] = 4;\n                Board markTilt = tilt(mark, d);\n                int markerPos = findMarkerPos(markTilt);\n\n                sc = scoreCurrentCandidate(real, nextIdx);\n                sc += 0.02 * heuristicFromInfo(info, nextIdx);\n                sc += markerBonus(info, markerPos, F[t], nextIdx);\n            }\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestBoard = real;\n                bestDir = d;\n            }\n        }\n\n        board = bestBoard;\n        cout << bestDir << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ld = long double;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr ld TINY = 1e-300L;\n\nstruct Cand {\n    vector<int> parts;      // sorted ascending\n    bool comp;              // false: union of cliques, true: complement\n    vector<ld> hist;        // expected noisy degree histogram\n    vector<ld> logHist;     // log(hist)\n    vector<ld> feat;        // for farthest-point selection\n    long long edge0 = 0;    // original edge count\n    long long tri0 = 0;     // original triangle count\n    ld triMean = 0;         // expected noisy triangle count\n    ld triVar = 1;          // approximate variance of noisy triangle count\n};\n\nstatic vector<vector<ld>> build_binom(int n, ld q) {\n    vector<vector<ld>> dp(n + 1, vector<ld>(n + 1, 0.0L));\n    dp[0][0] = 1.0L;\n    for (int i = 1; i <= n; ++i) {\n        dp[i][0] = dp[i - 1][0] * (1.0L - q);\n        for (int k = 1; k < i; ++k) {\n            dp[i][k] = dp[i - 1][k] * (1.0L - q) + dp[i - 1][k - 1] * q;\n        }\n        dp[i][i] = dp[i - 1][i - 1] * q;\n    }\n    return dp;\n}\n\nstatic string build_graph(const Cand& c, int N) {\n    array<int, MAXN> grp{};\n    int p = 0;\n    for (int i = 0; i < (int)c.parts.size(); ++i) {\n        for (int t = 0; t < c.parts[i]; ++t) grp[p++] = i;\n    }\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            bool same = (grp[i] == grp[j]);\n            bool e = c.comp ? !same : same;\n            s.push_back(e ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    ld eps;\n    cin >> M >> eps;\n\n    // N depends only on epsilon.\n    int N = 40 + (int)llround(125.0L * eps);\n    N = min(N, 100);\n\n    const long long totalPairs = 1LL * N * (N - 1) / 2;\n    const long long totalTri = 1LL * N * (N - 1) * (N - 2) / 6;\n\n    // Precompute degree distributions.\n    // r = original degree.\n    auto binStay = build_binom(N - 1, 1.0L - eps);\n    auto binFlip = build_binom(N - 1, eps);\n\n    vector<vector<ld>> degP(N, vector<ld>(N, 0.0L));\n    for (int r = 0; r < N; ++r) {\n        vector<ld> pmf(N, 0.0L);\n        int n1 = r;\n        int n0 = N - 1 - r;\n        for (int a = 0; a <= n1; ++a) {\n            ld pa = binStay[n1][a];\n            if (pa == 0.0L) continue;\n            for (int b = 0; b <= n0; ++b) {\n                pmf[a + b] += pa * binFlip[n0][b];\n            }\n        }\n        ld sum = 0.0L;\n        for (ld x : pmf) sum += x;\n        if (sum <= 0.0L) sum = 1.0L;\n        for (int d = 0; d < N; ++d) degP[r][d] = pmf[d] / sum;\n    }\n\n    auto make_candidate = [&](vector<int> parts, bool comp) -> Cand {\n        sort(parts.begin(), parts.end());\n        Cand c;\n        c.parts = parts;\n        c.comp = comp;\n\n        int k = (int)parts.size();\n        c.hist.assign(N, 0.0L);\n        c.logHist.assign(N, 0.0L);\n        c.feat.clear();\n        c.feat.reserve(N + 2);\n\n        long long same3 = 0; // sum C(s,3)\n        long long one1 = 0;  // sum C(s,2)*(N-s)\n        long long unionEdges = 0;\n\n        for (int s : parts) {\n            unionEdges += 1LL * s * (s - 1) / 2;\n            same3 += 1LL * s * (s - 1) * (s - 2) / 6;\n            one1 += 1LL * s * (s - 1) / 2 * (N - s);\n\n            int r = comp ? (N - s) : (s - 1);\n            ld w = (ld)s / (ld)N;\n            for (int d = 0; d < N; ++d) {\n                c.hist[d] += w * degP[r][d];\n            }\n        }\n\n        ld sumHist = 0.0L;\n        for (ld x : c.hist) sumHist += x;\n        if (sumHist <= 0.0L) sumHist = 1.0L;\n\n        for (int d = 0; d < N; ++d) {\n            c.hist[d] /= sumHist;\n            c.logHist[d] = logl(max(c.hist[d], TINY));\n            c.feat.push_back(sqrtl(max(c.hist[d], 0.0L)));\n        }\n\n        // Additional scalar features for selection.\n        c.edge0 = comp ? (totalPairs - unionEdges) : unionEdges;\n\n        if (!comp) {\n            long long zero = totalTri - same3 - one1;\n            long double p3 = powl(1.0L - eps, 3);\n            long double p1 = (1.0L - eps) * eps * eps;\n            long double p0 = eps * eps * eps;\n\n            c.tri0 = same3;\n            c.triMean = (ld)same3 * p3 + (ld)one1 * p1 + (ld)zero * p0;\n            c.triVar = (ld)same3 * p3 * (1.0L - p3)\n                     + (ld)one1 * p1 * (1.0L - p1)\n                     + (ld)zero * p0 * (1.0L - p0);\n        } else {\n            long long zero = same3;\n            long long two = one1;\n            long long three = totalTri - zero - two;\n\n            long double p0 = eps * eps * eps;\n            long double p2 = (1.0L - eps) * (1.0L - eps) * eps;\n            long double p3 = powl(1.0L - eps, 3);\n\n            c.tri0 = three;\n            c.triMean = (ld)zero * p0 + (ld)two * p2 + (ld)three * p3;\n            c.triVar = (ld)zero * p0 * (1.0L - p0)\n                     + (ld)two * p2 * (1.0L - p2)\n                     + (ld)three * p3 * (1.0L - p3);\n        }\n\n        // Inflate triangle variance a bit to avoid overconfidence.\n        c.triVar = max<ld>(1.0L, c.triVar * 2.0L);\n\n        c.feat.push_back((ld)c.edge0 / (ld)max<long long>(1, totalPairs) * 2.0L);\n        c.feat.push_back((ld)c.tri0 / (ld)max<long long>(1, totalTri) * 2.0L);\n        return c;\n    };\n\n    auto build_pool = [&](int step, int span) -> vector<Cand> {\n        vector<Cand> pool;\n        set<string> seen;\n\n        auto add = [&](const vector<int>& parts, bool comp) {\n            vector<int> p = parts;\n            sort(p.begin(), p.end());\n            string key;\n            key.reserve(32);\n            key.push_back(comp ? '1' : '0');\n            key.push_back(':');\n            for (int x : p) {\n                key += to_string(x);\n                key.push_back(',');\n            }\n            if (seen.insert(key).second) pool.push_back(make_candidate(p, comp));\n        };\n\n        int minS = max(4, N / 10);\n\n        // 2-partitions\n        {\n            int lo = max(minS, N / 2 - span);\n            int hi = min(N - minS, N / 2 + span);\n            for (int a = lo; a <= hi; a += step) {\n                int b = N - a;\n                if (a <= b && b >= minS) add({a, b}, false), add({a, b}, true);\n            }\n        }\n\n        // 3-partitions\n        {\n            int center = N / 3;\n            int loA = max(minS, center - span);\n            int hiA = min(N - 2 * minS, center + span);\n            for (int a = loA; a <= hiA; a += step) {\n                int loB = max(a, center - span);\n                int hiB = min(N - a - minS, center + span);\n                for (int b = loB; b <= hiB; b += step) {\n                    int c = N - a - b;\n                    if (c < b || c < minS) continue;\n                    add({a, b, c}, false);\n                    add({a, b, c}, true);\n                }\n            }\n        }\n\n        // 4-partitions\n        {\n            int center = N / 4;\n            int loA = max(minS, center - span);\n            int hiA = min(N - 3 * minS, center + span);\n            for (int a = loA; a <= hiA; a += step) {\n                int loB = max(a, center - span);\n                int hiB = min(N - a - 2 * minS, center + span);\n                for (int b = loB; b <= hiB; b += step) {\n                    int loC = max(b, center - span);\n                    int hiC = min(N - a - b - minS, center + span);\n                    for (int c = loC; c <= hiC; c += step) {\n                        int d = N - a - b - c;\n                        if (d < c || d < minS) continue;\n                        add({a, b, c, d}, false);\n                        add({a, b, c, d}, true);\n                    }\n                }\n            }\n        }\n\n        return pool;\n    };\n\n    int step = (N >= 70 ? 2 : 1);\n    int span = max(5, N / 6);\n\n    vector<Cand> pool = build_pool(step, span);\n    if ((int)pool.size() < M) {\n        pool = build_pool(1, span + max(4, N / 10));\n    }\n    if ((int)pool.size() < M) {\n        // Very rare fallback.\n        pool = build_pool(1, N / 3);\n    }\n\n    int P = (int)pool.size();\n\n    // Select a balanced seed.\n    int seed = 0;\n    ld bestVar = 1e100L;\n    for (int i = 0; i < P; ++i) {\n        if (pool[i].comp) continue;\n        ld mean = (ld)N / (ld)pool[i].parts.size();\n        ld var = 0.0L;\n        for (int s : pool[i].parts) {\n            ld d = (ld)s - mean;\n            var += d * d;\n        }\n        if (var < bestVar) {\n            bestVar = var;\n            seed = i;\n        }\n    }\n\n    auto dist = [&](const Cand& a, const Cand& b) -> ld {\n        ld s = 0.0L;\n        int D = (int)a.feat.size();\n        for (int i = 0; i < D; ++i) {\n            ld diff = a.feat[i] - b.feat[i];\n            s += diff * diff;\n        }\n        return s;\n    };\n\n    // Pairwise distances for farthest-point selection.\n    vector<vector<ld>> dmat(P, vector<ld>(P, 0.0L));\n    for (int i = 0; i < P; ++i) {\n        for (int j = i + 1; j < P; ++j) {\n            dmat[i][j] = dmat[j][i] = dist(pool[i], pool[j]);\n        }\n    }\n\n    vector<int> order;\n    vector<char> used(P, 0);\n    vector<ld> best(P, 1e100L);\n\n    order.push_back(seed);\n    used[seed] = 1;\n    for (int i = 0; i < P; ++i) best[i] = dmat[i][seed];\n\n    while ((int)order.size() < min(M, P)) {\n        int u = -1;\n        ld val = -1.0L;\n        for (int i = 0; i < P; ++i) {\n            if (used[i]) continue;\n            if (u == -1 || best[i] > val) {\n                u = i;\n                val = best[i];\n            }\n        }\n        if (u == -1) break;\n        order.push_back(u);\n        used[u] = 1;\n        for (int i = 0; i < P; ++i) {\n            if (!used[i]) best[i] = min(best[i], dmat[i][u]);\n        }\n    }\n\n    vector<Cand> chosen;\n    chosen.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        chosen.push_back(pool[order[i % (int)order.size()]]);\n    }\n\n    // Output graphs.\n    cout << N << '\\n';\n    for (int i = 0; i < M; ++i) {\n        cout << build_graph(chosen[i], N) << '\\n';\n    }\n    cout.flush();\n\n    // Precompute a constant edge variance.\n    const ld edgeVar = max<ld>(1.0L, (ld)totalPairs * eps * (1.0L - eps));\n\n    // Decode 100 queries.\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n\n        array<int, MAXN> deg{};\n        deg.fill(0);\n        array<array<unsigned char, MAXN>, MAXN> adj{};\n        int idx = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j, ++idx) {\n                if (H[idx] == '1') {\n                    adj[i][j] = adj[j][i] = 1;\n                    ++deg[i];\n                    ++deg[j];\n                }\n            }\n        }\n\n        long long edgeObs = 0;\n        array<int, MAXN> cnt{};\n        cnt.fill(0);\n        for (int i = 0; i < N; ++i) {\n            edgeObs += deg[i];\n            ++cnt[deg[i]];\n        }\n        edgeObs /= 2;\n\n        long long triObs = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) if (adj[i][j]) {\n                for (int k = j + 1; k < N; ++k) {\n                    if (adj[i][k] && adj[j][k]) ++triObs;\n                }\n            }\n        }\n\n        int bestId = 0;\n        ld bestScore = -1e100L;\n\n        for (int id = 0; id < M; ++id) {\n            const Cand& c = chosen[id];\n\n            ld score = 0.0L;\n\n            // Degree histogram likelihood.\n            for (int d = 0; d < N; ++d) {\n                if (cnt[d]) score += (ld)cnt[d] * c.logHist[d];\n            }\n\n            // Edge count Gaussian score.\n            ld edgeMean = (ld)totalPairs * eps + (1.0L - 2.0L * eps) * (ld)c.edge0;\n            ld de = (ld)edgeObs - edgeMean;\n            score -= de * de / (2.0L * edgeVar);\n\n            // Triangle count Gaussian score.\n            ld dt = (ld)triObs - c.triMean;\n            score -= dt * dt / (2.0L * c.triVar) + 0.5L * logl(c.triVar);\n\n            if (score > bestScore) {\n                bestScore = score;\n                bestId = id;\n            }\n        }\n\n        cout << bestId << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ld = long double;\n\nstatic constexpr int MAXD = 31;\nstatic constexpr int GRID = 20;\nstatic constexpr int CELLS = GRID * GRID;\nstatic constexpr ll INFLL = (1LL << 62);\n\nstruct Edge {\n    int u, v;\n    ll w;\n    int cell;\n    uint64_t morton;\n    ld rawImp = 0.0L;\n    ld normImp = 0.0L;\n};\n\nstruct Adj {\n    int to, id;\n};\n\nstatic inline ll sqdist(int x1, int y1, int x2, int y2) {\n    ll dx = (ll)x1 - x2;\n    ll dy = (ll)y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nstatic inline uint32_t part1by1(uint32_t n) {\n    n &= 0x0000ffffu;\n    n = (n | (n << 8)) & 0x00FF00FFu;\n    n = (n | (n << 4)) & 0x0F0F0F0Fu;\n    n = (n | (n << 2)) & 0x33333333u;\n    n = (n | (n << 1)) & 0x55555555u;\n    return n;\n}\n\nstatic inline uint64_t mortonCode(int x, int y) {\n    return (uint64_t)part1by1((uint32_t)x) | ((uint64_t)part1by1((uint32_t)y) << 1);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<int> deg(N, 0);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        deg[u]++;\n        deg[v]++;\n    }\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    vector<vector<Adj>> g(N);\n    for (int i = 0; i < N; ++i) g[i].reserve(deg[i]);\n    for (int i = 0; i < M; ++i) {\n        g[edges[i].u].push_back({edges[i].v, i});\n        g[edges[i].v].push_back({edges[i].u, i});\n    }\n\n    // Capacity profile used only for initial balanced greedy assignment.\n    vector<int> cap(D, M / D);\n    for (int i = 0; i < M % D; ++i) cap[i]++;\n\n    // Spatial features for edges.\n    for (int i = 0; i < M; ++i) {\n        int mx = xs[edges[i].u] + xs[edges[i].v];\n        int my = ys[edges[i].u] + ys[edges[i].v];\n        int cx = min(GRID - 1, (mx * GRID) / 2001);\n        int cy = min(GRID - 1, (my * GRID) / 2001);\n        edges[i].cell = cx * GRID + cy;\n        edges[i].morton = mortonCode(mx, my);\n    }\n\n    vector<ld> invSqrtDeg(N);\n    for (int i = 0; i < N; ++i) invSqrtDeg[i] = 1.0L / sqrtl((ld)deg[i]);\n\n    // ---------- Source sampling ----------\n    int Simp = min(50, N - 4);   // for importance estimation\n    int Seval = 4;               // for candidate evaluation\n    int Stotal = Simp + Seval;\n\n    vector<int> sources;\n    sources.reserve(Stotal);\n\n    int first = 0;\n    for (int i = 1; i < N; ++i) if (deg[i] > deg[first]) first = i;\n    sources.push_back(first);\n\n    vector<ll> mind2(N, INFLL);\n    vector<char> used(N, false);\n    used[first] = true;\n    for (int v = 0; v < N; ++v) mind2[v] = sqdist(xs[v], ys[v], xs[first], ys[first]);\n\n    for (int t = 1; t < Stotal; ++t) {\n        int best = -1;\n        ll bestd = -1;\n        int bestDeg = -1;\n        for (int v = 0; v < N; ++v) if (!used[v]) {\n            if (mind2[v] > bestd || (mind2[v] == bestd && deg[v] > bestDeg)) {\n                best = v;\n                bestd = mind2[v];\n                bestDeg = deg[v];\n            }\n        }\n        sources.push_back(best);\n        used[best] = true;\n        for (int v = 0; v < N; ++v) if (!used[v]) {\n            mind2[v] = min(mind2[v], sqdist(xs[v], ys[v], xs[best], ys[best]));\n        }\n    }\n\n    // ---------- Edge importance estimation (weighted Brandes on sampled sources) ----------\n    vector<ld> edgeBC(M, 0.0L);\n    vector<ll> dist(N);\n    vector<ld> sigma(N), delta(N);\n    vector<vector<int>> predV(N), predE(N);\n    for (int v = 0; v < N; ++v) {\n        predV[v].reserve(deg[v] + 2);\n        predE[v].reserve(deg[v] + 2);\n    }\n    vector<int> order;\n    order.reserve(N);\n\n    auto brandesSource = [&](int s) {\n        fill(dist.begin(), dist.end(), INFLL);\n        fill(sigma.begin(), sigma.end(), 0.0L);\n        fill(delta.begin(), delta.end(), 0.0L);\n        for (int v = 0; v < N; ++v) {\n            predV[v].clear();\n            predE[v].clear();\n        }\n        order.clear();\n\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        sigma[s] = 1.0L;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n            order.push_back(v);\n\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                int eid = e.id;\n                ll nd = d + edges[eid].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n                    sigma[to] = sigma[v];\n                    predV[to].clear();\n                    predE[to].clear();\n                    predV[to].push_back(v);\n                    predE[to].push_back(eid);\n                } else if (nd == dist[to]) {\n                    sigma[to] += sigma[v];\n                    predV[to].push_back(v);\n                    predE[to].push_back(eid);\n                }\n            }\n        }\n\n        for (int idx = (int)order.size() - 1; idx >= 0; --idx) {\n            int w = order[idx];\n            if (sigma[w] == 0.0L) continue;\n            for (int k = 0; k < (int)predV[w].size(); ++k) {\n                int v = predV[w][k];\n                int eid = predE[w][k];\n                ld c = (sigma[v] / sigma[w]) * (1.0L + delta[w]);\n                edgeBC[eid] += c;\n                delta[v] += c;\n            }\n        }\n    };\n\n    for (int i = 0; i < Simp; ++i) brandesSource(sources[i]);\n\n    ld meanRaw = 0.0L;\n    for (int i = 0; i < M; ++i) {\n        edges[i].rawImp = sqrtl(edgeBC[i] / (2.0L * max(1, Simp)) + 1.0L);\n        edges[i].rawImp *= 1.0L + 0.03L * ((ld)edges[i].w / 1000000.0L);\n        meanRaw += edges[i].rawImp;\n    }\n    meanRaw /= max(1, M);\n    if (meanRaw <= 0) meanRaw = 1.0L;\n\n    for (int i = 0; i < M; ++i) {\n        edges[i].normImp = edges[i].rawImp / meanRaw;\n    }\n\n    // ---------- Evaluation sources ----------\n    vector<vector<ll>> baseDist(Seval, vector<ll>(N));\n    auto dijkstraPlain = [&](int s, vector<ll> &out) {\n        fill(out.begin(), out.end(), INFLL);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        out[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != out[v]) continue;\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                int eid = e.id;\n                ll nd = d + edges[eid].w;\n                if (nd < out[to]) {\n                    out[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n    for (int i = 0; i < Seval; ++i) {\n        dijkstraPlain(sources[Simp + i], baseDist[i]);\n    }\n\n    auto dijkstraSkipDay = [&](int s, const vector<int> &dayOf, int banDay, vector<ll> &out) {\n        fill(out.begin(), out.end(), INFLL);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        out[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != out[v]) continue;\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                int eid = e.id;\n                if (dayOf[eid] == banDay) continue;\n                ll nd = d + edges[eid].w;\n                if (nd < out[to]) {\n                    out[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    // ---------- Deterministic order builders ----------\n    uint64_t baseSeed = 0x123456789abcdefULL\n                      ^ (uint64_t)N * 1000003ULL\n                      ^ (uint64_t)M * 10007ULL\n                      ^ (uint64_t)D * 1000000007ULL\n                      ^ (uint64_t)K * 1000000009ULL;\n\n    auto makeImportanceOrder = [&]() {\n        vector<pair<ld,int>> key(M);\n        for (int i = 0; i < M; ++i) key[i] = {-edges[i].rawImp, i};\n        sort(key.begin(), key.end());\n        vector<int> ord(M);\n        for (int i = 0; i < M; ++i) ord[i] = key[i].second;\n        return ord;\n    };\n\n    auto makeMortonOrder = [&]() {\n        vector<pair<uint64_t,int>> key(M);\n        for (int i = 0; i < M; ++i) key[i] = {edges[i].morton, i};\n        sort(key.begin(), key.end());\n        vector<int> ord(M);\n        for (int i = 0; i < M; ++i) ord[i] = key[i].second;\n        return ord;\n    };\n\n    auto makeDegreeBiasOrder = [&]() {\n        vector<pair<ld,int>> key(M);\n        for (int i = 0; i < M; ++i) {\n            ld s = edges[i].rawImp * (1.0L + 0.25L * (invSqrtDeg[edges[i].u] + invSqrtDeg[edges[i].v]));\n            key[i] = {-s, i};\n        }\n        sort(key.begin(), key.end());\n        vector<int> ord(M);\n        for (int i = 0; i < M; ++i) ord[i] = key[i].second;\n        return ord;\n    };\n\n    auto makeNoisyImportanceOrder = [&](uint64_t seed) {\n        mt19937_64 rng(seed);\n        vector<pair<ld,int>> key(M);\n        for (int i = 0; i < M; ++i) {\n            ld noise = ((ld)(rng() & ((1ULL << 53) - 1))) / ((ld)((1ULL << 53) - 1));\n            noise = noise * 2.0L - 1.0L; // [-1, 1]\n            ld s = edges[i].rawImp * (1.0L + 0.05L * noise);\n            key[i] = {-s, i};\n        }\n        sort(key.begin(), key.end());\n        vector<int> ord(M);\n        for (int i = 0; i < M; ++i) ord[i] = key[i].second;\n        return ord;\n    };\n\n    struct Params {\n        ld wV, wC, wDay, wCnt;\n    };\n\n    auto buildCandidate = [&](const vector<int> &ord, const Params &p) {\n        vector<array<ld, MAXD>> vLoad(N), cLoad(CELLS);\n        for (auto &a : vLoad) a.fill(0.0L);\n        for (auto &a : cLoad) a.fill(0.0L);\n\n        vector<ld> dayLoad(D, 0.0L);\n        vector<int> cnt(D, 0);\n        vector<int> ans(M, -1);\n\n        ld target = (ld)M / (ld)D;\n\n        auto addDelta = [&](int e, int d) -> ld {\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n            ld x = edges[e].normImp;\n            ld xu = x * invSqrtDeg[u];\n            ld xv = x * invSqrtDeg[v];\n\n            auto sq = [](ld z) { return z * z; };\n\n            ld delta = 0.0L;\n            delta += p.wV * (sq(vLoad[u][d] + xu) - sq(vLoad[u][d]));\n            delta += p.wV * (sq(vLoad[v][d] + xv) - sq(vLoad[v][d]));\n            delta += p.wC * (sq(cLoad[c][d] + x) - sq(cLoad[c][d]));\n            delta += p.wDay * (sq(dayLoad[d] + x - target) - sq(dayLoad[d] - target));\n            delta += p.wCnt * (sq((ld)cnt[d] + 1.0L - target) - sq((ld)cnt[d] - target));\n            return delta;\n        };\n\n        auto moveDelta = [&](int e, int a, int b) -> ld {\n            if (a == b) return 0.0L;\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n            ld x = edges[e].normImp;\n            ld xu = x * invSqrtDeg[u];\n            ld xv = x * invSqrtDeg[v];\n\n            auto sq = [](ld z) { return z * z; };\n\n            ld delta = 0.0L;\n            delta += p.wV * (sq(vLoad[u][a] - xu) + sq(vLoad[u][b] + xu)\n                           - sq(vLoad[u][a]) - sq(vLoad[u][b]));\n            delta += p.wV * (sq(vLoad[v][a] - xv) + sq(vLoad[v][b] + xv)\n                           - sq(vLoad[v][a]) - sq(vLoad[v][b]));\n            delta += p.wC * (sq(cLoad[c][a] - x) + sq(cLoad[c][b] + x)\n                           - sq(cLoad[c][a]) - sq(cLoad[c][b]));\n            delta += p.wDay * (sq(dayLoad[a] - x - target) + sq(dayLoad[b] + x - target)\n                             - sq(dayLoad[a] - target) - sq(dayLoad[b] - target));\n            delta += p.wCnt * (sq((ld)cnt[a] - 1.0L - target) + sq((ld)cnt[b] + 1.0L - target)\n                             - sq((ld)cnt[a] - target) - sq((ld)cnt[b] - target));\n            return delta;\n        };\n\n        auto applyMove = [&](int e, int a, int b) {\n            if (a == b) return;\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n            ld x = edges[e].normImp;\n            ld xu = x * invSqrtDeg[u];\n            ld xv = x * invSqrtDeg[v];\n\n            vLoad[u][a] -= xu; vLoad[u][b] += xu;\n            vLoad[v][a] -= xv; vLoad[v][b] += xv;\n            cLoad[c][a] -= x;   cLoad[c][b] += x;\n            dayLoad[a] -= x;    dayLoad[b] += x;\n            cnt[a]--;          cnt[b]++;\n            ans[e] = b;\n        };\n\n        // Initial balanced greedy assignment.\n        for (int e : ord) {\n            int bestD = -1;\n            ld best = numeric_limits<ld>::infinity();\n            for (int d = 0; d < D; ++d) {\n                if (cnt[d] >= cap[d]) continue;\n                ld sc = addDelta(e, d);\n                if (bestD == -1 || sc < best - 1e-18L || (fabsl(sc - best) <= 1e-18L && cnt[d] < cnt[bestD])) {\n                    best = sc;\n                    bestD = d;\n                }\n            }\n            if (bestD == -1) bestD = min_element(cnt.begin(), cnt.end()) - cnt.begin();\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n            ld x = edges[e].normImp;\n            ld xu = x * invSqrtDeg[u];\n            ld xv = x * invSqrtDeg[v];\n            ans[e] = bestD;\n            vLoad[u][bestD] += xu;\n            vLoad[v][bestD] += xv;\n            cLoad[c][bestD] += x;\n            dayLoad[bestD] += x;\n            cnt[bestD]++;\n        }\n\n        // Local improvement by single-edge moves.\n        for (int pass = 0; pass < 2; ++pass) {\n            bool improved = false;\n            for (int e : ord) {\n                int a = ans[e];\n                int bestD = a;\n                ld bestDelta = 0.0L;\n                for (int b = 0; b < D; ++b) {\n                    if (b == a) continue;\n                    if (cnt[b] >= K) continue;\n                    ld dlt = moveDelta(e, a, b);\n                    if (dlt < bestDelta - 1e-18L ||\n                        (fabsl(dlt - bestDelta) <= 1e-18L && cnt[b] < cnt[bestD])) {\n                        bestDelta = dlt;\n                        bestD = b;\n                    }\n                }\n                if (bestD != a) {\n                    applyMove(e, a, bestD);\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n\n        return ans;\n    };\n\n    auto evaluate = [&](const vector<int> &dayOf) -> ll {\n        ll total = 0;\n        vector<ll> dist2(N);\n        for (int i = 0; i < Seval; ++i) {\n            int s = sources[Simp + i];\n            const auto &base = baseDist[i];\n            for (int d = 0; d < D; ++d) {\n                dijkstraSkipDay(s, dayOf, d, dist2);\n                for (int v = 0; v < N; ++v) {\n                    ll cur = (dist2[v] >= INFLL / 2 ? 1000000000LL : dist2[v]);\n                    total += cur - base[v];\n                }\n            }\n        }\n        return total;\n    };\n\n    // ---------- Candidate schedules ----------\n    vector<int> ordImp = makeImportanceOrder();\n    vector<int> ordMorton = makeMortonOrder();\n    vector<int> ordDegree = makeDegreeBiasOrder();\n    vector<int> ordNoise = makeNoisyImportanceOrder(baseSeed + 1234567ULL);\n\n    vector<Params> params = {\n        {1.00L, 0.25L, 0.12L, 0.05L},\n        {0.70L, 0.70L, 0.08L, 0.03L},\n        {1.15L, 0.18L, 0.18L, 0.05L},\n        {0.95L, 0.30L, 0.10L, 0.08L}\n    };\n\n    vector<vector<int>> candidates;\n    candidates.push_back(buildCandidate(ordImp,    params[0]));\n    candidates.push_back(buildCandidate(ordMorton, params[1]));\n    candidates.push_back(buildCandidate(ordDegree, params[2]));\n    candidates.push_back(buildCandidate(ordNoise,  params[3]));\n\n    vector<int> bestAns = candidates[0];\n    ll bestVal = evaluate(candidates[0]);\n\n    for (int i = 1; i < (int)candidates.size(); ++i) {\n        ll val = evaluate(candidates[i]);\n        if (val < bestVal) {\n            bestVal = val;\n            bestAns = candidates[i];\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << bestAns[i] + 1;\n    }\n    cout << '\\n';\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXD = 14;\n\nusing Mat = array<array<unsigned char, MAXD>, MAXD>;\n\nstruct Rod {\n    int x, y, l, r;\n    int len() const { return r - l + 1; }\n};\n\nstruct Candidate {\n    vector<Rod> rods;\n    array<int, MAXD + 1> hist{};\n};\n\nstruct ObjData {\n    int D;\n    vector<string> f, r;\n    unsigned char runLen[2][MAXD][MAXD][MAXD]{}; // dir 0: z++, dir 1: z--\n};\n\nstruct PairInfo {\n    long double score;\n    int blocks;\n    int a, b;\n};\n\nstruct Preset {\n    long long runA, runB;\n    long long contA, contB;\n};\n\nstatic 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\nstatic void precompute_runlen(ObjData& obj) {\n    int D = obj.D;\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = D - 1; z >= 0; --z) {\n                if (obj.f[z][x] == '1' && obj.r[z][y] == '1') {\n                    obj.runLen[0][z][x][y] = 1 + ((z + 1 < D) ? obj.runLen[0][z + 1][x][y] : 0);\n                }\n            }\n            for (int z = 0; z < D; ++z) {\n                if (obj.f[z][x] == '1' && obj.r[z][y] == '1') {\n                    obj.runLen[1][z][x][y] = 1 + ((z > 0) ? obj.runLen[1][z - 1][x][y] : 0);\n                }\n            }\n        }\n    }\n}\n\nstatic pair<long long, vector<int>> hungarian_min(const vector<vector<long long>>& a) {\n    int n = (int)a.size();\n    vector<long long> u(n + 1), v(n + 1);\n    vector<int> 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<long long> minv(n + 1, (1LL << 60));\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            long long delta = (1LL << 60);\n            int j1 = 0;\n            for (int j = 1; j <= n; ++j) if (!used[j]) {\n                long long cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n\n    vector<int> rowToCol(n);\n    for (int j = 1; j <= n; ++j) {\n        if (p[j] != 0) rowToCol[p[j] - 1] = j - 1;\n    }\n    long long minCost = -v[0];\n    return {minCost, rowToCol};\n}\n\nstatic Preset get_preset(int variant) {\n    if (variant == 0) return {120, 90, 60, 35};  // short / compact\n    if (variant == 1) return {160, 50, 90, 20};  // medium\n    return {220, 15, 120, 8};                    // long\n}\n\nstatic long long cell_noise(uint64_t baseSeed, int p, int variant, int dir, int swapEqual, int z, int x, int y) {\n    uint64_t h = baseSeed;\n    h ^= uint64_t(p + 1) * 10007ULL;\n    h ^= uint64_t(variant + 3) * 1009ULL;\n    h ^= uint64_t(dir + 7) * 313ULL;\n    h ^= uint64_t(swapEqual + 11) * 911ULL;\n    h ^= uint64_t(z + 1) * 1000003ULL;\n    h ^= uint64_t(x + 5) * 1000033ULL;\n    h ^= uint64_t(y + 9) * 1000037ULL;\n    return (long long)(splitmix64(h) % 5ULL) - 2LL; // [-2, 2]\n}\n\nstatic Candidate build_candidate(\n    const ObjData& obj,\n    int p,\n    int variant,\n    int dir,\n    bool swapEqual,\n    const array<long long, MAXD + 1>& target,\n    long long targetScale,\n    uint64_t baseSeed\n) {\n    int D = obj.D;\n    Preset pr = get_preset(variant);\n\n    vector<Mat> layers(D, Mat{});\n    array<array<int, MAXD>, MAXD> streak{};\n    for (int x = 0; x < D; ++x) for (int y = 0; y < D; ++y) streak[x][y] = 0;\n\n    for (int step = 0; step < D; ++step) {\n        int z = (dir == 0 ? step : D - 1 - step);\n\n        vector<int> xs, ys;\n        xs.reserve(D);\n        ys.reserve(D);\n        for (int x = 0; x < D; ++x) if (obj.f[z][x] == '1') xs.push_back(x);\n        for (int y = 0; y < D; ++y) if (obj.r[z][y] == '1') ys.push_back(y);\n\n        bool rowsAreX;\n        if ((int)xs.size() < (int)ys.size()) rowsAreX = true;\n        else if ((int)ys.size() < (int)xs.size()) rowsAreX = false;\n        else rowsAreX = !swapEqual;\n\n        const vector<int>& rows = rowsAreX ? xs : ys; // smaller side\n        const vector<int>& cols = rowsAreX ? ys : xs; // larger side\n        int m = (int)rows.size();\n        int k = (int)cols.size();\n\n        vector<vector<long long>> w(m, vector<long long>(k, 0));\n        vector<long long> bestExtraW(k, -(1LL << 60));\n        vector<int> bestExtraRow(k, -1);\n\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < k; ++j) {\n                int x = rowsAreX ? rows[i] : cols[j];\n                int y = rowsAreX ? cols[j] : rows[i];\n\n                int run = obj.runLen[dir][z][x][y];\n                int st = streak[x][y];\n\n                long long runTerm = pr.runA * min(run, p) - pr.runB * max(0, run - p);\n                long long contTerm;\n                if (st + 1 <= p) contTerm = pr.contA * (st + 1);\n                else contTerm = -pr.contB * (st + 1 - p);\n\n                long long val = runTerm + contTerm + targetScale * target[run];\n                val += cell_noise(baseSeed, p, variant, dir, (int)swapEqual, z, x, y);\n\n                w[i][j] = val;\n                if (val > bestExtraW[j] || (val == bestExtraW[j] && i < bestExtraRow[j])) {\n                    bestExtraW[j] = val;\n                    bestExtraRow[j] = i;\n                }\n            }\n        }\n\n        // Exact minimum edge cover by matching the smaller side to the larger side.\n        vector<vector<long long>> cost(k, vector<long long>(k, 0));\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < k; ++j) {\n                cost[i][j] = bestExtraW[j] - w[i][j];\n            }\n        }\n        auto [dummyCost, rowToCol] = hungarian_min(cost);\n        (void)dummyCost;\n\n        vector<int> colToRow(k, -1);\n        for (int i = 0; i < m; ++i) colToRow[rowToCol[i]] = i;\n\n        Mat cur{};\n        for (int j = 0; j < k; ++j) {\n            int i = colToRow[j];\n            int x, y;\n            if (i >= 0) {\n                if (rowsAreX) {\n                    x = rows[i];\n                    y = cols[j];\n                } else {\n                    x = cols[j];\n                    y = rows[i];\n                }\n            } else {\n                int bi = bestExtraRow[j];\n                if (rowsAreX) {\n                    x = rows[bi];\n                    y = cols[j];\n                } else {\n                    x = cols[j];\n                    y = rows[bi];\n                }\n            }\n            cur[x][y] = 1;\n        }\n\n        array<array<int, MAXD>, MAXD> nextStreak{};\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (cur[x][y]) nextStreak[x][y] = streak[x][y] + 1;\n                else nextStreak[x][y] = 0;\n            }\n        }\n        streak = nextStreak;\n        layers[z] = cur;\n    }\n\n    Candidate cand;\n    cand.hist.fill(0);\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            int s = -1;\n            for (int z = 0; z < D; ++z) {\n                if (layers[z][x][y]) {\n                    if (s == -1) s = z;\n                } else if (s != -1) {\n                    Rod rd{x, y, s, z - 1};\n                    cand.hist[rd.len()]++;\n                    cand.rods.push_back(rd);\n                    s = -1;\n                }\n            }\n            if (s != -1) {\n                Rod rd{x, y, s, D - 1};\n                cand.hist[rd.len()]++;\n                cand.rods.push_back(rd);\n            }\n        }\n    }\n\n    return cand;\n}\n\nstatic vector<int> make_base_pvals(int D) {\n    vector<int> pvals;\n    for (int p = 1; p <= D; ++p) pvals.push_back(p);\n    return pvals;\n}\n\nstatic array<long long, MAXD + 1> make_target_from_hist(const array<int, MAXD + 1>& hist, int D) {\n    array<long long, MAXD + 1> target{};\n    target.fill(0);\n\n    long long total = 0;\n    for (int L = 1; L <= D; ++L) total += hist[L];\n    if (total == 0) total = 1;\n\n    for (int L = 1; L <= D; ++L) {\n        long long sm = 3LL * hist[L];\n        if (L > 1) sm += hist[L - 1];\n        if (L < D) sm += hist[L + 1];\n\n        long long raw = sm * (2LL * L - 1) * 250LL / total;\n        raw = min(8000LL, raw);\n        target[L] = raw;\n    }\n    return target;\n}\n\nstatic vector<int> make_target_pvals(const array<long long, MAXD + 1>& target, int D) {\n    vector<pair<long long, int>> ord;\n    for (int L = 1; L <= D; ++L) ord.push_back({target[L], L});\n    sort(ord.begin(), ord.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    set<int> pset;\n    pset.insert(1);\n    pset.insert(D);\n    int take = min(3, D);\n    for (int i = 0; i < take; ++i) {\n        int L = ord[i].second;\n        for (int d = -1; d <= 1; ++d) {\n            int p = L + d;\n            if (1 <= p && p <= D) pset.insert(p);\n        }\n    }\n\n    vector<int> pvals(pset.begin(), pset.end());\n    return pvals;\n}\n\nstatic vector<Candidate> build_pool(\n    const ObjData& obj,\n    const vector<int>& pvals,\n    const array<long long, MAXD + 1>& target,\n    long long targetScale,\n    uint64_t baseSeed,\n    int roundTag\n) {\n    vector<Candidate> pool;\n    pool.reserve((int)pvals.size() * 3 * 2 * 2);\n\n    for (int p : pvals) {\n        for (int variant = 0; variant < 3; ++variant) {\n            for (int dir : {0, 1}) {\n                for (bool swapEqual : {false, true}) {\n                    uint64_t seed = baseSeed;\n                    seed ^= splitmix64((uint64_t)(roundTag + 1) * 1000003ULL);\n                    seed ^= splitmix64((uint64_t)(p + 1) * 10007ULL);\n                    seed ^= splitmix64((uint64_t)(variant + 3) * 1009ULL);\n                    seed ^= splitmix64((uint64_t)(dir + 7) * 313ULL);\n                    seed ^= splitmix64((uint64_t)(swapEqual ? 1 : 0) * 911ULL);\n\n                    pool.push_back(build_candidate(obj, p, variant, dir, swapEqual, target, targetScale, seed));\n                }\n            }\n        }\n    }\n    return pool;\n}\n\nstatic long double pair_score(const Candidate& A, const Candidate& B, int D) {\n    long double res = 0.0L;\n    for (int L = 1; L <= D; ++L) {\n        int k = min(A.hist[L], B.hist[L]);\n        res += (long double)k / (long double)L;\n        res += (long double)(A.hist[L] - k + B.hist[L] - k) * (long double)L;\n    }\n    return res;\n}\n\nstatic int pair_blocks(const Candidate& A, const Candidate& B, int D) {\n    int res = 0;\n    for (int L = 1; L <= D; ++L) res += max(A.hist[L], B.hist[L]);\n    return res;\n}\n\nstatic long long hist_distance(const Candidate& A1, const Candidate& B1, const Candidate& A2, const Candidate& B2, int D) {\n    long long d = 0;\n    for (int L = 1; L <= D; ++L) {\n        d += 1LL * (2 * L - 1) * (llabs((long long)A1.hist[L] - (long long)A2.hist[L]) +\n                                   llabs((long long)B1.hist[L] - (long long)B2.hist[L]));\n    }\n    return d;\n}\n\nstatic pair<int, int> choose_diverse_second(\n    const vector<PairInfo>& pairs,\n    const vector<Candidate>& poolA,\n    const vector<Candidate>& poolB,\n    int D,\n    int topK = 30\n) {\n    if (pairs.empty()) return {0, 0};\n    int bestIdx = 0;\n    long long bestDist = -1;\n\n    int lim = min(topK, (int)pairs.size());\n    for (int i = 0; i < lim; ++i) {\n        long long dist = hist_distance(\n            poolA[pairs[0].a], poolB[pairs[0].b],\n            poolA[pairs[i].a], poolB[pairs[i].b],\n            D\n        );\n        if (dist > bestDist) {\n            bestDist = dist;\n            bestIdx = i;\n        }\n    }\n    return {pairs[bestIdx].a, pairs[bestIdx].b};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    ObjData obj[2];\n    for (int t = 0; t < 2; ++t) {\n        obj[t].D = D;\n        obj[t].f.resize(D);\n        obj[t].r.resize(D);\n        for (int i = 0; i < D; ++i) cin >> obj[t].f[i];\n        for (int i = 0; i < D; ++i) cin >> obj[t].r[i];\n        precompute_runlen(obj[t]);\n    }\n\n    uint64_t baseSeed = 1469598103934665603ULL;\n    auto mix_str = [&](const string& s) {\n        for (unsigned char c : s) baseSeed = splitmix64(baseSeed ^ (uint64_t)c);\n    };\n    baseSeed = splitmix64(baseSeed ^ (uint64_t)D);\n    for (int t = 0; t < 2; ++t) {\n        for (auto& s : obj[t].f) mix_str(s);\n        for (auto& s : obj[t].r) mix_str(s);\n    }\n\n    // Round 0: base pools.\n    vector<int> baseP = make_base_pvals(D);\n    array<long long, MAXD + 1> zero{};\n    zero.fill(0);\n\n    vector<Candidate> basePool[2];\n    basePool[0] = build_pool(obj[0], baseP, zero, 0, baseSeed ^ 1111ULL, 0);\n    basePool[1] = build_pool(obj[1], baseP, zero, 0, baseSeed ^ 2222ULL, 0);\n\n    vector<PairInfo> basePairs;\n    basePairs.reserve(basePool[0].size() * basePool[1].size());\n\n    for (int i = 0; i < (int)basePool[0].size(); ++i) {\n        for (int j = 0; j < (int)basePool[1].size(); ++j) {\n            long double sc = pair_score(basePool[0][i], basePool[1][j], D);\n            int bl = pair_blocks(basePool[0][i], basePool[1][j], D);\n            basePairs.push_back({sc, bl, i, j});\n        }\n    }\n\n    sort(basePairs.begin(), basePairs.end(), [&](const PairInfo& a, const PairInfo& b) {\n        if (fabsl(a.score - b.score) > 1e-18L) return a.score < b.score;\n        return a.blocks < b.blocks;\n    });\n\n    PairInfo best0 = basePairs[0];\n    auto [secAIdx, secBIdx] = choose_diverse_second(basePairs, basePool[0], basePool[1], D);\n\n    // Round 1: target-guided pools from the best two base pairs.\n    array<long long, MAXD + 1> targetA0 = make_target_from_hist(basePool[1][best0.b].hist, D);\n    array<long long, MAXD + 1> targetB0 = make_target_from_hist(basePool[0][best0.a].hist, D);\n    array<long long, MAXD + 1> targetA1 = make_target_from_hist(basePool[1][secBIdx].hist, D);\n    array<long long, MAXD + 1> targetB1 = make_target_from_hist(basePool[0][secAIdx].hist, D);\n\n    vector<int> pA0 = make_target_pvals(targetA0, D);\n    vector<int> pB0 = make_target_pvals(targetB0, D);\n    vector<int> pA1 = make_target_pvals(targetA1, D);\n    vector<int> pB1 = make_target_pvals(targetB1, D);\n\n    vector<Candidate> poolA = basePool[0];\n    vector<Candidate> poolB = basePool[1];\n\n    auto add_pool = [&](vector<Candidate>& dst, const vector<Candidate>& src) {\n        dst.insert(dst.end(), src.begin(), src.end());\n    };\n\n    auto targA0 = build_pool(obj[0], pA0, targetA0, 1, baseSeed ^ 3333ULL, 1);\n    auto targB0 = build_pool(obj[1], pB0, targetB0, 1, baseSeed ^ 4444ULL, 1);\n    auto targA1 = build_pool(obj[0], pA1, targetA1, 1, baseSeed ^ 5555ULL, 2);\n    auto targB1 = build_pool(obj[1], pB1, targetB1, 1, baseSeed ^ 6666ULL, 2);\n\n    add_pool(poolA, targA0);\n    add_pool(poolA, targA1);\n    add_pool(poolB, targB0);\n    add_pool(poolB, targB1);\n\n    // Final exact search among all candidates.\n    int bestA = 0, bestB = 0;\n    long double bestScore = numeric_limits<long double>::infinity();\n    int bestBlocks = INT_MAX;\n\n    for (int i = 0; i < (int)poolA.size(); ++i) {\n        for (int j = 0; j < (int)poolB.size(); ++j) {\n            long double sc = pair_score(poolA[i], poolB[j], D);\n            int bl = pair_blocks(poolA[i], poolB[j], D);\n            if (sc + 1e-18L < bestScore || (fabsl(sc - bestScore) <= 1e-18L && bl < bestBlocks)) {\n                bestScore = sc;\n                bestBlocks = bl;\n                bestA = i;\n                bestB = j;\n            }\n        }\n    }\n\n    const Candidate& A = poolA[bestA];\n    const Candidate& B = poolB[bestB];\n\n    // Assign IDs: rods of the same length are congruent.\n    array<vector<int>, MAXD + 1> idxA, idxB;\n    for (int i = 0; i < (int)A.rods.size(); ++i) idxA[A.rods[i].len()].push_back(i);\n    for (int i = 0; i < (int)B.rods.size(); ++i) idxB[B.rods[i].len()].push_back(i);\n\n    vector<int> idA(A.rods.size(), 0), idB(B.rods.size(), 0);\n    int n = 0;\n\n    for (int L = 1; L <= D; ++L) {\n        int k = min((int)idxA[L].size(), (int)idxB[L].size());\n        for (int i = 0; i < k; ++i) {\n            ++n;\n            idA[idxA[L][i]] = n;\n            idB[idxB[L][i]] = n;\n        }\n        for (int i = k; i < (int)idxA[L].size(); ++i) {\n            ++n;\n            idA[idxA[L][i]] = n;\n        }\n        for (int i = k; i < (int)idxB[L].size(); ++i) {\n            ++n;\n            idB[idxB[L][i]] = n;\n        }\n    }\n\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n\n    auto fill_out = [&](vector<int>& out, const vector<Rod>& rods, const vector<int>& ids) {\n        for (int i = 0; i < (int)rods.size(); ++i) {\n            int id = ids[i];\n            const Rod& rd = rods[i];\n            for (int z = rd.l; z <= rd.r; ++z) {\n                out[rd.x * D * D + rd.y * D + z] = id;\n            }\n        }\n    };\n\n    fill_out(outA, A.rods, idA);\n    fill_out(outB, B.rods, idB);\n\n    cout << 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    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << outB[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INFLL = (1LL << 60);\nstatic const ll PENALTY = 1000000000000LL;\nstatic const int MAXR = 5001;\n\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n + 1);\n        sz.assign(n + 1, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct ConnResult {\n    ll cost = 0;\n    vector<char> used;\n};\n\nstruct EvalResult {\n    vector<int> sel;       // live selected stations\n    vector<int> rad;       // radii aligned with sel\n    vector<int> owner;     // resident -> station index in sel, -1 if uncovered\n    vector<int> bestDist;   // resident -> assigned distance\n    vector<char> inSel;\n    vector<char> used;\n    ll cov = 0;\n    ll conn = 0;\n    ll total = INFLL;\n    int uncovered = 0;\n};\n\nstatic int N, M, K;\nstatic vector<int> xs, ys;\nstatic vector<int> ax, ay;\nstatic vector<Edge> edges;\n\nstatic vector<vector<ll>> distGraph;\nstatic vector<vector<int>> nxtHop;\nstatic vector<vector<int>> edgeId;\nstatic vector<vector<int>> distSR;\nstatic vector<vector<int>> residentOrder; // residents -> stations sorted by distance\n\nstatic vector<int> hardOrder;\nstatic vector<pair<ll,int>> singleRank;\nstatic vector<pair<ll,int>> coverRank;\n\nstatic mt19937 rng(712367821);\nstatic auto startTime = chrono::steady_clock::now();\n\nstatic inline bool time_over() {\n    using namespace chrono;\n    return duration_cast<milliseconds>(steady_clock::now() - startTime).count() > 1850;\n}\n\nstatic int ceil_sqrt_ll(ll x) {\n    long double y = sqrt((long double)x);\n    int r = (int)y;\n    while ((ll)r * r < x) ++r;\n    while (r > 0 && (ll)(r - 1) * (r - 1) >= x) --r;\n    return r;\n}\n\nstatic vector<int> normalize_sel(vector<int> sel) {\n    if (find(sel.begin(), sel.end(), 1) == sel.end()) sel.push_back(1);\n    sort(sel.begin(), sel.end());\n    sel.erase(unique(sel.begin(), sel.end()), sel.end());\n    return sel;\n}\n\nstatic void add_path_edges(int a, int b, vector<char>& mark, vector<int>& cand) {\n    while (a != b) {\n        int c = nxtHop[a][b];\n        int id = edgeId[a][c];\n        if (!mark[id]) {\n            mark[id] = 1;\n            cand.push_back(id);\n        }\n        a = c;\n    }\n}\n\nstatic ConnResult reduce_candidate_edges(const vector<int>& candIds, const vector<char>& termMark, bool storeUsed) {\n    ConnResult res;\n    if (candIds.empty()) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<int> ids = candIds;\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        if (edges[i].w != edges[j].w) return edges[i].w < edges[j].w;\n        return i < j;\n    });\n\n    DSU dsu(N);\n    vector<char> tree(M, 0);\n    ll cost = 0;\n    for (int id : ids) {\n        if (dsu.unite(edges[id].u, edges[id].v)) {\n            tree[id] = 1;\n            cost += edges[id].w;\n        }\n    }\n\n    int rootComp = -1;\n    for (int v = 1; v <= N; ++v) {\n        if (termMark[v]) {\n            rootComp = dsu.find(v);\n            break;\n        }\n    }\n    for (int v = 1; v <= N; ++v) {\n        if (termMark[v] && dsu.find(v) != rootComp) {\n            res.cost = INFLL;\n            if (storeUsed) res.used.assign(M, 0);\n            return res;\n        }\n    }\n\n    vector<vector<pair<int,int>>> adj(N + 1);\n    vector<int> deg(N + 1, 0);\n    for (int id = 0; id < M; ++id) {\n        if (!tree[id]) continue;\n        int u = edges[id].u, v = edges[id].v;\n        adj[u].push_back({v, id});\n        adj[v].push_back({u, id});\n        deg[u]++;\n        deg[v]++;\n    }\n\n    queue<int> q;\n    for (int v = 1; v <= N; ++v) {\n        if (!termMark[v] && deg[v] == 1) q.push(v);\n    }\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (termMark[v] || deg[v] != 1) continue;\n\n        int rem = -1, to = -1;\n        for (auto [nx, id] : adj[v]) {\n            if (tree[id]) {\n                rem = id;\n                to = nx;\n                break;\n            }\n        }\n        if (rem == -1) continue;\n\n        tree[rem] = 0;\n        cost -= edges[rem].w;\n        deg[v]--;\n        deg[to]--;\n        if (!termMark[to] && deg[to] == 1) q.push(to);\n    }\n\n    res.cost = cost;\n    if (storeUsed) {\n        res.used.assign(M, 0);\n        for (int id = 0; id < M; ++id) if (tree[id]) res.used[id] = 1;\n    }\n    return res;\n}\n\nstatic ConnResult build_conn_mst(const vector<int>& terminals, bool storeUsed) {\n    ConnResult res;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<ll> best(t, INFLL);\n    vector<int> par(t, -1);\n    vector<char> usedT(t, 0);\n    best[0] = 0;\n    vector<pair<int,int>> termEdges;\n    termEdges.reserve(t - 1);\n\n    for (int it = 0; it < t; ++it) {\n        int x = -1;\n        ll bd = INFLL;\n        for (int i = 0; i < t; ++i) {\n            if (!usedT[i] && best[i] < bd) {\n                bd = best[i];\n                x = i;\n            }\n        }\n        usedT[x] = 1;\n        if (par[x] != -1) termEdges.push_back({terminals[x], terminals[par[x]]});\n        for (int y = 0; y < t; ++y) {\n            if (usedT[y]) continue;\n            ll d = distGraph[terminals[x]][terminals[y]];\n            if (d < best[y]) {\n                best[y] = d;\n                par[y] = x;\n            }\n        }\n    }\n\n    vector<char> mark(M, 0);\n    vector<int> cand;\n    vector<char> termMark(N + 1, 0);\n    for (int s : terminals) termMark[s] = 1;\n    for (auto [u, v] : termEdges) add_path_edges(u, v, mark, cand);\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_star(const vector<int>& terminals, int rootIdx, bool storeUsed) {\n    ConnResult res;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<char> termMark(N + 1, 0);\n    for (int s : terminals) termMark[s] = 1;\n\n    vector<char> mark(M, 0);\n    vector<int> cand;\n    int root = terminals[rootIdx];\n    for (int i = 0; i < t; ++i) {\n        if (i == rootIdx) continue;\n        add_path_edges(root, terminals[i], mark, cand);\n    }\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_greedy(const vector<int>& terminals, int startIdx, bool storeUsed) {\n    ConnResult res;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<char> termMark(N + 1, 0);\n    for (int s : terminals) termMark[s] = 1;\n\n    vector<char> inTree(N + 1, 0), done(t, 0), mark(M, 0);\n    vector<int> treeVerts;\n    treeVerts.reserve(N);\n\n    int start = terminals[startIdx];\n    inTree[start] = 1;\n    treeVerts.push_back(start);\n    done[startIdx] = 1;\n    int doneCnt = 1;\n\n    vector<int> cand;\n    while (doneCnt < t) {\n        ll bestD = INFLL;\n        int bestTi = -1, bestV = -1;\n\n        for (int i = 0; i < t; ++i) {\n            if (done[i]) continue;\n            int term = terminals[i];\n            for (int v : treeVerts) {\n                ll d = distGraph[v][term];\n                if (d < bestD) {\n                    bestD = d;\n                    bestTi = i;\n                    bestV = v;\n                }\n            }\n        }\n\n        int a = bestV;\n        int b = terminals[bestTi];\n        while (a != b) {\n            int c = nxtHop[a][b];\n            int id = edgeId[a][c];\n            if (!mark[id]) {\n                mark[id] = 1;\n                cand.push_back(id);\n            }\n            if (!inTree[c]) {\n                inTree[c] = 1;\n                treeVerts.push_back(c);\n            }\n            a = c;\n        }\n\n        if (!inTree[b]) {\n            inTree[b] = 1;\n            treeVerts.push_back(b);\n        }\n        done[bestTi] = 1;\n        ++doneCnt;\n    }\n\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_best(const vector<int>& terminals, bool storeUsed) {\n    ConnResult best;\n    best.cost = INFLL;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        best.cost = 0;\n        if (storeUsed) best.used.assign(M, 0);\n        return best;\n    }\n\n    auto consider = [&](ConnResult cand) {\n        if (cand.cost < best.cost) best = std::move(cand);\n    };\n\n    consider(build_conn_mst(terminals, storeUsed));\n    consider(build_conn_star(terminals, 0, storeUsed));\n\n    if (t <= 30) {\n        int center = 0;\n        ll bestSum = INFLL;\n        for (int i = 0; i < t; ++i) {\n            ll s = 0;\n            for (int j = 0; j < t; ++j) s += distGraph[terminals[i]][terminals[j]];\n            if (s < bestSum) {\n                bestSum = s;\n                center = i;\n            }\n        }\n        consider(build_conn_star(terminals, center, storeUsed));\n        consider(build_conn_greedy(terminals, 0, storeUsed));\n        consider(build_conn_greedy(terminals, center, storeUsed));\n    }\n\n    return best;\n}\n\nstatic int choose_medoid(const vector<int>& resList) {\n    int bestV = 1;\n    int bestMax = INT_MAX;\n    ll bestSum = INFLL;\n    ll bestRoot = INFLL;\n\n    for (int v = 1; v <= N; ++v) {\n        int mx = 0;\n        ll sum = 0;\n        for (int k : resList) {\n            int d = distSR[v][k];\n            if (d > mx) mx = d;\n            sum += d;\n            if (mx > bestMax) break;\n        }\n        if (mx < bestMax ||\n            (mx == bestMax && (sum < bestSum || (sum == bestSum && distGraph[1][v] < bestRoot)))) {\n            bestMax = mx;\n            bestSum = sum;\n            bestRoot = distGraph[1][v];\n            bestV = v;\n        }\n    }\n    return bestV;\n}\n\nstatic EvalResult core_eval(vector<int> selRaw, bool storeUsed, bool improveResidents) {\n    EvalResult res;\n    res.sel = normalize_sel(std::move(selRaw));\n    int t = (int)res.sel.size();\n\n    res.inSel.assign(N + 1, 0);\n    for (int s : res.sel) res.inSel[s] = 1;\n\n    res.rad.assign(t, 0);\n    res.owner.assign(K, -1);\n    res.bestDist.assign(K, INT_MAX);\n\n    vector<int> cnt(t, 0);\n    vector<int> freq(t * MAXR, 0);\n\n    for (int k : hardOrder) {\n        int bestJ = -1;\n        ll bestInc = INFLL;\n        int bestD = INT_MAX;\n\n        for (int j = 0; j < t; ++j) {\n            int d = distSR[res.sel[j]][k];\n            if (d > 5000) continue;\n            ll r = res.rad[j];\n            ll inc = 1LL * max<ll>(r, d) * max<ll>(r, d) - r * r;\n            if (inc < bestInc || (inc == bestInc && (d < bestD || (d == bestD && r < res.rad[bestJ >= 0 ? bestJ : j])))) {\n                bestInc = inc;\n                bestJ = j;\n                bestD = d;\n            }\n        }\n\n        if (bestJ == -1) {\n            res.uncovered++;\n            continue;\n        }\n\n        res.owner[k] = bestJ;\n        res.bestDist[k] = bestD;\n        cnt[bestJ]++;\n        freq[bestJ * MAXR + bestD]++;\n        if (bestD > res.rad[bestJ]) res.rad[bestJ] = bestD;\n    }\n\n    if (improveResidents && res.uncovered == 0 && t <= 15) {\n        vector<int> ord;\n        ord.reserve(K);\n        for (int k = 0; k < K; ++k) if (res.owner[k] != -1) ord.push_back(k);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return res.bestDist[a] > res.bestDist[b];\n        });\n\n        for (int k : ord) {\n            int a = res.owner[k];\n            if (a < 0) continue;\n\n            int da = res.bestDist[k];\n            int oldRa = res.rad[a];\n            int newRa = oldRa;\n\n            if (da == oldRa && freq[a * MAXR + da] == 1) {\n                int x = oldRa - 1;\n                while (x > 0 && freq[a * MAXR + x] == 0) --x;\n                newRa = x;\n            }\n\n            ll bestDelta = 0;\n            int bestB = -1;\n            int bestDb = -1;\n            int bestNewRb = -1;\n\n            for (int b = 0; b < t; ++b) {\n                if (b == a) continue;\n                int db = distSR[res.sel[b]][k];\n                if (db > 5000) continue;\n                int oldRb = res.rad[b];\n                int newRb = max(oldRb, db);\n                ll delta = 1LL * newRa * newRa + 1LL * newRb * newRb\n                         - 1LL * oldRa * oldRa - 1LL * oldRb * oldRb;\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    bestB = b;\n                    bestDb = db;\n                    bestNewRb = newRb;\n                }\n            }\n\n            if (bestB != -1) {\n                int b = bestB;\n\n                freq[a * MAXR + da]--;\n                cnt[a]--;\n                if (cnt[a] == 0) {\n                    res.rad[a] = 0;\n                } else if (da == oldRa && freq[a * MAXR + oldRa] == 0) {\n                    int x = oldRa - 1;\n                    while (x > 0 && freq[a * MAXR + x] == 0) --x;\n                    res.rad[a] = x;\n                }\n\n                freq[b * MAXR + bestDb]++;\n                cnt[b]++;\n                res.rad[b] = max(res.rad[b], bestNewRb);\n\n                res.owner[k] = b;\n                res.bestDist[k] = bestDb;\n            }\n        }\n    }\n\n    // prune empty stations except root\n    vector<int> keep;\n    keep.reserve(t);\n    for (int j = 0; j < t; ++j) {\n        if (res.sel[j] == 1 || cnt[j] > 0) keep.push_back(j);\n    }\n\n    if ((int)keep.size() != t) {\n        vector<int> ns, nr;\n        ns.reserve(keep.size());\n        nr.reserve(keep.size());\n        vector<int> mp(t, -1);\n        for (int idx = 0; idx < (int)keep.size(); ++idx) mp[keep[idx]] = idx;\n        for (int idx : keep) {\n            ns.push_back(res.sel[idx]);\n            nr.push_back(res.rad[idx]);\n        }\n        for (int k = 0; k < K; ++k) {\n            if (res.owner[k] != -1) res.owner[k] = mp[res.owner[k]];\n        }\n        res.sel = std::move(ns);\n        res.rad = std::move(nr);\n        t = (int)res.sel.size();\n    }\n\n    res.inSel.assign(N + 1, 0);\n    for (int s : res.sel) res.inSel[s] = 1;\n\n    res.cov = 0;\n    for (int r : res.rad) res.cov += 1LL * r * r;\n\n    ConnResult cr = build_conn_best(res.sel, storeUsed);\n    res.conn = cr.cost;\n    if (storeUsed) res.used = std::move(cr.used);\n\n    res.total = res.cov + res.conn + PENALTY * res.uncovered;\n    return res;\n}\n\nstatic EvalResult strong_eval(vector<int> sel, bool storeUsed) {\n    EvalResult cur = core_eval(std::move(sel), false, true);\n    EvalResult best = cur;\n\n    for (int it = 0; it < 2 && !time_over(); ++it) {\n        if (cur.uncovered > 0 || cur.sel.size() <= 1) break;\n\n        vector<vector<int>> clusters(cur.sel.size());\n        for (int k = 0; k < K; ++k) {\n            int o = cur.owner[k];\n            if (o >= 0) clusters[o].push_back(k);\n        }\n\n        vector<int> ns = {1};\n        for (int j = 0; j < (int)cur.sel.size(); ++j) {\n            if (clusters[j].empty()) continue;\n            int v = choose_medoid(clusters[j]);\n            ns.push_back(v);\n        }\n        ns = normalize_sel(std::move(ns));\n\n        if (ns == cur.sel) break;\n        EvalResult cand = core_eval(ns, false, true);\n        if (cand.total < best.total) best = cand;\n        if (cand.total < cur.total) cur = cand;\n        else break;\n    }\n\n    if (storeUsed) best = core_eval(best.sel, true, true);\n    return best;\n}\n\nstatic vector<int> make_kmeans_seed(int C, int startIdx) {\n    if (C <= 0) return {1};\n    C = min(C, K);\n\n    auto dist2p = [&](int i, int j) -> ll {\n        ll dx = (ll)ax[i] - ax[j];\n        ll dy = (ll)ay[i] - ay[j];\n        return dx * dx + dy * dy;\n    };\n\n    vector<int> centers;\n    centers.reserve(C);\n    startIdx %= K;\n    if (startIdx < 0) startIdx += K;\n    centers.push_back(startIdx);\n\n    vector<ll> mind2(K, INFLL);\n    for (int k = 0; k < K; ++k) mind2[k] = dist2p(k, startIdx);\n\n    for (int c = 1; c < C; ++c) {\n        int nxt = 0;\n        ll best = -1;\n        for (int k = 0; k < K; ++k) {\n            if (mind2[k] > best) {\n                best = mind2[k];\n                nxt = k;\n            }\n        }\n        centers.push_back(nxt);\n        for (int k = 0; k < K; ++k) mind2[k] = min(mind2[k], dist2p(k, nxt));\n    }\n\n    vector<pair<double,double>> cen(C);\n    for (int i = 0; i < C; ++i) cen[i] = {(double)ax[centers[i]], (double)ay[centers[i]]};\n\n    for (int it = 0; it < 3; ++it) {\n        vector<vector<int>> groups(C);\n        for (int k = 0; k < K; ++k) {\n            int bestc = 0;\n            long double bestd = 1e100;\n            for (int c = 0; c < C; ++c) {\n                long double dx = (long double)ax[k] - cen[c].first;\n                long double dy = (long double)ay[k] - cen[c].second;\n                long double d = dx * dx + dy * dy;\n                if (d < bestd) {\n                    bestd = d;\n                    bestc = c;\n                }\n            }\n            groups[bestc].push_back(k);\n        }\n\n        for (int c = 0; c < C; ++c) {\n            if (groups[c].empty()) continue;\n            long double sx = 0, sy = 0;\n            for (int k : groups[c]) {\n                sx += ax[k];\n                sy += ay[k];\n            }\n            cen[c] = {(double)(sx / groups[c].size()), (double)(sy / groups[c].size())};\n        }\n    }\n\n    vector<vector<int>> groups(C);\n    for (int k = 0; k < K; ++k) {\n        int bestc = 0;\n        long double bestd = 1e100;\n        for (int c = 0; c < C; ++c) {\n            long double dx = (long double)ax[k] - cen[c].first;\n            long double dy = (long double)ay[k] - cen[c].second;\n            long double d = dx * dx + dy * dy;\n            if (d < bestd) {\n                bestd = d;\n                bestc = c;\n            }\n        }\n        groups[bestc].push_back(k);\n    }\n\n    vector<int> chosen = {1};\n    for (int c = 0; c < C; ++c) {\n        if (groups[c].empty()) continue;\n        int bestV = 1;\n        int bestMax = INT_MAX;\n        ll bestSum = INFLL;\n        for (int v = 1; v <= N; ++v) {\n            int mx = 0;\n            ll sum = 0;\n            for (int k : groups[c]) {\n                int d = distSR[v][k];\n                mx = max(mx, d);\n                sum += d;\n                if (mx > bestMax) break;\n            }\n            if (mx < bestMax || (mx == bestMax && sum < bestSum)) {\n                bestMax = mx;\n                bestSum = sum;\n                bestV = v;\n            }\n        }\n        chosen.push_back(bestV);\n    }\n\n    sort(chosen.begin(), chosen.end());\n    chosen.erase(unique(chosen.begin(), chosen.end()), chosen.end());\n    if (find(chosen.begin(), chosen.end(), 1) == chosen.end()) chosen.push_back(1);\n    sort(chosen.begin(), chosen.end());\n    return chosen;\n}\n\nstatic vector<int> make_add_pool(const EvalResult& cur) {\n    vector<int> pool;\n    vector<char> seen(N + 1, 0);\n    auto addv = [&](int v) {\n        if (v < 1 || v > N) return;\n        if (cur.inSel[v]) return;\n        if (seen[v]) return;\n        seen[v] = 1;\n        pool.push_back(v);\n    };\n\n    if (cur.uncovered > 0) {\n        vector<int> unc;\n        for (int k : hardOrder) {\n            if (cur.owner[k] == -1) unc.push_back(k);\n        }\n        if (unc.empty()) {\n            for (int k = 0; k < K; ++k) if (cur.owner[k] == -1) unc.push_back(k);\n        }\n        for (int i = 0; i < (int)unc.size() && i < 6; ++i) {\n            int k = unc[i];\n            addv(residentOrder[k][0]);\n            if (N >= 2) addv(residentOrder[k][1]);\n            if (N >= 3) addv(residentOrder[k][2]);\n        }\n    } else {\n        vector<pair<int,int>> far;\n        far.reserve(K);\n        for (int k = 0; k < K; ++k) {\n            if (cur.owner[k] != -1) far.push_back({cur.bestDist[k], k});\n        }\n        sort(far.begin(), far.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n        for (int i = 0; i < (int)far.size() && i < 6; ++i) {\n            int k = far[i].second;\n            addv(residentOrder[k][0]);\n            if (N >= 2) addv(residentOrder[k][1]);\n            if (N >= 3) addv(residentOrder[k][2]);\n        }\n    }\n\n    for (int i = 0; i < (int)singleRank.size() && i < 8; ++i) addv(singleRank[i].second);\n    for (int i = 0; i < (int)coverRank.size() && i < 6; ++i) addv(coverRank[i].second);\n\n    return pool;\n}\n\nstatic void insert_top(vector<pair<ll, vector<int>>>& top, ll score, vector<int>&& sel, int lim) {\n    top.push_back({score, std::move(sel)});\n    sort(top.begin(), top.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second.size() < b.second.size();\n    });\n    if ((int)top.size() > lim) top.resize(lim);\n}\n\nstatic EvalResult search_from_seed(vector<int> seed) {\n    EvalResult cur = strong_eval(seed, false);\n\n    for (int iter = 0; iter < 4 && !time_over(); ++iter) {\n        vector<int> pool = make_add_pool(cur);\n        vector<pair<ll, vector<int>>> top;\n        top.reserve(24);\n\n        // add\n        for (int v : pool) {\n            vector<int> tmp = cur.sel;\n            tmp.push_back(v);\n            EvalResult fast = core_eval(std::move(tmp), false, false);\n            insert_top(top, fast.total, std::move(fast.sel), 6);\n            if (time_over()) break;\n        }\n\n        // remove\n        for (int s : cur.sel) {\n            if (s == 1) continue;\n            vector<int> tmp;\n            tmp.reserve(cur.sel.size() - 1);\n            for (int x : cur.sel) if (x != s) tmp.push_back(x);\n            EvalResult fast = core_eval(std::move(tmp), false, false);\n            insert_top(top, fast.total, std::move(fast.sel), 6);\n            if (time_over()) break;\n        }\n\n        // swap a few worst stations\n        vector<pair<int,int>> worst;\n        for (int i = 0; i < (int)cur.sel.size(); ++i) {\n            if (cur.sel[i] == 1) continue;\n            worst.push_back({cur.rad[i], cur.sel[i]});\n        }\n        sort(worst.begin(), worst.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n\n        int remLim = min(3, (int)worst.size());\n        int addLim = min(4, (int)pool.size());\n        for (int i = 0; i < remLim; ++i) {\n            for (int j = 0; j < addLim; ++j) {\n                int rem = worst[i].second;\n                int add = pool[j];\n                if (cur.inSel[add]) continue;\n                vector<int> tmp;\n                tmp.reserve(cur.sel.size());\n                for (int x : cur.sel) if (x != rem) tmp.push_back(x);\n                tmp.push_back(add);\n                EvalResult fast = core_eval(std::move(tmp), false, false);\n                insert_top(top, fast.total, std::move(fast.sel), 6);\n                if (time_over()) break;\n            }\n            if (time_over()) break;\n        }\n\n        // strong polish top candidates\n        EvalResult best = cur;\n        for (auto& [score, sel] : top) {\n            EvalResult cand = strong_eval(sel, false);\n            if (cand.total < best.total) best = std::move(cand);\n            if (time_over()) break;\n        }\n\n        // random perturbation if stuck\n        if (best.total >= cur.total && !pool.empty() && cur.sel.size() > 1) {\n            int remIdx = -1;\n            for (int i = 0; i < (int)cur.sel.size(); ++i) {\n                if (cur.sel[i] == 1) continue;\n                if (remIdx == -1 || cur.rad[i] > cur.rad[remIdx]) remIdx = i;\n            }\n            if (remIdx != -1) {\n                int add = pool[(int)(rng() % pool.size())];\n                if (!cur.inSel[add]) {\n                    vector<int> tmp;\n                    tmp.reserve(cur.sel.size());\n                    for (int x : cur.sel) if (x != cur.sel[remIdx]) tmp.push_back(x);\n                    tmp.push_back(add);\n                    EvalResult cand = strong_eval(tmp, false);\n                    if (cand.total < best.total) best = std::move(cand);\n                }\n            }\n        }\n\n        if (best.total < cur.total) cur = std::move(best);\n        else break;\n    }\n\n    // final prune phase\n    for (int rep = 0; rep < 2 && !time_over(); ++rep) {\n        EvalResult best = cur;\n        for (int s : cur.sel) {\n            if (s == 1) continue;\n            vector<int> tmp;\n            tmp.reserve(cur.sel.size() - 1);\n            for (int x : cur.sel) if (x != s) tmp.push_back(x);\n            EvalResult cand = strong_eval(tmp, false);\n            if (cand.total < best.total) best = std::move(cand);\n            if (time_over()) break;\n        }\n        if (best.total < cur.total) cur = std::move(best);\n        else break;\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    xs.resize(N + 1);\n    ys.resize(N + 1);\n    for (int i = 1; i <= N; ++i) cin >> xs[i] >> ys[i];\n\n    edges.resize(M);\n    edgeId.assign(N + 1, vector<int>(N + 1, -1));\n    distGraph.assign(N + 1, vector<ll>(N + 1, INFLL));\n    nxtHop.assign(N + 1, vector<int>(N + 1, -1));\n\n    for (int i = 1; i <= N; ++i) {\n        distGraph[i][i] = 0;\n        nxtHop[i][i] = i;\n    }\n\n    vector<vector<pair<int,ll>>> adj(N + 1);\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n        edgeId[u][v] = edgeId[v][u] = j;\n        if (w < distGraph[u][v]) {\n            distGraph[u][v] = distGraph[v][u] = w;\n            nxtHop[u][v] = v;\n            nxtHop[v][u] = u;\n        }\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n\n    ax.resize(K);\n    ay.resize(K);\n    for (int i = 0; i < K; ++i) cin >> ax[i] >> ay[i];\n\n    // APSP\n    for (int k = 1; k <= N; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            if (distGraph[i][k] >= INFLL / 4) continue;\n            for (int j = 1; j <= N; ++j) {\n                if (distGraph[k][j] >= INFLL / 4) continue;\n                ll nd = distGraph[i][k] + distGraph[k][j];\n                if (nd < distGraph[i][j]) {\n                    distGraph[i][j] = nd;\n                    nxtHop[i][j] = nxtHop[i][k];\n                }\n            }\n        }\n    }\n\n    // station-resident distances\n    distSR.assign(N + 1, vector<int>(K, 0));\n    residentOrder.assign(K, vector<int>(N));\n    for (int k = 0; k < K; ++k) {\n        for (int v = 1; v <= N; ++v) {\n            ll dx = (ll)xs[v] - ax[k];\n            ll dy = (ll)ys[v] - ay[k];\n            ll d2 = dx * dx + dy * dy;\n            distSR[v][k] = ceil_sqrt_ll(d2);\n        }\n        iota(residentOrder[k].begin(), residentOrder[k].end(), 1);\n        sort(residentOrder[k].begin(), residentOrder[k].end(), [&](int a, int b) {\n            if (distSR[a][k] != distSR[b][k]) return distSR[a][k] < distSR[b][k];\n            return a < b;\n        });\n    }\n\n    // resident hardness\n    vector<int> minDistRes(K), coverCntRes(K);\n    for (int k = 0; k < K; ++k) {\n        int mn = MAXR, cnt = 0;\n        for (int v = 1; v <= N; ++v) {\n            int d = distSR[v][k];\n            mn = min(mn, d);\n            if (d <= 5000) cnt++;\n        }\n        minDistRes[k] = mn;\n        coverCntRes[k] = cnt;\n    }\n\n    hardOrder.resize(K);\n    iota(hardOrder.begin(), hardOrder.end(), 0);\n    sort(hardOrder.begin(), hardOrder.end(), [&](int a, int b) {\n        if (minDistRes[a] != minDistRes[b]) return minDistRes[a] > minDistRes[b];\n        if (coverCntRes[a] != coverCntRes[b]) return coverCntRes[a] < coverCntRes[b];\n        return a < b;\n    });\n\n    // static ranks\n    singleRank.clear();\n    coverRank.clear();\n    for (int v = 2; v <= N; ++v) {\n        EvalResult e = core_eval({1, v}, false, true);\n        singleRank.push_back({e.total, v});\n        int cnt = 0;\n        for (int k = 0; k < K; ++k) if (distSR[v][k] <= 5000) cnt++;\n        coverRank.push_back({-(ll)cnt, v});\n    }\n    sort(singleRank.begin(), singleRank.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n    sort(coverRank.begin(), coverRank.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n\n    auto make_kmeans_seed = [&](int C, int startIdx) {\n        if (C <= 0) return vector<int>{1};\n        C = min(C, K);\n\n        auto dist2p = [&](int i, int j) -> ll {\n            ll dx = (ll)ax[i] - ax[j];\n            ll dy = (ll)ay[i] - ay[j];\n            return dx * dx + dy * dy;\n        };\n\n        vector<int> centers;\n        centers.reserve(C);\n        startIdx %= K;\n        if (startIdx < 0) startIdx += K;\n        centers.push_back(startIdx);\n\n        vector<ll> mind2(K, INFLL);\n        for (int k = 0; k < K; ++k) mind2[k] = dist2p(k, startIdx);\n\n        for (int c = 1; c < C; ++c) {\n            int nxt = 0;\n            ll best = -1;\n            for (int k = 0; k < K; ++k) {\n                if (mind2[k] > best) {\n                    best = mind2[k];\n                    nxt = k;\n                }\n            }\n            centers.push_back(nxt);\n            for (int k = 0; k < K; ++k) mind2[k] = min(mind2[k], dist2p(k, nxt));\n        }\n\n        vector<pair<double,double>> cen(C);\n        for (int i = 0; i < C; ++i) cen[i] = {(double)ax[centers[i]], (double)ay[centers[i]]};\n\n        for (int it = 0; it < 3; ++it) {\n            vector<vector<int>> groups(C);\n            for (int k = 0; k < K; ++k) {\n                int bestc = 0;\n                long double bestd = 1e100;\n                for (int c = 0; c < C; ++c) {\n                    long double dx = (long double)ax[k] - cen[c].first;\n                    long double dy = (long double)ay[k] - cen[c].second;\n                    long double d = dx * dx + dy * dy;\n                    if (d < bestd) {\n                        bestd = d;\n                        bestc = c;\n                    }\n                }\n                groups[bestc].push_back(k);\n            }\n\n            for (int c = 0; c < C; ++c) {\n                if (groups[c].empty()) continue;\n                long double sx = 0, sy = 0;\n                for (int k : groups[c]) {\n                    sx += ax[k];\n                    sy += ay[k];\n                }\n                cen[c] = {(double)(sx / groups[c].size()), (double)(sy / groups[c].size())};\n            }\n        }\n\n        vector<vector<int>> groups(C);\n        for (int k = 0; k < K; ++k) {\n            int bestc = 0;\n            long double bestd = 1e100;\n            for (int c = 0; c < C; ++c) {\n                long double dx = (long double)ax[k] - cen[c].first;\n                long double dy = (long double)ay[k] - cen[c].second;\n                long double d = dx * dx + dy * dy;\n                if (d < bestd) {\n                    bestd = d;\n                    bestc = c;\n                }\n            }\n            groups[bestc].push_back(k);\n        }\n\n        vector<int> chosen = {1};\n        for (int c = 0; c < C; ++c) {\n            if (groups[c].empty()) continue;\n            int bestV = 1;\n            int bestMax = INT_MAX;\n            ll bestSum = INFLL;\n            for (int v = 1; v <= N; ++v) {\n                int mx = 0;\n                ll sum = 0;\n                for (int k : groups[c]) {\n                    int d = distSR[v][k];\n                    mx = max(mx, d);\n                    sum += d;\n                    if (mx > bestMax) break;\n                }\n                if (mx < bestMax || (mx == bestMax && sum < bestSum)) {\n                    bestMax = mx;\n                    bestSum = sum;\n                    bestV = v;\n                }\n            }\n            chosen.push_back(bestV);\n        }\n\n        sort(chosen.begin(), chosen.end());\n        chosen.erase(unique(chosen.begin(), chosen.end()), chosen.end());\n        if (find(chosen.begin(), chosen.end(), 1) == chosen.end()) chosen.push_back(1);\n        sort(chosen.begin(), chosen.end());\n        return chosen;\n    };\n\n    // Seeds\n    vector<vector<int>> seeds;\n    if (!singleRank.empty()) seeds.push_back(normalize_sel({1, singleRank[0].second}));\n\n    {\n        int L = min(6, (int)singleRank.size());\n        ll bestT = INFLL;\n        vector<int> bestSel = {1};\n        for (int i = 0; i < L; ++i) {\n            for (int j = i + 1; j < L; ++j) {\n                vector<int> s = {1, singleRank[i].second, singleRank[j].second};\n                EvalResult e = strong_eval(s, false);\n                if (e.total < bestT) {\n                    bestT = e.total;\n                    bestSel = e.sel;\n                }\n                if (time_over()) break;\n            }\n            if (time_over()) break;\n        }\n        seeds.push_back(normalize_sel(bestSel));\n    }\n\n    {\n        vector<int> s = {1};\n        for (int i = 0; i < (int)coverRank.size() && i < 4; ++i) s.push_back(coverRank[i].second);\n        seeds.push_back(normalize_sel(s));\n    }\n\n    seeds.push_back(normalize_sel(make_kmeans_seed(6, 0)));\n    seeds.push_back(normalize_sel(make_kmeans_seed(10, K / 2)));\n\n    {\n        vector<int> cand;\n        for (int i = 0; i < (int)singleRank.size() && i < 8; ++i) cand.push_back(singleRank[i].second);\n        for (int i = 0; i < (int)coverRank.size() && i < 8; ++i) cand.push_back(coverRank[i].second);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        shuffle(cand.begin(), cand.end(), rng);\n        vector<int> s = {1};\n        for (int v : cand) {\n            if (v == 1) continue;\n            s.push_back(v);\n            if ((int)s.size() >= 5) break;\n        }\n        seeds.push_back(normalize_sel(s));\n    }\n\n    // Dedup seeds\n    {\n        vector<vector<int>> uniq;\n        for (auto s : seeds) {\n            s = normalize_sel(std::move(s));\n            bool dup = false;\n            for (auto& t : uniq) {\n                if (t == s) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) uniq.push_back(std::move(s));\n        }\n        seeds = std::move(uniq);\n    }\n\n    EvalResult bestOverall;\n    bestOverall.total = INFLL;\n\n    for (auto& seed : seeds) {\n        if (time_over()) break;\n        EvalResult cur = search_from_seed(seed);\n        if (cur.total < bestOverall.total) bestOverall = std::move(cur);\n    }\n\n    if (bestOverall.sel.empty() || bestOverall.uncovered > 0) {\n        vector<int> allSel;\n        for (int v = 1; v <= N; ++v) allSel.push_back(v);\n        bestOverall = strong_eval(allSel, true);\n    } else {\n        bestOverall = strong_eval(bestOverall.sel, true);\n        if (bestOverall.uncovered > 0) {\n            vector<int> allSel;\n            for (int v = 1; v <= N; ++v) allSel.push_back(v);\n            bestOverall = strong_eval(allSel, true);\n        }\n    }\n\n    vector<int> P(N + 1, 0);\n    for (int i = 0; i < (int)bestOverall.sel.size(); ++i) {\n        P[bestOverall.sel[i]] = bestOverall.rad[i];\n    }\n\n    for (int i = 1; i <= N; ++i) {\n        if (i > 1) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (bestOverall.used.empty() ? 0 : (bestOverall.used[j] ? 1 : 0));\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * (N + 1) / 2; // 465\nstatic constexpr int LIMIT = 10000;\nstatic constexpr int INF = 1e9;\n\nstatic constexpr int BEAM_DEPTH = 3;\nstatic constexpr int ROOT_CAND = 10;\nstatic constexpr int SUB_CAND = 5;\n\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\nstruct State {\n    array<int, V> board{};\n    array<int, V> pos{};\n    array<unsigned char, V> fixed{};\n    array<unsigned char, V> avail{};\n    array<int, V> parentCnt{};\n    array<int, V> childCnt{};\n};\n\nstruct BFSRes {\n    array<int, V> dist{};\n    array<int, V> par{};\n    array<int, V> pen{};\n};\n\nstruct Candidate {\n    int target;\n    int len;\n    int pen;\n    int unlock;\n    int center;\n    int rowBias;\n    long long score;\n};\n\nstruct Choice {\n    int target = -1;\n    int len = INF;\n    long long score = (1LL << 60);\n    vector<int> path;\n};\n\nstruct Result {\n    vector<Move> ops;\n    bool complete = false;\n};\n\narray<pair<int, int>, V> coord;\narray<int, V> centerDist;\narray<int, V> needParents;\narray<int, V> needChildren;\nvector<int> adj[V];\nvector<int> parentsList[V];\nvector<int> childrenList[V];\n\ninline int id(int x, int y) {\n    return x * (x + 1) / 2 + y;\n}\n\ninline array<int, V> make_weights(const State& st, int num, bool topDown) {\n    array<int, V> w;\n    w.fill(0);\n\n    auto mark = [&](int label, int val) {\n        if (0 <= label && label < V) {\n            w[st.pos[label]] = val;\n        }\n    };\n\n    if (topDown) {\n        mark(num + 1, 64);\n        mark(num + 2, 32);\n        mark(num + 3, 16);\n        mark(num + 4, 8);\n        mark(num + 5, 4);\n    } else {\n        mark(num - 1, 64);\n        mark(num - 2, 32);\n        mark(num - 3, 16);\n        mark(num - 4, 8);\n        mark(num - 5, 4);\n    }\n    return w;\n}\n\ninline int transition_penalty(const State& st, const array<int, V>& weight, int v) {\n    return weight[v] + 1 + (V - st.board[v]) / 32;\n}\n\ninline bool better_parent(int a, int b, bool topDown) {\n    if (b == -1) return true;\n    if (coord[a].first != coord[b].first) {\n        if (topDown) return coord[a].first < coord[b].first;   // shallower preferred\n        return coord[a].first > coord[b].first;                // deeper preferred\n    }\n    if (centerDist[a] != centerDist[b]) return centerDist[a] < centerDist[b];\n    if (coord[a].second != coord[b].second) return coord[a].second < coord[b].second;\n    return a < b;\n}\n\nBFSRes bfs_from(const State& st, int src, const array<int, V>& weight, bool topDown) {\n    BFSRes res;\n    res.dist.fill(-1);\n    res.par.fill(-1);\n    res.pen.fill(INF);\n\n    vector<int> q;\n    q.reserve(V);\n    q.push_back(src);\n    res.dist[src] = 0;\n    res.pen[src] = 0;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        for (int v : adj[u]) {\n            if (st.fixed[v] || res.dist[v] != -1) continue;\n            res.dist[v] = res.dist[u] + 1;\n            q.push_back(v);\n        }\n    }\n\n    for (int u : q) {\n        if (res.pen[u] == INF) continue;\n        for (int v : adj[u]) {\n            if (st.fixed[v]) continue;\n            if (res.dist[v] != res.dist[u] + 1) continue;\n\n            int cand = res.pen[u] + transition_penalty(st, weight, v);\n            if (cand < res.pen[v] || (cand == res.pen[v] && better_parent(u, res.par[v], topDown))) {\n                res.pen[v] = cand;\n                res.par[v] = u;\n            }\n        }\n    }\n\n    return res;\n}\n\nvector<int> build_path(int src, int tgt, const array<int, V>& par) {\n    vector<int> path;\n    for (int v = tgt;; v = par[v]) {\n        path.push_back(v);\n        if (v == src) break;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid apply_path(State& st, const vector<int>& path, vector<Move>* ops) {\n    for (int i = 0; i + 1 < (int)path.size(); ++i) {\n        int a = path[i];\n        int b = path[i + 1];\n        int va = st.board[a];\n        int vb = st.board[b];\n        swap(st.board[a], st.board[b]);\n        st.pos[va] = b;\n        st.pos[vb] = a;\n        if (ops) {\n            ops->push_back({coord[a].first, coord[a].second, coord[b].first, coord[b].second});\n        }\n    }\n}\n\nvoid fix_cell(State& st, int t, bool topDown) {\n    st.fixed[t] = 1;\n    st.avail[t] = 0;\n\n    if (topDown) {\n        for (int c : childrenList[t]) {\n            if (st.fixed[c]) continue;\n            ++st.parentCnt[c];\n            if (!st.avail[c] && st.parentCnt[c] == needParents[c]) {\n                st.avail[c] = 1;\n            }\n        }\n    } else {\n        for (int p : parentsList[t]) {\n            if (st.fixed[p]) continue;\n            ++st.childCnt[p];\n            if (!st.avail[p] && st.childCnt[p] == needChildren[p]) {\n                st.avail[p] = 1;\n            }\n        }\n    }\n}\n\nint unlock_score(const State& st, int t, bool topDown) {\n    int sc = 0;\n    if (topDown) {\n        for (int c : childrenList[t]) {\n            if (st.fixed[c]) continue;\n            if (st.parentCnt[c] + 1 == needParents[c]) ++sc;\n        }\n    } else {\n        for (int p : parentsList[t]) {\n            if (st.fixed[p]) continue;\n            if (st.childCnt[p] + 1 == needChildren[p]) ++sc;\n        }\n    }\n    return sc;\n}\n\nstatic inline bool cmp_score(const Candidate& a, const Candidate& b) {\n    if (a.score != b.score) return a.score < b.score;\n    if (a.len != b.len) return a.len < b.len;\n    if (a.pen != b.pen) return a.pen < b.pen;\n    if (a.unlock != b.unlock) return a.unlock > b.unlock;\n    if (a.center != b.center) return a.center < b.center;\n    if (a.rowBias != b.rowBias) return a.rowBias < b.rowBias;\n    return a.target < b.target;\n}\n\nstatic inline bool cmp_len(const Candidate& a, const Candidate& b) {\n    if (a.len != b.len) return a.len < b.len;\n    if (a.score != b.score) return a.score < b.score;\n    if (a.pen != b.pen) return a.pen < b.pen;\n    if (a.unlock != b.unlock) return a.unlock > b.unlock;\n    return a.target < b.target;\n}\n\nstatic inline bool cmp_unlock(const Candidate& a, const Candidate& b) {\n    if (a.unlock != b.unlock) return a.unlock > b.unlock;\n    if (a.score != b.score) return a.score < b.score;\n    if (a.len != b.len) return a.len < b.len;\n    if (a.pen != b.pen) return a.pen < b.pen;\n    return a.target < b.target;\n}\n\nstatic inline bool cmp_pen(const Candidate& a, const Candidate& b) {\n    if (a.pen != b.pen) return a.pen < b.pen;\n    if (a.score != b.score) return a.score < b.score;\n    if (a.len != b.len) return a.len < b.len;\n    if (a.unlock != b.unlock) return a.unlock > b.unlock;\n    return a.target < b.target;\n}\n\nvector<Candidate> build_candidates(const State& st, const BFSRes& bfs, bool topDown, int maxCand, bool diversify) {\n    vector<Candidate> all;\n    all.reserve(V);\n\n    for (int t = 0; t < V; ++t) {\n        if (!st.avail[t] || st.fixed[t]) continue;\n        int len = bfs.dist[t];\n        if (len < 0) continue;\n\n        int un = unlock_score(st, t, topDown);\n        int center = centerDist[t];\n        int rowBias = topDown ? coord[t].first : (N - 1 - coord[t].first);\n\n        long long score = 120LL * len + 3LL * bfs.pen[t] - 50LL * un + 3LL * center + 4LL * rowBias;\n        all.push_back({t, len, bfs.pen[t], un, center, rowBias, score});\n    }\n\n    if (all.empty()) return all;\n\n    if ((int)all.size() <= maxCand) {\n        sort(all.begin(), all.end(), cmp_score);\n        return all;\n    }\n\n    if (!diversify) {\n        partial_sort(all.begin(), all.begin() + maxCand, all.end(), cmp_score);\n        all.resize(maxCand);\n        return all;\n    }\n\n    vector<Candidate> picked;\n    picked.reserve(maxCand);\n    array<unsigned char, V> used{};\n    used.fill(0);\n\n    auto take_from = [&](auto cmp, int k) {\n        if ((int)picked.size() >= maxCand || k <= 0) return;\n        vector<Candidate> tmp = all;\n        k = min(k, (int)tmp.size());\n        if (k == (int)tmp.size()) {\n            sort(tmp.begin(), tmp.end(), cmp);\n        } else {\n            partial_sort(tmp.begin(), tmp.begin() + k, tmp.end(), cmp);\n        }\n        for (int i = 0; i < k && (int)picked.size() < maxCand; ++i) {\n            int t = tmp[i].target;\n            if (!used[t]) {\n                used[t] = 1;\n                picked.push_back(tmp[i]);\n            }\n        }\n    };\n\n    take_from(cmp_score, 4);\n    take_from(cmp_len, 2);\n    take_from(cmp_unlock, 2);\n    take_from(cmp_pen, 2);\n\n    if ((int)picked.size() < maxCand) {\n        sort(all.begin(), all.end(), cmp_score);\n        for (const auto& c : all) {\n            if (!used[c.target]) {\n                used[c.target] = 1;\n                picked.push_back(c);\n                if ((int)picked.size() == maxCand) break;\n            }\n        }\n    }\n\n    sort(picked.begin(), picked.end(), cmp_score);\n    return picked;\n}\n\nChoice greedy_choice(const State& st, int num, bool topDown) {\n    Choice ch;\n    auto w = make_weights(st, num, topDown);\n    BFSRes bfs = bfs_from(st, st.pos[num], w, topDown);\n    auto cand = build_candidates(st, bfs, topDown, V, false);\n    if (cand.empty()) return ch;\n\n    ch.target = cand[0].target;\n    ch.len = cand[0].len;\n    ch.score = cand[0].score;\n    ch.path = build_path(st.pos[num], ch.target, bfs.par);\n    return ch;\n}\n\nlong long eval_cost(const State& st, int num, bool topDown, int depth, int usedOps) {\n    if (depth <= 0 || num < 0 || num >= V) return 0;\n\n    auto w = make_weights(st, num, topDown);\n    BFSRes bfs = bfs_from(st, st.pos[num], w, topDown);\n    auto cand = build_candidates(st, bfs, topDown, SUB_CAND, false);\n\n    int next = topDown ? num + 1 : num - 1;\n    long long best = (1LL << 60);\n\n    auto try_candidate = [&](const Candidate& c) {\n        if (usedOps + c.len > LIMIT) return;\n        vector<int> path = build_path(st.pos[num], c.target, bfs.par);\n\n        State s1 = st;\n        apply_path(s1, path, nullptr);\n        fix_cell(s1, c.target, topDown);\n\n        long long tail = 0;\n        if (depth > 1 && 0 <= next && next < V) {\n            tail = eval_cost(s1, next, topDown, depth - 1, usedOps + c.len);\n        }\n        if (tail >= (1LL << 60)) return;\n\n        best = min(best, (long long)c.len + tail);\n    };\n\n    for (const auto& c : cand) try_candidate(c);\n\n    if (best >= (1LL << 60)) {\n        Choice g = greedy_choice(st, num, topDown);\n        if (g.target != -1 && usedOps + g.len <= LIMIT) {\n            State s1 = st;\n            apply_path(s1, g.path, nullptr);\n            fix_cell(s1, g.target, topDown);\n\n            long long tail = 0;\n            if (depth > 1 && 0 <= next && next < V) {\n                tail = eval_cost(s1, next, topDown, depth - 1, usedOps + g.len);\n            }\n            if (tail < (1LL << 60)) best = (long long)g.len + tail;\n        }\n    }\n\n    return best;\n}\n\nChoice choose_best_move_beam(const State& st, int num, bool topDown, int usedOps) {\n    Choice best;\n    auto w = make_weights(st, num, topDown);\n    BFSRes bfs = bfs_from(st, st.pos[num], w, topDown);\n    auto cand = build_candidates(st, bfs, topDown, ROOT_CAND, true);\n\n    int next = topDown ? num + 1 : num - 1;\n    long long bestTotal = (1LL << 60);\n    long long bestLocal = (1LL << 60);\n    int bestLen = INF;\n    int bestTarget = -1;\n    vector<int> bestPath;\n\n    for (const auto& c : cand) {\n        if (usedOps + c.len > LIMIT) continue;\n\n        vector<int> path = build_path(st.pos[num], c.target, bfs.par);\n        State s1 = st;\n        apply_path(s1, path, nullptr);\n        fix_cell(s1, c.target, topDown);\n\n        long long tail = 0;\n        if (BEAM_DEPTH > 1 && 0 <= next && next < V) {\n            tail = eval_cost(s1, next, topDown, BEAM_DEPTH - 1, usedOps + c.len);\n        }\n        if (tail >= (1LL << 60)) continue;\n\n        long long total = (long long)c.len + tail;\n        if (total < bestTotal ||\n            (total == bestTotal && (c.score < bestLocal ||\n             (c.score == bestLocal && (c.len < bestLen ||\n              (c.len == bestLen && c.target < bestTarget)))))) {\n            bestTotal = total;\n            bestLocal = c.score;\n            bestLen = c.len;\n            bestTarget = c.target;\n            bestPath = move(path);\n        }\n    }\n\n    if (bestTarget == -1) return greedy_choice(st, num, topDown);\n\n    best.target = bestTarget;\n    best.len = bestLen;\n    best.score = bestLocal;\n    best.path = move(bestPath);\n    return best;\n}\n\nResult run_solver(const array<int, V>& initBoard, bool topDown, bool useBeam) {\n    State st;\n    for (int i = 0; i < V; ++i) {\n        st.fixed[i] = 0;\n        st.avail[i] = 0;\n        st.parentCnt[i] = 0;\n        st.childCnt[i] = 0;\n    }\n\n    for (int i = 0; i < V; ++i) {\n        st.board[i] = initBoard[i];\n        st.pos[initBoard[i]] = i;\n    }\n\n    if (topDown) {\n        st.avail[id(0, 0)] = 1;\n    } else {\n        for (int y = 0; y < N; ++y) {\n            st.avail[id(N - 1, y)] = 1;\n        }\n    }\n\n    vector<Move> ops;\n    ops.reserve(LIMIT);\n\n    int done = 0;\n    for (; done < V; ++done) {\n        if ((int)ops.size() >= LIMIT) break;\n\n        int num = topDown ? done : (V - 1 - done);\n        Choice ch = useBeam ? choose_best_move_beam(st, num, topDown, (int)ops.size())\n                            : greedy_choice(st, num, topDown);\n\n        if (ch.target == -1) break;\n        if ((int)ops.size() + ch.len > LIMIT) {\n            if (useBeam) ch = greedy_choice(st, num, topDown);\n            if (ch.target == -1 || (int)ops.size() + ch.len > LIMIT) break;\n        }\n\n        apply_path(st, ch.path, &ops);\n        fix_cell(st, ch.target, topDown);\n    }\n\n    Result res;\n    res.ops = move(ops);\n    res.complete = (done == V);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Build graph and structural information.\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = id(x, y);\n            coord[u] = {x, y};\n            centerDist[u] = abs(2 * y - x);\n\n            if (x > 0) {\n                if (y > 0) parentsList[u].push_back(id(x - 1, y - 1));\n                if (y < x) parentsList[u].push_back(id(x - 1, y));\n            }\n            if (x + 1 < N) {\n                childrenList[u].push_back(id(x + 1, y));\n                childrenList[u].push_back(id(x + 1, y + 1));\n            }\n\n            if (y > 0) {\n                int v = id(x, y - 1);\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n            if (x + 1 < N) {\n                int d1 = id(x + 1, y);\n                int d2 = id(x + 1, y + 1);\n                adj[u].push_back(d1);\n                adj[d1].push_back(u);\n                adj[u].push_back(d2);\n                adj[d2].push_back(u);\n            }\n        }\n    }\n\n    for (int i = 0; i < V; ++i) {\n        needParents[i] = (int)parentsList[i].size();\n        needChildren[i] = (int)childrenList[i].size();\n    }\n\n    array<int, V> initBoard{};\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            initBoard[id(x, y)] = v;\n        }\n    }\n\n    // Safe greedy baselines.\n    Result rTopGreedy = run_solver(initBoard, true, false);\n    Result rBottomGreedy = run_solver(initBoard, false, false);\n\n    // Beam-search variants.\n    Result rTopBeam = run_solver(initBoard, true, true);\n    Result rBottomBeam = run_solver(initBoard, false, true);\n\n    Result best = rTopGreedy;\n\n    auto consider = [&](const Result& r) {\n        if (r.complete && (!best.complete || r.ops.size() < best.ops.size())) {\n            best = r;\n        }\n    };\n\n    consider(rBottomGreedy);\n    consider(rTopBeam);\n    consider(rBottomBeam);\n\n    // If somehow no complete solution was found, keep the top greedy output.\n    if (!best.complete) best = rTopGreedy;\n\n    cout << best.ops.size() << '\\n';\n    for (const auto& mv : best.ops) {\n        cout << mv.x1 << ' ' << mv.y1 << ' ' << mv.x2 << ' ' << mv.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int INF = 1e9;\n\nstruct TreeMeta {\n    vector<vector<int>> child;\n    vector<int> parent;\n    vector<int> depth;\n    vector<int> subtree;\n    vector<int> childCnt;\n    // rank[0] : depth-based order\n    // rank[1] : preorder-based order\n    // rank[2] : build/BFS-like order\n    vector<vector<int>> rank;\n};\n\nint D, N, M;\nvector<vector<int>> cellId;\nvector<int> cellR, cellC;\nvector<int> gridDist;\nvector<int> nextDeg;\nint er, ec;\n\nconst int dr[4] = {1, 0, 0, -1};\nconst int dc[4] = {0, -1, 1, 0};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nTreeMeta buildTreeA(const vector<vector<bool>>& obstacle) {\n    TreeMeta tr;\n    tr.child.assign(M + 1, {});\n    tr.parent.assign(M + 1, 0);\n    tr.depth.assign(M + 1, 0);\n    tr.subtree.assign(M + 1, 0);\n    tr.childCnt.assign(M + 1, 0);\n    tr.rank.assign(3, vector<int>(M + 1, -1));\n\n    vector<vector<bool>> vis(D, vector<bool>(D, false));\n    queue<int> q;\n\n    vis[er][ec] = true;\n    int bfsOrder = 0;\n\n    // Tree A: plain BFS from entrance, with fixed direction order.\n    for (int k = 0; k < 4; ++k) {\n        int nr = er + dr[k], nc = ec + dc[k];\n        if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n        int v = cellId[nr][nc];\n        if (v == -1) continue;\n        vis[nr][nc] = true;\n        tr.parent[v] = 0;\n        tr.depth[v] = 1;\n        tr.child[0].push_back(v);\n        tr.rank[2][v] = bfsOrder++;\n        q.push(v);\n    }\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        int r = cellR[u], c = cellC[u];\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc] || vis[nr][nc]) continue;\n            int v = cellId[nr][nc];\n            if (v == -1) continue;\n            vis[nr][nc] = true;\n            tr.parent[v] = u;\n            tr.depth[v] = tr.depth[u] + 1;\n            tr.child[u].push_back(v);\n            tr.rank[2][v] = bfsOrder++;\n            q.push(v);\n        }\n    }\n\n    return tr;\n}\n\nTreeMeta buildTreeB(const vector<vector<bool>>& obstacle) {\n    TreeMeta tr;\n    tr.child.assign(M + 1, {});\n    tr.parent.assign(M + 1, 0);\n    tr.depth.assign(M + 1, 0);\n    tr.subtree.assign(M + 1, 0);\n    tr.childCnt.assign(M + 1, 0);\n    tr.rank.assign(3, vector<int>(M + 1, -1));\n\n    vector<int> ord;\n    ord.reserve(M);\n    for (int id = 1; id <= M; ++id) ord.push_back(id);\n\n    // Process shallow cells first, and among them prefer cells with many forward neighbors.\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (gridDist[a] != gridDist[b]) return gridDist[a] < gridDist[b];\n        if (nextDeg[a] != nextDeg[b]) return nextDeg[a] > nextDeg[b];\n        if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n        return cellC[a] < cellC[b];\n    });\n\n    int buildOrder = 0;\n    for (int v : ord) {\n        int d = gridDist[v];\n        if (d == 1) {\n            tr.parent[v] = 0;\n            tr.depth[v] = 1;\n            tr.child[0].push_back(v);\n            tr.rank[2][v] = buildOrder++;\n            continue;\n        }\n\n        int best = -1;\n        int bestScore = INF;\n        int r = cellR[v], c = cellC[v];\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n            if (gridDist[cellId[nr][nc]] != d - 1) continue;\n            int p = cellId[nr][nc];\n            if (p == -1) continue;\n\n            // Prefer parents that currently have fewer children, and among them\n            // those with larger future branching potential.\n            int score = tr.childCnt[p] * 100 - nextDeg[p];\n            if (score < bestScore ||\n                (score == bestScore &&\n                 (cellR[p] < cellR[best] ||\n                  (cellR[p] == cellR[best] && cellC[p] < cellC[best])))) {\n                bestScore = score;\n                best = p;\n            }\n        }\n\n        if (best == -1) {\n            // Fallback should never happen under valid input.\n            best = 0;\n        }\n\n        tr.parent[v] = best;\n        tr.depth[v] = tr.depth[best] + 1;\n        tr.child[best].push_back(v);\n        ++tr.childCnt[best];\n        tr.rank[2][v] = buildOrder++;\n    }\n\n    return tr;\n}\n\nvoid computeMeta(TreeMeta& tr) {\n    // subtree sizes\n    function<int(int)> dfsSub = [&](int u) -> int {\n        int s = 1;\n        for (int v : tr.child[u]) s += dfsSub(v);\n        tr.subtree[u] = s;\n        return s;\n    };\n    dfsSub(0);\n\n    // rank[0] : depth order\n    vector<int> nodes;\n    nodes.reserve(M);\n    for (int i = 1; i <= M; ++i) nodes.push_back(i);\n    sort(nodes.begin(), nodes.end(), [&](int a, int b) {\n        if (tr.depth[a] != tr.depth[b]) return tr.depth[a] < tr.depth[b];\n        if (tr.subtree[a] != tr.subtree[b]) return tr.subtree[a] > tr.subtree[b];\n        if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n        return cellC[a] < cellC[b];\n    });\n    for (int i = 0; i < M; ++i) tr.rank[0][nodes[i]] = i;\n\n    // rank[1] : preorder with larger subtrees first\n    int cnt = 0;\n    function<void(int)> dfsPre = [&](int u) {\n        if (u != 0) tr.rank[1][u] = cnt++;\n        vector<int> ch = tr.child[u];\n        sort(ch.begin(), ch.end(), [&](int a, int b) {\n            if (tr.subtree[a] != tr.subtree[b]) return tr.subtree[a] > tr.subtree[b];\n            if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n            return cellC[a] < cellC[b];\n        });\n        for (int v : ch) dfsPre(v);\n    };\n    dfsPre(0);\n\n    // childCnt\n    for (int i = 0; i <= M; ++i) tr.childCnt[i] = (int)tr.child[i].size();\n}\n\nint chainLen(const TreeMeta& tr, const vector<int>& remChild, int u) {\n    int cnt = 0;\n    int x = u;\n    while (tr.parent[x] != 0 && remChild[tr.parent[x]] == 1) {\n        ++cnt;\n        x = tr.parent[x];\n    }\n    return cnt;\n}\n\nint pickLeaf(const TreeMeta& tr, const vector<int>& remChild, const vector<char>& used,\n             int t, int rankKind, int gamma) {\n    int best = -1;\n    long long bestScore = (1LL << 60);\n    long long bestEff = (1LL << 60);\n    int bestChain = -1;\n\n    for (int u = 1; u <= M; ++u) {\n        if (used[u] || remChild[u] != 0) continue;\n        int ch = chainLen(tr, remChild, u);\n        long long eff = tr.rank[rankKind][u] + 1LL * gamma * ch;\n        long long score = llabs(eff - t);\n\n        if (best == -1 ||\n            score < bestScore ||\n            (score == bestScore && eff < bestEff) ||\n            (score == bestScore && eff == bestEff && ch > bestChain) ||\n            (score == bestScore && eff == bestEff && ch == bestChain &&\n             (cellR[u] < cellR[best] || (cellR[u] == cellR[best] && cellC[u] < cellC[best])))) {\n            best = u;\n            bestScore = score;\n            bestEff = eff;\n            bestChain = ch;\n        }\n    }\n    return best;\n}\n\nlong long simulate(const TreeMeta& tr, const vector<int>& perm, int rankKind, int gamma) {\n    vector<int> remChild = tr.childCnt;\n    vector<char> used(M + 1, 0);\n    vector<int> assigned(M + 1, -1);\n\n    for (int t : perm) {\n        int u = pickLeaf(tr, remChild, used, t, rankKind, gamma);\n        used[u] = 1;\n        assigned[u] = t;\n        int p = tr.parent[u];\n        if (p != 0) --remChild[p];\n    }\n\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int v : tr.child[0]) pq.push({assigned[v], v});\n\n    vector<int> seq;\n    seq.reserve(M);\n    while (!pq.empty()) {\n        auto [lab, u] = pq.top();\n        pq.pop();\n        seq.push_back(lab);\n        for (int v : tr.child[u]) pq.push({assigned[v], v});\n    }\n\n    long long 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 Choice {\n    int treeId = 0;\n    int rankKind = 0;\n    int gamma = 0;\n    long long score = (1LL << 60);\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    er = 0;\n    ec = (D - 1) / 2;\n\n    auto freeCell = [&](int r, int c) {\n        return inside(r, c) && !obstacle[r][c] && !(r == er && c == ec);\n    };\n\n    // Grid distances from entrance\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n    dist[er][ec] = 0;\n    q.push({er, ec});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc] || dist[nr][nc] != -1) continue;\n            dist[nr][nc] = dist[r][c] + 1;\n            q.push({nr, nc});\n        }\n    }\n\n    // Build cell compression\n    M = 0;\n    cellId.assign(D, vector<int>(D, -1));\n    cellR.assign(1, 0);\n    cellC.assign(1, 0);\n    gridDist.assign(1, 0);\n    nextDeg.assign(1, 0);\n\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (freeCell(r, c)) {\n                int id = ++M;\n                cellId[r][c] = id;\n                cellR.push_back(r);\n                cellC.push_back(c);\n                gridDist.push_back(dist[r][c]);\n            }\n        }\n    }\n\n    nextDeg.assign(M + 1, 0);\n    for (int id = 1; id <= M; ++id) {\n        int r = cellR[id], c = cellC[id];\n        int d = gridDist[id];\n        int cnt = 0;\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n            int nid = cellId[nr][nc];\n            if (nid != -1 && gridDist[nid] == d + 1) ++cnt;\n        }\n        nextDeg[id] = cnt;\n    }\n\n    // Build candidate trees\n    vector<TreeMeta> trees;\n    trees.push_back(buildTreeA(obstacle));\n    trees.push_back(buildTreeB(obstacle));\n\n    for (auto& tr : trees) computeMeta(tr);\n\n    // Monte Carlo selection of heuristic parameters\n    vector<vector<int>> samples;\n    {\n        uint64_t seed = 88172645463393265ULL;\n        seed ^= (uint64_t)D * 1000003ULL + (uint64_t)N * 9176ULL;\n        for (int i = 0; i < min(M, 12); ++i) seed ^= (uint64_t)(cellR[i % max(1, M)] + 1) * 1315423911ULL + (uint64_t)(cellC[i % max(1, M)] + 7);\n\n        mt19937_64 rng(seed);\n        int S = 24;\n        samples.reserve(S);\n        vector<int> base(M);\n        iota(base.begin(), base.end(), 0);\n        for (int s = 0; s < S; ++s) {\n            auto perm = base;\n            shuffle(perm.begin(), perm.end(), rng);\n            samples.push_back(move(perm));\n        }\n    }\n\n    vector<int> gammaCandidates = {-2, 0, 1, 2, 4};\n    Choice best;\n\n    for (int ti = 0; ti < (int)trees.size(); ++ti) {\n        for (int rk = 0; rk < 3; ++rk) {\n            for (int gamma : gammaCandidates) {\n                long long sum = 0;\n                for (auto& perm : samples) {\n                    sum += simulate(trees[ti], perm, rk, gamma);\n                }\n                if (sum < best.score ||\n                    (sum == best.score && ti < best.treeId) ||\n                    (sum == best.score && ti == best.treeId && rk < best.rankKind) ||\n                    (sum == best.score && ti == best.treeId && rk == best.rankKind && gamma < best.gamma)) {\n                    best.treeId = ti;\n                    best.rankKind = rk;\n                    best.gamma = gamma;\n                    best.score = sum;\n                }\n            }\n        }\n    }\n\n    TreeMeta& tr = trees[best.treeId];\n    int rankKind = best.rankKind;\n    int gamma = best.gamma;\n\n    // Online placement\n    vector<int> remChild = tr.childCnt;\n    vector<char> used(M + 1, 0);\n    vector<int> assigned(M + 1, -1);\n\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        int u = pickLeaf(tr, remChild, used, t, rankKind, gamma);\n        used[u] = 1;\n        assigned[u] = t;\n        int p = tr.parent[u];\n        if (p != 0) --remChild[p];\n\n        cout << cellR[u] << ' ' << cellC[u] << '\\n' << flush;\n    }\n\n    // Final removal order: smallest available label first on the rooted tree\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int v : tr.child[0]) pq.push({assigned[v], v});\n\n    vector<int> order;\n    order.reserve(M);\n\n    while (!pq.empty()) {\n        auto [lab, u] = pq.top();\n        pq.pop();\n        order.push_back(u);\n        for (int v : tr.child[u]) pq.push({assigned[v], v});\n    }\n\n    for (int u : order) {\n        cout << cellR[u] << ' ' << cellC[u] << '\\n';\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXM = 100;\nstatic const int MAXV = MAXN * MAXN;\n\nstruct Edge {\n    int u, v;\n};\n\nstruct RemInfo {\n    bool ok = false;\n    int same = 0;      // same-color neighbors\n    int loss0 = 0;     // sides that would become 0/outside after removal\n    int adjTypes = 0;  // distinct neighboring colors\n};\n\nstruct TrialWeights {\n    long long cntW;\n    long long touchW;\n    long long lossW;\n    long long sameW;\n    long long adjW;\n    long long distW;\n    long long coreW;   // bonus for non-core cells, penalty for core cells\n};\n\nint n, m, N;\nvector<int> initBoard, boardCur;\nint nb[MAXV][4];\nint distToBorder[MAXV];\nint sameDegOrig[MAXV];\nint adjColorCountOrig[MAXV];\nbool origB[MAXM + 1];\nbool origAdj[MAXM + 1][MAXM + 1];\nbool frozenCell[MAXV];\nbool borderTouchCell[MAXV];\nbool isArt[MAXV];\nvector<int> colorCells[MAXM + 1];\nvector<int> candidateCells;\nvector<Edge> pairEdges[MAXM + 1][MAXM + 1];\n\nint curCnt[MAXM + 1];\nint curTouchSides[MAXM + 1];\nint curPairCnt[MAXM + 1][MAXM + 1];\n\nint artDisc[MAXV], artLow[MAXV], artVis[MAXV], artTimer;\n\ninline int id(int i, int j) { return i * n + j; }\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\nint countZeros(const vector<int>& b) {\n    int z = 0;\n    for (int x : b) if (x == 0) ++z;\n    return z;\n}\n\nlong long coreUtility(int idx, int variant, uint64_t seed) {\n    long long u = 0;\n    u += 1000LL * adjColorCountOrig[idx];\n    u += 100LL * sameDegOrig[idx];\n    u += borderTouchCell[idx] ? 500LL : 0LL;\n    u -= 5LL * distToBorder[idx];\n    if (variant == 1) u += 100LL * (4 - sameDegOrig[idx]);\n    u += (long long)(splitmix64(seed + 1234567ULL * idx + 998244353ULL * (uint64_t)variant) & 63ULL);\n    return u;\n}\n\nvoid recomputeArtColor(int c) {\n    for (int idx : colorCells[c]) {\n        isArt[idx] = false;\n        artVis[idx] = 0;\n    }\n    if (curCnt[c] <= 1) return;\n\n    int root = -1;\n    for (int idx : colorCells[c]) {\n        if (boardCur[idx] == c) {\n            root = idx;\n            break;\n        }\n    }\n    if (root == -1) return;\n\n    artTimer = 0;\n    function<void(int,int)> dfs = [&](int u, int p) {\n        artVis[u] = 1;\n        artDisc[u] = artLow[u] = ++artTimer;\n        int child = 0;\n\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[u][d];\n            if (v == -1 || v == p) continue;\n            if (boardCur[v] != c) continue;\n            if (!artVis[v]) {\n                ++child;\n                dfs(v, u);\n                artLow[u] = min(artLow[u], artLow[v]);\n                if (p != -1 && artLow[v] >= artDisc[u]) isArt[u] = true;\n            } else {\n                artLow[u] = min(artLow[u], artDisc[v]);\n            }\n        }\n\n        if (p == -1 && child > 1) isArt[u] = true;\n    };\n\n    dfs(root, -1);\n}\n\nvoid initState(const vector<int>& startBoard) {\n    boardCur = startBoard;\n    memset(curCnt, 0, sizeof(curCnt));\n    memset(curTouchSides, 0, sizeof(curTouchSides));\n    memset(curPairCnt, 0, sizeof(curPairCnt));\n    memset(isArt, 0, sizeof(isArt));\n    memset(artVis, 0, sizeof(artVis));\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c > 0) curCnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c == 0) continue;\n\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1 || boardCur[v] == 0) curTouchSides[c]++;\n        }\n\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = boardCur[right];\n            if (d > 0 && d != c && origB[d]) {\n                curPairCnt[c][d]++;\n                curPairCnt[d][c]++;\n            }\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = boardCur[down];\n            if (d > 0 && d != c && origB[d]) {\n                curPairCnt[c][d]++;\n                curPairCnt[d][c]++;\n            }\n        }\n    }\n\n    for (int c = 1; c <= m; ++c) {\n        if (origB[c]) recomputeArtColor(c);\n    }\n}\n\nRemInfo analyzeCell(int idx) {\n    RemInfo r;\n    int c = boardCur[idx];\n    if (c == 0) return r;\n    if (!origB[c]) return r;\n    if (frozenCell[idx]) return r;\n    if (isArt[idx]) return r;\n    if (curCnt[c] <= 1) return r;\n\n    int same = 0, loss0 = 0, adjTypes = 0;\n    int loss[MAXM + 1];\n    memset(loss, 0, sizeof(loss));\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            ++loss0;\n        } else {\n            int t = boardCur[v];\n            if (t == c) {\n                ++same;\n            } else {\n                if (!origB[t]) return r; // would expose a non-border-touching color to 0\n                if (loss[t] == 0) ++adjTypes;\n                ++loss[t];\n            }\n        }\n    }\n\n    if (loss0 == 0) return r;\n    if (curTouchSides[c] - loss0 + same <= 0) return r;\n\n    for (int t = 1; t <= m; ++t) {\n        if (loss[t] == 0) continue;\n        if (curPairCnt[c][t] <= loss[t]) return r; // would delete the last adjacency witness\n    }\n\n    if (same > 1) {\n        int start = -1;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v != -1 && boardCur[v] == c) {\n                start = v;\n                break;\n            }\n        }\n        if (start == -1) return r;\n\n        ++artTimer;\n        vector<int> q;\n        q.reserve(curCnt[c]);\n        q.push_back(start);\n        artVis[start] = artTimer;\n        int seen = 1;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v == -1 || v == idx) continue;\n                if (boardCur[v] == c && artVis[v] != artTimer) {\n                    artVis[v] = artTimer;\n                    q.push_back(v);\n                    ++seen;\n                }\n            }\n        }\n\n        if (seen != curCnt[c] - 1) return r;\n    }\n\n    r.ok = true;\n    r.same = same;\n    r.loss0 = loss0;\n    r.adjTypes = adjTypes;\n    return r;\n}\n\nlong long scoreCell(int idx, const RemInfo& info, const TrialWeights& w, const vector<char>& core, uint64_t seed) {\n    int c = boardCur[idx];\n    long long s = 0;\n\n    s += w.cntW * curCnt[c];\n    s += w.touchW * curTouchSides[c];\n    s += w.lossW * info.loss0;\n    s -= w.sameW * info.same;\n    s -= w.adjW * info.adjTypes;\n    s -= w.distW * distToBorder[idx];\n    if (w.coreW != 0) s += (core[idx] ? -w.coreW : w.coreW);\n\n    s += (long long)(splitmix64(seed + 1234567ULL * idx + 998244353ULL) & 1023ULL);\n    return s;\n}\n\nvoid removeCell(int idx) {\n    int c = boardCur[idx];\n    boardCur[idx] = 0;\n    curCnt[c]--;\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) continue;\n        int t = boardCur[v];\n        if (t == c) continue;\n\n        if (origB[t]) curTouchSides[t]++;\n\n        if (origB[c] && origB[t]) {\n            curPairCnt[c][t]--;\n            curPairCnt[t][c]--;\n        }\n    }\n\n    recomputeArtColor(c);\n}\n\nvector<char> buildCore(int variant, uint64_t seed) {\n    vector<char> terminal(N, false), core(N, false);\n\n    vector<long long> util(N);\n    for (int i = 0; i < N; ++i) util[i] = coreUtility(i, variant, seed);\n\n    // Frozen cells are mandatory.\n    for (int idx = 0; idx < N; ++idx) {\n        if (frozenCell[idx]) terminal[idx] = core[idx] = true;\n    }\n\n    // Each border-touching color keeps at least one border cell.\n    for (int c = 1; c <= m; ++c) {\n        if (!origB[c]) continue;\n\n        bool hasBorderTerminal = false;\n        int bestIdx = -1;\n        long long bestSc = -(1LL << 60);\n\n        for (int idx : colorCells[c]) {\n            if (!borderTouchCell[idx]) continue;\n            if (terminal[idx]) hasBorderTerminal = true;\n            if (util[idx] > bestSc) {\n                bestSc = util[idx];\n                bestIdx = idx;\n            }\n        }\n\n        if (!hasBorderTerminal && bestIdx != -1) {\n            terminal[bestIdx] = core[bestIdx] = true;\n        }\n    }\n\n    // Select one witness edge for every border-touching color pair that is actually adjacent.\n    struct Task {\n        int a, b, cnt;\n    };\n    vector<Task> tasks;\n    tasks.reserve(5000);\n\n    for (int a = 1; a <= m; ++a) {\n        for (int b = a + 1; b <= m; ++b) {\n            if (origB[a] && origB[b] && origAdj[a][b] && !pairEdges[a][b].empty()) {\n                tasks.push_back({a, b, (int)pairEdges[a][b].size()});\n            }\n        }\n    }\n\n    if (variant == 0) {\n        sort(tasks.begin(), tasks.end(), [&](const Task& x, const Task& y) {\n            if (x.cnt != y.cnt) return x.cnt < y.cnt;\n            if (x.a != y.a) return x.a < y.a;\n            return x.b < y.b;\n        });\n    } else {\n        sort(tasks.begin(), tasks.end(), [&](const Task& x, const Task& y) {\n            if (x.cnt != y.cnt) return x.cnt > y.cnt;\n            if (x.a != y.a) return x.a < y.a;\n            return x.b < y.b;\n        });\n    }\n\n    for (const auto& t : tasks) {\n        bool covered = false;\n        for (const auto& e : pairEdges[t.a][t.b]) {\n            if (terminal[e.u] && terminal[e.v]) {\n                covered = true;\n                break;\n            }\n        }\n        if (covered) continue;\n\n        long long bestSc = -(1LL << 60);\n        Edge bestE{-1, -1};\n\n        for (const auto& e : pairEdges[t.a][t.b]) {\n            int gu = terminal[e.u] ? 1 : 0;\n            int gv = terminal[e.v] ? 1 : 0;\n            long long sc = 0;\n            sc += 100000LL * (gu + gv);\n            sc -= 50000LL * ((terminal[e.u] ? 0 : 1) + (terminal[e.v] ? 0 : 1));\n            sc += util[e.u] + util[e.v];\n            sc += (long long)(splitmix64(seed + 911382323ULL * e.u + 972663749ULL * e.v + 1000003ULL * t.a + 10007ULL * t.b) & 255ULL);\n\n            if (sc > bestSc) {\n                bestSc = sc;\n                bestE = e;\n            }\n        }\n\n        if (bestE.u != -1) {\n            terminal[bestE.u] = core[bestE.u] = true;\n            terminal[bestE.v] = core[bestE.v] = true;\n        }\n    }\n\n    // Connect terminals inside each color by shortest paths and prune non-terminal leaves.\n    vector<int> vis(N, 0), par(N, -1);\n    int stamp = 0;\n\n    for (int c = 1; c <= m; ++c) {\n        if (!origB[c]) continue;\n\n        vector<int> terms;\n        terms.reserve(colorCells[c].size());\n        for (int idx : colorCells[c]) {\n            if (terminal[idx]) terms.push_back(idx);\n        }\n\n        if (terms.empty()) continue;\n\n        auto termScore = [&](int idx) {\n            long long s = util[idx];\n            if (borderTouchCell[idx]) s += 5000;\n            return s;\n        };\n\n        int root = terms[0];\n        long long bestRoot = termScore(root);\n        for (int idx : terms) {\n            long long s = termScore(idx);\n            if (s > bestRoot) {\n                bestRoot = s;\n                root = idx;\n            }\n        }\n        core[root] = true;\n\n        // Greedily attach every other terminal to the current core.\n        for (int t : terms) {\n            if (core[t]) continue;\n\n            ++stamp;\n            vector<int> q;\n            q.reserve(colorCells[c].size());\n            q.push_back(t);\n            vis[t] = stamp;\n            par[t] = -1;\n\n            int meet = -1;\n            for (size_t head = 0; head < q.size(); ++head) {\n                int u = q[head];\n                if (core[u] && u != t) {\n                    meet = u;\n                    break;\n                }\n                for (int d = 0; d < 4; ++d) {\n                    int v = nb[u][d];\n                    if (v == -1 || initBoard[v] != c || vis[v] == stamp) continue;\n                    vis[v] = stamp;\n                    par[v] = u;\n                    q.push_back(v);\n                }\n            }\n\n            if (meet == -1) continue;\n\n            for (int x = meet; x != -1 && !core[x]; x = par[x]) {\n                core[x] = true;\n            }\n            core[t] = true;\n        }\n\n        // Prune non-terminal leaves from the connected core.\n        vector<int> deg(N, 0);\n        queue<int> q;\n        for (int idx : colorCells[c]) {\n            if (!core[idx]) continue;\n            int d = 0;\n            for (int k = 0; k < 4; ++k) {\n                int v = nb[idx][k];\n                if (v != -1 && initBoard[v] == c && core[v]) d++;\n            }\n            deg[idx] = d;\n        }\n\n        for (int idx : colorCells[c]) {\n            if (core[idx] && !terminal[idx] && deg[idx] <= 1) q.push(idx);\n        }\n\n        while (!q.empty()) {\n            int x = q.front();\n            q.pop();\n            if (!core[x] || terminal[x] || deg[x] > 1) continue;\n\n            core[x] = false;\n            for (int k = 0; k < 4; ++k) {\n                int v = nb[x][k];\n                if (v == -1 || initBoard[v] != c || !core[v]) continue;\n                deg[v]--;\n                if (!terminal[v] && deg[v] <= 1) q.push(v);\n            }\n        }\n    }\n\n    return core;\n}\n\nvector<int> runTrial(const vector<int>& startBoard, const TrialWeights& w, uint64_t seed, const vector<char>& core) {\n    initState(startBoard);\n\n    while (true) {\n        int bestIdx = -1;\n        long long bestScore = -(1LL << 60);\n        RemInfo bestInfo;\n\n        for (int idx : candidateCells) {\n            if (boardCur[idx] == 0) continue;\n            RemInfo info = analyzeCell(idx);\n            if (!info.ok) continue;\n            long long sc = scoreCell(idx, info, w, core, seed);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestIdx = idx;\n                bestInfo = info;\n            }\n        }\n\n        if (bestIdx == -1) break;\n        removeCell(bestIdx);\n    }\n\n    return boardCur;\n}\n\nbool validate(const vector<int>& b) {\n    bool outAdj[MAXM + 1][MAXM + 1];\n    memset(outAdj, 0, sizeof(outAdj));\n    bool outTouch0[MAXM + 1];\n    memset(outTouch0, 0, sizeof(outTouch0));\n\n    vector<int> cnt(MAXM + 1, 0);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c > 0) cnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c == 0) continue;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1 || b[v] == 0) {\n                outTouch0[c] = true;\n            } else if (b[v] != c) {\n                int t = b[v];\n                outAdj[c][t] = outAdj[t][c] = true;\n            }\n        }\n    }\n\n    for (int c = 1; c <= m; ++c) {\n        if (outTouch0[c] != origB[c]) return false;\n        for (int d = 1; d <= m; ++d) {\n            if (outAdj[c][d] != origAdj[c][d]) return false;\n        }\n    }\n\n    // Connectivity of each color 1..m\n    vector<int> seen(N, 0);\n    int stamp = 1;\n    vector<int> q;\n    q.reserve(N);\n\n    for (int c = 1; c <= m; ++c) {\n        int start = -1;\n        for (int idx = 0; idx < N; ++idx) {\n            if (b[idx] == c) {\n                start = idx;\n                break;\n            }\n        }\n        if (start == -1) return false;\n\n        ++stamp;\n        q.clear();\n        q.push_back(start);\n        seen[start] = stamp;\n        int got = 1;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == c && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                    ++got;\n                }\n            }\n        }\n\n        if (got != cnt[c]) return false;\n    }\n\n    // 0-color connectivity through outside.\n    int zeroCnt = 0;\n    for (int idx = 0; idx < N; ++idx) if (b[idx] == 0) zeroCnt++;\n    if (zeroCnt > 0) {\n        ++stamp;\n        q.clear();\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    int idx = id(i, j);\n                    if (b[idx] == 0 && seen[idx] != stamp) {\n                        seen[idx] = stamp;\n                        q.push_back(idx);\n                    }\n                }\n            }\n        }\n        if (q.empty()) return false;\n\n        int got = 0;\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            ++got;\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == 0 && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                }\n            }\n        }\n        if (got != zeroCnt) return false;\n    }\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    N = n * n;\n    initBoard.assign(N, 0);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c;\n            cin >> c;\n            initBoard[id(i, j)] = c;\n            colorCells[c].push_back(id(i, j));\n        }\n    }\n\n    // Neighbors and geometric features.\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = id(i, j);\n            nb[idx][0] = (i == 0 ? -1 : id(i - 1, j));\n            nb[idx][1] = (i + 1 == n ? -1 : id(i + 1, j));\n            nb[idx][2] = (j == 0 ? -1 : id(i, j - 1));\n            nb[idx][3] = (j + 1 == n ? -1 : id(i, j + 1));\n            distToBorder[idx] = min(min(i, j), min(n - 1 - i, n - 1 - j));\n            borderTouchCell[idx] = (i == 0 || i == n - 1 || j == 0 || j == n - 1);\n        }\n    }\n\n    // Original outside-touch colors.\n    memset(origB, 0, sizeof(origB));\n    for (int i = 0; i < n; ++i) {\n        origB[initBoard[id(i, 0)]] = true;\n        origB[initBoard[id(i, n - 1)]] = true;\n    }\n    for (int j = 0; j < n; ++j) {\n        origB[initBoard[id(0, j)]] = true;\n        origB[initBoard[id(n - 1, j)]] = true;\n    }\n\n    // Original adjacency.\n    memset(origAdj, 0, sizeof(origAdj));\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = initBoard[right];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = initBoard[down];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n    }\n\n    // Per-cell local statistics and frozen cells.\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int same = 0;\n        bool seenDiff[MAXM + 1] = {};\n        int diffCnt = 0;\n        bool frozen = false;\n\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1) continue;\n            int t = initBoard[v];\n            if (t == c) {\n                ++same;\n            } else {\n                if (!seenDiff[t]) {\n                    seenDiff[t] = true;\n                    ++diffCnt;\n                }\n                if (t > 0 && !origB[t]) frozen = true;\n            }\n        }\n\n        sameDegOrig[idx] = same;\n        adjColorCountOrig[idx] = diffCnt;\n        frozenCell[idx] = frozen;\n    }\n\n    // Build witness edge lists.\n    for (int idx = 0; idx < N; ++idx) {\n        for (int dir : {1, 3}) { // down, right\n            int v = nb[idx][dir];\n            if (v == -1) continue;\n            int a = initBoard[idx];\n            int b = initBoard[v];\n            if (a == b) continue;\n            if (a > b) swap(a, b), pairEdges[a][b].push_back({v, idx});\n            else pairEdges[a][b].push_back({idx, v});\n        }\n    }\n\n    candidateCells.reserve(N);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        if (c >= 1 && c <= m && origB[c] && !frozenCell[idx]) candidateCells.push_back(idx);\n    }\n\n    vector<int> bestBoard = initBoard;\n    int bestZeros = 0;\n\n    // No-core greedy trials.\n    vector<char> emptyCore(N, false);\n    vector<pair<TrialWeights, uint64_t>> plainTrials = {\n        {{300, 800, 500, 1200, 300, 10, 0}, 123456789ULL},\n        {{700, 300, 300, 1500, 200, 5, 0},   987654321ULL}\n    };\n\n    for (auto [w, seed] : plainTrials) {\n        vector<int> cand = runTrial(initBoard, w, seed, emptyCore);\n        if (validate(cand)) {\n            int z = countZeros(cand);\n            if (z > bestZeros) {\n                bestZeros = z;\n                bestBoard = std::move(cand);\n            }\n        }\n    }\n\n    // Core-guided trials.\n    {\n        vector<char> core0 = buildCore(0, 19260817ULL);\n        TrialWeights w{100, 1200, 800, 900, 500, 20, 12000};\n        vector<int> cand = runTrial(initBoard, w, 1145141919ULL, core0);\n        if (validate(cand)) {\n            int z = countZeros(cand);\n            if (z > bestZeros) {\n                bestZeros = z;\n                bestBoard = std::move(cand);\n            }\n        }\n    }\n\n    {\n        vector<char> core1 = buildCore(1, 998244353ULL);\n        TrialWeights w{700, 300, 300, 1500, 200, 5, 16000};\n        vector<int> cand = runTrial(initBoard, w, 20240329ULL, core1);\n        if (validate(cand)) {\n            int z = countZeros(cand);\n            if (z > bestZeros) {\n                bestZeros = z;\n                bestBoard = std::move(cand);\n            }\n        }\n    }\n\n    // Extra improvement pass from the current best board with a core-guided style.\n    {\n        vector<char> core2 = buildCore(0, 1145141ULL);\n        TrialWeights w{200, 1000, 1000, 800, 400, 15, 10000};\n        vector<int> cand = runTrial(bestBoard, w, 424242ULL, core2);\n        if (validate(cand)) {\n            int z = countZeros(cand);\n            if (z > bestZeros) {\n                bestZeros = z;\n                bestBoard = std::move(cand);\n            }\n        }\n    }\n\n    if (!validate(bestBoard)) bestBoard = initBoard;\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << bestBoard[id(i, j)];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ld = long double;\n\nstruct Bucket {\n    vector<int> items;\n    int l = 0, r = -1;      // descending rank interval [l, r]\n    bool sameGroup = false; // all items in this bucket are known equal\n    bool exhausted = false;  // no more useful queries expected here\n    ld value = 0.0L;        // estimated total weight of this interval\n};\n\nstruct PartResult {\n    vector<int> ans;\n    ld score = numeric_limits<ld>::infinity();\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    const ld MU = 100000.0L;\n    const ld CAP = MU * (ld)N / (ld)D;\n\n    mt19937_64 rng(\n        0x9e3779b97f4a7c15ULL ^\n        (uint64_t)N * 1000003ULL ^\n        (uint64_t)D * 10007ULL ^\n        (uint64_t)Q * 10000019ULL\n    );\n\n    auto rand_int = [&](int l, int r) -> int {\n        uniform_int_distribution<int> dist(l, r);\n        return dist(rng);\n    };\n\n    // Rank-based expected weights for descending rank r = 0..N-1.\n    vector<ld> rankExp(N, 0.0L);\n    vector<ld> H(N + 1, 0.0L);\n    for (int i = 1; i <= N; ++i) H[i] = H[i - 1] + 1.0L / (ld)i;\n\n    ld capProb = 1.0L - expl(-CAP / MU);\n    for (int r = 0; r < N; ++r) {\n        ld p = ((ld)N - (ld)r - 0.5L) / (ld)N;\n        if (p < 1e-18L) p = 1e-18L;\n        if (p > 1.0L - 1e-18L) p = 1.0L - 1e-18L;\n\n        ld harm = MU * (H[N] - H[r]);\n        ld quant = -MU * log1pl(-capProb * p);\n\n        ld v = 0.65L * harm + 0.35L * quant;\n        if (v < 1.0L) v = 1.0L;\n        if (v > CAP) v = CAP;\n        rankExp[r] = v;\n    }\n\n    vector<ld> pref(N + 1, 0.0L);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + rankExp[i];\n\n    auto intervalValue = [&](int l, int r) -> ld {\n        if (l > r) return 0.0L;\n        return pref[r + 1] - pref[l];\n    };\n\n    vector<ld> win(N, 0.0L);\n    vector<int> deg(N, 0);\n\n    vector<vector<unsigned char>> seen(N, vector<unsigned char>(N, 0));\n    auto is_seen = [&](int a, int b) -> bool {\n        if (a > b) swap(a, b);\n        return seen[a][b] != 0;\n    };\n    auto mark_seen = [&](int a, int b) {\n        if (a > b) swap(a, b);\n        seen[a][b] = 1;\n    };\n\n    int queries_left = Q;\n\n    auto pct = [&](int i) -> ld {\n        return (win[i] + 0.5L) / (ld)(deg[i] + 1);\n    };\n\n    auto ask = [&](int a, int b) -> int {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n' << flush;\n        char c;\n        cin >> c;\n        --queries_left;\n        mark_seen(a, b);\n\n        int res = (c == '>' ? 1 : (c == '<' ? -1 : 0));\n        ++deg[a];\n        ++deg[b];\n        if (res > 0) {\n            win[a] += 1.0L;\n        } else if (res < 0) {\n            win[b] += 1.0L;\n        } else {\n            win[a] += 0.5L;\n            win[b] += 0.5L;\n        }\n        return res;\n    };\n\n    // Warm-up: a few random disjoint comparisons.\n    {\n        int warm = min({N / 2, max(4, Q / 12), 10});\n        vector<int> perm(N);\n        iota(perm.begin(), perm.end(), 0);\n        shuffle(perm.begin(), perm.end(), rng);\n        for (int i = 0; i < warm; ++i) {\n            ask(perm[2 * i], perm[2 * i + 1]);\n        }\n    }\n\n    vector<Bucket> buckets;\n    {\n        Bucket root;\n        root.items.resize(N);\n        iota(root.items.begin(), root.items.end(), 0);\n        root.l = 0;\n        root.r = N - 1;\n        root.sameGroup = false;\n        root.exhausted = false;\n        root.value = pref[N];\n        buckets.push_back(move(root));\n    }\n\n    auto sort_by_pct = [&](vector<int>& items) {\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n    };\n\n    auto sort_for_pivot = [&](vector<int> items) {\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] < deg[b]; // low-degree pivot preferred\n            return a < b;\n        });\n        return items;\n    };\n\n    auto pick_split_bucket = [&]() -> int {\n        int best = -1;\n        ld bestMetric = -1.0L;\n        ld bestValue = -1.0L;\n\n        for (int i = 0; i < (int)buckets.size(); ++i) {\n            const auto& bk = buckets[i];\n            int m = (int)bk.items.size();\n            if (m <= 1) continue;\n            if (bk.sameGroup || bk.exhausted) continue;\n            if (m - 1 > queries_left) continue;\n\n            ld metric = bk.value / (ld)(m - 1);\n            if (metric > bestMetric + 1e-18L ||\n                (fabsl(metric - bestMetric) <= 1e-18L && bk.value > bestValue)) {\n                bestMetric = metric;\n                bestValue = bk.value;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    auto split_bucket = [&](int idx) {\n        Bucket cur = buckets[idx];\n        buckets[idx] = buckets.back();\n        buckets.pop_back();\n\n        int m = (int)cur.items.size();\n        if (m <= 1) {\n            buckets.push_back(move(cur));\n            return;\n        }\n\n        vector<int> ord = sort_for_pivot(cur.items);\n        int mid = m / 2;\n        int lo = max(0, mid - 1);\n        int hi = min(m - 1, mid + 1);\n\n        int pivot = ord[lo];\n        for (int i = lo + 1; i <= hi; ++i) {\n            if (deg[ord[i]] < deg[pivot]) pivot = ord[i];\n        }\n\n        vector<int> greater, equal, less;\n        greater.reserve(m);\n        equal.reserve(m);\n        less.reserve(m);\n\n        for (int x : cur.items) {\n            if (x == pivot) continue;\n            int res = ask(pivot, x);\n            if (res > 0) {\n                // pivot heavier => x is lighter\n                less.push_back(x);\n            } else if (res < 0) {\n                greater.push_back(x);\n            } else {\n                equal.push_back(x);\n            }\n        }\n\n        int g = (int)greater.size();\n        int e = (int)equal.size();\n\n        if (!greater.empty()) {\n            Bucket bk;\n            bk.items = move(greater);\n            bk.l = cur.l;\n            bk.r = cur.l + g - 1;\n            bk.sameGroup = false;\n            bk.exhausted = (bk.items.size() <= 1);\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n\n        {\n            Bucket bk;\n            bk.items.reserve(1 + e);\n            bk.items.push_back(pivot);\n            for (int x : equal) bk.items.push_back(x);\n            bk.l = cur.l + g;\n            bk.r = cur.l + g + e;\n            bk.sameGroup = (e > 0);\n            bk.exhausted = (bk.items.size() <= 1) || bk.sameGroup;\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n\n        if (!less.empty()) {\n            Bucket bk;\n            bk.items = move(less);\n            bk.l = cur.l + g + e + 1;\n            bk.r = cur.r;\n            bk.sameGroup = false;\n            bk.exhausted = (bk.items.size() <= 1);\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n    };\n\n    // Main splitting phase.\n    while (queries_left > 0) {\n        int idx = pick_split_bucket();\n        if (idx == -1) break;\n        split_bucket(idx);\n    }\n\n    const int SMALL_T = 8;\n    int pairPtr = 0;\n    vector<pair<int, int>> allPairs;\n    allPairs.reserve(N * (N - 1) / 2);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            allPairs.push_back({i, j});\n        }\n    }\n    shuffle(allPairs.begin(), allPairs.end(), rng);\n\n    auto global_adjacent_pair = [&]() -> pair<int, int> {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n        for (int i = 0; i + 1 < N; ++i) {\n            int a = ord[i], b = ord[i + 1];\n            if (!is_seen(a, b)) return {a, b};\n        }\n        return {-1, -1};\n    };\n\n    auto next_random_unseen_pair = [&]() -> pair<int, int> {\n        while (pairPtr < (int)allPairs.size()) {\n            auto [a, b] = allPairs[pairPtr++];\n            if (!is_seen(a, b)) return {a, b};\n        }\n        for (int t = 0; t < 200; ++t) {\n            int a = rand_int(0, N - 1);\n            int b = rand_int(0, N - 2);\n            if (b >= a) ++b;\n            if (!is_seen(a, b)) return {a, b};\n        }\n        return {-1, -1};\n    };\n\n    // Use remaining queries to refine ambiguous areas.\n    while (queries_left > 0) {\n        int bestIdx = -1;\n        ld bestValue = -1.0L;\n        for (int i = 0; i < (int)buckets.size(); ++i) {\n            const auto& bk = buckets[i];\n            if (bk.exhausted) continue;\n            if ((int)bk.items.size() <= 1) continue;\n            if (bk.value > bestValue) {\n                bestValue = bk.value;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx != -1) {\n            auto& bk = buckets[bestIdx];\n            int m = (int)bk.items.size();\n\n            if (m <= SMALL_T) {\n                bool completed = true;\n                for (int i = 0; i < m && queries_left > 0; ++i) {\n                    for (int j = i + 1; j < m && queries_left > 0; ++j) {\n                        int a = bk.items[i], b = bk.items[j];\n                        if (is_seen(a, b)) continue;\n                        ask(a, b);\n                    }\n                }\n                // All pairs in this small bucket have been tried.\n                bk.exhausted = true;\n                continue;\n            } else {\n                vector<int> cand = bk.items;\n                sort(cand.begin(), cand.end(), [&](int a, int b) {\n                    ld pa = pct(a), pb = pct(b);\n                    if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n                    if (deg[a] != deg[b]) return deg[a] > deg[b];\n                    return a < b;\n                });\n                bool found = false;\n                for (int i = 0; i + 1 < m; ++i) {\n                    int a = cand[i], b = cand[i + 1];\n                    if (!is_seen(a, b)) {\n                        ask(a, b);\n                        found = true;\n                        break;\n                    }\n                }\n                if (found) continue;\n            }\n        }\n\n        auto p = global_adjacent_pair();\n        if (p.first != -1) {\n            ask(p.first, p.second);\n            continue;\n        }\n\n        p = next_random_unseen_pair();\n        if (p.first == -1) {\n            // Fallback: any valid distinct pair.\n            int a = rand_int(0, N - 1);\n            int b = rand_int(0, N - 2);\n            if (b >= a) ++b;\n            ask(a, b);\n        } else {\n            ask(p.first, p.second);\n        }\n    }\n\n    // Final estimation of item weights.\n    vector<ld> est(N, 0.0L);\n    for (const auto& bk : buckets) {\n        int m = (int)bk.items.size();\n        if (m == 0) continue;\n\n        ld intervalSum = intervalValue(bk.l, bk.r);\n        ld avg = intervalSum / (ld)m;\n\n        if (bk.sameGroup) {\n            for (int x : bk.items) est[x] = avg;\n            continue;\n        }\n\n        vector<int> ord = bk.items;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n\n        vector<ld> tmp(m);\n        ld sumTmp = 0.0L;\n        for (int j = 0; j < m; ++j) {\n            int x = ord[j];\n            ld target = rankExp[bk.l + j];\n\n            ld conf;\n            if (bk.exhausted) {\n                conf = 0.85L;\n            } else {\n                conf = 0.25L + 0.50L * (ld)deg[x] / ((ld)deg[x] + 10.0L);\n                if (conf > 0.85L) conf = 0.85L;\n            }\n\n            ld v = avg * (1.0L - conf) + target * conf;\n            tmp[j] = v;\n            sumTmp += v;\n        }\n\n        ld scale = (sumTmp > 1e-18L ? intervalSum / sumTmp : 1.0L);\n        for (int j = 0; j < m; ++j) {\n            est[ord[j]] = tmp[j] * scale;\n            if (est[ord[j]] < 1.0L) est[ord[j]] = 1.0L;\n            if (est[ord[j]] > CAP) est[ord[j]] = CAP;\n        }\n    }\n\n    auto local_search = [&](vector<vector<int>>& bins, vector<ld>& load, const vector<ld>& w) {\n        auto remove_from_bin = [&](int item, int b, vector<int>& posInBin, vector<int>& where) {\n            int idx = posInBin[item];\n            int last = bins[b].back();\n            bins[b][idx] = last;\n            posInBin[last] = idx;\n            bins[b].pop_back();\n            where[item] = -1;\n        };\n\n        auto add_to_bin = [&](int item, int b, vector<int>& posInBin, vector<int>& where) {\n            where[item] = b;\n            posInBin[item] = (int)bins[b].size();\n            bins[b].push_back(item);\n        };\n\n        vector<int> where(N, -1), posInBin(N, -1);\n        for (int b = 0; b < D; ++b) {\n            for (int x : bins[b]) {\n                where[x] = b;\n                posInBin[x] = (int)(&x - &bins[b][0]); // placeholder, not used\n            }\n        }\n        // Rebuild positions safely.\n        for (int b = 0; b < D; ++b) {\n            for (int i = 0; i < (int)bins[b].size(); ++i) {\n                int x = bins[b][i];\n                where[x] = b;\n                posInBin[x] = i;\n            }\n        }\n\n        auto apply_move = [&](int item, int from, int to) {\n            int idx = posInBin[item];\n            int last = bins[from].back();\n            bins[from][idx] = last;\n            posInBin[last] = idx;\n            bins[from].pop_back();\n\n            load[from] -= w[item];\n\n            where[item] = to;\n            posInBin[item] = (int)bins[to].size();\n            bins[to].push_back(item);\n            load[to] += w[item];\n        };\n\n        auto apply_swap = [&](int x, int bx, int y, int by) {\n            int ix = posInBin[x];\n            int iy = posInBin[y];\n            bins[bx][ix] = y;\n            bins[by][iy] = x;\n            posInBin[x] = iy;\n            posInBin[y] = ix;\n            where[x] = by;\n            where[y] = bx;\n            load[bx] += w[y] - w[x];\n            load[by] += w[x] - w[y];\n        };\n\n        for (int iter = 0; iter < 160; ++iter) {\n            ld bestDelta = 0.0L;\n            int bestType = 0; // 1: move, 2: swap\n            int ba = -1, bb = -1, bx = -1, by = -1;\n\n            for (int a = 0; a < D; ++a) {\n                for (int b = 0; b < D; ++b) {\n                    if (a == b) continue;\n                    if (load[a] <= load[b] + 1e-18L) continue;\n                    ld d = load[a] - load[b];\n\n                    if ((int)bins[a].size() > 1) {\n                        for (int x : bins[a]) {\n                            ld ww = w[x];\n                            ld delta = 2.0L * ww * (ww - d);\n                            if (delta < bestDelta) {\n                                bestDelta = delta;\n                                bestType = 1;\n                                ba = a; bb = b; bx = x;\n                            }\n                        }\n                    }\n\n                    for (int x : bins[a]) {\n                        for (int y : bins[b]) {\n                            ld diff = w[x] - w[y];\n                            ld delta = 2.0L * diff * (diff - d);\n                            if (delta < bestDelta) {\n                                bestDelta = delta;\n                                bestType = 2;\n                                ba = a; bb = b; bx = x; by = y;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestDelta >= -1e-12L) break;\n\n            if (bestType == 1) {\n                apply_move(bx, ba, bb);\n            } else if (bestType == 2) {\n                apply_swap(bx, ba, by, bb);\n            } else {\n                break;\n            }\n        }\n\n        vector<int> ans(N, 0);\n        for (int b = 0; b < D; ++b) {\n            for (int x : bins[b]) ans[x] = b;\n        }\n\n        ld sumsq = 0.0L;\n        for (int b = 0; b < D; ++b) sumsq += load[b] * load[b];\n        return PartResult{ans, sumsq};\n    };\n\n    auto build_partition = [&](int mode, ld noiseAmp, int offset) -> PartResult {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        vector<ld> key(N, 0.0L);\n        for (int i = 0; i < N; ++i) {\n            ld noise = 0.0L;\n            if (noiseAmp > 0.0L) {\n                ld u = (ld)rand_int(0, 1000000) / 1000000.0L;\n                noise = (2.0L * u - 1.0L) * noiseAmp;\n            }\n            key[i] = est[i] * (1.0L + noise);\n        }\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (fabsl(key[a] - key[b]) > 1e-18L) return key[a] > key[b];\n            return a < b;\n        });\n\n        vector<vector<int>> bins(D);\n        vector<ld> load(D, 0.0L);\n\n        if (mode == 0) {\n            // LPT greedy\n            for (int id : ord) {\n                int best = 0;\n                for (int d = 1; d < D; ++d) {\n                    if (load[d] < load[best] - 1e-18L ||\n                        (fabsl(load[d] - load[best]) <= 1e-18L && bins[d].size() < bins[best].size())) {\n                        best = d;\n                    }\n                }\n                bins[best].push_back(id);\n                load[best] += est[id];\n            }\n        } else {\n            // Cyclic assignment with offset.\n            if (D == 0) offset = 0;\n            offset %= D;\n            if (offset < 0) offset += D;\n            for (int i = 0; i < N; ++i) {\n                int b = (i + offset) % D;\n                bins[b].push_back(ord[i]);\n                load[b] += est[ord[i]];\n            }\n        }\n\n        PartResult res = local_search(bins, load, est);\n        return res;\n    };\n\n    // Try several restarts with different initial packings.\n    PartResult best;\n    int restarts = min(8, 4 + Q / 1000);\n    for (int r = 0; r < restarts; ++r) {\n        int mode = r % 2; // 0 = LPT, 1 = cyclic\n        ld noiseAmp = (r == 0 ? 0.0L : min(0.05L, 0.01L * (ld)r));\n        int offset = (D > 0 ? rand_int(0, D - 1) : 0);\n        PartResult cur = build_partition(mode, noiseAmp, offset);\n        if (cur.score < best.score) best = move(cur);\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << best.ans[i];\n    }\n    cout << '\\n' << flush;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing i16 = int16_t;\n\nstatic constexpr int MAXN = 205;\nstatic constexpr int MAXM = 10;\nstatic constexpr int MAX_SEQ = 512;\nstatic constexpr ll INF = (1LL << 60);\n\nint n, m;\n\nstruct Board {\n    i16 st[MAXM][MAXN];\n    i16 len[MAXM];\n    i16 posStack[MAXN];\n    i16 posIdx[MAXN];\n    int cur;\n};\n\nstruct Node {\n    Board b;\n    ll spent = 0;\n    ll eval = 0;\n    uint8_t path[MAX_SEQ]{};\n    uint16_t plen = 0;\n};\n\nstruct Candidate {\n    bool ok = false;\n    ll energy = INF;\n    vector<int> path;\n};\n\nstruct Preset {\n    int lookK;\n    ll remW, badW, nearW, sqW, topW, emptyW;\n    ll emptyBonus, fitGood, fitBad;\n    int noise;\n    int beamWidth;\n    int completeTop;\n    int depthThresh;\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\nstatic inline bool timeUp(const chrono::steady_clock::time_point &start, double limitSec) {\n    return chrono::duration<double>(chrono::steady_clock::now() - start).count() > limitSec;\n}\n\nstatic inline void flush(Board &b, vector<pair<int,int>> *ops) {\n    while (b.cur <= n) {\n        int x = b.cur;\n        int s = b.posStack[x];\n        if (s < 0) break;\n        if (b.posIdx[x] != b.len[s] - 1) break;\n\n        if (ops) ops->push_back({x, 0});\n        b.posStack[x] = -1;\n        b.posIdx[x] = -1;\n        --b.len[s];\n        ++b.cur;\n    }\n}\n\n// Operation 1 + forced free removal of the current smallest.\n// dest is 0-indexed stack index.\nstatic inline bool applyForcedMove(Board &b, ll &spent, int dest, vector<pair<int,int>> *ops) {\n    int x = b.cur;\n    int s = b.posStack[x];\n    int idx = b.posIdx[x];\n    int from = idx + 1;              // first moved box\n    int k = b.len[s] - from;         // number of moved boxes\n    if (k <= 0) return false;\n\n    spent += k + 1;\n\n    if (ops) ops->push_back({(int)b.st[s][from], dest + 1});\n\n    int base = b.len[dest];\n    for (int t = 0; t < k; ++t) {\n        int v = b.st[s][from + t];\n        b.st[dest][base + t] = (i16)v;\n        b.posStack[v] = (i16)dest;\n        b.posIdx[v] = (i16)(base + t);\n    }\n    b.len[dest] += k;\n\n    if (ops) ops->push_back({x, 0});\n\n    b.posStack[x] = -1;\n    b.posIdx[x] = -1;\n    b.len[s] = idx;\n    ++b.cur;\n\n    flush(b, ops);\n    return true;\n}\n\nstatic inline ll fitPenalty(const Board &b, int dest, const Preset &P) {\n    int src = b.posStack[b.cur];\n    int idx = b.posIdx[b.cur];\n    int firstMoved = b.st[src][idx + 1];\n\n    if (b.len[dest] == 0) return -P.emptyBonus;\n\n    int top = b.st[dest][b.len[dest] - 1];\n    int diff = top - firstMoved;\n\n    if (diff >= 0) {\n        return -P.fitGood + min<ll>(4, diff / 4);\n    } else {\n        return P.fitBad + min<ll>(6, (-diff) / 4);\n    }\n}\n\nstatic inline ll heuristic(const Board &b, const Preset &P, uint64_t seed) {\n    if (b.cur > n) return 0;\n\n    int rem = n - b.cur + 1;\n    int L = min(rem, P.lookK);\n\n    ll near = 0;\n    for (int t = 0; t < L; ++t) {\n        int v = b.cur + t;\n        int s = b.posStack[v];\n        int depth = b.len[s] - 1 - b.posIdx[v];\n        near += 1LL * (L - t) * depth;\n    }\n\n    ll bad = 0;\n    ll sumSq = 0;\n    ll topSum = 0;\n    ll empty = 0;\n    ll maxH = 0;\n\n    for (int s = 0; s < m; ++s) {\n        int h = b.len[s];\n        sumSq += 1LL * h * h;\n        maxH = std::max(maxH, (ll)h);\n\n        if (h == 0) {\n            ++empty;\n            continue;\n        }\n\n        topSum += b.st[s][h - 1];\n        for (int i = 0; i + 1 < h; ++i) {\n            if (b.st[s][i] < b.st[s][i + 1]) bad += 2;\n            if (i + 2 < h && b.st[s][i] < b.st[s][i + 2]) bad += 1;\n        }\n    }\n\n    ll remW = P.remW, badW = P.badW, nearW = P.nearW, sqW = P.sqW, topW = P.topW, emptyW = P.emptyW;\n\n    if (rem > 120) emptyW *= 2;\n    if (rem < 50) {\n        badW += 2;\n        nearW += 3;\n    }\n\n    ll sc = 0;\n    sc += remW * rem;\n    sc += badW * bad;\n    sc += nearW * near / 16;\n    sc += sqW * sumSq / 20;\n    sc += topW * topSum / 20;\n    sc -= emptyW * empty;\n    sc += maxH;\n\n    if (P.noise > 0) {\n        uint64_t x = seed;\n        x ^= (uint64_t)b.cur * 0x9e3779b97f4a7c15ULL;\n        x ^= (uint64_t)bad * 0xbf58476d1ce4e5b9ULL;\n        x ^= (uint64_t)sumSq * 0x94d049bb133111ebULL;\n        sc += (ll)(splitmix64(x) % (uint64_t)P.noise);\n    }\n\n    return sc;\n}\n\nstatic inline Candidate candidateFromNode(const Node &node) {\n    Candidate c;\n    c.ok = true;\n    c.energy = node.spent;\n    c.path.resize(node.plen);\n    for (int i = 0; i < (int)node.plen; ++i) c.path[i] = (int)node.path[i];\n    return c;\n}\n\nstatic inline ll eval1(const Board &b, ll spent, int dest, const Preset &P, uint64_t seed) {\n    Board tb = b;\n    ll sp = spent;\n    if (!applyForcedMove(tb, sp, dest, nullptr)) return INF;\n    if (tb.cur > n) return sp + fitPenalty(b, dest, P);\n    return sp + heuristic(tb, P, seed) + fitPenalty(b, dest, P);\n}\n\nstatic inline ll eval2(const Board &b, ll spent, int dest, const Preset &P, uint64_t seed) {\n    Board t1 = b;\n    ll sp1 = spent;\n    if (!applyForcedMove(t1, sp1, dest, nullptr)) return INF;\n\n    ll base = fitPenalty(b, dest, P);\n    if (t1.cur > n) return sp1 + base;\n\n    int src2 = t1.posStack[t1.cur];\n    ll best = INF;\n\n    for (int d2 = 0; d2 < m; ++d2) {\n        if (d2 == src2) continue;\n        Board t2 = t1;\n        ll sp2 = sp1;\n        if (!applyForcedMove(t2, sp2, d2, nullptr)) continue;\n        ll sc = sp2 + heuristic(t2, P, seed) + fitPenalty(t1, d2, P);\n        best = min(best, sc);\n    }\n\n    return best + base;\n}\n\nstatic inline Candidate completeGreedy(Node node, const Preset &P, uint64_t seed,\n                                       const chrono::steady_clock::time_point &start,\n                                       double limitSec) {\n    Candidate res;\n    flush(node.b, nullptr);\n\n    vector<int> path;\n    path.reserve(128);\n    for (int i = 0; i < (int)node.plen; ++i) path.push_back((int)node.path[i]);\n\n    int steps = 0;\n    while (node.b.cur <= n) {\n        if ((steps & 7) == 0 && timeUp(start, limitSec)) return {};\n        ++steps;\n\n        int src = node.b.posStack[node.b.cur];\n        ll bestScore = INF;\n        int bestDest = -1;\n\n        bool use2 = (n - node.b.cur + 1 > P.depthThresh);\n        for (int d = 0; d < m; ++d) {\n            if (d == src) continue;\n            ll sc = use2 ? eval2(node.b, node.spent, d, P, seed)\n                         : eval1(node.b, node.spent, d, P, seed);\n            if (sc < bestScore || (sc == bestScore && (bestDest == -1 || d < bestDest))) {\n                bestScore = sc;\n                bestDest = d;\n            }\n        }\n\n        if (bestDest < 0) return {};\n        path.push_back(bestDest);\n        if ((int)path.size() > 5000) return {};\n\n        if (!applyForcedMove(node.b, node.spent, bestDest, nullptr)) return {};\n    }\n\n    res.ok = true;\n    res.energy = node.spent;\n    res.path = std::move(path);\n    return res;\n}\n\nstatic inline bool simulatePrefix(const Board &init, const vector<int> &path, int steps, Node &out) {\n    out = Node{};\n    out.b = init;\n    out.spent = 0;\n    out.plen = 0;\n    flush(out.b, nullptr);\n\n    if (steps > (int)path.size()) return false;\n    for (int i = 0; i < steps; ++i) {\n        if (out.b.cur > n) return false;\n        int d = path[i];\n        if (d < 0 || d >= m) return false;\n        if (d == out.b.posStack[out.b.cur]) return false;\n        if (!applyForcedMove(out.b, out.spent, d, nullptr)) return false;\n        out.path[out.plen++] = (uint8_t)d;\n    }\n    return true;\n}\n\nstatic inline Candidate refineMutations(const Board &init, Candidate best, const Preset &P, uint64_t seed,\n                                        const chrono::steady_clock::time_point &start, double limitSec) {\n    if (!best.ok || best.path.empty()) return best;\n\n    int cap = min<int>(12, (int)best.path.size());\n    if (cap == 0) return best;\n\n    uint64_t s = seed;\n    for (int iter = 0; iter < 8; ++iter) {\n        if (timeUp(start, limitSec)) break;\n        s = splitmix64(s + 0x9e3779b97f4a7c15ULL + (uint64_t)iter);\n\n        int p = (int)(s % cap);\n\n        Node pref;\n        if (!simulatePrefix(init, best.path, p, pref)) continue;\n        if (pref.b.cur > n) continue;\n\n        int src = pref.b.posStack[pref.b.cur];\n        int old = best.path[p];\n\n        vector<pair<ll,int>> choices;\n        choices.reserve(m - 1);\n        for (int d = 0; d < m; ++d) {\n            if (d == src || d == old) continue;\n            ll sc = eval1(pref.b, pref.spent, d, P, s);\n            choices.push_back({sc, d});\n        }\n\n        sort(choices.begin(), choices.end());\n        int lim = min<int>(3, (int)choices.size());\n\n        for (int i = 0; i < lim; ++i) {\n            int d = choices[i].second;\n            Node mutated = pref;\n            if (!applyForcedMove(mutated.b, mutated.spent, d, nullptr)) continue;\n            mutated.path[mutated.plen++] = (uint8_t)d;\n\n            Candidate cand = completeGreedy(mutated, P, s ^ 0x123456789abcdefULL, start, limitSec);\n            if (cand.ok && cand.energy < best.energy) best = std::move(cand);\n        }\n    }\n\n    return best;\n}\n\nstatic inline Candidate beamAttempt(const Board &init, const Preset &P, uint64_t seed,\n                                    const chrono::steady_clock::time_point &start,\n                                    double searchLimitSec, double fullLimitSec) {\n    Candidate best;\n    vector<Node> beam;\n\n    Node root{};\n    root.b = init;\n    root.spent = 0;\n    root.plen = 0;\n    flush(root.b, nullptr);\n    root.eval = heuristic(root.b, P, seed);\n    beam.push_back(root);\n\n    int layer = 0;\n    while (!beam.empty()) {\n        if ((layer & 3) == 0 && timeUp(start, searchLimitSec)) break;\n\n        vector<Node> cand;\n        cand.reserve(beam.size() * (m - 1));\n\n        for (const Node &node : beam) {\n            if ((layer & 7) == 0 && timeUp(start, searchLimitSec)) break;\n\n            if (node.b.cur > n) {\n                Candidate c = candidateFromNode(node);\n                if (!best.ok || c.energy < best.energy) best = std::move(c);\n                continue;\n            }\n\n            int src = node.b.posStack[node.b.cur];\n            for (int d = 0; d < m; ++d) {\n                if (d == src) continue;\n\n                Node child = node;\n                if (!applyForcedMove(child.b, child.spent, d, nullptr)) continue;\n                child.path[child.plen++] = (uint8_t)d;\n\n                if (child.b.cur > n) {\n                    Candidate c = candidateFromNode(child);\n                    if (!best.ok || c.energy < best.energy) best = std::move(c);\n                } else {\n                    child.eval = child.spent + heuristic(child.b, P, seed) + fitPenalty(node.b, d, P);\n                    cand.push_back(std::move(child));\n                }\n            }\n        }\n\n        if (cand.empty()) break;\n\n        vector<int> ord(cand.size());\n        iota(ord.begin(), ord.end(), 0);\n\n        auto cmp = [&](int a, int b) {\n            if (cand[a].eval != cand[b].eval) return cand[a].eval < cand[b].eval;\n            if (cand[a].spent != cand[b].spent) return cand[a].spent < cand[b].spent;\n            return cand[a].b.cur > cand[b].b.cur;\n        };\n\n        int keep = min<int>(P.beamWidth, (int)ord.size());\n        if ((int)ord.size() > keep) {\n            nth_element(ord.begin(), ord.begin() + keep, ord.end(), cmp);\n            ord.resize(keep);\n        }\n        sort(ord.begin(), ord.end(), cmp);\n\n        vector<Node> next;\n        next.reserve(ord.size());\n        for (int id : ord) next.push_back(std::move(cand[id]));\n        beam.swap(next);\n\n        ++layer;\n    }\n\n    if (!beam.empty()) {\n        vector<int> ord(beam.size());\n        iota(ord.begin(), ord.end(), 0);\n        auto cmp = [&](int a, int b) {\n            if (beam[a].eval != beam[b].eval) return beam[a].eval < beam[b].eval;\n            if (beam[a].spent != beam[b].spent) return beam[a].spent < beam[b].spent;\n            return beam[a].b.cur > beam[b].b.cur;\n        };\n        sort(ord.begin(), ord.end(), cmp);\n\n        int lim = min<int>(P.completeTop, (int)ord.size());\n        for (int i = 0; i < lim; ++i) {\n            Candidate c = completeGreedy(beam[ord[i]], P, seed, start, fullLimitSec);\n            if (c.ok && (!best.ok || c.energy < best.energy)) best = std::move(c);\n        }\n    }\n\n    return best;\n}\n\nstatic inline bool replayPath(const Board &init, const vector<int> &path,\n                              vector<pair<int,int>> &ops, ll &energy) {\n    Board b = init;\n    energy = 0;\n    ops.clear();\n    ops.reserve(1000);\n\n    flush(b, &ops);\n\n    for (int d : path) {\n        if (b.cur > n) return false;\n        if (d < 0 || d >= m) return false;\n        if (d == b.posStack[b.cur]) return false;\n        if (!applyForcedMove(b, energy, d, &ops)) return false;\n        if ((int)ops.size() > 5000) return false;\n    }\n\n    if (b.cur <= n) return false;\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    Board init{};\n    init.cur = 1;\n    memset(init.posStack, -1, sizeof(init.posStack));\n    memset(init.posIdx, -1, sizeof(init.posIdx));\n\n    uint64_t baseSeed = 0x123456789abcdefULL;\n\n    int h = n / m;\n    for (int s = 0; s < m; ++s) {\n        init.len[s] = h;\n        for (int i = 0; i < h; ++i) {\n            int v;\n            cin >> v;\n            init.st[s][i] = (i16)v;\n            init.posStack[v] = (i16)s;\n            init.posIdx[v] = (i16)i;\n            baseSeed = splitmix64(baseSeed ^ (uint64_t)v);\n        }\n    }\n\n    Node root{};\n    root.b = init;\n    root.spent = 0;\n    root.plen = 0;\n    flush(root.b, nullptr);\n\n    Preset basePreset{\n        16, 2, 3, 10, 2, 1, 18,\n        6, 4, 6,\n        0, 1, 1, 1000\n    };\n\n    vector<Preset> presets = {\n        {16, 2, 4, 10, 2, 1, 18, 6, 4, 6,  3,  60,  8, 80},\n        {18, 3, 4, 12, 3, 1, 22, 8, 5, 7,  7,  80, 10, 65},\n        {20, 3, 5, 14, 3, 2, 24, 9, 6, 8, 11, 100, 12, 60},\n        {22, 4, 5, 16, 4, 2, 28,10, 6, 9, 13, 120, 12, 55},\n    };\n\n    auto start = chrono::steady_clock::now();\n    const double SEARCH_LIMIT = 1.60;\n    const double FULL_LIMIT = 1.85;\n\n    Candidate best = completeGreedy(root, basePreset, splitmix64(baseSeed ^ 0x9e3779b97f4a7c15ULL), start, FULL_LIMIT);\n    int bestPresetIdx = -1;\n    uint64_t bestSeed = splitmix64(baseSeed ^ 0x9e3779b97f4a7c15ULL);\n\n    for (int t = 0; t < (int)presets.size(); ++t) {\n        if (timeUp(start, SEARCH_LIMIT)) break;\n        uint64_t seed = splitmix64(baseSeed + 0x9e3779b97f4a7c15ULL * (uint64_t)(t + 1));\n        Candidate cand = beamAttempt(init, presets[t], seed, start, SEARCH_LIMIT, FULL_LIMIT);\n        if (cand.ok && (!best.ok || cand.energy < best.energy)) {\n            best = std::move(cand);\n            bestPresetIdx = t;\n            bestSeed = seed;\n        }\n    }\n\n    if (best.ok && bestPresetIdx >= 0) {\n        best = refineMutations(init, best, presets[bestPresetIdx], bestSeed, start, FULL_LIMIT);\n    }\n\n    vector<pair<int,int>> ops;\n    ll verifiedEnergy = 0;\n\n    if (!best.ok || !replayPath(init, best.path, ops, verifiedEnergy)) {\n        Candidate fb = completeGreedy(root, basePreset, splitmix64(baseSeed ^ 0xabcdef123456789ULL), start, FULL_LIMIT);\n        if (!fb.ok || !replayPath(init, fb.path, ops, verifiedEnergy)) {\n            return 0;\n        }\n        best = std::move(fb);\n    } else {\n        best.energy = verifiedEnergy;\n    }\n\n    for (auto [v, i] : ops) {\n        cout << v << ' ' << i << '\\n';\n    }\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing i128 = __int128_t;\n\nstatic const int DR[4] = {-1, 1, 0, 0};\nstatic const int DC[4] = {0, 0, -1, 1};\nstatic const int REV[4] = {1, 0, 3, 2};\nstatic const char CH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Edge {\n    int to, dir;\n};\n\nstruct TreeInfo {\n    int root;\n    vector<int> parent;\n    vector<int> order;\n    vector<vector<pair<int,int>>> children;\n    vector<long long> subW;\n    vector<int> subCnt;\n};\n\nint N, TOT;\nvector<int> D;\nvector<vector<Edge>> adj, highAdj, lowAdj;\nvector<array<int,4>> nxt;\nvector<long long> localScore, nodeHeu;\n\n// BFS from origin: shortest paths, but neighbor order prefers low-weight cells\nvector<int> parent0, pdir0, dist0;\n\nstatic void emitTour(int u, const vector<vector<pair<int,int>>>& ch, vector<int>& out) {\n    for (auto [v, dir] : ch[u]) {\n        out.push_back(dir);\n        emitTour(v, ch, out);\n        out.push_back(REV[dir]);\n    }\n}\n\nstatic vector<int> reverseRoute(const vector<int>& dirs) {\n    vector<int> rev;\n    rev.reserve(dirs.size());\n    for (auto it = dirs.rbegin(); it != dirs.rend(); ++it) {\n        rev.push_back(REV[*it]);\n    }\n    return rev;\n}\n\nstatic pair<i128,int> evaluateRoute(const vector<int>& dirs) {\n    vector<int> first(TOT, -1), last(TOT, -1);\n    vector<long long> acc(TOT, 0);\n\n    int cur = 0;\n    int t = 0;\n    for (int dir : dirs) {\n        cur = nxt[cur][dir];\n        ++t;\n        if (first[cur] == -1) {\n            first[cur] = last[cur] = t;\n        } else {\n            int gap = t - last[cur];\n            acc[cur] += 1LL * gap * (gap - 1) / 2;\n            last[cur] = t;\n        }\n    }\n\n    i128 total = 0;\n    for (int u = 0; u < TOT; ++u) {\n        // All cells must be visited in a valid route.\n        int gap = first[u] + t - last[u];\n        acc[u] += 1LL * gap * (gap - 1) / 2;\n        total += (i128)acc[u] * (i128)D[u];\n    }\n    return {total, t};\n}\n\nstatic bool better(i128 num1, int den1, i128 num2, int den2) {\n    // compare num1/den1 < num2/den2\n    return num1 * (i128)den2 < num2 * (i128)den1;\n}\n\nstatic TreeInfo buildTree(int root, const vector<vector<Edge>>& orderAdj, bool bfsMode) {\n    TreeInfo tr;\n    tr.root = root;\n    tr.parent.assign(TOT, -1);\n    tr.order.reserve(TOT);\n    tr.children.assign(TOT, {});\n\n    if (bfsMode) {\n        vector<int> q;\n        q.reserve(TOT);\n        int head = 0;\n        tr.parent[root] = root;\n        q.push_back(root);\n        tr.order.push_back(root);\n\n        while (head < (int)q.size()) {\n            int u = q[head++];\n            for (const auto& e : orderAdj[u]) {\n                int v = e.to;\n                if (tr.parent[v] == -1) {\n                    tr.parent[v] = u;\n                    tr.children[u].push_back({v, e.dir});\n                    tr.order.push_back(v);\n                    q.push_back(v);\n                }\n            }\n        }\n    } else {\n        vector<int> st;\n        vector<int> it(TOT, 0);\n        st.reserve(TOT);\n        tr.parent[root] = root;\n        st.push_back(root);\n        tr.order.push_back(root);\n\n        while (!st.empty()) {\n            int u = st.back();\n            if (it[u] == (int)orderAdj[u].size()) {\n                st.pop_back();\n                continue;\n            }\n            auto e = orderAdj[u][it[u]++];\n            int v = e.to;\n            if (tr.parent[v] == -1) {\n                tr.parent[v] = u;\n                tr.children[u].push_back({v, e.dir});\n                tr.order.push_back(v);\n                st.push_back(v);\n            }\n        }\n    }\n\n    tr.subW.assign(TOT, 0);\n    tr.subCnt.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        tr.subW[u] = D[u];\n        tr.subCnt[u] = 1;\n    }\n    for (int i = TOT - 1; i >= 0; --i) {\n        int u = tr.order[i];\n        if (u == root) continue;\n        int p = tr.parent[u];\n        tr.subW[p] += tr.subW[u];\n        tr.subCnt[p] += tr.subCnt[u];\n    }\n\n    return tr;\n}\n\nstatic vector<int> pathToRoot(int root) {\n    vector<int> dirs;\n    int x = root;\n    while (x != 0) {\n        dirs.push_back(pdir0[x]);\n        x = parent0[x];\n    }\n    reverse(dirs.begin(), dirs.end());\n    return dirs;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    TOT = N * 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    D.assign(TOT, 0);\n    auto id = [&](int r, int c) { return r * N + c; };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> D[id(i, j)];\n        }\n    }\n\n    adj.assign(TOT, {});\n    nxt.assign(TOT, {});\n    for (int i = 0; i < TOT; ++i) nxt[i].fill(-1);\n\n    auto addEdge = [&](int u, int vtx, int dirUV, int dirVU) {\n        adj[u].push_back({vtx, dirUV});\n        adj[vtx].push_back({u, dirVU});\n        nxt[u][dirUV] = vtx;\n        nxt[vtx][dirVU] = u;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                addEdge(u, id(i + 1, j), 1, 0); // D / U\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                addEdge(u, id(i, j + 1), 3, 2); // R / L\n            }\n        }\n    }\n\n    localScore.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        long long s = D[u];\n        for (auto e : adj[u]) s += D[e.to];\n        localScore[u] = s;\n    }\n\n    // Heuristic importance used for adjacency ordering.\n    nodeHeu.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        nodeHeu[u] = localScore[u] * 1000LL + 100LL * D[u] + (long long)adj[u].size();\n    }\n\n    highAdj = adj;\n    lowAdj = adj;\n    for (int u = 0; u < TOT; ++u) {\n        sort(highAdj[u].begin(), highAdj[u].end(), [&](const Edge& a, const Edge& b) {\n            if (nodeHeu[a.to] != nodeHeu[b.to]) return nodeHeu[a.to] > nodeHeu[b.to];\n            return a.to < b.to;\n        });\n        sort(lowAdj[u].begin(), lowAdj[u].end(), [&](const Edge& a, const Edge& b) {\n            if (nodeHeu[a.to] != nodeHeu[b.to]) return nodeHeu[a.to] < nodeHeu[b.to];\n            return a.to < b.to;\n        });\n    }\n\n    // Shortest paths from origin, preferring low-score cells among shortest options.\n    parent0.assign(TOT, -1);\n    pdir0.assign(TOT, -1);\n    dist0.assign(TOT, -1);\n    {\n        vector<int> q;\n        q.reserve(TOT);\n        int head = 0;\n        q.push_back(0);\n        parent0[0] = 0;\n        dist0[0] = 0;\n\n        while (head < (int)q.size()) {\n            int u = q[head++];\n            for (const auto& e : lowAdj[u]) {\n                int vtx = e.to;\n                if (dist0[vtx] == -1) {\n                    dist0[vtx] = dist0[u] + 1;\n                    parent0[vtx] = u;\n                    pdir0[vtx] = e.dir;\n                    q.push_back(vtx);\n                }\n            }\n        }\n    }\n\n    // Candidate roots from several heuristics.\n    vector<int> roots;\n    vector<char> used(TOT, 0);\n    auto addRoot = [&](int x) {\n        if (!used[x]) {\n            used[x] = 1;\n            roots.push_back(x);\n        }\n    };\n\n    addRoot(0);\n\n    auto addTop = [&](auto scorer, int K) {\n        vector<pair<long double,int>> vec;\n        vec.reserve(TOT);\n        for (int u = 0; u < TOT; ++u) vec.push_back({scorer(u), u});\n        sort(vec.begin(), vec.end(), [&](const auto& a, const auto& b) {\n            if (fabsl(a.first - b.first) > 1e-18L) return a.first > b.first;\n            return a.second < b.second;\n        });\n        for (int i = 0; i < K && i < (int)vec.size(); ++i) addRoot(vec[i].second);\n    };\n\n    addTop([&](int u) -> long double { return (long double)localScore[u]; }, 8);\n    addTop([&](int u) -> long double { return (long double)D[u]; }, 8);\n    addTop([&](int u) -> long double { return (long double)(localScore[u] + 10LL * D[u]) / (dist0[u] + 1.0L); }, 8);\n    addTop([&](int u) -> long double { return (long double)(nodeHeu[u]) / (dist0[u] + 1.0L); }, 8);\n\n    vector<long double> rootRank(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        rootRank[u] = (long double)(localScore[u] + 10LL * D[u]) / (dist0[u] + 1.0L);\n    }\n\n    vector<int> others;\n    others.reserve(roots.size());\n    for (int x : roots) if (x != 0) others.push_back(x);\n    sort(others.begin(), others.end(), [&](int a, int b) {\n        if (fabsl(rootRank[a] - rootRank[b]) > 1e-18L) return rootRank[a] > rootRank[b];\n        if (dist0[a] != dist0[b]) return dist0[a] < dist0[b];\n        return a < b;\n    });\n\n    roots.clear();\n    roots.push_back(0);\n    for (int x : others) roots.push_back(x);\n    if ((int)roots.size() > 12) roots.resize(12);\n\n    // Tree modes: BFS/DFS x high/low adjacency.\n    struct Mode {\n        const vector<vector<Edge>>* ordAdj;\n        bool bfsMode;\n    };\n    vector<Mode> modes = {\n        {&highAdj, true},\n        {&lowAdj,  true},\n        {&highAdj, false},\n        {&lowAdj,  false},\n    };\n\n    string bestRoute;\n    i128 bestNum = 0;\n    int bestDen = 1;\n    bool hasBest = false;\n\n    auto saveCandidate = [&](const vector<int>& dirs) {\n        auto [num, den] = evaluateRoute(dirs);\n        if (!hasBest || better(num, den, bestNum, bestDen) || (!better(bestNum, bestDen, num, den) && den < bestDen)) {\n            hasBest = true;\n            bestNum = num;\n            bestDen = den;\n            bestRoute.clear();\n            bestRoute.reserve(dirs.size());\n            for (int d : dirs) bestRoute.push_back(CH[d]);\n        }\n    };\n\n    auto timeStart = chrono::steady_clock::now();\n    auto timeOver = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - timeStart).count() > 1850;\n    };\n\n    for (int root : roots) {\n        if (timeOver()) break;\n\n        vector<int> path = pathToRoot(root);\n\n        for (const auto& mode : modes) {\n            if (timeOver()) break;\n\n            TreeInfo tr = buildTree(root, *mode.ordAdj, mode.bfsMode);\n\n            vector<long double> keyDensity(TOT), keyWeight(TOT);\n            for (int u = 0; u < TOT; ++u) {\n                keyDensity[u] = (long double)tr.subW[u] / (long double)tr.subCnt[u];\n                keyWeight[u] = (long double)tr.subW[u];\n            }\n\n            for (int variant = 0; variant < 4; ++variant) {\n                if (timeOver()) break;\n\n                vector<vector<pair<int,int>>> ch = tr.children;\n                for (int u = 0; u < TOT; ++u) {\n                    auto cmpAsc = [&](const pair<int,int>& a, const pair<int,int>& b) {\n                        long double ka = (variant < 2 ? keyDensity[a.first] : keyWeight[a.first]);\n                        long double kb = (variant < 2 ? keyDensity[b.first] : keyWeight[b.first]);\n                        if (fabsl(ka - kb) > 1e-18L) {\n                            if (variant % 2 == 0) return ka < kb;\n                            else return ka > kb;\n                        }\n                        return a.first < b.first;\n                    };\n                    if ((int)ch[u].size() >= 2) sort(ch[u].begin(), ch[u].end(), cmpAsc);\n                }\n\n                vector<int> tour;\n                tour.reserve(2 * (TOT - 1));\n                emitTour(root, ch, tour);\n\n                vector<int> dirs;\n                dirs.reserve(path.size() * 2 + tour.size());\n                for (int d : path) dirs.push_back(d);\n                for (int d : tour) dirs.push_back(d);\n                for (auto it = path.rbegin(); it != path.rend(); ++it) dirs.push_back(REV[*it]);\n\n                saveCandidate(dirs);\n\n                vector<int> revDirs = reverseRoute(dirs);\n                saveCandidate(revDirs);\n            }\n        }\n    }\n\n    if (!hasBest) {\n        // Fallback: just output a trivial DFS-like route from origin tree.\n        // In practice this should never happen.\n        TreeInfo tr = buildTree(0, highAdj, true);\n        vector<long double> keyDensity(TOT), keyWeight(TOT);\n        for (int u = 0; u < TOT; ++u) {\n            keyDensity[u] = (long double)tr.subW[u] / (long double)tr.subCnt[u];\n            keyWeight[u] = (long double)tr.subW[u];\n        }\n        vector<vector<pair<int,int>>> ch = tr.children;\n        for (int u = 0; u < TOT; ++u) {\n            sort(ch[u].begin(), ch[u].end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n                if (fabsl(keyDensity[a.first] - keyDensity[b.first]) > 1e-18L) return keyDensity[a.first] < keyDensity[b.first];\n                return a.first < b.first;\n            });\n        }\n        vector<int> tour;\n        emitTour(0, ch, tour);\n        bestRoute.clear();\n        for (int d : tour) bestRoute.push_back(CH[d]);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 15;\nstatic constexpr int CELLS = H * H;\nstatic constexpr int MAXM = 205;\nstatic constexpr int INF = 100000000;\nstatic constexpr int FUTK = 10;\n\nint N, M, si, sj;\nvector<string> words;\n\nint boardLetter[CELLS];\nint distCell[CELLS][CELLS];\nint letterDist[26][26];\nvector<int> cellsByLetter[26];\n\nstring suffixes[MAXM][5];\nint suffixLB[MAXM][5];\n\nstruct FastRng {\n    uint64_t x;\n    explicit FastRng(uint64_t seed = 88172645463393265ULL) : x(seed) {}\n    uint64_t next() {\n        uint64_t z = (x += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int nextInt(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n};\n\ninline int safeAdd1(int x) {\n    return (x >= INF - 1 ? INF : x + 1);\n}\n\ninline bool usedBit(const array<uint64_t, 4>& u, int i) {\n    return (u[i >> 6] >> (i & 63)) & 1ULL;\n}\ninline void setBit(array<uint64_t, 4>& u, int i) {\n    u[i >> 6] |= (1ULL << (i & 63));\n}\n\ninline int minCost(const array<int, CELLS>& dp) {\n    return *min_element(dp.begin(), dp.end());\n}\n\n// 2D Manhattan distance transform:\n// out[q] = min_p src[p] + manhattan(p, q)\nvoid manhattanTransform(const array<int, CELLS>& src, array<int, CELLS>& out) {\n    int horiz[CELLS];\n\n    for (int r = 0; r < H; ++r) {\n        int base = r * H;\n        int left[H], right[H];\n\n        left[0] = src[base];\n        for (int c = 1; c < H; ++c) {\n            left[c] = min(src[base + c], safeAdd1(left[c - 1]));\n        }\n\n        right[H - 1] = src[base + H - 1];\n        for (int c = H - 2; c >= 0; --c) {\n            right[c] = min(src[base + c], safeAdd1(right[c + 1]));\n        }\n\n        for (int c = 0; c < H; ++c) {\n            horiz[base + c] = min(left[c], right[c]);\n        }\n    }\n\n    for (int c = 0; c < H; ++c) {\n        int up[H], down[H];\n\n        up[0] = horiz[c];\n        for (int r = 1; r < H; ++r) {\n            up[r] = min(horiz[r * H + c], safeAdd1(up[r - 1]));\n        }\n\n        down[H - 1] = horiz[(H - 1) * H + c];\n        for (int r = H - 2; r >= 0; --r) {\n            down[r] = min(horiz[r * H + c], safeAdd1(down[r + 1]));\n        }\n\n        for (int r = 0; r < H; ++r) {\n            out[r * H + c] = min(up[r], down[r]);\n        }\n    }\n}\n\nvoid applyChar(array<int, CELLS>& dp, char ch) {\n    array<int, CELLS> mv;\n    manhattanTransform(dp, mv);\n    int need = ch - 'A';\n    for (int i = 0; i < CELLS; ++i) {\n        dp[i] = (boardLetter[i] == need ? safeAdd1(mv[i]) : INF);\n    }\n}\n\nvoid applyString(array<int, CELLS>& dp, const string& s) {\n    for (char ch : s) applyChar(dp, ch);\n}\n\nvoid buildMoveAndBestStart(const array<int, CELLS>& dp,\n                           array<int, CELLS>& move,\n                           array<int, 26>& bestStart) {\n    manhattanTransform(dp, move);\n    bestStart.fill(INF);\n    for (int i = 0; i < CELLS; ++i) {\n        bestStart[boardLetter[i]] = min(bestStart[boardLetter[i]], move[i]);\n    }\n}\n\nbool overlapValid(const string& tail, const string& w, int k) {\n    if (k > (int)tail.size()) return false;\n    for (int i = 0; i < k; ++i) {\n        if (tail[(int)tail.size() - k + i] != w[i]) return false;\n    }\n    return true;\n}\n\nint wordApproxScore(const string& tail, int idx, const array<int, 26>& bestStart) {\n    int best = INF;\n    int lim = min(4, (int)tail.size());\n    const string& w = words[idx];\n    for (int k = 0; k <= lim; ++k) {\n        if (!overlapValid(tail, w, k)) continue;\n        int c = w[k] - 'A';\n        best = min(best, bestStart[c] + suffixLB[idx][k]);\n    }\n    return best;\n}\n\nint estimateFutureFromBestStart(const string& tail,\n                                const array<uint64_t, 4>& used,\n                                const array<int, 26>& bestStart) {\n    int best[FUTK];\n    for (int i = 0; i < FUTK; ++i) best[i] = INF;\n    int cnt = 0, rem = 0;\n\n    for (int idx = 0; idx < M; ++idx) {\n        if (usedBit(used, idx)) continue;\n        ++rem;\n        int sc = wordApproxScore(tail, idx, bestStart);\n        if (cnt < FUTK) {\n            int pos = cnt++;\n            while (pos > 0 && best[pos - 1] > sc) {\n                best[pos] = best[pos - 1];\n                --pos;\n            }\n            best[pos] = sc;\n        } else if (sc < best[FUTK - 1]) {\n            int pos = FUTK - 1;\n            while (pos > 0 && best[pos - 1] > sc) {\n                best[pos] = best[pos - 1];\n                --pos;\n            }\n            best[pos] = sc;\n        }\n    }\n\n    int k = min(FUTK, rem);\n    int sum = 0;\n    for (int i = 0; i < k; ++i) sum += best[i];\n    return sum;\n}\n\nstruct Node {\n    array<int, CELLS> dp{};\n    array<uint64_t, 4> used{};\n    string tail;\n    int lastWord = -1;\n    int ov = 0;\n    int parent = -1;\n    int depth = 0;\n    int cost = INF;\n    int future = INF;\n};\n\nNode makeRoot(int idx) {\n    Node st;\n    st.dp.fill(INF);\n    st.dp[si * H + sj] = 0;\n    applyString(st.dp, words[idx]);\n\n    st.used.fill(0);\n    setBit(st.used, idx);\n    st.tail = words[idx].substr(max(0, (int)words[idx].size() - 4));\n    st.lastWord = idx;\n    st.ov = 0;\n    st.parent = -1;\n    st.depth = 1;\n    st.cost = minCost(st.dp);\n\n    array<int, CELLS> move;\n    array<int, 26> bestStart;\n    buildMoveAndBestStart(st.dp, move, bestStart);\n    st.future = estimateFutureFromBestStart(st.tail, st.used, bestStart);\n    return st;\n}\n\nNode bestChildForCandidate(const Node& st, int parentId, int idx) {\n    Node best;\n    int bestPr = INF * 4;\n    array<uint64_t, 4> used2 = st.used;\n    setBit(used2, idx);\n\n    int lim = min(4, (int)st.tail.size());\n    for (int k = 0; k <= lim; ++k) {\n        if (!overlapValid(st.tail, words[idx], k)) continue;\n\n        array<int, CELLS> dp2 = st.dp;\n        applyString(dp2, suffixes[idx][k]);\n\n        int cost2 = minCost(dp2);\n\n        array<int, CELLS> move2;\n        array<int, 26> bestStart2;\n        buildMoveAndBestStart(dp2, move2, bestStart2);\n\n        string tail2 = st.tail + suffixes[idx][k];\n        if ((int)tail2.size() > 4) tail2.erase(0, (int)tail2.size() - 4);\n\n        int future2 = estimateFutureFromBestStart(tail2, used2, bestStart2);\n        int pr = cost2 + future2;\n\n        if (pr < bestPr ||\n            (pr == bestPr && cost2 < best.cost) ||\n            (pr == bestPr && cost2 == best.cost && k > best.ov)) {\n            bestPr = pr;\n            best.dp = dp2;\n            best.used = used2;\n            best.tail = tail2;\n            best.lastWord = idx;\n            best.ov = k;\n            best.parent = parentId;\n            best.depth = st.depth + 1;\n            best.cost = cost2;\n            best.future = future2;\n        }\n    }\n\n    return best;\n}\n\nstring reconstructString(const vector<Node>& pool, int id) {\n    vector<pair<int, int>> seq;\n    while (id != -1) {\n        seq.push_back({pool[id].lastWord, pool[id].ov});\n        id = pool[id].parent;\n    }\n    reverse(seq.begin(), seq.end());\n\n    string s = words[seq[0].first];\n    for (int i = 1; i < (int)seq.size(); ++i) {\n        s += suffixes[seq[i].first][seq[i].second];\n    }\n    return s;\n}\n\nstruct RunResult {\n    int cost = INF;\n    string s;\n};\n\nRunResult beamSearch(const vector<int>& seedIndices, int beamSize, int candK, uint64_t runSeed) {\n    FastRng rng(runSeed);\n\n    vector<Node> pool;\n    pool.reserve(60000);\n\n    vector<int> beam;\n    beam.reserve(seedIndices.size());\n\n    for (int idx : seedIndices) {\n        Node root = makeRoot(idx);\n        pool.push_back(std::move(root));\n        beam.push_back((int)pool.size() - 1);\n    }\n\n    auto cmp = [&](int a, int b) {\n        int pa = pool[a].cost + pool[a].future;\n        int pb = pool[b].cost + pool[b].future;\n        if (pa != pb) return pa < pb;\n        if (pool[a].cost != pool[b].cost) return pool[a].cost < pool[b].cost;\n        if (pool[a].future != pool[b].future) return pool[a].future < pool[b].future;\n        return a < b;\n    };\n\n    sort(beam.begin(), beam.end(), cmp);\n    if ((int)beam.size() > beamSize) beam.resize(beamSize);\n\n    for (int depth = 1; depth < M; ++depth) {\n        vector<int> nxt;\n        nxt.reserve((int)beam.size() * candK);\n\n        for (int id : beam) {\n            array<int, CELLS> move;\n            array<int, 26> bestStart;\n            buildMoveAndBestStart(pool[id].dp, move, bestStart);\n\n            vector<pair<int, int>> cand;\n            cand.reserve(M);\n            for (int idx = 0; idx < M; ++idx) {\n                if (usedBit(pool[id].used, idx)) continue;\n                int sc = wordApproxScore(pool[id].tail, idx, bestStart);\n                sc += (int)(rng.next() % 3); // tiny noise for diversity\n                cand.push_back({sc, idx});\n            }\n\n            sort(cand.begin(), cand.end());\n            if ((int)cand.size() > candK) cand.resize(candK);\n\n            for (auto [sc, idx] : cand) {\n                (void)sc;\n                Node child = bestChildForCandidate(pool[id], id, idx);\n                pool.push_back(std::move(child));\n                nxt.push_back((int)pool.size() - 1);\n            }\n        }\n\n        sort(nxt.begin(), nxt.end(), cmp);\n        if ((int)nxt.size() > beamSize) nxt.resize(beamSize);\n        beam.swap(nxt);\n    }\n\n    int bestId = beam[0];\n    for (int id : beam) {\n        if (cmp(id, bestId)) bestId = id;\n    }\n\n    RunResult res;\n    res.cost = pool[bestId].cost;\n    res.s = reconstructString(pool, bestId);\n    return res;\n}\n\npair<long long, vector<int>> solveTypingPath(const string& s) {\n    int L = (int)s.size();\n    vector<array<int16_t, CELLS>> par(L);\n\n    array<int, CELLS> dp, ndp;\n    dp.fill(INF);\n    dp[si * H + sj] = 0;\n\n    for (int i = 0; i < L; ++i) {\n        int c = s[i] - 'A';\n        ndp.fill(INF);\n        par[i].fill(-1);\n\n        for (int q : cellsByLetter[c]) {\n            int best = INF, bestp = -1;\n            for (int p = 0; p < CELLS; ++p) {\n                if (dp[p] >= INF) continue;\n                int v = dp[p] + distCell[p][q] + 1;\n                if (v < best) {\n                    best = v;\n                    bestp = p;\n                }\n            }\n            ndp[q] = best;\n            par[i][q] = (int16_t)bestp;\n        }\n        dp = ndp;\n    }\n\n    int end = -1, best = INF;\n    for (int q : cellsByLetter[s.back() - 'A']) {\n        if (dp[q] < best) {\n            best = dp[q];\n            end = q;\n        }\n    }\n\n    vector<int> path(L);\n    int cur = end;\n    for (int i = L - 1; i >= 0; --i) {\n        path[i] = cur;\n        cur = par[i][cur];\n    }\n    return {best, path};\n}\n\nvector<int> sampleSeeds(const vector<pair<int, int>>& ranked, int poolSize, int fixedTop, int take, FastRng& rng) {\n    vector<int> res;\n    int n = (int)ranked.size();\n    fixedTop = min(fixedTop, min(take, n));\n    for (int i = 0; i < fixedTop; ++i) res.push_back(ranked[i].second);\n\n    vector<int> pool;\n    int lim = min(poolSize, n);\n    for (int i = fixedTop; i < lim; ++i) pool.push_back(ranked[i].second);\n\n    for (int i = (int)pool.size() - 1; i > 0; --i) {\n        int j = rng.nextInt(0, i);\n        swap(pool[i], pool[j]);\n    }\n\n    for (int i = 0; i < take - fixedTop && i < (int)pool.size(); ++i) {\n        res.push_back(pool[i]);\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    cin >> si >> sj;\n    words.resize(M);\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    for (int i = 0; i < M; ++i) cin >> words[i];\n\n    for (int c = 0; c < 26; ++c) cellsByLetter[c].clear();\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * H + j;\n            int c = grid[i][j] - 'A';\n            boardLetter[id] = c;\n            cellsByLetter[c].push_back(id);\n        }\n    }\n\n    for (int a = 0; a < CELLS; ++a) {\n        int x1 = a / H, y1 = a % H;\n        for (int b = 0; b < CELLS; ++b) {\n            int x2 = b / H, y2 = b % H;\n            distCell[a][b] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) letterDist[a][b] = INF;\n    }\n    for (int a = 0; a < CELLS; ++a) {\n        int ca = boardLetter[a];\n        for (int b = 0; b < CELLS; ++b) {\n            int cb = boardLetter[b];\n            letterDist[ca][cb] = min(letterDist[ca][cb], distCell[a][b]);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        for (int k = 0; k <= 4; ++k) {\n            suffixes[i][k] = words[i].substr(k);\n            const string& t = suffixes[i][k];\n            int lb = (int)t.size();\n            for (int j = 1; j < (int)t.size(); ++j) {\n                lb += letterDist[t[j - 1] - 'A'][t[j] - 'A'];\n            }\n            suffixLB[i][k] = lb;\n        }\n    }\n\n    // Rank seed words by exact one-word cost + future estimate.\n    vector<pair<int, int>> seedRank; // (priority, idx)\n    seedRank.reserve(M);\n\n    for (int i = 0; i < M; ++i) {\n        Node root = makeRoot(i);\n        seedRank.push_back({root.cost + root.future, i});\n    }\n    sort(seedRank.begin(), seedRank.end());\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n\n    vector<RunResult> results;\n\n    // Run 1: strong deterministic top seeds\n    {\n        FastRng rng(baseSeed ^ 0x123456789abcdefULL);\n        vector<int> seeds = sampleSeeds(seedRank, 10, 10, 10, rng);\n        results.push_back(beamSearch(seeds, 10, 14, rng.next()));\n    }\n\n    // Run 2: diversified random subset from top 20\n    {\n        FastRng rng(baseSeed ^ 0xfedcba987654321ULL);\n        vector<int> seeds = sampleSeeds(seedRank, 20, 4, 12, rng);\n        results.push_back(beamSearch(seeds, 8, 18, rng.next()));\n    }\n\n    // Run 3: another diversified random subset from top 30\n    {\n        FastRng rng(baseSeed ^ 0x314159265358979ULL);\n        vector<int> seeds = sampleSeeds(seedRank, 30, 4, 12, rng);\n        results.push_back(beamSearch(seeds, 8, 20, rng.next()));\n    }\n\n    int bestIdx = 0;\n    for (int i = 1; i < (int)results.size(); ++i) {\n        if (results[i].cost < results[bestIdx].cost ||\n            (results[i].cost == results[bestIdx].cost &&\n             results[i].s.size() < results[bestIdx].s.size())) {\n            bestIdx = i;\n        }\n    }\n\n    auto [finalCost, path] = solveTypingPath(results[bestIdx].s);\n\n    for (int idx : path) {\n        cout << idx / H << ' ' << idx % H << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Block {\n    vector<pair<int,int>> cells;\n    double est = 0.0;\n};\n\nint N, M;\ndouble eps;\ndouble inv_coef;\n\nvector<vector<int>> known; // -1 unknown, 0 empty, 1 positive\nvector<pair<int,int>> positives;\nint op_cnt = 0;\n\nstatic inline double transform_estimate(double raw, int k) {\n    return (raw - k * eps) * inv_coef;\n}\n\ndouble ask_set(const vector<pair<int,int>>& cells) {\n    cout << \"q \" << cells.size();\n    for (auto [i, j] : cells) cout << ' ' << i << ' ' << j;\n    cout << '\\n' << flush;\n\n    int resp;\n    cin >> resp;\n    ++op_cnt;\n    return transform_estimate(resp, (int)cells.size());\n}\n\nvoid drill_cell(int i, int j) {\n    if (known[i][j] != -1) return;\n    cout << \"q 1 \" << i << ' ' << j << '\\n' << flush;\n\n    int resp;\n    cin >> resp;\n    ++op_cnt;\n\n    known[i][j] = (resp > 0 ? 1 : 0);\n    if (resp > 0) positives.push_back({i, j});\n}\n\ninline int id(int i, int j) { return i * N + j; }\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> eps;\n    inv_coef = 1.0 / (1.0 - 2.0 * eps);\n\n    // Read prior shape information (unused in this heuristic).\n    for (int k = 0; k < M; ++k) {\n        int d;\n        cin >> d;\n        for (int t = 0; t < d; ++t) {\n            int i, j;\n            cin >> i >> j;\n        }\n    }\n\n    known.assign(N, vector<int>(N, -1));\n    positives.clear();\n\n    vector<pair<int,int>> all_cells;\n    all_cells.reserve(N * N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) all_cells.push_back({i, j});\n    }\n\n    // Estimate total occupied count from the whole board.\n    double board_est = 0.0;\n    for (int rep = 0; rep < 3; ++rep) board_est += ask_set(all_cells);\n    board_est /= 3.0;\n    if (board_est < 0) board_est = 0;\n\n    // Row / column estimates.\n    vector<double> row_est(N, 0.0), col_est(N, 0.0);\n    vector<vector<pair<int,int>>> rows(N), cols(N);\n    for (int i = 0; i < N; ++i) {\n        rows[i].reserve(N);\n        for (int j = 0; j < N; ++j) rows[i].push_back({i, j});\n    }\n    for (int j = 0; j < N; ++j) {\n        cols[j].reserve(N);\n        for (int i = 0; i < N; ++i) cols[j].push_back({i, j});\n    }\n\n    for (int i = 0; i < N; ++i) row_est[i] = ask_set(rows[i]);\n    for (int j = 0; j < N; ++j) col_est[j] = ask_set(cols[j]);\n\n    // Overlapping 4x4 blocks with 4 offsets.\n    vector<Block> blocks;\n    blocks.reserve(400);\n\n    for (int oi = 0; oi < 2; ++oi) {\n        for (int oj = 0; oj < 2; ++oj) {\n            for (int r = oi; r + 3 < N; r += 2) {\n                for (int c = oj; c + 3 < N; c += 2) {\n                    Block b;\n                    b.cells.reserve(16);\n                    for (int i = r; i < r + 4; ++i) {\n                        for (int j = c; j < c + 4; ++j) {\n                            b.cells.push_back({i, j});\n                        }\n                    }\n                    b.est = ask_set(b.cells);\n                    blocks.push_back(move(b));\n                }\n            }\n        }\n    }\n\n    // Repeat a few ambiguous blocks once more to reduce noise.\n    vector<int> amb;\n    for (int idx = 0; idx < (int)blocks.size(); ++idx) {\n        if (blocks[idx].est > 0.4 && blocks[idx].est < 2.4) amb.push_back(idx);\n    }\n    sort(amb.begin(), amb.end(), [&](int a, int b) {\n        return fabs(blocks[a].est - 1.0) < fabs(blocks[b].est - 1.0);\n    });\n\n    int extra_repeats = min<int>(24, (int)amb.size());\n    for (int t = 0; t < extra_repeats; ++t) {\n        int idx = amb[t];\n        double est2 = ask_set(blocks[idx].cells);\n        blocks[idx].est = (blocks[idx].est + est2) * 0.5;\n    }\n\n    // Build heatmap.\n    vector<double> base(N * N, 0.0);\n\n    for (int i = 0; i < N; ++i) {\n        double x = max(0.0, row_est[i]) / N;\n        for (int j = 0; j < N; ++j) base[id(i, j)] += 0.15 * x;\n    }\n    for (int j = 0; j < N; ++j) {\n        double x = max(0.0, col_est[j]) / N;\n        for (int i = 0; i < N; ++i) base[id(i, j)] += 0.15 * x;\n    }\n    for (const auto& b : blocks) {\n        double x = max(0.0, b.est) / 16.0;\n        double add = 0.70 * x;\n        for (auto [i, j] : b.cells) base[id(i, j)] += add;\n    }\n\n    vector<double> heat(N * N, 0.0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int p = id(i, j);\n            double sum = base[p];\n            int cnt = 1;\n            if (i > 0) { sum += base[id(i - 1, j)]; ++cnt; }\n            if (i + 1 < N) { sum += base[id(i + 1, j)]; ++cnt; }\n            if (j > 0) { sum += base[id(i, j - 1)]; ++cnt; }\n            if (j + 1 < N) { sum += base[id(i, j + 1)]; ++cnt; }\n            heat[p] = 0.65 * base[p] + 0.35 * (sum / cnt);\n        }\n    }\n\n    vector<int> ord(N * N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (fabs(heat[a] - heat[b]) > 1e-12) return heat[a] > heat[b];\n        return a < b;\n    });\n\n    double total_est = max(0.0, board_est);\n\n    // Candidate sizes:\n    // - seedLimit: cells we drill first\n    // - expandLimit: slightly larger set used for local expansion\n    int seedLimit = (int)ceil(total_est * (1.25 + 0.50 * eps) + 10.0);\n    seedLimit = max(18, min(seedLimit, N * N));\n\n    int expandLimit = min(N * N, seedLimit + max(18, seedLimit / 5));\n\n    vector<char> inExpand(N * N, false);\n    for (int t = 0; t < expandLimit; ++t) inExpand[ord[t]] = true;\n\n    double lowHeat = 0.10;\n    if (expandLimit > 0) lowHeat = max(0.10, heat[ord[min(expandLimit - 1, N * N - 1)]] * 0.65);\n\n    queue<pair<int,int>> q;\n    static const int di[4] = {-1, 1, 0, 0};\n    static const int dj[4] = {0, 0, -1, 1};\n\n    auto maybe_expand_from = [&](int i, int j) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            if (known[ni][nj] != -1) continue;\n            int p = id(ni, nj);\n            if (!inExpand[p] && heat[p] < lowHeat) continue;\n            drill_cell(ni, nj);\n            if (known[ni][nj] == 1) q.push({ni, nj});\n        }\n    };\n\n    // Phase 1: drill the strongest cells.\n    for (int t = 0; t < seedLimit; ++t) {\n        int p = ord[t];\n        int i = p / N, j = p % N;\n        if (known[i][j] != -1) continue;\n        drill_cell(i, j);\n        if (known[i][j] == 1) q.push({i, j});\n    }\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        maybe_expand_from(i, j);\n    }\n\n    // Phase 2: drill the remaining cells inside the expanded candidate set.\n    for (int t = seedLimit; t < expandLimit; ++t) {\n        int p = ord[t];\n        int i = p / N, j = p % N;\n        if (known[i][j] != -1) continue;\n        drill_cell(i, j);\n        if (known[i][j] == 1) q.push({i, j});\n    }\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        maybe_expand_from(i, j);\n    }\n\n    // First guess.\n    vector<pair<int,int>> ans;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (known[i][j] == 1) ans.push_back({i, j});\n        }\n    }\n\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) cout << ' ' << i << ' ' << j;\n    cout << '\\n' << flush;\n\n    int ok;\n    cin >> ok;\n    if (ok == 1) return 0;\n\n    // Fallback: exact scan for all remaining cells.\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (known[i][j] == -1) drill_cell(i, j);\n        }\n    }\n\n    ans.clear();\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (known[i][j] == 1) ans.push_back({i, j});\n        }\n    }\n\n    cout << \"a \" << ans.size();\n    for (auto [i, j] : ans) cout << ' ' << i << ' ' << j;\n    cout << '\\n' << flush;\n\n    cin >> ok;\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const long long INFLL = (1LL << 60);\n\nint W, D, N;\n\nenum class Mode {\n    LOW_IDX,\n    HIGH_IDX,\n    UNIFORM,\n    REF\n};\n\nstruct Candidate {\n    vector<int> h;     // sorted heights\n    vector<int> pref;  // prefix sums except W\n    long long shortage = 0;\n};\n\nstatic inline vector<int> build_pref(const vector<int>& h) {\n    vector<int> pref;\n    pref.reserve(max(0, (int)h.size() - 1));\n    int s = 0;\n    for (int i = 0; i + 1 < (int)h.size(); ++i) {\n        s += h[i];\n        pref.push_back(s);\n    }\n    return pref;\n}\n\nstatic inline long long shortage_cost(const vector<int>& a, const vector<int>& h) {\n    long long c = 0;\n    for (int i = 0; i < (int)a.size(); ++i) {\n        long long area = 1LL * W * h[i];\n        if (a[i] > area) c += 100LL * (a[i] - area);\n    }\n    return c;\n}\n\nstatic Candidate make_candidate(const vector<int>& a, vector<int> h) {\n    sort(h.begin(), h.end());\n    Candidate c;\n    c.h = move(h);\n    c.pref = build_pref(c.h);\n    c.shortage = shortage_cost(a, c.h);\n    return c;\n}\n\nstatic inline long long gain_of_increment(const vector<int>& a, const vector<int>& h, int i) {\n    long long cur_short = 1LL * a[i] - 1LL * W * h[i];\n    if (cur_short <= 0) return 0;\n    return min<long long>(W, cur_short);\n}\n\nstatic inline int sym_diff_size(const vector<int>& x, const vector<int>& y) {\n    int i = 0, j = 0, c = 0;\n    while (i < (int)x.size() || j < (int)y.size()) {\n        int a = (i < (int)x.size() ? x[i] : INT_MAX);\n        int b = (j < (int)y.size() ? y[j] : INT_MAX);\n        if (a < b) {\n            ++c;\n            ++i;\n        } else if (b < a) {\n            ++c;\n            ++j;\n        } else {\n            ++i;\n            ++j;\n        }\n    }\n    return c;\n}\n\nstatic inline int boundary_diff_after_increment(const vector<int>& h, int idx, const vector<int>& refPref) {\n    int n = (int)h.size();\n    vector<int> cur;\n    cur.reserve(max(0, n - 1));\n    int s = 0;\n    for (int j = 0; j + 1 < n; ++j) {\n        s += h[j] + (j >= idx ? 1 : 0);\n        cur.push_back(s);\n    }\n    return sym_diff_size(cur, refPref);\n}\n\nstatic Candidate build_concentrated(const vector<int>& a, int m) {\n    int n = (int)a.size();\n    m = max(1, min(m, n));\n    vector<int> h(n, 1);\n    int extra = W - n;\n    int q = extra / m;\n    int r = extra % m;\n\n    for (int i = n - m; i < n; ++i) h[i] += q;\n    for (int i = n - r; i < n; ++i) h[i] += 1;\n\n    return make_candidate(a, move(h));\n}\n\nstatic Candidate build_proportional(const vector<int>& a) {\n    int n = (int)a.size();\n    vector<int> h(n, 1);\n    int extra = W - n;\n\n    long long sumA = 0;\n    for (int x : a) sumA += x;\n\n    vector<pair<long long, int>> rem;\n    rem.reserve(n);\n\n    long long used = 0;\n    for (int i = 0; i < n; ++i) {\n        long long num = 1LL * extra * a[i];\n        int add = (int)(num / sumA);\n        h[i] += add;\n        used += add;\n        rem.push_back({num % sumA, i});\n    }\n\n    int left = extra - (int)used;\n    sort(rem.begin(), rem.end(), [&](auto& x, auto& y) {\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n\n    for (int t = 0; t < left; ++t) h[rem[t].second] += 1;\n\n    return make_candidate(a, move(h));\n}\n\nstatic Candidate build_greedy(const vector<int>& a, Mode mode, const vector<int>* ref = nullptr) {\n    int n = (int)a.size();\n    vector<int> h(n, 1);\n    int extra = W - n;\n\n    vector<int> refPref;\n    if (mode == Mode::REF && ref) refPref = build_pref(*ref);\n\n    for (int step = 0; step < extra; ++step) {\n        long long bestGain = -1;\n        long long bestK1 = INFLL, bestK2 = INFLL;\n        int bestIdx = -1;\n\n        for (int i = 0; i < n; ++i) {\n            // keep the vector sorted\n            if (i + 1 < n && h[i] >= h[i + 1]) continue;\n\n            long long gain = gain_of_increment(a, h, i);\n            long long k1 = 0, k2 = 0;\n\n            switch (mode) {\n                case Mode::LOW_IDX:\n                    k1 = i;\n                    k2 = 0;\n                    break;\n                case Mode::HIGH_IDX:\n                    k1 = -i;\n                    k2 = 0;\n                    break;\n                case Mode::UNIFORM:\n                    k1 = llabs(1LL * (h[i] + 1) * n - W);\n                    k2 = i;\n                    break;\n                case Mode::REF:\n                    if (ref) {\n                        k1 = boundary_diff_after_increment(h, i, refPref);\n                        k2 = llabs(1LL * (h[i] + 1) - (*ref)[i]);\n                    } else {\n                        k1 = i;\n                        k2 = 0;\n                    }\n                    break;\n            }\n\n            if (gain > bestGain ||\n                (gain == bestGain &&\n                 (k1 < bestK1 ||\n                  (k1 == bestK1 &&\n                   (k2 < bestK2 ||\n                    (k2 == bestK2 && i < bestIdx)))))) {\n                bestGain = gain;\n                bestK1 = k1;\n                bestK2 = k2;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx < 0) bestIdx = n - 1;\n        h[bestIdx]++;\n    }\n\n    return make_candidate(a, move(h));\n}\n\nstatic inline void add_unique(vector<Candidate>& vec, Candidate cand) {\n    for (const auto& x : vec) {\n        if (x.h == cand.h) return;\n    }\n    vec.push_back(move(cand));\n}\n\nstruct SolveResult {\n    vector<vector<int>> heights;\n    long long cost = INFLL;\n};\n\nstatic SolveResult solve(const vector<vector<Candidate>>& sets) {\n    int dnum = (int)sets.size();\n    vector<vector<int>> parent(dnum);\n\n    vector<long long> prev(sets[0].size(), INFLL), cur;\n    for (int c = 0; c < (int)sets[0].size(); ++c) {\n        prev[c] = sets[0][c].shortage;\n    }\n\n    for (int d = 1; d < dnum; ++d) {\n        int pc = (int)sets[d - 1].size();\n        int cc = (int)sets[d].size();\n        cur.assign(cc, INFLL);\n        parent[d].assign(cc, -1);\n\n        for (int c = 0; c < cc; ++c) {\n            for (int p = 0; p < pc; ++p) {\n                long long trans = 1LL * W * sym_diff_size(sets[d - 1][p].pref, sets[d][c].pref);\n                long long val = prev[p] + trans + sets[d][c].shortage;\n                if (val < cur[c]) {\n                    cur[c] = val;\n                    parent[d][c] = p;\n                }\n            }\n        }\n        prev.swap(cur);\n    }\n\n    int last = (int)(min_element(prev.begin(), prev.end()) - prev.begin());\n\n    vector<int> choice(dnum);\n    choice[dnum - 1] = last;\n    for (int d = dnum - 1; d >= 1; --d) {\n        choice[d - 1] = parent[d][choice[d]];\n    }\n\n    SolveResult res;\n    res.cost = prev[last];\n    res.heights.resize(dnum);\n    for (int d = 0; d < dnum; ++d) {\n        res.heights[d] = sets[d][choice[d]].h;\n    }\n    return res;\n}\n\nstatic vector<vector<Candidate>> build_base_sets(const vector<vector<int>>& a) {\n    vector<vector<Candidate>> sets(D);\n    for (int d = 0; d < D; ++d) {\n        vector<int> ms = {1, 2, 4, 8, 16, max(1, N / 3), max(1, N / 2), N - 1, N};\n        sort(ms.begin(), ms.end());\n        ms.erase(unique(ms.begin(), ms.end()), ms.end());\n\n        for (int m : ms) {\n            if (1 <= m && m <= N) add_unique(sets[d], build_concentrated(a[d], m));\n        }\n\n        add_unique(sets[d], build_proportional(a[d]));\n        add_unique(sets[d], build_greedy(a[d], Mode::LOW_IDX));\n        add_unique(sets[d], build_greedy(a[d], Mode::HIGH_IDX));\n        add_unique(sets[d], build_greedy(a[d], Mode::UNIFORM));\n    }\n    return sets;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int i = 0; i < N; ++i) cin >> a[d][i];\n    }\n\n    // Pass 1\n    auto sets1 = build_base_sets(a);\n    auto res1 = solve(sets1);\n\n    // Pass 2: add the first solution and a ref-close greedy candidate\n    auto sets2 = sets1;\n    for (int d = 0; d < D; ++d) {\n        add_unique(sets2[d], make_candidate(a[d], res1.heights[d]));\n        if (d > 0) {\n            add_unique(sets2[d], build_greedy(a[d], Mode::REF, &res1.heights[d - 1]));\n        }\n    }\n    auto res2 = solve(sets2);\n\n    // Output the second-pass best sequence\n    for (int d = 0; d < D; ++d) {\n        int y = 0;\n        for (int k = 0; k < N; ++k) {\n            int h = res2.heights[d][k];\n            cout << 0 << ' ' << y << ' ' << W << ' ' << (y + h) << '\\n';\n            y += h;\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr ll MOD = 998244353LL;\nstatic constexpr int H = 9;\nstatic constexpr int W = 9;\nstatic constexpr int CELLS = 81;\nstatic constexpr int S = 3;\nstatic constexpr int POS = 7;\nstatic constexpr int STAMPS = 20;\nstatic constexpr int ACTIONS = STAMPS * POS * POS; // 980\nstatic constexpr int NOOP = ACTIONS;\nstatic constexpr int KMAX = 81;\n\nstatic constexpr int GREEDY_TOP = 8;\nstatic constexpr int LOOK_TOP = 8;\nstatic constexpr int BEAM_W = 8;\nstatic constexpr int BEAM_BRANCH = 6;\n\nstatic constexpr int POOL_GAIN = 24;\nstatic constexpr int POOL_SUM = 8;\nstatic constexpr int POOL_RANDOM = 2;\n\nstatic constexpr int RUIN_ROUNDS = 6;\n\nint N, M, K;\n\nstruct Action {\n    int m = -1, p = -1, q = -1;\n    array<int, CELLS> add{};\n    array<int, 9> cells{};\n    array<int, 9> vals{};\n};\n\nstruct Cand {\n    ll score = LLONG_MIN;\n    int id = -1;\n};\n\nstruct Result {\n    array<int, CELLS> board{};\n    array<int, KMAX> seq{};\n    ll score = 0;\n};\n\nstruct BeamState {\n    array<int, CELLS> board{};\n    array<int, KMAX> seq{};\n    ll score = 0;\n    ll key = 0;\n};\n\narray<array<array<int, 3>, 3>, STAMPS> stamps;\narray<Action, ACTIONS + 1> acts; // last one is NOOP\narray<ll, ACTIONS> actionSum{};\narray<int, ACTIONS> sumOrder{};\narray<int, CELLS> initBoard{};\n\ninline ll calc_score(const array<int, CELLS>& b) {\n    ll s = 0;\n    for (int x : b) s += x;\n    return s;\n}\n\ninline ll eval_gain(const array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    ll g = 0;\n    for (int t = 0; t < 9; ++t) {\n        int c = ac.cells[t];\n        int w = ac.vals[t];\n        int x = board[c];\n        if ((ll)x >= MOD - w) g += (ll)w - MOD;\n        else g += w;\n    }\n    return g;\n}\n\ninline void apply_action(array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    for (int t = 0; t < 9; ++t) {\n        int c = ac.cells[t];\n        int x = board[c] + ac.vals[t];\n        if (x >= MOD) x -= MOD;\n        board[c] = x;\n    }\n}\n\ninline void remove_action(array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    for (int t = 0; t < 9; ++t) {\n        int c = ac.cells[t];\n        int x = board[c] - ac.vals[t];\n        if (x < 0) x += MOD;\n        board[c] = x;\n    }\n}\n\ninline ll delta_replace_one(const array<int, CELLS>& board, int oldId, int newId) {\n    const auto& ao = acts[oldId].add;\n    const auto& an = acts[newId].add;\n    ll delta = 0;\n    for (int c = 0; c < CELLS; ++c) {\n        ll x = board[c];\n        x -= ao[c];\n        if (x < 0) x += MOD;\n        x += an[c];\n        if (x >= MOD) x -= MOD;\n        delta += x - board[c];\n    }\n    return delta;\n}\n\ninline void apply_replace_one(array<int, CELLS>& board, int oldId, int newId) {\n    const auto& ao = acts[oldId].add;\n    const auto& an = acts[newId].add;\n    for (int c = 0; c < CELLS; ++c) {\n        ll x = board[c];\n        x -= ao[c];\n        if (x < 0) x += MOD;\n        x += an[c];\n        if (x >= MOD) x -= MOD;\n        board[c] = (int)x;\n    }\n}\n\ntemplate <size_t T>\ninline void push_top(array<Cand, T>& top, int& n, ll score, int id) {\n    if (n < (int)T) {\n        int pos = n++;\n        while (pos > 0 &&\n               (top[pos - 1].score < score ||\n                (top[pos - 1].score == score && top[pos - 1].id > id))) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {score, id};\n    } else if (score > top[T - 1].score ||\n               (score == top[T - 1].score && id < top[T - 1].id)) {\n        int pos = (int)T - 1;\n        while (pos > 0 &&\n               (top[pos - 1].score < score ||\n                (top[pos - 1].score == score && top[pos - 1].id > id))) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {score, id};\n    }\n}\n\ntemplate <size_t T>\ninline int build_top(const array<int, CELLS>& board, array<Cand, T>& top) {\n    int n = 0;\n    for (int id = 0; id < ACTIONS; ++id) {\n        ll g = eval_gain(board, id);\n        push_top(top, n, g, id);\n    }\n    return n;\n}\n\ninline ll best_gain(const array<int, CELLS>& board) {\n    ll best = LLONG_MIN;\n    for (int id = 0; id < ACTIONS; ++id) {\n        best = max(best, eval_gain(board, id));\n    }\n    return best;\n}\n\ninline Result make_empty() {\n    Result r;\n    r.board = initBoard;\n    r.seq.fill(NOOP);\n    r.score = calc_score(r.board);\n    return r;\n}\n\ninline void add_unique(vector<int>& v, int x) {\n    for (int y : v) if (y == x) return;\n    v.push_back(x);\n}\n\nResult construct_greedy(bool stop_positive, bool randomize, mt19937_64& rng) {\n    Result r = make_empty();\n\n    for (int step = 0; step < KMAX; ++step) {\n        array<Cand, GREEDY_TOP> top{};\n        int n = build_top(r.board, top);\n        if (n == 0) break;\n        if (stop_positive && top[0].score <= 0) break;\n\n        int chosen = top[0].id;\n        if (randomize && n > 1) {\n            int lim = min(n, 4);\n            chosen = top[(int)(rng() % (unsigned long long)lim)].id;\n        }\n\n        ll g = eval_gain(r.board, chosen);\n        apply_action(r.board, chosen);\n        r.seq[step] = chosen;\n        r.score += g;\n    }\n\n    r.score = calc_score(r.board);\n    return r;\n}\n\nResult construct_lookahead(bool randomize, mt19937_64& rng) {\n    Result r = make_empty();\n    const int LOOK_STEPS = 10;\n\n    for (int step = 0; step < KMAX; ++step) {\n        array<Cand, LOOK_TOP> top{};\n        int n = build_top(r.board, top);\n        if (n == 0) break;\n\n        vector<pair<ll, int>> cand;\n        cand.reserve(min(n, LOOK_TOP) + 1);\n\n        // No-op candidate\n        cand.push_back({0, NOOP});\n\n        int lim = min(n, LOOK_TOP);\n        for (int i = 0; i < lim; ++i) {\n            int id = top[i].id;\n            ll score = top[i].score;\n            if (step < LOOK_STEPS) {\n                array<int, CELLS> tmp = r.board;\n                apply_action(tmp, id);\n                score += max(0LL, best_gain(tmp));\n            }\n            cand.push_back({score, id});\n        }\n\n        sort(cand.begin(), cand.end(), [](const auto& a, const auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n\n        if (cand[0].first <= 0) break;\n\n        int chosen = cand[0].second;\n        if (randomize && (int)cand.size() > 1) {\n            int lim2 = min<int>(4, (int)cand.size());\n            chosen = cand[(int)(rng() % (unsigned long long)lim2)].second;\n        }\n\n        if (chosen == NOOP) break;\n\n        ll g = eval_gain(r.board, chosen);\n        apply_action(r.board, chosen);\n        r.seq[step] = chosen;\n        r.score += g;\n    }\n\n    r.score = calc_score(r.board);\n    return r;\n}\n\nResult construct_beam(bool randomize, mt19937_64& rng) {\n    vector<BeamState> beam(1);\n    beam[0].board = initBoard;\n    beam[0].seq.fill(NOOP);\n    beam[0].score = calc_score(initBoard);\n    beam[0].key = beam[0].score;\n\n    for (int step = 0; step < KMAX; ++step) {\n        vector<BeamState> nxt;\n        nxt.reserve((int)beam.size() * (BEAM_BRANCH + 2));\n\n        for (const auto& st : beam) {\n            array<Cand, BEAM_BRANCH + 4> top{};\n            int n = build_top(st.board, top);\n\n            vector<int> ids;\n            ids.reserve(BEAM_BRANCH + 2);\n            for (int i = 0; i < min(n, BEAM_BRANCH); ++i) add_unique(ids, top[i].id);\n            if (randomize && n > 0) {\n                int lim = min(n, 4);\n                add_unique(ids, top[(int)(rng() % (unsigned long long)lim)].id);\n                add_unique(ids, top[(int)(rng() % (unsigned long long)n)].id);\n            }\n            add_unique(ids, NOOP);\n\n            for (int id : ids) {\n                BeamState ch = st;\n                ch.seq[step] = id;\n                if (id != NOOP) {\n                    ll g = eval_gain(st.board, id);\n                    apply_action(ch.board, id);\n                    ch.score += g;\n                }\n                ch.key = ch.score + max(0LL, best_gain(ch.board));\n                nxt.push_back(std::move(ch));\n            }\n        }\n\n        sort(nxt.begin(), nxt.end(), [](const BeamState& a, const BeamState& b) {\n            if (a.key != b.key) return a.key > b.key;\n            if (a.score != b.score) return a.score > b.score;\n            return a.seq < b.seq;\n        });\n\n        if ((int)nxt.size() > BEAM_W) nxt.resize(BEAM_W);\n        beam.swap(nxt);\n    }\n\n    const auto& best = *max_element(beam.begin(), beam.end(), [](const BeamState& a, const BeamState& b) {\n        if (a.score != b.score) return a.score < b.score;\n        return a.key < b.key;\n    });\n\n    Result r;\n    r.board = best.board;\n    r.seq = best.seq;\n    r.score = calc_score(r.board);\n    return r;\n}\n\nvector<int> build_pool(const array<int, CELLS>& board, mt19937_64& rng) {\n    array<Cand, 32> top{};\n    int n = build_top(board, top);\n\n    vector<int> pool;\n    pool.reserve(POOL_GAIN + POOL_SUM + POOL_RANDOM + 1);\n\n    add_unique(pool, NOOP);\n    for (int i = 0; i < min(n, POOL_GAIN); ++i) add_unique(pool, top[i].id);\n    for (int i = 0; i < min(POOL_SUM, ACTIONS); ++i) add_unique(pool, sumOrder[i]);\n    for (int i = 0; i < POOL_RANDOM; ++i) add_unique(pool, (int)(rng() % (unsigned long long)ACTIONS));\n\n    return pool;\n}\n\nvoid local_pool_improve(Result& r, int passes, mt19937_64& rng) {\n    for (int pass = 0; pass < passes; ++pass) {\n        vector<int> pool = build_pool(r.board, rng);\n\n        vector<pair<ll, int>> slots;\n        slots.reserve(KMAX);\n        for (int pos = 0; pos < KMAX; ++pos) {\n            if (r.seq[pos] == NOOP) continue;\n            ll rem = delta_replace_one(r.board, r.seq[pos], NOOP);\n            slots.push_back({rem, pos});\n        }\n\n        sort(slots.begin(), slots.end(), [](const auto& a, const auto& b) {\n            if (a.first != b.first) return a.first < b.first; // weak slots first\n            return a.second < b.second;\n        });\n\n        bool any = false;\n        for (auto [_, pos] : slots) {\n            int old = r.seq[pos];\n            ll bestDelta = 0;\n            int bestId = old;\n\n            for (int id : pool) {\n                if (id == old) continue;\n                ll d = delta_replace_one(r.board, old, id);\n                if (d > bestDelta || (d == bestDelta && id < bestId)) {\n                    bestDelta = d;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != old && bestDelta > 0) {\n                apply_replace_one(r.board, old, bestId);\n                r.seq[pos] = bestId;\n                r.score += bestDelta;\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    r.score = calc_score(r.board);\n}\n\nvoid exact_single_improve(Result& r, int passes = 1) {\n    for (int pass = 0; pass < passes; ++pass) {\n        bool any = false;\n        for (int pos = 0; pos < KMAX; ++pos) {\n            int old = r.seq[pos];\n            ll bestDelta = 0;\n            int bestId = old;\n\n            for (int id = 0; id <= ACTIONS; ++id) {\n                if (id == old) continue;\n                ll d = delta_replace_one(r.board, old, id);\n                if (d > bestDelta || (d == bestDelta && id < bestId)) {\n                    bestDelta = d;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != old && bestDelta > 0) {\n                apply_replace_one(r.board, old, bestId);\n                r.seq[pos] = bestId;\n                r.score += bestDelta;\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    r.score = calc_score(r.board);\n}\n\nvoid ruin_recreate(Result& r, mt19937_64& rng) {\n    static const array<int, RUIN_ROUNDS> ruinSizes = {8, 12, 16, 20, 12, 8};\n\n    for (int round = 0; round < RUIN_ROUNDS; ++round) {\n        Result cur = r;\n\n        vector<pair<ll, int>> removable;\n        removable.reserve(KMAX);\n        for (int pos = 0; pos < KMAX; ++pos) {\n            if (cur.seq[pos] == NOOP) continue;\n            ll rem = delta_replace_one(cur.board, cur.seq[pos], NOOP);\n            removable.push_back({rem, pos});\n        }\n\n        if ((int)removable.size() < 2) break;\n\n        sort(removable.begin(), removable.end(), [](const auto& a, const auto& b) {\n            if (a.first != b.first) return a.first < b.first; // weakest first\n            return a.second < b.second;\n        });\n\n        int target = min(ruinSizes[round], (int)removable.size());\n        vector<int> positions;\n        positions.reserve(target);\n\n        // take from among the weakest and shuffle a bit\n        int lim = min((int)removable.size(), target * 3);\n        for (int i = 0; i < lim; ++i) positions.push_back(removable[i].second);\n        shuffle(positions.begin(), positions.end(), rng);\n        positions.resize(target);\n\n        // Remove selected actions.\n        for (int pos : positions) {\n            if (cur.seq[pos] != NOOP) {\n                remove_action(cur.board, cur.seq[pos]);\n                cur.seq[pos] = NOOP;\n            }\n        }\n\n        // Refill removed slots greedily on the modified board.\n        for (int pos : positions) {\n            array<Cand, GREEDY_TOP> top{};\n            int n = build_top(cur.board, top);\n            if (n == 0) continue;\n\n            int chosen = top[0].id;\n            if (n > 1 && (rng() & 3ULL) == 0) {\n                int lim2 = min(n, 4);\n                chosen = top[(int)(rng() % (unsigned long long)lim2)].id;\n            }\n\n            ll g = eval_gain(cur.board, chosen);\n            apply_action(cur.board, chosen);\n            cur.seq[pos] = chosen;\n            cur.score += g;\n        }\n\n        local_pool_improve(cur, 1, rng);\n        if (cur.score > r.score) r = std::move(cur);\n    }\n\n    r.score = calc_score(r.board);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\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    for (int m = 0; m < STAMPS; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    // Precompute actions.\n    int id = 0;\n    for (int m = 0; m < STAMPS; ++m) {\n        for (int p = 0; p < POS; ++p) {\n            for (int q = 0; q < POS; ++q) {\n                Action ac{};\n                ac.m = m;\n                ac.p = p;\n                ac.q = q;\n\n                ll s = 0;\n                int t = 0;\n                for (int di = 0; di < 3; ++di) {\n                    for (int dj = 0; dj < 3; ++dj) {\n                        int c = (p + di) * W + (q + dj);\n                        int v = stamps[m][di][dj];\n                        ac.cells[t] = c;\n                        ac.vals[t] = v;\n                        ac.add[c] = v;\n                        ++t;\n                        s += v;\n                    }\n                }\n                acts[id] = ac;\n                actionSum[id] = s;\n                ++id;\n            }\n        }\n    }\n    acts[ACTIONS] = Action{}; // NOOP\n\n    for (int i = 0; i < ACTIONS; ++i) sumOrder[i] = i;\n    sort(sumOrder.begin(), sumOrder.end(), [&](int x, int y) {\n        if (actionSum[x] != actionSum[y]) return actionSum[x] > actionSum[y];\n        return x < y;\n    });\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            initBoard[i * W + j] = a[i][j];\n        }\n    }\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<Result> cand;\n    cand.reserve(6);\n\n    cand.push_back(make_empty());\n    cand.push_back(construct_greedy(true, false, rng));   // stop when non-positive\n    cand.push_back(construct_greedy(false, false, rng));  // always fill\n    cand.push_back(construct_greedy(true, true, rng));    // randomized greedy\n    cand.push_back(construct_lookahead(true, rng));       // lookahead\n    cand.push_back(construct_beam(true, rng));            // beam search\n\n    // Light improvement for all candidates.\n    for (auto& r : cand) {\n        local_pool_improve(r, 1, rng);\n    }\n\n    // Ruin-and-recreate on the best few.\n    vector<int> ord(cand.size());\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        return cand[x].score > cand[y].score;\n    });\n\n    int strongCnt = min<int>(3, (int)ord.size());\n    for (int t = 0; t < strongCnt; ++t) {\n        ruin_recreate(cand[ord[t]], rng);\n        exact_single_improve(cand[ord[t]], 1);\n        local_pool_improve(cand[ord[t]], 1, rng);\n    }\n\n    // Pick the best after refinement.\n    Result best = cand[0];\n    for (auto& r : cand) {\n        if (r.score > best.score) best = r;\n    }\n\n    // Final exact polishing.\n    exact_single_improve(best, 1);\n    local_pool_improve(best, 1, rng);\n    exact_single_improve(best, 1);\n\n    vector<tuple<int, int, int>> ans;\n    ans.reserve(KMAX);\n    for (int i = 0; i < KMAX; ++i) {\n        int aid = best.seq[i];\n        if (aid == NOOP) continue;\n        ans.emplace_back(acts[aid].m, acts[aid].p, acts[aid].q);\n    }\n\n    cout << ans.size() << '\\n';\n    for (auto [m, p, q] : ans) {\n        cout << m << ' ' << p << ' ' << q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int FULL_MASK = (1 << N) - 1;\nstatic constexpr int BEAM = 8000; // enough for strong search, still fast\n\nstruct Node {\n    array<uint8_t, N> p{};      // next unread index in each source row\n    array<uint8_t, N> mask{};   // dispatched ranks for each gate (bitmask of ranks 0..4)\n    uint8_t curRow = 0;         // current crane row (if start==false, crane is at (curRow, 4))\n    bool start = true;          // true only at the beginning\n    int turns = 0;             // M0 so far\n    int inv = 0;               // M1 so far\n    int lb = 0;                // optimistic lower bound of remaining inversions\n    int parent = -1;           // parent node index in global pool\n    int choice = -1;           // chosen source row at this step\n    int eval = 0;              // turns + 100*(inv + lb)\n};\n\nstatic inline uint64_t packKey(const Node& s) {\n    // bits:\n    // 0..2   : curRow\n    // 3..27  : mask[0..4] (5 bits each)\n    // 28..42 : p[0..4] (3 bits each)\n    // 43     : start\n    uint64_t k = 0;\n    k |= uint64_t(s.curRow);\n    for (int i = 0; i < N; ++i) {\n        k |= uint64_t(s.mask[i]) << (3 + 5 * i);\n        k |= uint64_t(s.p[i]) << (28 + 3 * i);\n    }\n    if (s.start) k |= 1ULL << 43;\n    return k;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inN;\n    cin >> inN; // fixed to 5\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> A[i][j];\n    }\n\n    // rankOf[v] = local rank 0..4 inside its destination gate\n    array<int, 25> rankOf{};\n    array<vector<int>, N> gateVals;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            gateVals[A[i][j] / N].push_back(A[i][j]);\n        }\n    }\n    for (int g = 0; g < N; ++g) {\n        sort(gateVals[g].begin(), gateVals[g].end());\n        for (int r = 0; r < N; ++r) rankOf[gateVals[g][r]] = r;\n    }\n\n    // addInv[mask][r] = number of already-dispatched ranks in mask that are > r\n    int addInv[32][N]{};\n    // forcedLB[mask] = lower bound of future inversions caused by already-dispatched\n    // higher ranks and still-undispatched lower ranks.\n    int forcedLB[32]{};\n\n    for (int mask = 0; mask < 32; ++mask) {\n        for (int r = 0; r < N; ++r) {\n            addInv[mask][r] = __builtin_popcount((unsigned)(mask >> (r + 1)));\n        }\n        int lb = 0;\n        for (int hi = 0; hi < N; ++hi) if (mask & (1 << hi)) {\n            lb += __builtin_popcount((unsigned)((FULL_MASK ^ mask) & ((1 << hi) - 1)));\n        }\n        forcedLB[mask] = lb;\n    }\n\n    // Exact move cost for one chosen container:\n    // start == true  : current crane is at (0,0)\n    // start == false : current crane is at (curRow, 4)\n    int costStart[N][N];\n    int costMid[N][N][N];\n    for (int r = 0; r < N; ++r) {\n        for (int g = 0; g < N; ++g) {\n            // from (0,0) to (r,0), pick, to (g,4), release\n            costStart[r][g] = r + abs(r - g) + 6; // moves + P + Q\n        }\n    }\n    for (int c = 0; c < N; ++c) {\n        for (int r = 0; r < N; ++r) {\n            for (int g = 0; g < N; ++g) {\n                // from (c,4) to (r,0), pick, to (g,4), release\n                costMid[c][r][g] = abs(c - r) + abs(r - g) + 10;\n            }\n        }\n    }\n\n    vector<Node> pool;\n    pool.reserve(200000);\n\n    Node root;\n    root.start = true;\n    root.curRow = 0;\n    root.turns = 0;\n    root.inv = 0;\n    root.lb = 0;\n    root.eval = 0;\n    pool.push_back(root);\n\n    vector<int> layer = {0};\n\n    for (int step = 0; step < N * N; ++step) {\n        unordered_map<uint64_t, int> pos;\n        pos.reserve(layer.size() * N * 2);\n        pos.max_load_factor(0.7f);\n\n        vector<Node> nxt;\n        nxt.reserve(layer.size() * N);\n\n        for (int gid : layer) {\n            const Node& s = pool[gid];\n            for (int r = 0; r < N; ++r) {\n                if (s.p[r] >= N) continue;\n\n                int v = A[r][s.p[r]];\n                int g = v / N;\n                int rk = rankOf[v];\n\n                Node t = s;\n                t.p[r]++;\n\n                int oldMask = t.mask[g];\n                int newMask = oldMask | (1 << rk);\n\n                t.mask[g] = (uint8_t)newMask;\n                t.inv += addInv[oldMask][rk];\n                t.lb += forcedLB[newMask] - forcedLB[oldMask];\n\n                if (s.start) t.turns += costStart[r][g];\n                else t.turns += costMid[s.curRow][r][g];\n\n                t.curRow = (uint8_t)g;\n                t.start = false;\n                t.parent = gid;\n                t.choice = r;\n                t.eval = t.turns + 100 * (t.inv + t.lb);\n\n                uint64_t key = packKey(t);\n                auto it = pos.find(key);\n                int exact = t.turns + 100 * t.inv;\n\n                if (it == pos.end()) {\n                    pos[key] = (int)nxt.size();\n                    nxt.push_back(t);\n                } else {\n                    Node& u = nxt[it->second];\n                    int exactU = u.turns + 100 * u.inv;\n                    if (exact < exactU) {\n                        u = t;\n                    }\n                }\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        vector<int> ord(nxt.size());\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (nxt[a].eval != nxt[b].eval) return nxt[a].eval < nxt[b].eval;\n            int ea = nxt[a].turns + 100 * nxt[a].inv;\n            int eb = nxt[b].turns + 100 * nxt[b].inv;\n            if (ea != eb) return ea < eb;\n            if (nxt[a].turns != nxt[b].turns) return nxt[a].turns < nxt[b].turns;\n            if (nxt[a].inv != nxt[b].inv) return nxt[a].inv < nxt[b].inv;\n            return nxt[a].lb < nxt[b].lb;\n        });\n\n        if ((int)ord.size() > BEAM) ord.resize(BEAM);\n\n        vector<int> newLayer;\n        newLayer.reserve(ord.size());\n        for (int idx : ord) {\n            pool.push_back(nxt[idx]);\n            newLayer.push_back((int)pool.size() - 1);\n        }\n        layer.swap(newLayer);\n    }\n\n    // Pick the best final node.\n    int bestId = layer[0];\n    int bestScore = pool[bestId].turns + 100 * pool[bestId].inv;\n    for (int id : layer) {\n        int sc = pool[id].turns + 100 * pool[id].inv;\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestId = id;\n        }\n    }\n\n    // Reconstruct chosen source-row sequence.\n    vector<int> order;\n    for (int id = bestId; pool[id].parent != -1; id = pool[id].parent) {\n        order.push_back(pool[id].choice);\n    }\n    reverse(order.begin(), order.end());\n\n    // Emit the operations for the large crane.\n    string big;\n    big.reserve(10000);\n\n    int x = 0, y = 0; // large crane position; starts at (0,0)\n    array<int, N> ptr{};\n    ptr.fill(0);\n\n    auto move_to = [&](int nx, int ny) {\n        while (x < nx) { big.push_back('D'); ++x; }\n        while (x > nx) { big.push_back('U'); --x; }\n        while (y < ny) { big.push_back('R'); ++y; }\n        while (y > ny) { big.push_back('L'); --y; }\n    };\n\n    for (int r : order) {\n        int v = A[r][ptr[r]++];\n        int g = v / N;\n\n        // go to source gate (r,0)\n        move_to(r, 0);\n        big.push_back('P');\n\n        // go to destination gate (g,4)\n        move_to(g, N - 1);\n        big.push_back('Q');\n    }\n\n    int T = (int)big.size();\n    vector<string> ans(N, string(T, '.'));\n\n    // Large crane\n    ans[0] = big;\n\n    // Bomb the 4 small cranes on turn 1, then they do nothing.\n    for (int i = 1; i < N; ++i) ans[i][0] = 'B';\n\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct P {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> H[i][j];\n    }\n\n    auto gen_base_cycle = [&](int N) {\n        vector<P> seq;\n        seq.reserve(N * N);\n        seq.push_back({0, 0});\n        for (int y = 1; y < N; ++y) seq.push_back({0, y});\n\n        for (int x = 1; x <= N - 2; ++x) {\n            if (x % 2 == 1) {\n                for (int y = N - 1; y >= 1; --y) seq.push_back({x, y});\n            } else {\n                for (int y = 1; y <= N - 1; ++y) seq.push_back({x, y});\n            }\n        }\n\n        for (int y = N - 1; y >= 0; --y) seq.push_back({N - 1, y});\n        for (int x = N - 2; x >= 1; --x) seq.push_back({x, 0});\n        return seq;\n    };\n\n    auto transform = [&](const P& p, int t) -> P {\n        int x = p.x, y = p.y;\n        switch (t) {\n            case 0: return {x, y};\n            case 1: return {x, N - 1 - y};\n            case 2: return {N - 1 - x, y};\n            case 3: return {N - 1 - x, N - 1 - y};\n            case 4: return {y, x};\n            case 5: return {y, N - 1 - x};\n            case 6: return {N - 1 - y, x};\n            case 7: return {N - 1 - y, N - 1 - x};\n        }\n        return {x, y};\n    };\n\n    vector<P> base = gen_base_cycle(N);\n\n    ll bestCost = (1LL << 60);\n    vector<P> bestSeq;\n    int bestStart = 0;\n\n    auto eval_candidate = [&](vector<P> seq) {\n        int L = (int)seq.size();\n        vector<ll> pref(L + 1, 0);\n        for (int i = 0; i < L; ++i) {\n            pref[i + 1] = pref[i] + H[seq[i].x][seq[i].y];\n        }\n\n        ll mn = pref[0];\n        for (int i = 1; i < L; ++i) mn = min(mn, pref[i]);\n\n        for (int s = 0; s < L; ++s) {\n            if (pref[s] != mn) continue; // valid rotation start\n\n            ll cost = 100LL * (seq[s].x + seq[s].y); // empty move to the start cell\n            ll cur = 0;\n            for (int k = 0; k < L; ++k) {\n                const P& p = seq[(s + k) % L];\n                cur += H[p.x][p.y];\n                if (k + 1 < L) cost += 100 + cur; // move to next cell\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSeq = seq;\n                bestStart = s;\n            }\n        }\n    };\n\n    for (int t = 0; t < 8; ++t) {\n        vector<P> seq;\n        seq.reserve(base.size());\n        for (const auto& p : base) seq.push_back(transform(p, t));\n\n        eval_candidate(seq);\n        reverse(seq.begin(), seq.end());\n        eval_candidate(seq);\n    }\n\n    // Output operations\n    vector<string> ops;\n    ops.reserve(1000);\n\n    auto add_op = [&](const string& s) {\n        ops.push_back(s);\n    };\n\n    // Move empty from (0,0) to the chosen start cell\n    int cx = 0, cy = 0;\n    P startP = bestSeq[bestStart];\n    while (cx < startP.x) {\n        add_op(\"D\");\n        ++cx;\n    }\n    while (cx > startP.x) {\n        add_op(\"U\");\n        --cx;\n    }\n    while (cy < startP.y) {\n        add_op(\"R\");\n        ++cy;\n    }\n    while (cy > startP.y) {\n        add_op(\"L\");\n        --cy;\n    }\n\n    int L = (int)bestSeq.size();\n    for (int step = 0; step < L; ++step) {\n        int idx = (bestStart + step) % L;\n        P p = bestSeq[idx];\n        int h = H[p.x][p.y];\n        if (h > 0) {\n            add_op(\"+\" + to_string(h));\n        } else if (h < 0) {\n            add_op(\"-\" + to_string(-h));\n        }\n\n        if (step + 1 < L) {\n            P q = bestSeq[(bestStart + step + 1) % L];\n            if (q.x == p.x + 1 && q.y == p.y) add_op(\"D\");\n            else if (q.x == p.x - 1 && q.y == p.y) add_op(\"U\");\n            else if (q.x == p.x && q.y == p.y + 1) add_op(\"R\");\n            else if (q.x == p.x && q.y == p.y - 1) add_op(\"L\");\n            else {\n                // Should never happen for our Hamiltonian cycle.\n                // If it does, the output would be invalid, so keep a safe fallback.\n                // But in practice, this branch is unreachable.\n            }\n        }\n    }\n\n    for (const auto& s : ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXM = 15;\nstatic constexpr int MAXS = 60;\nstatic constexpr int MAXP = 36;\nstatic constexpr int MAXV = 100;\n\nstruct Seed {\n    array<int, MAXM> x{};\n    int sum = 0;\n};\n\nstruct SelState {\n    vector<int> sel; // size 36\n    array<array<int, MAXV + 1>, MAXM> cnt{};\n    array<int, MAXM> mx{};\n    array<int, MAXM> sec{};\n    array<int, MAXM> cntMx{};\n    array<long long, MAXS> rowSum{};\n    long long pairSum = 0;\n    long long cov = 0;\n};\n\nstatic inline void recalc_traits(SelState& st, int M) {\n    st.cov = 0;\n    for (int l = 0; l < M; l++) {\n        int mx = 0, sec = 0, cmax = 0;\n        bool found = false;\n        for (int v = MAXV; v >= 0; v--) {\n            int c = st.cnt[l][v];\n            if (!c) continue;\n            if (!found) {\n                mx = v;\n                cmax = c;\n                found = true;\n            } else {\n                sec = v;\n                break;\n            }\n        }\n        st.mx[l] = mx;\n        st.sec[l] = sec;\n        st.cntMx[l] = cmax;\n        st.cov += mx;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int S = 2 * N * (N - 1); // 60\n    const int P = N * N;           // 36\n\n    vector<Seed> seeds(S);\n    for (int i = 0; i < S; i++) {\n        int s = 0;\n        for (int j = 0; j < M; j++) {\n            cin >> seeds[i].x[j];\n            s += seeds[i].x[j];\n        }\n        seeds[i].sum = s;\n    }\n\n    // Grid graph\n    vector<pair<int, int>> edges;\n    vector<vector<int>> cellNbs(P);\n    vector<int> cellDeg(P), cellDist(P);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            int deg = 0;\n            if (i > 0) deg++;\n            if (i + 1 < N) deg++;\n            if (j > 0) deg++;\n            if (j + 1 < N) deg++;\n            cellDeg[id] = deg;\n            cellDist[id] = abs(2 * i - (N - 1)) + abs(2 * j - (N - 1));\n\n            if (i + 1 < N) {\n                int to = (i + 1) * N + j;\n                edges.push_back({id, to});\n                cellNbs[id].push_back(to);\n                cellNbs[to].push_back(id);\n            }\n            if (j + 1 < N) {\n                int to = i * N + (j + 1);\n                edges.push_back({id, to});\n                cellNbs[id].push_back(to);\n                cellNbs[to].push_back(id);\n            }\n        }\n    }\n\n    vector<int> posDeg, posSnake;\n    {\n        vector<tuple<int, int, int>> cells;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int id = i * N + j;\n                cells.emplace_back(-cellDeg[id], cellDist[id], id);\n            }\n        }\n        sort(cells.begin(), cells.end());\n        for (auto &t : cells) posDeg.push_back(get<2>(t));\n\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; j++) posSnake.push_back(i * N + j);\n            } else {\n                for (int j = N - 1; j >= 0; j--) posSnake.push_back(i * N + j);\n            }\n        }\n    }\n\n    mt19937 rng(712367821);\n\n    auto read_pool = [&]() {\n        for (int i = 0; i < S; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    };\n\n    auto build_state = [&](const vector<int>& sel,\n                           const array<array<int, MAXS>, MAXS>& W) {\n        SelState st;\n        st.sel = sel;\n\n        for (int l = 0; l < M; l++) {\n            for (int v = 0; v <= MAXV; v++) st.cnt[l][v] = 0;\n        }\n\n        for (int id : sel) {\n            for (int l = 0; l < M; l++) {\n                st.cnt[l][seeds[id].x[l]]++;\n            }\n        }\n\n        st.rowSum.fill(0);\n        for (int id : sel) {\n            for (int x = 0; x < S; x++) st.rowSum[x] += W[x][id];\n        }\n\n        st.pairSum = 0;\n        for (int i = 0; i < P; i++) {\n            for (int j = i + 1; j < P; j++) {\n                st.pairSum += W[sel[i]][sel[j]];\n            }\n        }\n\n        recalc_traits(st, M);\n        return st;\n    };\n\n    auto score_sel = [&](const SelState& st, long long beta) {\n        return st.pairSum + beta * st.cov;\n    };\n\n    auto refine_selection = [&](SelState st,\n                                const array<array<int, MAXS>, MAXS>& W,\n                                long long betaSel) {\n        for (int iter = 0; iter < 2; iter++) {\n            vector<char> inSel(S, 0);\n            for (int id : st.sel) inSel[id] = 1;\n\n            // shortlist of promising unselected seeds\n            vector<pair<long long, int>> candScore;\n            candScore.reserve(S);\n\n            for (int x = 0; x < S; x++) if (!inSel[x]) {\n                long long gain = 0;\n                for (int l = 0; l < M; l++) {\n                    gain += max(0, seeds[x].x[l] - st.mx[l]);\n                }\n                long long approx = st.rowSum[x] + 40LL * gain + seeds[x].sum;\n                candScore.push_back({approx, x});\n            }\n\n            sort(candScore.begin(), candScore.end(),\n                 [&](const auto& a, const auto& b) {\n                     if (a.first != b.first) return a.first > b.first;\n                     return a.second < b.second;\n                 });\n\n            vector<int> shortlist;\n            for (int i = 0; i < (int)candScore.size() && i < 12; i++) {\n                shortlist.push_back(candScore[i].second);\n            }\n\n            long long bestDelta = 0;\n            int bestPos = -1, bestCand = -1;\n\n            for (int pos = 0; pos < P; pos++) {\n                int old = st.sel[pos];\n                for (int cand : shortlist) {\n                    if (cand == old) continue;\n\n                    long long dPair = st.rowSum[cand] - W[cand][old] - st.rowSum[old];\n\n                    long long dCov = 0;\n                    for (int l = 0; l < M; l++) {\n                        int ov = seeds[old].x[l];\n                        int nv = seeds[cand].x[l];\n                        int mx = st.mx[l];\n                        int sec = st.sec[l];\n                        int cntMx = st.cntMx[l];\n\n                        int newMax = mx;\n                        if (nv > mx) {\n                            newMax = nv;\n                        } else if (ov == mx && cntMx == 1) {\n                            newMax = max(sec, nv);\n                        }\n                        dCov += newMax - mx;\n                    }\n\n                    long long d = dPair + betaSel * dCov;\n                    if (d > bestDelta) {\n                        bestDelta = d;\n                        bestPos = pos;\n                        bestCand = cand;\n                    }\n                }\n            }\n\n            if (bestDelta <= 0) break;\n\n            int old = st.sel[bestPos];\n            st.sel[bestPos] = bestCand;\n\n            // update row sums\n            for (int x = 0; x < S; x++) {\n                st.rowSum[x] += W[x][bestCand] - W[x][old];\n            }\n\n            // update trait counts\n            for (int l = 0; l < M; l++) {\n                st.cnt[l][seeds[old].x[l]]--;\n                st.cnt[l][seeds[bestCand].x[l]]++;\n            }\n\n            st.pairSum += bestDelta - betaSel * 0; // placeholder, pairSum corrected below\n            // pairSum must be updated precisely\n            // dPair was computed from the old state, so use it directly:\n            // recompute with the same values is unnecessary here, but easiest is:\n            // pairSum += dPair\n            // To keep this compact, recompute pairSum from rowSum/selection would be expensive.\n            // Instead, we do a tiny exact update here:\n            long long exactPairDelta = 0;\n            for (int j = 0; j < P; j++) if (j != bestPos) {\n                int other = st.sel[j];\n                exactPairDelta += W[bestCand][other] - W[old][other];\n            }\n            st.pairSum += exactPairDelta;\n\n            recalc_traits(st, M);\n        }\n\n        return st;\n    };\n\n    auto score_arr = [&](const vector<int>& perm, const auto& Wsel) {\n        long long sc = 0;\n        for (auto [u, v] : edges) sc += Wsel[perm[u]][perm[v]];\n        return sc;\n    };\n\n    auto delta_swap = [&](const vector<int>& perm, int a, int b, const auto& Wsel) {\n        int sa = perm[a];\n        int sb = perm[b];\n        long long d = 0;\n\n        for (int na : cellNbs[a]) {\n            if (na == b) continue;\n            d += (long long)Wsel[sb][perm[na]] - Wsel[sa][perm[na]];\n        }\n        for (int nb : cellNbs[b]) {\n            if (nb == a) continue;\n            d += (long long)Wsel[sa][perm[nb]] - Wsel[sb][perm[nb]];\n        }\n        return d;\n    };\n\n    auto refine_arrangement = [&](vector<int> perm, const auto& Wsel) {\n        long long cur = score_arr(perm, Wsel);\n        for (int pass = 0; pass < 2; pass++) {\n            long long bestDelta = 0;\n            int bi = -1, bj = -1;\n\n            for (int a = 0; a < P; a++) {\n                for (int b = a + 1; b < P; b++) {\n                    long long d = delta_swap(perm, a, b, Wsel);\n                    if (d > bestDelta) {\n                        bestDelta = d;\n                        bi = a;\n                        bj = b;\n                    }\n                }\n            }\n\n            if (bestDelta <= 0) break;\n            swap(perm[bi], perm[bj]);\n            cur += bestDelta;\n        }\n        return pair<long long, vector<int>>(cur, perm);\n    };\n\n    auto make_conn_order = [&](const vector<long long>& localConn, const vector<int>& localSum) {\n        vector<int> ord(P);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (localConn[a] != localConn[b]) return localConn[a] > localConn[b];\n            if (localSum[a] != localSum[b]) return localSum[a] > localSum[b];\n            return a < b;\n        });\n        return ord;\n    };\n\n    auto make_snake_order = [&](const auto& Wsel,\n                                const vector<long long>& localConn,\n                                const vector<int>& localSum) {\n        vector<int> ord;\n        vector<char> used(P, 0);\n\n        int start = 0;\n        for (int i = 1; i < P; i++) {\n            if (localConn[i] > localConn[start] ||\n                (localConn[i] == localConn[start] && localSum[i] > localSum[start])) {\n                start = i;\n            }\n        }\n\n        ord.push_back(start);\n        used[start] = 1;\n\n        while ((int)ord.size() < P) {\n            int last = ord.back();\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < P; i++) if (!used[i]) {\n                long long sc = 7LL * Wsel[last][i] + localConn[i] + localSum[i];\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            used[best] = 1;\n            ord.push_back(best);\n        }\n        return ord;\n    };\n\n    auto build_grow_perm = [&](const auto& Wsel,\n                               const vector<long long>& localConn,\n                               const vector<int>& localSum) {\n        vector<int> perm(P, -1);\n        vector<char> filled(P, 0), usedSeed(P, 0);\n\n        vector<pair<int, int>> centerPairs = {\n            {14, 15}, {20, 21}, {14, 20}, {15, 21}\n        };\n\n        int bestA = 0, bestB = 1;\n        int bestPos1 = 14, bestPos2 = 15;\n        long long bestSc = -(1LL << 60);\n\n        for (auto [c1, c2] : centerPairs) {\n            for (int i = 0; i < P; i++) {\n                for (int j = i + 1; j < P; j++) {\n                    long long sc = 20LL * Wsel[i][j] + localConn[i] + localConn[j];\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        bestA = i;\n                        bestB = j;\n                        bestPos1 = c1;\n                        bestPos2 = c2;\n                    }\n                }\n            }\n        }\n\n        perm[bestPos1] = bestA;\n        perm[bestPos2] = bestB;\n        filled[bestPos1] = filled[bestPos2] = 1;\n        usedSeed[bestA] = usedSeed[bestB] = 1;\n\n        int placed = 2;\n        while (placed < P) {\n            int bestCell = -1, bestAdj = -1;\n            for (int c = 0; c < P; c++) if (!filled[c]) {\n                int adj = 0;\n                for (int nb : cellNbs[c]) if (filled[nb]) adj++;\n                if (bestCell == -1 ||\n                    adj > bestAdj ||\n                    (adj == bestAdj && cellDeg[c] > cellDeg[bestCell]) ||\n                    (adj == bestAdj && cellDeg[c] == cellDeg[bestCell] && cellDist[c] < cellDist[bestCell])) {\n                    bestCell = c;\n                    bestAdj = adj;\n                }\n            }\n\n            int bestSeed = -1;\n            long long bestVal = -(1LL << 60);\n            for (int s = 0; s < P; s++) if (!usedSeed[s]) {\n                long long adjScore = 0;\n                for (int nb : cellNbs[bestCell]) if (filled[nb]) {\n                    adjScore += Wsel[s][perm[nb]];\n                }\n                long long sc = 1000LL * bestAdj + 50LL * adjScore + localConn[s] + localSum[s];\n                if (sc > bestVal) {\n                    bestVal = sc;\n                    bestSeed = s;\n                }\n            }\n\n            perm[bestCell] = bestSeed;\n            filled[bestCell] = 1;\n            usedSeed[bestSeed] = 1;\n            placed++;\n        }\n\n        return perm;\n    };\n\n    auto best_pair_in_sel = [&](const vector<int>& sel, const auto& W) {\n        int best = 0;\n        for (int i = 0; i < P; i++) {\n            for (int j = i + 1; j < P; j++) {\n                best = max(best, W[sel[i]][sel[j]]);\n            }\n        }\n        return best;\n    };\n\n    for (int turn = 0; turn < T; turn++) {\n        if (turn > 0) read_pool();\n\n        // Pair weights for current pool\n        array<array<int, MAXS>, MAXS> W{};\n        vector<long long> connAll(S, 0), score0(S, 0);\n\n        for (int i = 0; i < S; i++) {\n            for (int j = i + 1; j < S; j++) {\n                int w = 0;\n                for (int l = 0; l < M; l++) {\n                    w += max(seeds[i].x[l], seeds[j].x[l]);\n                }\n                W[i][j] = W[j][i] = w;\n                connAll[i] += w;\n                connAll[j] += w;\n            }\n        }\n        for (int i = 0; i < S; i++) {\n            score0[i] = connAll[i] + 20LL * seeds[i].sum;\n        }\n\n        vector<int> ordScore(S);\n        iota(ordScore.begin(), ordScore.end(), 0);\n        sort(ordScore.begin(), ordScore.end(), [&](int a, int b) {\n            if (score0[a] != score0[b]) return score0[a] > score0[b];\n            return a < b;\n        });\n\n        double rem = (T <= 1 ? 0.0 : double(T - 1 - turn) / double(T - 1));\n        long long betaSel = 18 + (long long)llround(10.0 * rem);\n\n        // Candidate 1: top by score0\n        vector<int> candTop(ordScore.begin(), ordScore.begin() + P);\n\n        // Candidate 2: coverage greedy\n        vector<int> candCover;\n        {\n            vector<char> used(S, 0);\n            array<int, MAXM> curMx{};\n            curMx.fill(0);\n            array<long long, MAXS> attach{};\n            attach.fill(0);\n\n            for (int step = 0; step < P; step++) {\n                int best = -1;\n                long long bestSc = -(1LL << 60);\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    long long gain = 0;\n                    for (int l = 0; l < M; l++) {\n                        gain += max(0, seeds[i].x[l] - curMx[l]);\n                    }\n                    long long sc = 100LL * gain + 3LL * attach[i] + seeds[i].sum;\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n                used[best] = 1;\n                candCover.push_back(best);\n                for (int x = 0; x < S; x++) attach[x] += W[x][best];\n                for (int l = 0; l < M; l++) curMx[l] = max(curMx[l], seeds[best].x[l]);\n            }\n        }\n\n        // Candidate 3: pair greedy\n        vector<int> candPair;\n        {\n            int bi = 0, bj = 1;\n            long long bestPair = -(1LL << 60);\n            for (int i = 0; i < S; i++) {\n                for (int j = i + 1; j < S; j++) {\n                    long long sc = 100LL * W[i][j] + score0[i] + score0[j];\n                    if (sc > bestPair) {\n                        bestPair = sc;\n                        bi = i;\n                        bj = j;\n                    }\n                }\n            }\n\n            candPair.push_back(bi);\n            candPair.push_back(bj);\n            vector<char> used(S, 0);\n            used[bi] = used[bj] = 1;\n\n            array<int, MAXM> curMx{};\n            curMx.fill(0);\n            for (int l = 0; l < M; l++) curMx[l] = max(seeds[bi].x[l], seeds[bj].x[l]);\n            array<long long, MAXS> attach{};\n            attach.fill(0);\n            for (int x = 0; x < S; x++) attach[x] = W[x][bi] + W[x][bj];\n\n            while ((int)candPair.size() < P) {\n                int best = -1;\n                long long bestSc = -(1LL << 60);\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    long long gain = 0;\n                    for (int l = 0; l < M; l++) {\n                        gain += max(0, seeds[i].x[l] - curMx[l]);\n                    }\n                    long long sc = 80LL * gain + 3LL * attach[i] + seeds[i].sum;\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n                used[best] = 1;\n                candPair.push_back(best);\n                for (int x = 0; x < S; x++) attach[x] += W[x][best];\n                for (int l = 0; l < M; l++) curMx[l] = max(curMx[l], seeds[best].x[l]);\n            }\n        }\n\n        // Candidate 4: trait-specialist mix\n        vector<int> candTrait;\n        {\n            vector<char> used(S, 0);\n            for (int l = 0; l < M; l++) {\n                vector<int> ord(S);\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (seeds[a].x[l] != seeds[b].x[l]) return seeds[a].x[l] > seeds[b].x[l];\n                    if (score0[a] != score0[b]) return score0[a] > score0[b];\n                    return a < b;\n                });\n                for (int k = 0; k < 2 && (int)candTrait.size() < P; k++) {\n                    int id = ord[k];\n                    if (!used[id]) {\n                        used[id] = 1;\n                        candTrait.push_back(id);\n                    }\n                }\n            }\n            for (int id : ordScore) {\n                if ((int)candTrait.size() == P) break;\n                if (!used[id]) {\n                    used[id] = 1;\n                    candTrait.push_back(id);\n                }\n            }\n        }\n\n        vector<vector<int>> candidates = {candTop, candCover, candPair, candTrait};\n\n        vector<int> bestSel, bestPerm;\n        long long bestFit = -(1LL << 60);\n\n        for (auto cand : candidates) {\n            SelState st = build_state(cand, W);\n            st = refine_selection(st, W, betaSel);\n\n            // Local matrix for chosen subset\n            array<array<int, MAXP>, MAXP> Wsel{};\n            vector<long long> localConn(P, 0);\n            vector<int> localSum(P, 0);\n\n            for (int i = 0; i < P; i++) {\n                localSum[i] = seeds[st.sel[i]].sum;\n                for (int j = 0; j < P; j++) {\n                    Wsel[i][j] = W[st.sel[i]][st.sel[j]];\n                    localConn[i] += Wsel[i][j];\n                }\n            }\n\n            vector<int> ordConn = make_conn_order(localConn, localSum);\n            vector<int> ordSnake = make_snake_order(Wsel, localConn, localSum);\n\n            vector<vector<int>> starts;\n            {\n                vector<int> perm(P, -1);\n                for (int i = 0; i < P; i++) perm[posDeg[i]] = ordConn[i];\n                starts.push_back(perm);\n            }\n            {\n                vector<int> perm(P, -1);\n                for (int i = 0; i < P; i++) perm[posSnake[i]] = ordConn[i];\n                starts.push_back(perm);\n            }\n            {\n                vector<int> perm(P, -1);\n                for (int i = 0; i < P; i++) perm[posDeg[i]] = ordSnake[i];\n                starts.push_back(perm);\n            }\n            {\n                vector<int> perm(P, -1);\n                for (int i = 0; i < P; i++) perm[posSnake[i]] = ordSnake[i];\n                starts.push_back(perm);\n            }\n            starts.push_back(build_grow_perm(Wsel, localConn, localSum));\n\n            long long bestArrScore = -(1LL << 60);\n            vector<int> bestLocalPerm;\n\n            for (auto perm : starts) {\n                auto [sc, p2] = refine_arrangement(perm, Wsel);\n                if (sc > bestArrScore) {\n                    bestArrScore = sc;\n                    bestLocalPerm = move(p2);\n                }\n            }\n\n            int bp = best_pair_in_sel(st.sel, W);\n            long long fit = bestArrScore + 6LL * st.cov + 20LL * bp;\n\n            if (fit > bestFit) {\n                bestFit = fit;\n                bestSel = move(st.sel);\n                bestPerm = move(bestLocalPerm);\n            }\n        }\n\n        // Output\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int pos = i * N + j;\n                int localIdx = bestPerm[pos];\n                int seedId = bestSel[localIdx];\n                cout << seedId << (j + 1 == N ? '\\n' : ' ');\n            }\n        }\n        cout.flush();\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Point {\n    int x, y;\n};\n\nstruct State {\n    int x, y, d; // 0=R, 1=D, 2=L, 3=U\n};\n\nstruct Job {\n    Point s, t;\n    vector<State> pickStates;\n    vector<State> dropStates;\n    int pairDist;\n    int srcRow, srcSnake, srcMorton;\n    int tgtRow, tgtSnake, tgtMorton;\n    int midSnake;\n    int midMorton;\n};\n\nstruct Plan {\n    ll cost = (1LL << 60);\n    Point startRoot{0, 0};\n    vector<int> ord;\n    vector<int> pickSel, dropSel;\n    vector<Job> jobs;\n};\n\nstatic const int DX4[4] = {0, 1, 0, -1};\nstatic const int DY4[4] = {1, 0, -1, 0};\n\nint N, M, V;\nvector<string> S, T;\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\ninline int manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\ninline int orientDist(int a, int b) {\n    int cw = (b - a + 4) % 4;\n    int ccw = (a - b + 4) % 4;\n    return min(cw, ccw);\n}\ninline char orientChar(int a, int b) {\n    int cw = (b - a + 4) % 4;\n    int ccw = (a - b + 4) % 4;\n    return (cw <= ccw ? 'R' : 'L');\n}\ninline int turnCost(const State& a, const State& b) {\n    return max(1, max(manhattan(a.x, a.y, b.x, b.y), orientDist(a.d, b.d)));\n}\n\ninline int rowKey(const Point& p) {\n    return p.x * N + p.y;\n}\ninline int snakeKey(const Point& p) {\n    return p.x * N + ((p.x & 1) ? (N - 1 - p.y) : p.y);\n}\ninline int mortonKey(const Point& p) {\n    int r = 0;\n    for (int b = 0; b < 5; b++) {\n        r |= ((p.x >> b) & 1) << (2 * b);\n        r |= ((p.y >> b) & 1) << (2 * b + 1);\n    }\n    return r;\n}\ninline int diagKey(const Point& p) {\n    return (p.x + p.y) * N + p.x;\n}\ninline Point midPoint(const Job& j) {\n    return {(j.s.x + j.t.x) / 2, (j.s.y + j.t.y) / 2};\n}\n\nvector<State> makeStatesAtCell(const Point& c) {\n    vector<State> res;\n    for (int d = 0; d < 4; d++) {\n        int rx = c.x - DX4[d];\n        int ry = c.y - DY4[d];\n        if (inside(rx, ry)) res.push_back({rx, ry, d});\n    }\n    return res;\n}\n\nvoid fillJob(Job& j, const Point& s, const Point& t) {\n    j.s = s;\n    j.t = t;\n    j.pickStates = makeStatesAtCell(s);\n    j.dropStates = makeStatesAtCell(t);\n    j.pairDist = manhattan(s, t);\n\n    j.srcRow = rowKey(s);\n    j.srcSnake = snakeKey(s);\n    j.srcMorton = mortonKey(s);\n\n    j.tgtRow = rowKey(t);\n    j.tgtSnake = snakeKey(t);\n    j.tgtMorton = mortonKey(t);\n\n    Point m = midPoint(j);\n    j.midSnake = snakeKey(m);\n    j.midMorton = mortonKey(m);\n}\n\nvector<int> hungarian(const vector<vector<int>>& a) {\n    int n = (int)a.size();\n    if (n == 0) return {};\n    const int INF = 1e9;\n\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, 0);\n        do {\n            used[j0] = 1;\n            int i0 = p[j0], j1 = 0;\n            int delta = INF;\n            for (int j = 1; j <= n; j++) if (!used[j]) {\n                int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n\n    vector<int> ans(n);\n    for (int j = 1; j <= n; j++) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nvector<Job> buildJobsHungarian(const vector<Point>& src, const vector<Point>& tgt) {\n    int K = (int)src.size();\n    vector<vector<int>> cost(K, vector<int>(K));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < K; j++) cost[i][j] = manhattan(src[i], tgt[j]);\n    }\n    vector<int> assign = hungarian(cost);\n\n    vector<Job> jobs(K);\n    for (int i = 0; i < K; i++) {\n        fillJob(jobs[i], src[i], tgt[assign[i]]);\n    }\n    return jobs;\n}\n\nvector<int> sortedIdxByKey(const vector<Point>& pts, int mode) {\n    vector<int> ord((int)pts.size());\n    iota(ord.begin(), ord.end(), 0);\n\n    auto key = [&](const Point& p) -> int {\n        if (mode == 0) return rowKey(p);\n        if (mode == 1) return snakeKey(p);\n        if (mode == 2) return mortonKey(p);\n        return diagKey(p);\n    };\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        int ka = key(pts[a]), kb = key(pts[b]);\n        if (ka != kb) return ka < kb;\n        if (pts[a].x != pts[b].x) return pts[a].x < pts[b].x;\n        return pts[a].y < pts[b].y;\n    });\n    return ord;\n}\n\nvector<Job> buildJobsShifted(const vector<Point>& src, const vector<Point>& tgt, int mode, int shift, bool reverseTgt) {\n    int K = (int)src.size();\n    vector<int> is = sortedIdxByKey(src, mode);\n    vector<int> it = sortedIdxByKey(tgt, mode);\n    if (reverseTgt) reverse(it.begin(), it.end());\n    if (K > 0) shift %= K;\n\n    vector<Job> jobs(K);\n    for (int i = 0; i < K; i++) {\n        int tj = it[(i + shift) % K];\n        fillJob(jobs[i], src[is[i]], tgt[tj]);\n    }\n    return jobs;\n}\n\nvector<int> orderByKey(const vector<Job>& jobs, int mode) {\n    vector<int> ord((int)jobs.size());\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        int ka, kb;\n        if (mode == 0) { ka = jobs[a].srcRow; kb = jobs[b].srcRow; }\n        else if (mode == 1) { ka = jobs[a].srcSnake; kb = jobs[b].srcSnake; }\n        else if (mode == 2) { ka = jobs[a].tgtSnake; kb = jobs[b].tgtSnake; }\n        else if (mode == 3) { ka = jobs[a].midMorton; kb = jobs[b].midMorton; }\n        else if (mode == 4) { ka = jobs[a].midSnake; kb = jobs[b].midSnake; }\n        else { ka = jobs[a].pairDist; kb = jobs[b].pairDist; }\n\n        if (ka != kb) return ka < kb;\n        if (jobs[a].s.x != jobs[b].s.x) return jobs[a].s.x < jobs[b].s.x;\n        if (jobs[a].s.y != jobs[b].s.y) return jobs[a].s.y < jobs[b].s.y;\n        if (jobs[a].t.x != jobs[b].t.x) return jobs[a].t.x < jobs[b].t.x;\n        return jobs[a].t.y < jobs[b].t.y;\n    });\n    return ord;\n}\n\nll transitionProxyCost(const Job& a, const Job& b) {\n    ll best = (1LL << 60);\n    for (const auto& q : a.dropStates) {\n        for (const auto& p : b.pickStates) {\n            best = min(best, (ll)turnCost(q, p));\n        }\n    }\n    return best;\n}\n\nll startProxyCost(const Job& j) {\n    ll best = (1LL << 60);\n    for (const auto& p : j.pickStates) {\n        best = min(best, (ll)max(1, orientDist(0, p.d)));\n    }\n    return best;\n}\n\nll proxyOrderCost(const vector<int>& ord, const vector<Job>& jobs) {\n    if (ord.empty()) return 0;\n    ll res = startProxyCost(jobs[ord[0]]);\n    for (int i = 0; i + 1 < (int)ord.size(); i++) {\n        res += transitionProxyCost(jobs[ord[i]], jobs[ord[i + 1]]);\n    }\n    return res;\n}\n\nvoid improveOrder(vector<int>& ord, const vector<Job>& jobs) {\n    int n = (int)ord.size();\n    if (n <= 2) return;\n\n    ll cur = proxyOrderCost(ord, jobs);\n    for (int pass = 0; pass < 2; pass++) {\n        bool changed = false;\n        for (int i = 0; i + 1 < n; i++) {\n            swap(ord[i], ord[i + 1]);\n            ll cand = proxyOrderCost(ord, jobs);\n            if (cand < cur) {\n                cur = cand;\n                changed = true;\n            } else {\n                swap(ord[i], ord[i + 1]);\n            }\n        }\n        if (!changed) break;\n    }\n}\n\nvector<int> greedyOrder(const vector<Job>& jobs, int seed) {\n    int n = (int)jobs.size();\n    vector<int> ord;\n    ord.reserve(n);\n    vector<char> used(n, 0);\n    ord.push_back(seed);\n    used[seed] = 1;\n    int cur = seed;\n\n    while ((int)ord.size() < n) {\n        int best = -1;\n        ll bestScore = (1LL << 60);\n        int bestTie = INT_MAX;\n        for (int j = 0; j < n; j++) if (!used[j]) {\n            ll sc = transitionProxyCost(jobs[cur], jobs[j]);\n            int tie = jobs[j].pairDist;\n            if (sc < bestScore || (sc == bestScore && tie < bestTie)) {\n                bestScore = sc;\n                bestTie = tie;\n                best = j;\n            }\n        }\n        used[best] = 1;\n        ord.push_back(best);\n        cur = best;\n    }\n    return ord;\n}\n\nvector<vector<int>> makeOrderCandidates(const vector<Job>& jobs) {\n    vector<vector<int>> cand;\n\n    auto add = [&](vector<int> ord) {\n        if (ord.empty()) return;\n        cand.push_back(ord);\n        vector<int> rev = ord;\n        reverse(rev.begin(), rev.end());\n        cand.push_back(rev);\n    };\n\n    add(orderByKey(jobs, 0)); // source row\n    add(orderByKey(jobs, 1)); // source snake\n    add(orderByKey(jobs, 2)); // target snake\n    add(orderByKey(jobs, 3)); // midpoint morton\n    add(orderByKey(jobs, 4)); // midpoint snake\n    add(orderByKey(jobs, 5)); // pair distance\n\n    if (!jobs.empty()) {\n        vector<int> base = orderByKey(jobs, 3);\n        add(greedyOrder(jobs, base[0]));\n        base = orderByKey(jobs, 1);\n        add(greedyOrder(jobs, base[0]));\n    }\n\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    for (auto& ord : cand) improveOrder(ord, jobs);\n\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n    return cand;\n}\n\nPlan solveOrder(const vector<Job>& jobs, const vector<int>& ord) {\n    Plan res;\n    res.jobs = jobs;\n    res.ord = ord;\n\n    int n = (int)ord.size();\n    if (n == 0) {\n        res.cost = 0;\n        res.startRoot = {0, 0};\n        return res;\n    }\n\n    vector<vector<State>> P(n), D(n);\n    for (int i = 0; i < n; i++) {\n        P[i] = jobs[ord[i]].pickStates;\n        D[i] = jobs[ord[i]].dropStates;\n    }\n\n    const ll INF = (1LL << 60);\n    vector<vector<ll>> dp(n);\n    vector<vector<int>> parPick(n), parPrev(n);\n\n    // First job: initial root is chosen as the root of the picked state.\n    dp[0].assign(D[0].size(), INF);\n    parPick[0].assign(D[0].size(), -1);\n    parPrev[0].assign(D[0].size(), -1);\n\n    for (int q = 0; q < (int)D[0].size(); q++) {\n        ll best = INF;\n        int bp = -1;\n        for (int p = 0; p < (int)P[0].size(); p++) {\n            ll c = max(1, orientDist(0, P[0][p].d)) + turnCost(P[0][p], D[0][q]);\n            if (c < best) {\n                best = c;\n                bp = p;\n            }\n        }\n        dp[0][q] = best;\n        parPick[0][q] = bp;\n    }\n\n    // Remaining jobs.\n    for (int i = 1; i < n; i++) {\n        dp[i].assign(D[i].size(), INF);\n        parPick[i].assign(D[i].size(), -1);\n        parPrev[i].assign(D[i].size(), -1);\n\n        for (int prevQ = 0; prevQ < (int)D[i - 1].size(); prevQ++) {\n            if (dp[i - 1][prevQ] >= INF) continue;\n            const State& curDrop = D[i - 1][prevQ];\n\n            for (int p = 0; p < (int)P[i].size(); p++) {\n                ll mid = dp[i - 1][prevQ] + turnCost(curDrop, P[i][p]);\n                for (int q = 0; q < (int)D[i].size(); q++) {\n                    ll c = mid + turnCost(P[i][p], D[i][q]);\n                    if (c < dp[i][q]) {\n                        dp[i][q] = c;\n                        parPrev[i][q] = prevQ;\n                        parPick[i][q] = p;\n                    }\n                }\n            }\n        }\n    }\n\n    int bestQ = 0;\n    for (int q = 1; q < (int)D[n - 1].size(); q++) {\n        if (dp[n - 1][q] < dp[n - 1][bestQ]) bestQ = q;\n    }\n\n    res.cost = dp[n - 1][bestQ];\n    res.pickSel.assign(n, -1);\n    res.dropSel.assign(n, -1);\n\n    int curQ = bestQ;\n    for (int i = n - 1; i >= 0; i--) {\n        res.dropSel[i] = curQ;\n        res.pickSel[i] = parPick[i][curQ];\n        curQ = parPrev[i][curQ];\n    }\n\n    const State& firstPick = P[0][res.pickSel[0]];\n    res.startRoot = {firstPick.x, firstPick.y};\n    return res;\n}\n\nvector<char> buildMovePath(const State& a, const State& b) {\n    vector<char> path;\n    int dx = b.x - a.x;\n    int dy = b.y - a.y;\n    while (dx > 0) { path.push_back('D'); dx--; }\n    while (dx < 0) { path.push_back('U'); dx++; }\n    while (dy > 0) { path.push_back('R'); dy--; }\n    while (dy < 0) { path.push_back('L'); dy++; }\n    return path;\n}\n\nvoid emitTurn(char mv, char rot, char act) {\n    char buf[4] = {mv, rot, '.', act};\n    cout.write(buf, 4);\n    cout.put('\\n');\n}\n\nvoid emitSegment(const State& a, const State& b, char finalAct) {\n    vector<char> path = buildMovePath(a, b);\n    int m = (int)path.size();\n    int r = orientDist(a.d, b.d);\n    char rc = (r ? orientChar(a.d, b.d) : '.');\n    int L = max(1, max(m, r));\n\n    for (int i = 0; i < L; i++) {\n        char mv = (i < m ? path[i] : '.');\n        char rot = (i < r ? rc : '.');\n        char act = (i + 1 == L ? finalAct : '.');\n        emitTurn(mv, rot, act);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> V;\n    S.resize(N);\n    T.resize(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<Point> src, tgt;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool a = (S[i][j] == '1');\n            bool b = (T[i][j] == '1');\n            if (a && !b) src.push_back({i, j});\n            if (b && !a) tgt.push_back({i, j});\n        }\n    }\n\n    int K = (int)src.size();\n    if ((int)tgt.size() != K) {\n        int mn = min((int)src.size(), (int)tgt.size());\n        src.resize(mn);\n        tgt.resize(mn);\n        K = mn;\n    }\n\n    if (K == 0) {\n        cout << 2 << '\\n';\n        cout << 0 << ' ' << 1 << '\\n';\n        cout << 0 << ' ' << 0 << '\\n';\n        return 0;\n    }\n\n    // Small candidate set: enough diversity, but fast.\n    vector<vector<Job>> jobLists;\n    jobLists.push_back(buildJobsHungarian(src, tgt));\n    jobLists.push_back(buildJobsShifted(src, tgt, 0, 0, false));              // row-row\n    jobLists.push_back(buildJobsShifted(src, tgt, 1, 0, false));              // snake-snake\n    jobLists.push_back(buildJobsShifted(src, tgt, 2, 0, false));              // morton-morton\n    jobLists.push_back(buildJobsShifted(src, tgt, 1, max(1, K / 2), false));  // shifted snake\n    jobLists.push_back(buildJobsShifted(src, tgt, 0, 0, true));               // row / reversed row\n\n    Plan best;\n    for (const auto& jobs : jobLists) {\n        auto orders = makeOrderCandidates(jobs);\n        for (const auto& ord : orders) {\n            Plan cur = solveOrder(jobs, ord);\n            if (cur.cost < best.cost) best = std::move(cur);\n        }\n    }\n\n    // Output a 2-vertex arm.\n    cout << 2 << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n    cout << best.startRoot.x << ' ' << best.startRoot.y << '\\n';\n\n    // Exact execution.\n    State cur{best.startRoot.x, best.startRoot.y, 0}; // initial direction: right\n    for (int i = 0; i < (int)best.ord.size(); i++) {\n        const Job& j = best.jobs[best.ord[i]];\n        const State& p = j.pickStates[best.pickSel[i]];\n        const State& q = j.dropStates[best.dropSel[i]];\n\n        emitSegment(cur, p, 'P'); // pick up\n        emitSegment(p, q, 'P');    // drop\n        cur = q;\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int MAXC = 100000;\n\nstruct Pt {\n    int x, y, w;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n    int score; // exact a-b\n    ll area;\n};\n\nstatic inline bool valid_rect(const Rect& r) {\n    return r.x1 < r.x2 && r.y1 < r.y2;\n}\n\nstatic inline ll rect_area(const Rect& r) {\n    return 1LL * (r.x2 - r.x1) * (r.y2 - r.y1);\n}\n\nstatic inline bool better(const Rect& a, const Rect& b) {\n    if (a.score != b.score) return a.score > b.score;\n    if (a.area != b.area) return a.area < b.area;\n    if (a.x1 != b.x1) return a.x1 < b.x1;\n    if (a.y1 != b.y1) return a.y1 < b.y1;\n    if (a.x2 != b.x2) return a.x2 < b.x2;\n    return a.y2 < b.y2;\n}\n\nstatic vector<int> uniq_sorted(vector<int> v) {\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nstruct RangeTree {\n    struct Node {\n        vector<int> ys;\n        vector<int> pref; // pref[i] = sum of first i elements\n    };\n\n    vector<Pt> pts;\n    vector<int> xs;\n    vector<Node> seg;\n\n    void build(vector<Pt> input) {\n        pts = move(input);\n        sort(pts.begin(), pts.end(), [](const Pt& a, const Pt& b) {\n            if (a.x != b.x) return a.x < b.x;\n            if (a.y != b.y) return a.y < b.y;\n            return a.w < b.w;\n        });\n        int n = (int)pts.size();\n        xs.resize(n);\n        for (int i = 0; i < n; ++i) xs[i] = pts[i].x;\n        seg.assign(4 * n + 5, {});\n        build_rec(1, 0, n - 1);\n    }\n\n    void build_rec(int idx, int l, int r) {\n        if (l == r) {\n            seg[idx].ys = {pts[l].y};\n            seg[idx].pref = {0, pts[l].w};\n            return;\n        }\n        int mid = (l + r) >> 1;\n        build_rec(idx << 1, l, mid);\n        build_rec(idx << 1 | 1, mid + 1, r);\n\n        const auto& A = seg[idx << 1];\n        const auto& B = seg[idx << 1 | 1];\n        auto& C = seg[idx];\n\n        C.ys.clear();\n        C.pref.clear();\n        C.ys.reserve(A.ys.size() + B.ys.size());\n        C.pref.reserve(A.ys.size() + B.ys.size() + 1);\n        C.pref.push_back(0);\n\n        int i = 0, j = 0;\n        while (i < (int)A.ys.size() || j < (int)B.ys.size()) {\n            if (j == (int)B.ys.size() || (i < (int)A.ys.size() && A.ys[i] <= B.ys[j])) {\n                int w = A.pref[i + 1] - A.pref[i];\n                C.ys.push_back(A.ys[i]);\n                C.pref.push_back(C.pref.back() + w);\n                ++i;\n            } else {\n                int w = B.pref[j + 1] - B.pref[j];\n                C.ys.push_back(B.ys[j]);\n                C.pref.push_back(C.pref.back() + w);\n                ++j;\n            }\n        }\n    }\n\n    int sum_node(const Node& nd, int y1, int y2) const {\n        auto it1 = lower_bound(nd.ys.begin(), nd.ys.end(), y1);\n        auto it2 = upper_bound(nd.ys.begin(), nd.ys.end(), y2);\n        int l = (int)(it1 - nd.ys.begin());\n        int r = (int)(it2 - nd.ys.begin());\n        return nd.pref[r] - nd.pref[l];\n    }\n\n    int query_rec(int idx, int l, int r, int ql, int qr, int y1, int y2) const {\n        if (qr < l || r < ql) return 0;\n        if (ql <= l && r <= qr) return sum_node(seg[idx], y1, y2);\n        int mid = (l + r) >> 1;\n        return query_rec(idx << 1, l, mid, ql, qr, y1, y2)\n             + query_rec(idx << 1 | 1, mid + 1, r, ql, qr, y1, y2);\n    }\n\n    int query(int x1, int x2, int y1, int y2) const {\n        if (x1 > x2 || y1 > y2) return 0;\n        int l = (int)(lower_bound(xs.begin(), xs.end(), x1) - xs.begin());\n        int r = (int)(upper_bound(xs.begin(), xs.end(), x2) - xs.begin()) - 1;\n        if (l > r) return 0;\n        return query_rec(1, 0, (int)pts.size() - 1, l, r, y1, y2);\n    }\n};\n\nstatic int score_rect_exact(const Rect& r, const RangeTree& rt) {\n    return rt.query(r.x1, r.x2, r.y1, r.y2);\n}\n\nstatic Rect eval_rect(Rect r, const RangeTree& rt) {\n    r.score = score_rect_exact(r, rt);\n    r.area = rect_area(r);\n    return r;\n}\n\nstatic vector<int> build_boundaries(int S, int off) {\n    vector<int> b;\n    b.push_back(0);\n    if (off > 0) b.push_back(off);\n    for (int l = off; l < MAXC; l += S) {\n        int r = min(MAXC, l + S);\n        b.push_back(r);\n        if (r == MAXC) break;\n    }\n    return uniq_sorted(b);\n}\n\nstatic inline int cell_idx(int v, const vector<int>& b) {\n    int id = (int)(upper_bound(b.begin(), b.end(), v) - b.begin()) - 1;\n    id = max(0, min(id, (int)b.size() - 2));\n    return id;\n}\n\nstruct GridResult {\n    Rect best;\n    vector<Rect> cellSeeds;\n};\n\nstatic GridResult coarse_grid_search(const vector<Pt>& pts, int S, int ox, int oy) {\n    vector<int> bx = build_boundaries(S, ox);\n    vector<int> by = build_boundaries(S, oy);\n\n    int nx = (int)bx.size() - 1;\n    int ny = (int)by.size() - 1;\n    vector<int> w(nx * ny, 0);\n\n    for (const auto& p : pts) {\n        int ix = cell_idx(p.x, bx);\n        int iy = cell_idx(p.y, by);\n        w[ix * ny + iy] += p.w;\n    }\n\n    Rect best{0, 0, 1, 1, INT_MIN, (1LL << 60)};\n    vector<int> col(ny, 0);\n\n    for (int top = 0; top < nx; ++top) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < nx; ++bot) {\n            const int* row = &w[bot * ny];\n            for (int c = 0; c < ny; ++c) col[c] += row[c];\n\n            int cur = 0;\n            int left = 0;\n            for (int c = 0; c < ny; ++c) {\n                if (cur < 0) {\n                    cur = col[c];\n                    left = c;\n                } else {\n                    cur += col[c];\n                }\n\n                ll area = 1LL * (bx[bot + 1] - bx[top]) * (by[c + 1] - by[left]);\n                if (cur > best.score || (cur == best.score && area < best.area)) {\n                    best.score = cur;\n                    best.area = area;\n                    best.x1 = bx[top];\n                    best.y1 = by[left];\n                    best.x2 = bx[bot + 1];\n                    best.y2 = by[c + 1];\n                }\n            }\n        }\n    }\n\n    // Collect a few strong cell rectangles as additional seeds.\n    vector<pair<int, int>> cells;\n    cells.reserve(nx * ny);\n    for (int i = 0; i < nx; ++i) {\n        for (int j = 0; j < ny; ++j) {\n            int val = w[i * ny + j];\n            if (val > 0) cells.push_back({val, i * ny + j});\n        }\n    }\n    sort(cells.begin(), cells.end(), greater<>());\n    vector<Rect> extras;\n    for (int k = 0; k < (int)cells.size() && k < 3; ++k) {\n        int id = cells[k].second;\n        int i = id / ny;\n        int j = id % ny;\n        extras.push_back(Rect{bx[i], by[j], bx[i + 1], by[j + 1], 0, 0});\n    }\n\n    return {best, extras};\n}\n\nstatic vector<int> sample_coords(vector<int> vals, int limit, const vector<int>& anchors) {\n    vals = uniq_sorted(move(vals));\n    vector<int> res;\n    res.reserve(limit);\n\n    auto add = [&](int x) {\n        if (0 <= x && x <= MAXC) res.push_back(x);\n    };\n\n    for (int a : anchors) add(a);\n    res = uniq_sorted(move(res));\n\n    vector<int> rem;\n    rem.reserve(vals.size());\n    for (int x : vals) {\n        if (!binary_search(res.begin(), res.end(), x)) rem.push_back(x);\n    }\n\n    if ((int)res.size() >= limit) {\n        res.resize(limit);\n        return uniq_sorted(move(res));\n    }\n\n    int need = limit - (int)res.size();\n    if ((int)rem.size() <= need) {\n        res.insert(res.end(), rem.begin(), rem.end());\n        return uniq_sorted(move(res));\n    }\n\n    // Preserve extremes and sample the middle evenly.\n    int edge = min(8, need / 4);\n    for (int i = 0; i < edge; ++i) res.push_back(rem[i]);\n    for (int i = 0; i < edge; ++i) res.push_back(rem[(int)rem.size() - 1 - i]);\n\n    res = uniq_sorted(move(res));\n    need = limit - (int)res.size();\n    if (need > 0) {\n        for (int i = 0; i < need; ++i) {\n            int idx = (long long)(i + 1) * (int)(rem.size() - 1) / (need + 1);\n            res.push_back(rem[idx]);\n        }\n    }\n    return uniq_sorted(move(res));\n}\n\nstatic vector<int> collect_window_coords(const vector<Pt>& pts, const Rect& cur, bool useX, int margin) {\n    int lx = max(0, cur.x1 - margin);\n    int rx = min(MAXC, cur.x2 + margin);\n    int ly = max(0, cur.y1 - margin);\n    int ry = min(MAXC, cur.y2 + margin);\n\n    vector<int> vals;\n    vals.reserve(pts.size());\n    for (const auto& p : pts) {\n        if (lx <= p.x && p.x <= rx && ly <= p.y && p.y <= ry) {\n            vals.push_back(useX ? p.x : p.y);\n        }\n    }\n    return vals;\n}\n\nstatic Rect local_refine(Rect cur, const RangeTree& rt, const vector<Pt>& pts) {\n    cur = eval_rect(cur, rt);\n\n    for (int round = 0; round < 3; ++round) {\n        int margin = (round == 0 ? 8000 : (round == 1 ? 4000 : 2000));\n        vector<int> rawX = collect_window_coords(pts, cur, true, margin);\n        vector<int> rawY = collect_window_coords(pts, cur, false, margin);\n\n        if (rawX.empty() || rawY.empty()) break;\n\n        vector<int> candX = sample_coords(\n            rawX, 80,\n            {0, MAXC, cur.x1, cur.x2, max(0, cur.x1 - 1), min(MAXC, cur.x1 + 1),\n             max(0, cur.x2 - 1), min(MAXC, cur.x2 + 1)}\n        );\n        vector<int> candY = sample_coords(\n            rawY, 80,\n            {0, MAXC, cur.y1, cur.y2, max(0, cur.y1 - 1), min(MAXC, cur.y1 + 1),\n             max(0, cur.y2 - 1), min(MAXC, cur.y2 + 1)}\n        );\n\n        bool changed = false;\n\n        auto improve = [&](bool xBorder, bool lowerBorder) {\n            Rect best = cur;\n            const auto& cand = xBorder ? candX : candY;\n\n            for (int v : cand) {\n                Rect t = cur;\n                if (xBorder) {\n                    if (lowerBorder) t.x1 = v;\n                    else t.x2 = v;\n                } else {\n                    if (lowerBorder) t.y1 = v;\n                    else t.y2 = v;\n                }\n                if (!valid_rect(t)) continue;\n                t = eval_rect(t, rt);\n                if (better(t, best)) best = t;\n            }\n\n            if (better(best, cur)) {\n                cur = best;\n                changed = true;\n            }\n        };\n\n        if (round % 2 == 0) {\n            improve(true, true);   // x1\n            improve(true, false);  // x2\n            improve(false, true);  // y1\n            improve(false, false); // y2\n        } else {\n            improve(false, true);\n            improve(false, false);\n            improve(true, true);\n            improve(true, false);\n        }\n\n        if (!changed) break;\n    }\n\n    return cur;\n}\n\nstatic void add_seed(vector<Rect>& seeds, Rect r) {\n    if (!valid_rect(r)) return;\n    r.area = rect_area(r);\n    seeds.push_back(r);\n}\n\nstatic Rect mackerel_bbox(const vector<Pt>& mackerels) {\n    int mnx = MAXC, mxx = 0, mny = MAXC, mxy = 0;\n    for (const auto& p : mackerels) {\n        mnx = min(mnx, p.x);\n        mxx = max(mxx, p.x);\n        mny = min(mny, p.y);\n        mxy = max(mxy, p.y);\n    }\n    if (mnx == mxx) {\n        if (mxx < MAXC) ++mxx;\n        else --mnx;\n    }\n    if (mny == mxy) {\n        if (mxy < MAXC) ++mxy;\n        else --mny;\n    }\n    return {mnx, mny, mxx, mxy, 0, 0};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<Pt> mackerels(N), sardines(N), pts;\n    pts.reserve(2 * N);\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        mackerels[i].w = +1;\n        pts.push_back(mackerels[i]);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        sardines[i].w = -1;\n        pts.push_back(sardines[i]);\n    }\n\n    RangeTree rt;\n    rt.build(pts);\n\n    vector<Rect> seeds;\n\n    // Very small fallback rectangles around some mackerels.\n    for (int i = 0; i < N; i += max(1, N / 25)) {\n        int x1 = max(0, mackerels[i].x - 1);\n        int x2 = min(MAXC, mackerels[i].x + 1);\n        int y1 = max(0, mackerels[i].y - 1);\n        int y2 = min(MAXC, mackerels[i].y + 1);\n        if (x1 == x2) {\n            if (x2 < MAXC) ++x2;\n            else --x1;\n        }\n        if (y1 == y2) {\n            if (y2 < MAXC) ++y2;\n            else --y1;\n        }\n        add_seed(seeds, {x1, y1, x2, y2, 0, 0});\n    }\n\n    // Mackerel bounding box.\n    add_seed(seeds, mackerel_bbox(mackerels));\n\n    // Multi-scale coarse search.\n    for (int S : {400, 700, 1100}) {\n        for (int phase : {0, S / 3, 2 * S / 3}) {\n            int ox = phase;\n            int oy = (phase * 2) % S;\n            GridResult gr = coarse_grid_search(pts, S, ox, oy);\n            add_seed(seeds, gr.best);\n            for (auto r : gr.cellSeeds) add_seed(seeds, r);\n        }\n    }\n\n    // Deduplicate seeds.\n    sort(seeds.begin(), seeds.end(), [](const Rect& a, const Rect& b) {\n        if (a.x1 != b.x1) return a.x1 < b.x1;\n        if (a.y1 != b.y1) return a.y1 < b.y1;\n        if (a.x2 != b.x2) return a.x2 < b.x2;\n        return a.y2 < b.y2;\n    });\n    seeds.erase(unique(seeds.begin(), seeds.end(), [](const Rect& a, const Rect& b) {\n        return a.x1 == b.x1 && a.y1 == b.y1 && a.x2 == b.x2 && a.y2 == b.y2;\n    }), seeds.end());\n\n    // Exact evaluate all seeds, then refine the best few.\n    for (auto& r : seeds) r = eval_rect(r, rt);\n    sort(seeds.begin(), seeds.end(), better);\n    if ((int)seeds.size() > 10) seeds.resize(10);\n\n    Rect best{0, 0, 1, 1, INT_MIN, 1};\n    best = eval_rect(best, rt);\n\n    for (auto r : seeds) {\n        r = local_refine(r, rt, pts);\n        if (better(r, best)) best = r;\n    }\n\n    // Final safety fallback.\n    if (!valid_rect(best)) {\n        best = {0, 0, 1, 1, 0, 1};\n    }\n\n    // Output only a rectangle: always safe for vertex count and edge length.\n    cout << 4 << '\\n';\n    cout << best.x1 << ' ' << best.y1 << '\\n';\n    cout << best.x2 << ' ' << best.y1 << '\\n';\n    cout << best.x2 << ' ' << best.y2 << '\\n';\n    cout << best.x1 << ' ' << best.y2 << '\\n';\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing i128 = __int128_t;\n\nstruct Rect {\n    ll w, h;\n};\n\nstruct Op {\n    int p, r, b;\n    char d;\n};\n\nstruct SegPlan {\n    ll W = 0, H = 0;\n    int anchor = 0;          // relative index in the segment\n    vector<int> rot;         // 0/1 for each rectangle in the segment\n};\n\nstruct State {\n    ll W, H;\n    int prev_i = -1, prev_idx = -1, plan_idx = -1;\n};\n\nstruct Dataset {\n    vector<Rect> rects;  // local order\n    vector<int> orig;    // local -> original index\n    ll penalty = 0;      // omitted rectangles penalty\n};\n\nstruct Cand {\n    vector<Op> ops;\n    ll score = 0;\n    string sig;\n};\n\nstatic string serialize_ops(const vector<Op>& ops) {\n    string s;\n    s.reserve(ops.size() * 16);\n    for (const auto& op : ops) {\n        s += to_string(op.p);\n        s.push_back(',');\n        s += to_string(op.r);\n        s.push_back(',');\n        s.push_back(op.d);\n        s.push_back(',');\n        s += to_string(op.b);\n        s.push_back(';');\n    }\n    return s;\n}\n\nstatic uint64_t hash_plan(const SegPlan& p) {\n    uint64_t h = 1469598103934665603ULL;\n    for (int x : p.rot) {\n        h ^= (uint64_t)(x + 1);\n        h *= 1099511628211ULL;\n    }\n    h ^= (uint64_t)p.anchor + 0x9e3779b97f4a7c15ULL;\n    h *= 1099511628211ULL;\n    return h;\n}\n\nstatic pair<ll,ll> pack_dims(const Rect& x, bool rowMode, int rot) {\n    // rowMode:\n    //   rot=0 -> (w, h)\n    //   rot=1 -> (h, w)\n    // colMode:\n    //   rot=0 -> (h, w)\n    //   rot=1 -> (w, h)\n    if (rowMode) {\n        return rot ? make_pair(x.h, x.w) : make_pair(x.w, x.h);\n    } else {\n        return rot ? make_pair(x.w, x.h) : make_pair(x.h, x.w);\n    }\n}\n\nstatic int choose_rot_policy(const Rect& x, bool rowMode, int policy, int idx) {\n    auto [w0, h0] = pack_dims(x, rowMode, 0);\n    auto [w1, h1] = pack_dims(x, rowMode, 1);\n\n    auto choose_by = [&](ll a, ll b) {\n        i128 v0 = (i128)a * w0 + (i128)b * h0;\n        i128 v1 = (i128)a * w1 + (i128)b * h1;\n        if (v1 < v0) return 1;\n        if (v0 < v1) return 0;\n        ll s0 = w0 + h0, s1 = w1 + h1;\n        if (s1 < s0) return 1;\n        if (s0 < s1) return 0;\n        return (w1 < w0) ? 1 : 0;\n    };\n\n    switch (policy) {\n        case 0: // min width / height\n            return rowMode ? ((w1 < w0) ? 1 : 0) : ((h1 < h0) ? 1 : 0);\n        case 1: // min other dimension\n            return rowMode ? ((h1 < h0) ? 1 : 0) : ((w1 < w0) ? 1 : 0);\n        case 2: // min max-side\n        {\n            ll s0 = max(w0, h0), s1 = max(w1, h1);\n            if (s1 < s0) return 1;\n            if (s0 < s1) return 0;\n            return rowMode ? ((w1 < w0) ? 1 : 0) : ((h1 < h0) ? 1 : 0);\n        }\n        case 3: // threshold 1.0\n            return rowMode ? ((w0 > h0) ? 1 : 0) : ((h0 > w0) ? 1 : 0);\n        case 4: // threshold 1.2\n            return rowMode ? (((i128)w0 * 5 > (i128)h0 * 6) ? 1 : 0)\n                           : (((i128)h0 * 5 > (i128)w0 * 6) ? 1 : 0);\n        case 5: // threshold 1.5\n            return rowMode ? (((i128)w0 * 2 > (i128)h0 * 3) ? 1 : 0)\n                           : (((i128)h0 * 2 > (i128)w0 * 3) ? 1 : 0);\n        case 6: // parity mix\n            return (idx & 1) ? choose_by(1, 2) : choose_by(2, 1);\n        case 7: // hash mix\n        {\n            uint64_t z = (uint64_t)idx * 1000003ULL\n                       ^ (uint64_t)x.w * 911382323ULL\n                       ^ (uint64_t)x.h * 972663749ULL;\n            return (z & 1ULL) ? choose_by(1, 1) : choose_by(2, 1);\n        }\n        default:\n            return choose_by(1, 1);\n    }\n}\n\nstatic vector<int> select_cap_indices(const vector<ll>& vals, int pattern) {\n    int m = (int)vals.size();\n    set<int> st;\n    auto add = [&](int idx) {\n        if (0 <= idx && idx < m) st.insert(idx);\n    };\n\n    if (pattern == 0) {\n        add(0);\n        add(m / 4);\n        add(m / 2);\n        add((3 * m) / 4);\n        add(m - 1);\n    } else if (pattern == 1) {\n        add(0);\n        add(m / 6);\n        add(m / 3);\n        add(m / 2);\n        add((2 * m) / 3);\n        add((5 * m) / 6);\n        add(m - 1);\n    } else {\n        add(0);\n        add(m / 8);\n        add(m / 4);\n        add((3 * m) / 8);\n        add(m / 2);\n        add((5 * m) / 8);\n        add((3 * m) / 4);\n        add((7 * m) / 8);\n        add(m - 1);\n    }\n\n    return vector<int>(st.begin(), st.end());\n}\n\nstatic bool build_segment_plan(\n    const vector<Rect>& a, int l, int r, ll cap, bool rowMode, int variant, SegPlan& out\n) {\n    int m = r - l;\n    out.rot.assign(m, 0);\n\n    ll W = 0, H = 0;\n    int anchor = 0;\n\n    for (int k = 0; k < m; ++k) {\n        const Rect& x = a[l + k];\n        auto [w0, h0] = pack_dims(x, rowMode, 0);\n        auto [w1, h1] = pack_dims(x, rowMode, 1);\n\n        bool f0 = rowMode ? (h0 <= cap) : (w0 <= cap);\n        bool f1 = rowMode ? (h1 <= cap) : (w1 <= cap);\n        if (!f0 && !f1) return false;\n\n        int rot = 0;\n        if (f0 && f1) {\n            bool choose1 = false;\n            if (variant == 0) {\n                // minimize width (row) / height (col)\n                if (rowMode) {\n                    if (w1 < w0 || (w1 == w0 && h1 < h0)) choose1 = true;\n                } else {\n                    if (h1 < h0 || (h1 == h0 && w1 < w0)) choose1 = true;\n                }\n            } else if (variant == 1) {\n                // minimize max-side\n                ll s0 = max(w0, h0), s1 = max(w1, h1);\n                if (s1 < s0 || (s1 == s0 && ((rowMode ? w1 : h1) < (rowMode ? w0 : h0)))) choose1 = true;\n            } else {\n                // minimize abs difference\n                ll d0 = llabs(w0 - h0), d1 = llabs(w1 - h1);\n                if (d1 < d0 || (d1 == d0 && ((rowMode ? w1 : h1) < (rowMode ? w0 : h0)))) choose1 = true;\n            }\n            rot = choose1 ? 1 : 0;\n        } else {\n            rot = f1 ? 1 : 0;\n        }\n\n        ll w = rot ? w1 : w0;\n        ll h = rot ? h1 : h0;\n        out.rot[k] = rot;\n\n        if (rowMode) {\n            W += w;\n            if (h > H) {\n                H = h;\n                anchor = k;\n            }\n        } else {\n            W = max(W, w);\n            H += h;\n            if (w > W) {\n                W = w;\n                anchor = k;\n            }\n        }\n    }\n\n    out.W = W;\n    out.H = H;\n    out.anchor = anchor;\n    return true;\n}\n\nstatic vector<State> prune_frontier(vector<State> cand, int limit) {\n    if (cand.empty()) return cand;\n\n    sort(cand.begin(), cand.end(), [](const State& a, const State& b) {\n        if (a.W != b.W) return a.W < b.W;\n        if (a.H != b.H) return a.H < b.H;\n        if (a.prev_i != b.prev_i) return a.prev_i < b.prev_i;\n        if (a.prev_idx != b.prev_idx) return a.prev_idx < b.prev_idx;\n        return a.plan_idx < b.plan_idx;\n    });\n\n    // keep the best H for each W\n    vector<State> uniqW;\n    uniqW.reserve(cand.size());\n    for (size_t i = 0; i < cand.size();) {\n        size_t j = i + 1;\n        State best = cand[i];\n        while (j < cand.size() && cand[j].W == cand[i].W) {\n            if (cand[j].H < best.H) best = cand[j];\n            ++j;\n        }\n        uniqW.push_back(best);\n        i = j;\n    }\n\n    // Pareto frontier\n    vector<State> front;\n    front.reserve(uniqW.size());\n    ll bestH = (1LL << 62);\n    for (auto &s : uniqW) {\n        if (s.H < bestH) {\n            front.push_back(s);\n            bestH = s.H;\n        }\n    }\n\n    if ((int)front.size() <= limit) return front;\n\n    set<int> idxs;\n    auto add = [&](int idx) {\n        if (0 <= idx && idx < (int)front.size()) idxs.insert(idx);\n    };\n\n    add(0);\n    add((int)front.size() - 1);\n    add((int)front.size() / 2);\n    add((int)front.size() / 3);\n    add((2 * (int)front.size()) / 3);\n\n    vector<pair<ll,ll>> forms = {\n        {1,1}, {2,1}, {1,2}, {3,1}, {1,3},\n        {5,2}, {2,5}, {8,3}, {3,8}, {13,5}, {5,13}\n    };\n    auto best_by_linear = [&](ll a, ll b) {\n        int best = 0;\n        i128 bv = (i128)a * front[0].W + (i128)b * front[0].H;\n        for (int i = 1; i < (int)front.size(); ++i) {\n            i128 v = (i128)a * front[i].W + (i128)b * front[i].H;\n            if (v < bv || (v == bv && (front[i].W + front[i].H < front[best].W + front[best].H))) {\n                bv = v;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    for (auto [a, b] : forms) {\n        int p = best_by_linear(a, b);\n        add(p);\n        add(p - 1);\n        add(p + 1);\n    }\n\n    int K = min(limit, (int)front.size());\n    if (K >= 2) {\n        for (int k = 0; k < K; ++k) {\n            int idx = (int)((1LL * k * ((int)front.size() - 1)) / (K - 1));\n            add(idx);\n        }\n    } else {\n        add(0);\n    }\n\n    vector<State> sel;\n    sel.reserve(idxs.size());\n    for (int idx : idxs) sel.push_back(front[idx]);\n\n    if ((int)sel.size() > limit) sel.resize(limit);\n    return sel;\n}\n\nstatic vector<int> select_final_indices(const vector<State>& front) {\n    vector<int> ids;\n    if (front.empty()) return ids;\n\n    set<int> idxs;\n    auto add = [&](int idx) {\n        if (0 <= idx && idx < (int)front.size()) idxs.insert(idx);\n    };\n\n    int m = (int)front.size();\n    add(0);\n    add(m - 1);\n    add(m / 2);\n    add(m / 3);\n    add((2 * m) / 3);\n\n    vector<pair<ll,ll>> forms = {\n        {1,1}, {2,1}, {1,2}, {3,1}, {1,3},\n        {4,1}, {1,4}, {5,2}, {2,5}, {7,3}, {3,7},\n        {11,4}, {4,11}\n    };\n\n    auto best_by_linear = [&](ll a, ll b) {\n        int best = 0;\n        i128 bv = (i128)a * front[0].W + (i128)b * front[0].H;\n        for (int i = 1; i < m; ++i) {\n            i128 v = (i128)a * front[i].W + (i128)b * front[i].H;\n            if (v < bv || (v == bv && front[i].W + front[i].H < front[best].W + front[best].H)) {\n                bv = v;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    for (auto [a, b] : forms) {\n        int p = best_by_linear(a, b);\n        add(p);\n        add(p - 1);\n        add(p + 1);\n    }\n\n    int K = min(m, 16);\n    if (K >= 2) {\n        for (int k = 0; k < K; ++k) {\n            int idx = (int)((1LL * k * (m - 1)) / (K - 1));\n            add(idx);\n        }\n    } else {\n        add(0);\n    }\n\n    for (int idx : idxs) ids.push_back(idx);\n    return ids;\n}\n\nstatic vector<Op> reconstruct_ops(\n    const vector<Rect>& rects,\n    const vector<int>& orig,\n    const vector<vector<vector<SegPlan>>>& plans,\n    const vector<vector<State>>& dp,\n    bool rowMode,\n    int idx\n) {\n    int N = (int)rects.size();\n    vector<tuple<int,int,int>> steps; // (l, r, stateIdxAtR)\n    int cur_i = N, cur_idx = idx;\n\n    while (cur_i > 0) {\n        const State& s = dp[cur_i][cur_idx];\n        steps.push_back({s.prev_i, cur_i, cur_idx});\n        cur_idx = s.prev_idx;\n        cur_i = s.prev_i;\n    }\n    reverse(steps.begin(), steps.end());\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int prev_anchor = -1;\n    bool firstSeg = true;\n\n    for (auto [l, r, sidx] : steps) {\n        const State& s = dp[r][sidx];\n        const SegPlan& p = plans[l][r][s.plan_idx];\n\n        if (firstSeg) {\n            ops.push_back({orig[l], p.rot[0], -1, 'U'});\n        } else {\n            ops.push_back({orig[l], p.rot[0], prev_anchor, rowMode ? 'L' : 'U'});\n        }\n\n        for (int k = 1; k < (int)p.rot.size(); ++k) {\n            ops.push_back({orig[l + k], p.rot[k], orig[l + k - 1], rowMode ? 'U' : 'L'});\n        }\n\n        prev_anchor = orig[l + p.anchor];\n        firstSeg = false;\n    }\n\n    return ops;\n}\n\nstatic vector<Cand> build_family_candidates(const Dataset& ds, bool rowMode, int pattern) {\n    int N = (int)ds.rects.size();\n\n    vector<vector<vector<SegPlan>>> plans(N + 1, vector<vector<SegPlan>>(N + 1));\n\n    // Precompute interval plans\n    for (int l = 0; l < N; ++l) {\n        vector<ll> vals;\n        vals.reserve(2 * (N - l));\n        for (int r = l + 1; r <= N; ++r) {\n            const Rect& x = ds.rects[r - 1];\n            vals.push_back(x.w);\n            vals.push_back(x.h);\n\n            vector<ll> u = vals;\n            sort(u.begin(), u.end());\n            u.erase(unique(u.begin(), u.end()), u.end());\n\n            vector<int> idxs = select_cap_indices(u, pattern);\n            unordered_set<uint64_t> seen;\n            seen.reserve(idxs.size() * 4 + 8);\n\n            for (int id : idxs) {\n                ll cap = u[id];\n                for (int variant = 0; variant < 3; ++variant) {\n                    SegPlan p;\n                    if (build_segment_plan(ds.rects, l, r, cap, rowMode, variant, p)) {\n                        uint64_t h = hash_plan(p);\n                        if (seen.insert(h).second) plans[l][r].push_back(std::move(p));\n                    }\n                }\n            }\n\n            if (plans[l][r].empty()) {\n                // Extremely defensive fallback\n                SegPlan p;\n                build_segment_plan(ds.rects, l, r, u.back(), rowMode, 0, p);\n                plans[l][r].push_back(std::move(p));\n            }\n        }\n    }\n\n    // Prefix DP\n    vector<vector<State>> dp(N + 1);\n    dp[0].push_back({0, 0, -1, -1, -1});\n\n    const int LIMIT = 100;\n\n    for (int i = 1; i <= N; ++i) {\n        vector<State> cand;\n        for (int j = 0; j < i; ++j) {\n            const auto& vecPlans = plans[j][i];\n            const auto& prev = dp[j];\n            if (vecPlans.empty() || prev.empty()) continue;\n\n            cand.reserve(cand.size() + prev.size() * vecPlans.size());\n            for (int pid = 0; pid < (int)vecPlans.size(); ++pid) {\n                const SegPlan& p = vecPlans[pid];\n                for (int s = 0; s < (int)prev.size(); ++s) {\n                    const State& st = prev[s];\n                    cand.push_back({\n                        max(st.W, p.W),\n                        st.H + p.H,\n                        j, s, pid\n                    });\n                }\n            }\n        }\n        dp[i] = prune_frontier(std::move(cand), LIMIT);\n    }\n\n    // Extract representative final states\n    vector<Cand> res;\n    const auto& front = dp[N];\n    vector<int> ids = select_final_indices(front);\n\n    unordered_set<string> seen;\n    seen.reserve(ids.size() * 2 + 8);\n\n    for (int idx : ids) {\n        if (idx < 0 || idx >= (int)front.size()) continue;\n        vector<Op> ops = reconstruct_ops(ds.rects, ds.orig, plans, dp, rowMode, idx);\n\n        Cand c;\n        c.ops = std::move(ops);\n        c.score = front[idx].W + front[idx].H + ds.penalty;\n        c.sig = serialize_ops(c.ops);\n\n        if (seen.insert(c.sig).second) res.push_back(std::move(c));\n    }\n\n    return res;\n}\n\nstatic Cand build_chain_candidate(const Dataset& ds, bool rowMode, int policy) {\n    int N = (int)ds.rects.size();\n    Cand c;\n    vector<Op> ops;\n    ops.reserve(N);\n\n    ll W = 0, H = 0;\n    for (int i = 0; i < N; ++i) {\n        int r = choose_rot_policy(ds.rects[i], rowMode, policy, i);\n        auto [w, h] = pack_dims(ds.rects[i], rowMode, r);\n        if (rowMode) {\n            W += w;\n            H = max(H, h);\n        } else {\n            W = max(W, w);\n            H += h;\n        }\n\n        if (i == 0) {\n            ops.push_back({ds.orig[i], r, -1, 'U'});\n        } else {\n            ops.push_back({ds.orig[i], r, ds.orig[i - 1], rowMode ? 'U' : 'L'});\n        }\n    }\n\n    c.ops = std::move(ops);\n    c.score = W + H + ds.penalty;\n    c.sig = serialize_ops(c.ops);\n    return c;\n}\n\nstatic Dataset make_full_dataset(const vector<Rect>& base) {\n    Dataset ds;\n    ds.rects = base;\n    ds.orig.resize(base.size());\n    iota(ds.orig.begin(), ds.orig.end(), 0);\n    ds.penalty = 0;\n    return ds;\n}\n\nstatic Dataset make_drop_dataset(const vector<Rect>& base, int omit) {\n    Dataset ds;\n    ds.penalty = base[omit].w + base[omit].h;\n    ds.rects.reserve(base.size() - 1);\n    ds.orig.reserve(base.size() - 1);\n    for (int i = 0; i < (int)base.size(); ++i) {\n        if (i == omit) continue;\n        ds.rects.push_back(base[i]);\n        ds.orig.push_back(i);\n    }\n    return ds;\n}\n\nstatic int argmax_perimeter(const vector<Rect>& base) {\n    int id = 0;\n    for (int i = 1; i < (int)base.size(); ++i) {\n        ll a = base[i].w + base[i].h;\n        ll b = base[id].w + base[id].h;\n        if (a > b) id = i;\n    }\n    return id;\n}\n\nstatic int argmax_maxside(const vector<Rect>& base) {\n    int id = 0;\n    for (int i = 1; i < (int)base.size(); ++i) {\n        ll a = max(base[i].w, base[i].h);\n        ll b = max(base[id].w, base[id].h);\n        if (a > b) id = i;\n    }\n    return id;\n}\n\nstatic int argmax_area(const vector<Rect>& base) {\n    int id = 0;\n    for (int i = 1; i < (int)base.size(); ++i) {\n        i128 a = (i128)base[i].w * base[i].h;\n        i128 b = (i128)base[id].w * base[id].h;\n        if (a > b) id = i;\n    }\n    return id;\n}\n\nstatic int argmax_aspect(const vector<Rect>& base) {\n    int id = 0;\n    for (int i = 1; i < (int)base.size(); ++i) {\n        ll a1 = max(base[i].w, base[i].h), a2 = min(base[i].w, base[i].h);\n        ll b1 = max(base[id].w, base[id].h), b2 = min(base[id].w, base[id].h);\n        if ((i128)a1 * b2 > (i128)b1 * a2) id = i;\n    }\n    return id;\n}\n\nstatic void add_candidate(\n    vector<Cand>& pool,\n    unordered_map<string, int>& pos,\n    Cand c\n) {\n    auto it = pos.find(c.sig);\n    if (it == pos.end()) {\n        pos.emplace(c.sig, (int)pool.size());\n        pool.push_back(std::move(c));\n    } else {\n        int idx = it->second;\n        if (c.score < pool[idx].score) pool[idx] = std::move(c);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    ll sigma;\n    cin >> N >> T >> sigma;\n\n    vector<Rect> base(N);\n    for (int i = 0; i < N; ++i) cin >> base[i].w >> base[i].h;\n\n    vector<Cand> pool;\n    unordered_map<string, int> pos;\n    pos.reserve(2048);\n\n    Dataset full = make_full_dataset(base);\n\n    // Cheap baselines on the full set\n    for (int mode = 0; mode < 2; ++mode) {\n        bool rowMode = (mode == 0);\n        for (int policy = 0; policy <= 7; ++policy) {\n            add_candidate(pool, pos, build_chain_candidate(full, rowMode, policy));\n        }\n    }\n\n    // Cheap omission baselines\n    vector<int> drops = {\n        argmax_perimeter(base),\n        argmax_maxside(base),\n        argmax_area(base),\n        argmax_aspect(base)\n    };\n    sort(drops.begin(), drops.end());\n    drops.erase(unique(drops.begin(), drops.end()), drops.end());\n\n    for (int omit : drops) {\n        Dataset ds = make_drop_dataset(base, omit);\n        for (int mode = 0; mode < 2; ++mode) {\n            bool rowMode = (mode == 0);\n            for (int policy = 0; policy <= 2; ++policy) {\n                add_candidate(pool, pos, build_chain_candidate(ds, rowMode, policy));\n            }\n        }\n    }\n\n    // Stronger families: cap-based interval DP\n    for (int pattern = 0; pattern < 3; ++pattern) {\n        for (int mode = 0; mode < 2; ++mode) {\n            bool rowMode = (mode == 0);\n            vector<Cand> cands = build_family_candidates(full, rowMode, pattern);\n            for (auto& c : cands) add_candidate(pool, pos, std::move(c));\n        }\n    }\n\n    if (pool.empty()) {\n        Cand c;\n        vector<Op> ops;\n        for (int i = 0; i < N; ++i) {\n            if (i == 0) ops.push_back({i, 0, -1, 'U'});\n            else ops.push_back({i, 0, i - 1, 'U'});\n        }\n        c.ops = std::move(ops);\n        c.score = 0;\n        c.sig = serialize_ops(c.ops);\n        pool.push_back(std::move(c));\n    }\n\n    sort(pool.begin(), pool.end(), [](const Cand& a, const Cand& b) {\n        if (a.score != b.score) return a.score < b.score;\n        return a.sig < b.sig;\n    });\n\n    int use = min(T, (int)pool.size());\n    for (int t = 0; t < use; ++t) {\n        const Cand& c = pool[t];\n        cout << c.ops.size() << '\\n';\n        for (const auto& op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm; // Feedback is noisy; the candidate set is fixed in advance.\n    }\n\n    for (int t = use; t < T; ++t) {\n        const Cand& c = pool[0];\n        cout << c.ops.size() << '\\n';\n        for (const auto& op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm;\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing Key = array<long long, 6>;\n\nstruct Move {\n    long long gain = 0;\n    int v = -1, u = -1;\n};\n\nstruct Info {\n    vector<vector<int>> children;\n    vector<int> parent, roots, comp, depth, tin, tout, maxDown;\n    vector<long long> subW;\n    vector<vector<int>> compNodes;\n    long long score = 0;\n};\n\nstatic int N, M, H;\nstatic vector<int> A, X, Y, degv, r2v, mort, bucket8, neighSum;\nstatic vector<vector<int>> adj;\nstatic chrono::steady_clock::time_point start_time;\n\nstatic inline bool time_up() {\n    return chrono::duration_cast<chrono::milliseconds>(\n        chrono::steady_clock::now() - start_time\n    ).count() > 1850;\n}\n\nstatic int morton_code(int x, int y) {\n    int z = 0;\n    for (int i = 0; i < 10; ++i) {\n        z |= ((x >> i) & 1) << (2 * i);\n        z |= ((y >> i) & 1) << (2 * i + 1);\n    }\n    return z;\n}\n\nstatic inline long long sqdist(int i, int j) {\n    long long dx = X[i] - X[j];\n    long long dy = Y[i] - Y[j];\n    return dx * dx + dy * dy;\n}\n\nstatic Key orderKey1(int v) { return {A[v], -degv[v], r2v[v], neighSum[v], mort[v], v}; }\nstatic Key orderKey2(int v) { return {A[v], r2v[v], -degv[v], neighSum[v], mort[v], v}; }\nstatic Key orderKey3(int v) { return {A[v], -neighSum[v], -degv[v], r2v[v], mort[v], v}; }\n\nstatic Key prefKey1(int v) { return {A[v], -degv[v], r2v[v], neighSum[v], mort[v], v}; }\nstatic Key prefKey2(int v) { return {A[v], -neighSum[v], -degv[v], r2v[v], mort[v], v}; }\n\nstatic Key childHighKey(int v) { return {-A[v], -degv[v], -neighSum[v], -r2v[v], mort[v], v}; }\nstatic Key childLowKey(int v) { return {A[v], -degv[v], -neighSum[v], -r2v[v], mort[v], v}; }\n\nstatic Info compute_info(const vector<int>& parent) {\n    Info info;\n    info.parent = parent;\n    info.children.assign(N, {});\n    info.roots.clear();\n\n    for (int v = 0; v < N; ++v) {\n        if (parent[v] == -1) info.roots.push_back(v);\n        else info.children[parent[v]].push_back(v);\n    }\n\n    info.comp.assign(N, -1);\n    info.depth.assign(N, -1);\n    info.tin.assign(N, -1);\n    info.tout.assign(N, -1);\n    info.subW.assign(N, 0);\n    info.maxDown.assign(N, 0);\n    info.compNodes.clear();\n    info.score = 0;\n\n    int timer = 0, cid = 0;\n    for (int r : info.roots) {\n        info.compNodes.push_back({});\n        auto dfs = [&](auto&& self, int v, int d) -> void {\n            info.comp[v] = cid;\n            info.depth[v] = d;\n            info.tin[v] = timer++;\n            info.subW[v] = A[v];\n            info.maxDown[v] = 0;\n            info.score += 1LL * (d + 1) * A[v];\n            info.compNodes.back().push_back(v);\n            for (int ch : info.children[v]) {\n                self(self, ch, d + 1);\n                info.subW[v] += info.subW[ch];\n                info.maxDown[v] = max(info.maxDown[v], info.maxDown[ch] + 1);\n            }\n            info.tout[v] = timer;\n        };\n        dfs(dfs, r, 0);\n        ++cid;\n    }\n\n    return info;\n}\n\ntemplate <class PrefFunc>\nstatic vector<int> build_greedy(const vector<int>& order, PrefFunc pref) {\n    vector<int> parent(N, -2), depth(N, -1);\n\n    for (int v : order) {\n        int best = -1;\n        for (int u : adj[v]) {\n            if (depth[u] == -1 || depth[u] >= H) continue;\n            if (best == -1 ||\n                depth[u] > depth[best] ||\n                (depth[u] == depth[best] && pref(u) < pref(best))) {\n                best = u;\n            }\n        }\n        if (best == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = best;\n            depth[v] = depth[best] + 1;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) if (parent[i] == -2) parent[i] = -1;\n    return parent;\n}\n\nstatic vector<int> choose_seeds(const vector<int>& order, int K) {\n    vector<int> pool;\n    int lim = min(N, 250);\n    for (int i = 0; i < lim; ++i) pool.push_back(order[i]);\n\n    vector<int> seeds;\n    vector<char> used(N, 0);\n    if (pool.empty()) return seeds;\n\n    seeds.push_back(pool[0]);\n    used[pool[0]] = 1;\n\n    while ((int)seeds.size() < K) {\n        int best = -1;\n        long long bestScore = LLONG_MIN;\n        for (int v : pool) {\n            if (used[v]) continue;\n            long long md = (1LL << 60);\n            for (int s : seeds) md = min(md, sqdist(v, s));\n            long long score = md * 1000LL + 3000LL * degv[v] - 10000LL * A[v] - 30LL * r2v[v];\n            if (score > bestScore) {\n                bestScore = score;\n                best = v;\n            }\n        }\n        if (best == -1) break;\n        used[best] = 1;\n        seeds.push_back(best);\n    }\n    return seeds;\n}\n\nstatic vector<int> build_frontier_forest(const vector<int>& seedSet, int mode) {\n    vector<int> parent(N, -2), depth(N, -1);\n    vector<int> bestDepth(N, -1), bestPar(N, -1);\n    vector<long long> bestParQ(N, LLONG_MIN);\n    vector<int> placedCnt(N, 0);\n    vector<long long> rootScore(N, LLONG_MIN);\n    vector<char> placed(N, 0);\n\n    priority_queue<tuple<long long, int, int>> ready; // priority, depth, -v\n    priority_queue<pair<long long, int>> rootpq;      // priority, v\n\n    auto calcRootScore = [&](int v) {\n        long long s = -1000000LL * A[v] + 3000LL * degv[v] - 30LL * r2v[v] - 10LL * neighSum[v];\n        if (mode == 1) s = -1000000LL * A[v] + 2000LL * degv[v] + 10LL * neighSum[v] - 25LL * r2v[v];\n        if (mode == 2) s = -1000000LL * A[v] + 1500LL * degv[v] - 1000LL * bucket8[v] - 25LL * r2v[v];\n        s += 25000LL * placedCnt[v];\n        return s;\n    };\n\n    auto pushRoot = [&](int v) {\n        if (placed[v]) return;\n        long long s = calcRootScore(v);\n        if (s > rootScore[v]) {\n            rootScore[v] = s;\n            rootpq.push({s, v});\n        }\n    };\n\n    auto updateNeighbor = [&](int from, int to) {\n        if (placed[to]) return;\n        ++placedCnt[to];\n        pushRoot(to);\n\n        int nd = depth[from] + 1;\n        if (nd > H) return;\n        long long pq = 1000000LL * nd - 1000LL * A[to] + 100LL * degv[to] - 10LL * neighSum[to];\n        if (nd > bestDepth[to] || (nd == bestDepth[to] && pq > bestParQ[to])) {\n            bestDepth[to] = nd;\n            bestPar[to] = from;\n            bestParQ[to] = pq;\n            ready.emplace(pq, nd, -to);\n        }\n    };\n\n    auto placeRoot = [&](int v) {\n        placed[v] = 1;\n        parent[v] = -1;\n        depth[v] = 0;\n        for (int to : adj[v]) updateNeighbor(v, to);\n    };\n\n    auto placeChild = [&](int v) {\n        int p = bestPar[v];\n        placed[v] = 1;\n        parent[v] = p;\n        depth[v] = bestDepth[v];\n        for (int to : adj[v]) updateNeighbor(v, to);\n    };\n\n    for (int v = 0; v < N; ++v) pushRoot(v);\n\n    vector<int> seeds = seedSet;\n    sort(seeds.begin(), seeds.end(), [&](int x, int y) {\n        return calcRootScore(x) > calcRootScore(y);\n    });\n\n    for (int s : seeds) {\n        if (!placed[s]) placeRoot(s);\n    }\n\n    int placedCount = 0;\n    for (int v = 0; v < N; ++v) if (placed[v]) ++placedCount;\n\n    while (placedCount < N) {\n        bool progressed = false;\n\n        while (!ready.empty()) {\n            auto [pr, d, negv] = ready.top();\n            int v = -negv;\n            ready.pop();\n            if (placed[v]) continue;\n            if (d != bestDepth[v] || d > H) continue;\n            placeChild(v);\n            ++placedCount;\n            progressed = true;\n            break;\n        }\n        if (progressed) continue;\n\n        while (!rootpq.empty()) {\n            auto [s, v] = rootpq.top();\n            rootpq.pop();\n            if (placed[v]) continue;\n            if (s != rootScore[v]) continue;\n            placeRoot(v);\n            ++placedCount;\n            progressed = true;\n            break;\n        }\n\n        if (!progressed) break;\n    }\n\n    for (int v = 0; v < N; ++v) if (parent[v] == -2) parent[v] = -1;\n    return parent;\n}\n\nstatic vector<int> build_dfs_forest(const vector<int>& rootOrder, int mode) {\n    vector<vector<int>> ordAdj = adj;\n    for (int v = 0; v < N; ++v) {\n        sort(ordAdj[v].begin(), ordAdj[v].end(), [&](int x, int y) {\n            if (mode == 0) return childHighKey(x) < childHighKey(y);\n            return childLowKey(x) < childLowKey(y);\n        });\n    }\n\n    vector<int> parent(N, -2);\n    vector<char> vis(N, 0);\n\n    auto dfs = [&](auto&& self, int v, int d) -> void {\n        vis[v] = 1;\n        if (d == H) return;\n        for (int to : ordAdj[v]) {\n            if (!vis[to]) {\n                parent[to] = v;\n                self(self, to, d + 1);\n            }\n        }\n    };\n\n    for (int r : rootOrder) {\n        if (!vis[r]) {\n            parent[r] = -1;\n            dfs(dfs, r, 0);\n        }\n    }\n\n    for (int v = 0; v < N; ++v) if (parent[v] == -2) parent[v] = -1;\n    return parent;\n}\n\nstatic vector<int> exact_root_optimize(const vector<int>& parentIn) {\n    Info info = compute_info(parentIn);\n    vector<int> ans = parentIn;\n    vector<long long> f(N, 0);\n\n    auto bfs = [&](int s) {\n        vector<int> dist(N, -1);\n        queue<int> q;\n        q.push(s);\n        dist[s] = 0;\n        int far = s;\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            if (dist[v] > dist[far]) far = v;\n            int p = info.parent[v];\n            if (p != -1 && dist[p] == -1) {\n                dist[p] = dist[v] + 1;\n                q.push(p);\n            }\n            for (int ch : info.children[v]) {\n                if (dist[ch] == -1) {\n                    dist[ch] = dist[v] + 1;\n                    q.push(ch);\n                }\n            }\n        }\n        return pair<int, vector<int>>(far, move(dist));\n    };\n\n    for (int cid = 0; cid < (int)info.roots.size(); ++cid) {\n        int root = info.roots[cid];\n        const auto& nodes = info.compNodes[cid];\n        if ((int)nodes.size() == 1) continue;\n\n        long long W = info.subW[root];\n        long long base = 0;\n        for (int v : nodes) base += 1LL * info.depth[v] * A[v];\n\n        f[root] = base;\n        auto dfs = [&](auto&& self, int v) -> void {\n            for (int ch : info.children[v]) {\n                f[ch] = f[v] + W - 2LL * info.subW[ch];\n                self(self, ch);\n            }\n        };\n        dfs(dfs, root);\n\n        auto [x, dx0] = bfs(root);\n        auto [y, dx] = bfs(x);\n        auto [z, dy] = bfs(y);\n        (void)dx0;\n        (void)z;\n\n        int best = root;\n        long long bestVal = f[root];\n        int bestEcc = max(dx[root], dy[root]);\n\n        for (int v : nodes) {\n            int ecc = max(dx[v], dy[v]);\n            if (ecc > H) continue;\n            if (f[v] > bestVal ||\n                (f[v] == bestVal &&\n                 (ecc < bestEcc ||\n                  (ecc == bestEcc &&\n                   (degv[v] > degv[best] ||\n                    (degv[v] == degv[best] &&\n                     (A[v] < A[best] || (A[v] == A[best] && v < best)))))))) {\n                best = v;\n                bestVal = f[v];\n                bestEcc = ecc;\n            }\n        }\n\n        if (best == root) continue;\n\n        vector<char> vis(N, 0);\n        queue<int> q;\n        q.push(best);\n        vis[best] = 1;\n        ans[best] = -1;\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            auto tryPush = [&](int to) {\n                if (!vis[to]) {\n                    vis[to] = 1;\n                    ans[to] = v;\n                    q.push(to);\n                }\n            };\n\n            int p = info.parent[v];\n            if (p != -1) tryPush(p);\n            for (int ch : info.children[v]) tryPush(ch);\n        }\n    }\n\n    return ans;\n}\n\nstatic vector<int> merge_roots(vector<int> parent, int maxIter = 120) {\n    for (int iter = 0; iter < maxIter && !time_up(); ++iter) {\n        Info info = compute_info(parent);\n\n        long long bestGain = 0;\n        int bestV = -1, bestU = -1;\n\n        for (int v = 0; v < N; ++v) {\n            if (parent[v] != -1) continue; // only roots\n            int h = info.maxDown[v];\n            long long W = info.subW[v];\n            if (h == H) continue;\n\n            for (int u : adj[v]) {\n                if (info.comp[u] == info.comp[v]) continue;\n                int shift = info.depth[u] + 1;\n                if (shift + h > H) continue;\n\n                long long gain = 1LL * shift * W;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestV = v;\n                    bestU = u;\n                }\n            }\n        }\n\n        if (bestGain <= 0) break;\n        parent[bestV] = bestU;\n    }\n    return parent;\n}\n\nstatic Move find_best_move(const Info& info, const vector<int>& parent) {\n    long long bestGain = 0;\n    vector<pair<int, int>> cand;\n\n    for (int v = 0; v < N; ++v) {\n        if (info.maxDown[v] == H) continue;\n        for (int u : adj[v]) {\n            if (u == parent[v]) continue;\n            if (info.comp[u] == info.comp[v] &&\n                info.tin[v] <= info.tin[u] && info.tin[u] < info.tout[v]) {\n                continue;\n            }\n\n            int nd = info.depth[u] + 1;\n            if (nd + info.maxDown[v] > H) continue;\n\n            long long gain = 1LL * (nd - info.depth[v]) * info.subW[v];\n            if (gain <= 0) continue;\n\n            if (gain > bestGain) {\n                bestGain = gain;\n                cand.clear();\n                cand.push_back({v, u});\n            } else if (gain == bestGain) {\n                cand.push_back({v, u});\n            }\n        }\n    }\n\n    if (cand.empty()) return {};\n    static mt19937_64 rng(123456789);\n    auto [v, u] = cand[rng() % cand.size()];\n    return {bestGain, v, u};\n}\n\nstatic vector<int> hill_climb(vector<int> parent, int maxSteps) {\n    for (int step = 0; step < maxSteps && !time_up(); ++step) {\n        Info info = compute_info(parent);\n        Move mv = find_best_move(info, parent);\n        if (mv.v == -1) break;\n        parent[mv.v] = mv.u;\n        if (step % 20 == 19) parent = exact_root_optimize(parent);\n    }\n    return parent;\n}\n\nstatic vector<int> shake(vector<int> parent, mt19937_64& rng, int steps) {\n    Info info = compute_info(parent);\n\n    for (int it = 0; it < steps && !time_up(); ++it) {\n        int v = (int)(rng() % N);\n        if (info.maxDown[v] == H) continue;\n\n        vector<int> cand;\n        for (int u : adj[v]) {\n            if (u == parent[v]) continue;\n            if (info.comp[u] == info.comp[v] &&\n                info.tin[v] <= info.tin[u] && info.tin[u] < info.tout[v]) {\n                continue;\n            }\n            int nd = info.depth[u] + 1;\n            if (nd + info.maxDown[v] > H) continue;\n            cand.push_back(u);\n        }\n        if (cand.empty()) continue;\n\n        int u = cand[rng() % cand.size()];\n        long long gain = 1LL * ((info.depth[u] + 1) - info.depth[v]) * info.subW[v];\n        bool accept = false;\n        if (gain >= 0) accept = true;\n        else if (gain >= -20 && (rng() % 100) < 5) accept = true;\n\n        if (accept) {\n            parent[v] = u;\n            info = compute_info(parent);\n        }\n    }\n\n    return parent;\n}\n\nstatic vector<int> refine(vector<int> parent, mt19937_64& rng) {\n    parent = exact_root_optimize(parent);\n    parent = merge_roots(parent, 80);\n    parent = exact_root_optimize(parent);\n    parent = hill_climb(parent, 50);\n    parent = exact_root_optimize(parent);\n    parent = merge_roots(parent, 80);\n    parent = hill_climb(parent, 30);\n    parent = exact_root_optimize(parent);\n    return parent;\n}\n\nstatic long long evaluate_score(const vector<int>& parent) {\n    return compute_info(parent).score;\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 >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    adj.assign(N, {});\n    vector<pair<int, int>> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; ++i) cin >> X[i] >> Y[i];\n\n    degv.resize(N);\n    r2v.resize(N);\n    mort.resize(N);\n    bucket8.resize(N);\n    neighSum.resize(N);\n\n    const double PI = acos(-1.0);\n    for (int i = 0; i < N; ++i) {\n        degv[i] = (int)adj[i].size();\n        r2v[i] = (X[i] - 500) * (X[i] - 500) + (Y[i] - 500) * (Y[i] - 500);\n        mort[i] = morton_code(X[i], Y[i]);\n\n        long long s = 0;\n        for (int to : adj[i]) s += A[to];\n        neighSum[i] = (int)s;\n\n        double ang = atan2((double)Y[i] - 500.0, (double)X[i] - 500.0);\n        if (ang < 0) ang += 2.0 * PI;\n        int b = (int)(ang / (2.0 * PI) * 8.0);\n        b = max(0, min(7, b));\n        bucket8[i] = b;\n    }\n\n    vector<int> ord1(N), ord2(N), ord3(N);\n    iota(ord1.begin(), ord1.end(), 0);\n    iota(ord2.begin(), ord2.end(), 0);\n    iota(ord3.begin(), ord3.end(), 0);\n\n    sort(ord1.begin(), ord1.end(), [&](int x, int y) { return orderKey1(x) < orderKey1(y); });\n    sort(ord2.begin(), ord2.end(), [&](int x, int y) { return orderKey2(x) < orderKey2(y); });\n    sort(ord3.begin(), ord3.end(), [&](int x, int y) { return orderKey3(x) < orderKey3(y); });\n\n    vector<int> seeds1 = choose_seeds(ord1, 1);\n    vector<int> seeds3 = choose_seeds(ord1, 3);\n    vector<int> seeds6 = choose_seeds(ord1, 6);\n\n    vector<int> rootOrder1 = seeds6;\n    vector<int> rootOrder2 = seeds3;\n    vector<char> used(N, 0);\n    for (int s : seeds6) used[s] = 1;\n    for (int v : ord1) if (!used[v]) rootOrder1.push_back(v);\n    fill(used.begin(), used.end(), 0);\n    for (int s : seeds3) used[s] = 1;\n    for (int v : ord2) if (!used[v]) rootOrder2.push_back(v);\n\n    vector<int> cand1 = build_frontier_forest(seeds1, 0);\n    vector<int> cand2 = build_frontier_forest(seeds3, 1);\n    vector<int> cand3 = build_frontier_forest(seeds6, 2);\n    vector<int> cand4 = build_greedy(ord1, prefKey1);\n    vector<int> cand5 = build_greedy(ord2, prefKey2);\n    vector<int> cand6 = build_dfs_forest(rootOrder1, 0);\n    vector<int> cand7 = build_dfs_forest(rootOrder2, 1);\n\n    uint64_t seed = 88172645463393265ULL;\n    auto mix = [&](uint64_t x) {\n        seed ^= x + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2);\n    };\n    mix(N); mix(M); mix(H);\n    for (int i = 0; i < N; ++i) {\n        mix((uint64_t)A[i] << 32 ^ (uint64_t)X[i]);\n        mix((uint64_t)Y[i] << 16 ^ (uint64_t)degv[i]);\n    }\n    for (auto [u, v] : edges) mix(((uint64_t)u << 32) ^ (uint64_t)v);\n    mt19937_64 rng(seed);\n\n    struct Sol {\n        long long score = -1;\n        vector<int> parent;\n    };\n\n    vector<vector<int>> bases = {cand1, cand2, cand3, cand4, cand5, cand6, cand7};\n\n    Sol best;\n    for (auto& b : bases) {\n        if (time_up()) break;\n        vector<int> cur = refine(b, rng);\n        long long sc = evaluate_score(cur);\n        if (sc > best.score) {\n            best.score = sc;\n            best.parent = move(cur);\n        }\n    }\n\n    if (!time_up() && !best.parent.empty()) {\n        vector<int> cur = best.parent;\n        cur = shake(cur, rng, 80);\n        cur = refine(cur, rng);\n        long long sc = evaluate_score(cur);\n        if (sc > best.score) {\n            best.score = sc;\n            best.parent = move(cur);\n        }\n    }\n\n    if (best.parent.empty()) best.parent.assign(N, -1);\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << best.parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cand {\n    uint64_t mask;   // coverage over Oni bits (reduced universe later)\n    int cost;        // 2 * len\n    int len;         // strip length\n    int idx;         // row/col index\n    char dir;        // L/R/U/D\n    int orig;        // original candidate id\n};\n\nstruct U64Hash {\n    size_t operator()(uint64_t x) const noexcept {\n        x ^= x >> 33;\n        x *= 0xff51afd7ed558ccdULL;\n        x ^= x >> 33;\n        x *= 0xc4ceb9fe1a85ec53ULL;\n        x ^= x >> 33;\n        return (size_t)x;\n    }\n};\n\nstatic inline int pop64(uint64_t x) {\n    return __builtin_popcountll(x);\n}\n\nstatic inline char revDir(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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    vector<vector<int>> oniId(N, vector<int>(N, -1));\n    vector<pair<int,int>> oniPos;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'x') {\n                oniId[i][j] = (int)oniPos.size();\n                oniPos.push_back({i, j});\n            }\n        }\n    }\n\n    int M = (int)oniPos.size(); // 40\n    vector<Cand> cands;\n    cands.reserve(200);\n\n    auto addCand = [&](char dir, int idx, int len, uint64_t mask) {\n        if (mask == 0) return;\n        cands.push_back({mask, 2 * len, len, idx, dir, (int)cands.size()});\n    };\n\n    // Generate all useful candidates:\n    // only lengths where the newly removed border cell contains an Oni.\n    for (int i = 0; i < N; ++i) {\n        int firstF = N, lastF = -1;\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'o') {\n                firstF = min(firstF, j);\n                lastF = max(lastF, j);\n            }\n        }\n\n        uint64_t mask = 0;\n        for (int j = 0; j < firstF; ++j) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('L', i, j + 1, mask);\n            }\n        }\n\n        mask = 0;\n        for (int j = N - 1; j > lastF; --j) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('R', i, N - j, mask);\n            }\n        }\n    }\n\n    for (int j = 0; j < N; ++j) {\n        int firstF = N, lastF = -1;\n        for (int i = 0; i < N; ++i) {\n            if (C[i][j] == 'o') {\n                firstF = min(firstF, i);\n                lastF = max(lastF, i);\n            }\n        }\n\n        uint64_t mask = 0;\n        for (int i = 0; i < firstF; ++i) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('U', j, i + 1, mask);\n            }\n        }\n\n        mask = 0;\n        for (int i = N - 1; i > lastF; --i) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('D', j, N - i, mask);\n            }\n        }\n    }\n\n    // Deduplicate identical masks, keep the cheapest one.\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.idx < b.idx;\n    });\n\n    vector<Cand> uniq;\n    for (auto &c : cands) {\n        if (uniq.empty() || uniq.back().mask != c.mask) uniq.push_back(c);\n    }\n    cands.swap(uniq);\n\n    // Remove dominated candidates:\n    // if mask_i \u2286 mask_j and cost_j <= cost_i, i is useless.\n    {\n        int Cn = (int)cands.size();\n        vector<char> bad(Cn, false);\n        for (int i = 0; i < Cn; ++i) {\n            if (bad[i]) continue;\n            for (int j = 0; j < Cn; ++j) {\n                if (i == j || bad[i]) continue;\n                if ((cands[i].mask & ~cands[j].mask) == 0 && cands[j].cost <= cands[i].cost) {\n                    bad[i] = true;\n                    break;\n                }\n            }\n        }\n        vector<Cand> tmp;\n        for (int i = 0; i < Cn; ++i) if (!bad[i]) tmp.push_back(cands[i]);\n        cands.swap(tmp);\n    }\n\n    int Cn = (int)cands.size();\n    uint64_t fullMask = (M == 64 ? ~0ULL : ((1ULL << M) - 1ULL));\n\n    // Build original coverers and force unique-cover candidates.\n    vector<vector<int>> cover0(M);\n    for (int i = 0; i < Cn; ++i) {\n        uint64_t m = cands[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            cover0[b].push_back(i);\n            m &= (m - 1);\n        }\n    }\n\n    vector<char> forcedChosen(Cn, false);\n    vector<int> forcedSel;\n    for (int b = 0; b < M; ++b) {\n        if ((int)cover0[b].size() == 1) {\n            int id = cover0[b][0];\n            if (!forcedChosen[id]) {\n                forcedChosen[id] = true;\n                forcedSel.push_back(id);\n            }\n        }\n    }\n\n    uint64_t residualMask = fullMask;\n    long long forcedCost = 0;\n    for (int id : forcedSel) {\n        residualMask &= ~cands[id].mask;\n        forcedCost += cands[id].cost;\n    }\n\n    // Compress remaining bits.\n    vector<int> bitMap(64, -1);\n    vector<int> bits;\n    for (int b = 0; b < M; ++b) {\n        if ((residualMask >> b) & 1ULL) {\n            bitMap[b] = (int)bits.size();\n            bits.push_back(b);\n        }\n    }\n    int R = (int)bits.size();\n\n    // If forced candidates already cover everything.\n    if (R == 0) {\n        vector<pair<char,int>> ops;\n        for (int id : forcedSel) {\n            auto &c = cands[id];\n            for (int t = 0; t < c.len; ++t) ops.push_back({c.dir, c.idx});\n            for (int t = 0; t < c.len; ++t) ops.push_back({revDir(c.dir), c.idx});\n        }\n        for (auto [d, p] : ops) cout << d << ' ' << p << '\\n';\n        return 0;\n    }\n\n    vector<Cand> red;\n    red.reserve(Cn);\n    for (int i = 0; i < Cn; ++i) {\n        if (forcedChosen[i]) continue;\n        uint64_t m = cands[i].mask & residualMask;\n        if (m == 0) continue;\n        uint64_t nm = 0;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            m &= (m - 1);\n            nm |= 1ULL << bitMap[b];\n        }\n        red.push_back({nm, cands[i].cost, cands[i].len, cands[i].idx, cands[i].dir, cands[i].orig});\n    }\n\n    // Deduplicate and prune again on the reduced instance.\n    sort(red.begin(), red.end(), [&](const Cand& a, const Cand& b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.idx < b.idx;\n    });\n    {\n        vector<Cand> tmp;\n        for (auto &c : red) {\n            if (tmp.empty() || tmp.back().mask != c.mask) tmp.push_back(c);\n        }\n        red.swap(tmp);\n    }\n    {\n        int n = (int)red.size();\n        vector<char> bad(n, false);\n        for (int i = 0; i < n; ++i) {\n            if (bad[i]) continue;\n            for (int j = 0; j < n; ++j) {\n                if (i == j || bad[i]) continue;\n                if ((red[i].mask & ~red[j].mask) == 0 && red[j].cost <= red[i].cost) {\n                    bad[i] = true;\n                    break;\n                }\n            }\n        }\n        vector<Cand> tmp;\n        for (int i = 0; i < n; ++i) if (!bad[i]) tmp.push_back(red[i]);\n        red.swap(tmp);\n    }\n\n    Cn = (int)red.size();\n    vector<vector<int>> coverers(R);\n    vector<int> deg(R, 0), minCostBit(R, INT_MAX), maxCostBit(R, 0);\n\n    for (int i = 0; i < Cn; ++i) {\n        uint64_t m = red[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            coverers[b].push_back(i);\n            m &= (m - 1);\n        }\n    }\n    for (int b = 0; b < R; ++b) {\n        deg[b] = (int)coverers[b].size();\n        for (int id : coverers[b]) {\n            minCostBit[b] = min(minCostBit[b], red[id].cost);\n            maxCostBit[b] = max(maxCostBit[b], red[id].cost);\n        }\n    }\n\n    // Orders for dual lower bound.\n    vector<vector<int>> dualOrders(5, vector<int>(R));\n    for (int t = 0; t < 5; ++t) {\n        iota(dualOrders[t].begin(), dualOrders[t].end(), 0);\n    }\n    sort(dualOrders[0].begin(), dualOrders[0].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        return a < b;\n    });\n    sort(dualOrders[1].begin(), dualOrders[1].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        if (maxCostBit[a] != maxCostBit[b]) return maxCostBit[a] > maxCostBit[b];\n        return a < b;\n    });\n    sort(dualOrders[2].begin(), dualOrders[2].end(), [&](int a, int b) {\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        return a < b;\n    });\n    sort(dualOrders[3].begin(), dualOrders[3].end(), [&](int a, int b) {\n        long long lhs = 1LL * minCostBit[a] * max(1, deg[b]);\n        long long rhs = 1LL * minCostBit[b] * max(1, deg[a]);\n        if (lhs != rhs) return lhs < rhs;\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        return a < b;\n    });\n    sort(dualOrders[4].begin(), dualOrders[4].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] > deg[b];\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        return a < b;\n    });\n\n    auto cleanup = [&](vector<int> sel) -> vector<int> {\n        if (sel.empty()) return sel;\n        vector<int> cnt(R, 0);\n        for (int id : sel) {\n            uint64_t m = red[id].mask;\n            while (m) {\n                int b = __builtin_ctzll(m);\n                cnt[b]++;\n                m &= (m - 1);\n            }\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            sort(sel.begin(), sel.end(), [&](int a, int b) {\n                if (red[a].cost != red[b].cost) return red[a].cost > red[b].cost;\n                return a < b;\n            });\n\n            vector<int> nxt;\n            nxt.reserve(sel.size());\n            for (int id : sel) {\n                bool removable = true;\n                uint64_t m = red[id].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    if (cnt[b] <= 1) {\n                        removable = false;\n                        break;\n                    }\n                    m &= (m - 1);\n                }\n\n                if (removable) {\n                    uint64_t m2 = red[id].mask;\n                    while (m2) {\n                        int b = __builtin_ctzll(m2);\n                        cnt[b]--;\n                        m2 &= (m2 - 1);\n                    }\n                    changed = true;\n                } else {\n                    nxt.push_back(id);\n                }\n            }\n            sel.swap(nxt);\n        }\n        return sel;\n    };\n\n    auto greedySolve = [&](int K, bool ratioMode) -> pair<vector<int>, int> {\n        uint64_t U = (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL));\n        vector<int> sel;\n\n        while (U) {\n            // choose a forced candidate if some bit has only one coverer\n            vector<int> forced;\n            vector<char> seen(Cn, false);\n            uint64_t x = U;\n            while (x) {\n                int b = __builtin_ctzll(x);\n                x &= (x - 1);\n                if ((int)coverers[b].size() == 1) {\n                    int id = coverers[b][0];\n                    if (!seen[id]) {\n                        seen[id] = true;\n                        forced.push_back(id);\n                    }\n                }\n            }\n\n            if (!forced.empty()) {\n                for (int id : forced) {\n                    sel.push_back(id);\n                    U &= ~red[id].mask;\n                }\n                continue;\n            }\n\n            int best = -1;\n            int bestNew = -1;\n            int bestCost = INT_MAX;\n            long long bestScore = LLONG_MIN;\n\n            for (int id = 0; id < Cn; ++id) {\n                uint64_t nm = red[id].mask & U;\n                if (nm == 0) continue;\n                int newCnt = pop64(nm);\n\n                if (!ratioMode) {\n                    long long score = 1LL * K * newCnt - red[id].cost;\n                    if (best == -1 ||\n                        score > bestScore ||\n                        (score == bestScore && (newCnt > bestNew ||\n                                                (newCnt == bestNew && red[id].cost < bestCost)))) {\n                        best = id;\n                        bestScore = score;\n                        bestNew = newCnt;\n                        bestCost = red[id].cost;\n                    }\n                } else {\n                    if (best == -1) {\n                        best = id;\n                        bestNew = newCnt;\n                        bestCost = red[id].cost;\n                    } else {\n                        long long lhs = 1LL * newCnt * bestCost;\n                        long long rhs = 1LL * bestNew * red[id].cost;\n                        if (lhs > rhs ||\n                            (lhs == rhs && (newCnt > bestNew ||\n                                            (newCnt == bestNew && red[id].cost < bestCost)))) {\n                            best = id;\n                            bestNew = newCnt;\n                            bestCost = red[id].cost;\n                        }\n                    }\n                }\n            }\n\n            if (best == -1) break; // should not happen\n            sel.push_back(best);\n            U &= ~red[best].mask;\n        }\n\n        sel = cleanup(sel);\n\n        int cost = 0;\n        uint64_t cover = 0;\n        for (int id : sel) {\n            cost += red[id].cost;\n            cover |= red[id].mask;\n        }\n\n        // Safety fallback: if anything remains uncovered, add cheapest candidates.\n        if (cover != (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL))) {\n            uint64_t rem = ((R == 64 ? ~0ULL : ((1ULL << R) - 1ULL)) & ~cover);\n            while (rem) {\n                int b = __builtin_ctzll(rem);\n                int choose = -1;\n                int chooseCost = INT_MAX;\n                for (int id = 0; id < Cn; ++id) {\n                    if ((red[id].mask >> b) & 1ULL) {\n                        if (red[id].cost < chooseCost) {\n                            choose = id;\n                            chooseCost = red[id].cost;\n                        }\n                    }\n                }\n                if (choose == -1) break;\n                sel.push_back(choose);\n                cover |= red[choose].mask;\n                rem = ((R == 64 ? ~0ULL : ((1ULL << R) - 1ULL)) & ~cover);\n            }\n            sel = cleanup(sel);\n            cost = 0;\n            for (int id : sel) cost += red[id].cost;\n        }\n\n        return {sel, cost};\n    };\n\n    vector<int> bestSel;\n    int bestResCost = INT_MAX;\n\n    // Several greedy seeds.\n    vector<int> Ks = {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 50};\n    for (int K : Ks) {\n        auto [sel, cost] = greedySolve(K, false);\n        if (cost < bestResCost) {\n            bestResCost = cost;\n            bestSel = sel;\n        }\n    }\n    {\n        auto [sel, cost] = greedySolve(0, true);\n        if (cost < bestResCost) {\n            bestResCost = cost;\n            bestSel = sel;\n        }\n    }\n\n    bestSel = cleanup(bestSel);\n    bestResCost = 0;\n    {\n        uint64_t cover = 0;\n        for (int id : bestSel) {\n            bestResCost += red[id].cost;\n            cover |= red[id].mask;\n        }\n        (void)cover;\n    }\n\n    // Branch and bound search on the reduced problem.\n    chrono::steady_clock::time_point deadline = chrono::steady_clock::now() + chrono::milliseconds(1800);\n    bool timedOut = false;\n    uint64_t nodeCounter = 0;\n\n    unordered_map<uint64_t, int, U64Hash> memo;\n    memo.reserve(1 << 16);\n    memo.max_load_factor(0.7f);\n\n    vector<int> cur;\n\n    auto simpleLB = [&](uint64_t U) -> long long {\n        long long sumMin = 0;\n        int maxCover = 0;\n\n        uint64_t x = U;\n        while (x) {\n            int b = __builtin_ctzll(x);\n            x &= (x - 1);\n            sumMin += minCostBit[b];\n        }\n        for (int id = 0; id < Cn; ++id) {\n            int cov = pop64(red[id].mask & U);\n            if (cov > maxCover) maxCover = cov;\n        }\n        if (maxCover == 0) return (long long)1e9;\n        return (sumMin + maxCover - 1) / maxCover;\n    };\n\n    auto dualLB = [&](uint64_t U) -> long long {\n        long long best = 0;\n        for (int t = 0; t < 5; ++t) {\n            vector<int> slack(Cn);\n            for (int i = 0; i < Cn; ++i) slack[i] = red[i].cost;\n\n            long long val = 0;\n            for (int b : dualOrders[t]) {\n                if (((U >> b) & 1ULL) == 0) continue;\n                int delta = INT_MAX;\n                for (int id : coverers[b]) {\n                    delta = min(delta, slack[id]);\n                }\n                if (delta == INT_MAX || delta <= 0) continue;\n                val += delta;\n                for (int id : coverers[b]) slack[id] -= delta;\n            }\n            best = max(best, val);\n        }\n        return best;\n    };\n\n    auto choosePivot = [&](uint64_t U) -> int {\n        int pivot = -1;\n        int bestDeg = INT_MAX;\n        int bestMinCost = -1;\n        uint64_t x = U;\n        while (x) {\n            int b = __builtin_ctzll(x);\n            x &= (x - 1);\n            if (deg[b] < bestDeg || (deg[b] == bestDeg && minCostBit[b] > bestMinCost)) {\n                bestDeg = deg[b];\n                bestMinCost = minCostBit[b];\n                pivot = b;\n            }\n        }\n        return pivot;\n    };\n\n    function<void(uint64_t,int)> dfs = [&](uint64_t U, int cost) {\n        if (timedOut) return;\n        if ((++nodeCounter & 255ULL) == 0) {\n            if (chrono::steady_clock::now() > deadline) {\n                timedOut = true;\n                return;\n            }\n        }\n\n        if (cost >= bestResCost) return;\n        if (U == 0) {\n            bestResCost = cost;\n            bestSel = cur;\n            return;\n        }\n\n        auto it = memo.find(U);\n        if (it != memo.end() && it->second <= cost) return;\n        memo[U] = cost;\n\n        long long lb1 = simpleLB(U);\n        if (cost + lb1 >= bestResCost) return;\n        long long lb2 = dualLB(U);\n        if (cost + lb2 >= bestResCost) return;\n\n        int pivot = choosePivot(U);\n        if (pivot < 0) return;\n\n        vector<int> opts = coverers[pivot];\n        sort(opts.begin(), opts.end(), [&](int a, int b) {\n            int ca = pop64(red[a].mask & U);\n            int cb = pop64(red[b].mask & U);\n            long long lhs = 1LL * red[a].cost * cb;\n            long long rhs = 1LL * red[b].cost * ca;\n            if (lhs != rhs) return lhs < rhs;\n            if (ca != cb) return ca > cb;\n            if (red[a].cost != red[b].cost) return red[a].cost < red[b].cost;\n            return a < b;\n        });\n\n        for (int id : opts) {\n            uint64_t nU = U & ~red[id].mask;\n            if (nU == U) continue;\n            cur.push_back(id);\n            dfs(nU, cost + red[id].cost);\n            cur.pop_back();\n            if (timedOut) return;\n        }\n    };\n\n    uint64_t startU = (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL));\n    dfs(startU, 0);\n\n    // Final cleanup of the reduced selected set.\n    bestSel = cleanup(bestSel);\n    bestResCost = 0;\n    for (int id : bestSel) bestResCost += red[id].cost;\n\n    // Build output operations.\n    vector<pair<char,int>> outOps;\n    outOps.reserve((size_t)(forcedSel.size() + bestSel.size()) * 40);\n\n    auto emitCandidate = [&](const Cand& c) {\n        for (int t = 0; t < c.len; ++t) outOps.push_back({c.dir, c.idx});\n        for (int t = 0; t < c.len; ++t) outOps.push_back({revDir(c.dir), c.idx});\n    };\n\n    for (int id : forcedSel) emitCandidate(cands[id]);\n    for (int id : bestSel) emitCandidate(red[id]);\n\n    for (auto [d, p] : outOps) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T{};\nint avgT = 0;\nint bestTargetNode = 0;\n\nstruct XorShift64 {\n    uint64_t x;\n    explicit XorShift64(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        return (int)(next() % (uint64_t)mod);\n    }\n};\n\nstruct Plan {\n    array<array<int, 2>, MAXN> to;\n};\n\nstruct Eval {\n    Plan plan;\n    array<int, MAXN> cnt{};\n    array<array<int, 2>, MAXN> use{};\n    long long err = (1LL << 60);\n    int last = 0;\n};\n\nstatic inline long long llabsll(long long x) { return x < 0 ? -x : x; }\n\nvoid finalizePlan(Plan &p) {\n    for (int i = 0; i < N; ++i) {\n        if (p.to[i][0] == -1 && p.to[i][1] == -1) {\n            int d = (T[i] >= avgT ? i : bestTargetNode);\n            p.to[i][0] = p.to[i][1] = d;\n        } else if (p.to[i][0] == -1) {\n            p.to[i][0] = p.to[i][1];\n        } else if (p.to[i][1] == -1) {\n            p.to[i][1] = p.to[i][0];\n        }\n    }\n}\n\nint chooseDest(\n    int src,\n    const array<long long, MAXN> &rem,\n    int exclude,\n    long long selfBias,\n    long long samePenalty,\n    XorShift64 &rng\n) {\n    int best = 0;\n    long long bestSc = -(1LL << 60);\n\n    for (int j = 0; j < N; ++j) {\n        long long sc = 0;\n        sc += rem[j] * 200LL;\n        sc += 3LL * T[j];\n        sc -= 4LL * llabsll((long long)T[src] - (long long)T[j]);\n\n        if (j == src) {\n            long long selfAdj = ((long long)T[src] - (long long)avgT) * selfBias / max(1, avgT);\n            sc += selfAdj;\n        }\n\n        if (j == exclude) sc -= samePenalty;\n\n        sc += (long long)(rng.next() & 31ULL) - 15LL;\n\n        if (sc > bestSc) {\n            bestSc = sc;\n            best = j;\n        }\n    }\n    return best;\n}\n\nEval simulate(const Plan &p) {\n    Eval e;\n    e.plan = p;\n    e.cnt.fill(0);\n    for (int i = 0; i < N; ++i) e.use[i][0] = e.use[i][1] = 0;\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        e.cnt[x]++;\n        if (step == L - 1) {\n            e.last = x;\n            break;\n        }\n        int par = e.cnt[x] & 1; // 1 = odd visit -> a_i, 0 = even visit -> b_i\n        e.use[x][par]++;\n        x = p.to[x][par];\n    }\n\n    e.last = x;\n    long long err = 0;\n    for (int i = 0; i < N; ++i) err += llabsll((long long)e.cnt[i] - (long long)T[i]);\n    e.err = err;\n    return e;\n}\n\nPlan buildOnline(uint64_t seed, long long selfBias, long long samePenalty) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    XorShift64 rng(seed);\n    array<int, MAXN> cnt{};\n    cnt.fill(0);\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        cnt[x]++;\n        if (step == L - 1) break;\n\n        int par = cnt[x] & 1;\n        if (p.to[x][0] == -1 && p.to[x][1] == -1) {\n            array<long long, MAXN> rem{};\n            for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (long long)cnt[i];\n\n            int oddDest = chooseDest(x, rem, -1, selfBias, samePenalty, rng);\n            rem[oddDest] -= 1; // tiny bias for the second choice\n            int evenDest = chooseDest(x, rem, oddDest, selfBias, samePenalty, rng);\n\n            p.to[x][1] = oddDest;\n            p.to[x][0] = evenDest;\n        } else if (p.to[x][par] == -1) {\n            array<long long, MAXN> rem{};\n            for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (long long)cnt[i];\n            int other = p.to[x][1 - par];\n            p.to[x][par] = chooseDest(x, rem, other, selfBias, samePenalty, rng);\n        }\n\n        x = p.to[x][par];\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nPlan buildTransportFromSupply(const array<int, MAXN> &supply, int orderType, uint64_t seed, long long selfBias, long long samePenalty) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    XorShift64 rng(seed);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n\n    auto cmpDescSupply = [&](int a, int b) {\n        if (supply[a] != supply[b]) return supply[a] > supply[b];\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    };\n    auto cmpAscSupply = [&](int a, int b) {\n        if (supply[a] != supply[b]) return supply[a] < supply[b];\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    };\n    auto cmpDescT = [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        if (supply[a] != supply[b]) return supply[a] > supply[b];\n        return a < b;\n    };\n\n    if (orderType == 0) {\n        sort(ord.begin(), ord.end(), cmpDescSupply);\n    } else if (orderType == 1) {\n        sort(ord.begin(), ord.end(), cmpAscSupply);\n    } else {\n        // random order\n        for (int i = N - 1; i > 0; --i) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    array<long long, MAXN> rem{};\n    for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (i == 0 ? 1LL : 0LL);\n\n    for (int idx = 0; idx < N; ++idx) {\n        int i = ord[idx];\n        long long wOdd = (supply[i] + 1LL) / 2LL;\n        long long wEven = supply[i] / 2LL;\n\n        int dOdd = chooseDest(i, rem, -1, selfBias, samePenalty, rng);\n        rem[dOdd] -= wOdd;\n\n        int dEven = chooseDest(i, rem, dOdd, selfBias, samePenalty, rng);\n        rem[dEven] -= wEven;\n\n        p.to[i][1] = dOdd;\n        p.to[i][0] = dEven;\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nPlan buildTemplate(int type) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    });\n\n    int h1 = ord[0];\n    int h2 = ord[1];\n\n    for (int pos = 0; pos < N; ++pos) {\n        int i = ord[pos];\n        int nxt = ord[(pos + 1) % N];\n        int prv = ord[(pos + N - 1) % N];\n        int nxt2 = ord[(pos + 2) % N];\n\n        if (type == 0) {\n            if (T[i] >= avgT) {\n                p.to[i][1] = i;\n                p.to[i][0] = nxt;\n            } else {\n                p.to[i][1] = nxt;\n                p.to[i][0] = i;\n            }\n        } else if (type == 1) {\n            if (pos < 15) {\n                p.to[i][1] = i;\n                p.to[i][0] = i;\n            } else if (pos < 45) {\n                p.to[i][1] = i;\n                p.to[i][0] = nxt;\n            } else if (pos < 75) {\n                p.to[i][1] = nxt;\n                p.to[i][0] = i;\n            } else {\n                p.to[i][1] = nxt;\n                p.to[i][0] = nxt2;\n            }\n        } else if (type == 2) {\n            if (i == h1) {\n                p.to[i][1] = h1;\n                p.to[i][0] = h2;\n            } else if (T[i] >= avgT) {\n                p.to[i][1] = i;\n                p.to[i][0] = h1;\n            } else {\n                p.to[i][1] = h1;\n                p.to[i][0] = i;\n            }\n        } else {\n            p.to[i][1] = nxt;\n            p.to[i][0] = prv;\n        }\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nvoid buildCandidates(vector<Eval> &pool, uint64_t baseSeed) {\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    });\n\n    vector<int> ends;\n    for (int i = 0; i < N && (int)ends.size() < 4; ++i) {\n        if (T[ord[i]] > 0) ends.push_back(ord[i]);\n    }\n    if (T[0] > 0 && find(ends.begin(), ends.end(), 0) == ends.end()) ends.push_back(0);\n\n    int randomPositive = -1;\n    {\n        vector<int> pos;\n        for (int i = 0; i < N; ++i) if (T[i] > 0) pos.push_back(i);\n        if (!pos.empty()) {\n            XorShift64 rng(baseSeed ^ 0x123456789abcdefULL);\n            randomPositive = pos[rng.nextInt((int)pos.size())];\n            if (find(ends.begin(), ends.end(), randomPositive) == ends.end()) ends.push_back(randomPositive);\n        }\n    }\n    if ((int)ends.size() > 5) ends.resize(5);\n\n    long long onlineBiases[4] = {700, 1600, 3000, -800};\n    long long transportBiases[2] = {800, 2000};\n\n    int cid = 0;\n    for (int k = 0; k < 4; ++k) {\n        uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(cid + 1));\n        Plan p = buildOnline(seed, onlineBiases[k], 600);\n        pool.push_back(simulate(p));\n        ++cid;\n    }\n\n    for (int e : ends) {\n        array<int, MAXN> supply{};\n        for (int i = 0; i < N; ++i) supply[i] = T[i];\n        if (supply[e] <= 0) continue;\n        supply[e]--;\n\n        for (int ordType = 0; ordType < 3; ++ordType) {\n            for (int b = 0; b < 2; ++b) {\n                uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(cid + 1)) ^ (uint64_t)(e + 1000 * ordType + 17 * b);\n                Plan p = buildTransportFromSupply(supply, ordType, seed, transportBiases[b], 500);\n                pool.push_back(simulate(p));\n                ++cid;\n            }\n        }\n    }\n\n    for (int tp = 0; tp < 4; ++tp) {\n        Plan p = buildTemplate(tp);\n        pool.push_back(simulate(p));\n    }\n}\n\nEval refineByTransport(Eval cur, uint64_t seed) {\n    for (int iter = 0; iter < 2; ++iter) {\n        array<int, MAXN> supply = cur.cnt;\n        supply[cur.last]--;\n        if (supply[cur.last] < 0) supply[cur.last] = 0;\n\n        Plan p = buildTransportFromSupply(supply, 0, seed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(iter + 1)), 1600, 500);\n        Eval e = simulate(p);\n        if (e.err < cur.err) cur = std::move(e);\n        else break;\n    }\n    return cur;\n}\n\nEval localSearch(Eval cur, uint64_t seed, chrono::steady_clock::time_point start) {\n    XorShift64 rng(seed);\n\n    auto nowSeconds = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    for (int round = 0; round < 2; ++round) {\n        if (nowSeconds() > 1.93) break;\n        if (cur.err == 0) break;\n\n        vector<int> over, under;\n        over.reserve(N);\n        under.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            int d = cur.cnt[i] - T[i];\n            if (d > 0) over.push_back(i);\n            else if (d < 0) under.push_back(i);\n        }\n        if (over.empty() || under.empty()) break;\n\n        sort(over.begin(), over.end(), [&](int a, int b) {\n            return (cur.cnt[a] - T[a]) > (cur.cnt[b] - T[b]);\n        });\n        sort(under.begin(), under.end(), [&](int a, int b) {\n            return (T[a] - cur.cnt[a]) > (T[b] - cur.cnt[b]);\n        });\n\n        vector<int> overTop, underTop;\n        for (int i = 0; i < (int)min<size_t>(4, over.size()); ++i) overTop.push_back(over[i]);\n        for (int i = 0; i < (int)min<size_t>(3, under.size()); ++i) underTop.push_back(under[i]);\n\n        struct Slot {\n            int src, p, dest, use;\n        };\n\n        vector<Slot> slots;\n        for (int o : overTop) {\n            for (int i = 0; i < N; ++i) {\n                for (int p = 0; p < 2; ++p) {\n                    if (cur.plan.to[i][p] == o && cur.use[i][p] > 0) {\n                        slots.push_back({i, p, o, cur.use[i][p]});\n                    }\n                }\n            }\n        }\n\n        sort(slots.begin(), slots.end(), [&](const Slot &a, const Slot &b) {\n            return a.use > b.use;\n        });\n\n        long long bestErr = cur.err;\n        Eval bestCand = cur;\n        bool improved = false;\n\n        auto testPlan = [&](const Plan &pp) {\n            if (nowSeconds() > 1.93) return;\n            Eval e = simulate(pp);\n            if (e.err < bestErr) {\n                bestErr = e.err;\n                bestCand = std::move(e);\n                improved = true;\n            }\n        };\n\n        // 1) Change heavily used slots that currently point to overcounted nodes.\n        int slotLimit = min<int>(12, slots.size());\n        for (int i = 0; i < slotLimit; ++i) {\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[slots[i].src][slots[i].p] == u) continue;\n                Plan np = cur.plan;\n                np.to[slots[i].src][slots[i].p] = u;\n                testPlan(np);\n            }\n        }\n\n        // 2) Change one parity edge of overcounted source nodes.\n        for (int s = 0; s < (int)overTop.size(); ++s) {\n            int src = overTop[s];\n            int p = (cur.use[src][0] >= cur.use[src][1] ? 0 : 1);\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[src][p] == u) continue;\n                Plan np = cur.plan;\n                np.to[src][p] = u;\n                testPlan(np);\n            }\n        }\n\n        // 3) Change both edges of a strongly overcounted source to a better undercounted target.\n        for (int s = 0; s < (int)min<size_t>(3, overTop.size()); ++s) {\n            int src = overTop[s];\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[src][0] == u && cur.plan.to[src][1] == u) continue;\n                Plan np = cur.plan;\n                np.to[src][0] = np.to[src][1] = u;\n                testPlan(np);\n            }\n        }\n\n        if (improved) cur = std::move(bestCand);\n        else break;\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    avgT = L / N;\n    bestTargetNode = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[bestTargetNode]) bestTargetNode = i;\n    }\n\n    uint64_t baseSeed = 1469598103934665603ULL;\n    for (int i = 0; i < N; ++i) {\n        baseSeed ^= (uint64_t)(T[i] + 1);\n        baseSeed *= 1099511628211ULL;\n    }\n\n    auto start = chrono::steady_clock::now();\n\n    vector<Eval> pool;\n    pool.reserve(64);\n\n    buildCandidates(pool, baseSeed);\n\n    if (pool.empty()) {\n        Plan p;\n        for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = bestTargetNode;\n        auto e = simulate(p);\n        pool.push_back(std::move(e));\n    }\n\n    sort(pool.begin(), pool.end(), [&](const Eval &a, const Eval &b) {\n        return a.err < b.err;\n    });\n\n    int topK = min<int>(3, pool.size());\n    Eval best = pool[0];\n\n    for (int i = 0; i < topK; ++i) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > 1.90) break;\n\n        Eval cur = pool[i];\n        cur = refineByTransport(cur, baseSeed ^ (0xabcdef0123456789ULL + (uint64_t)i * 1337ULL));\n        cur = localSearch(cur, baseSeed ^ (0x123456789abcdef0ULL + (uint64_t)i * 10007ULL), start);\n\n        if (cur.err < best.err) best = std::move(cur);\n    }\n\n    // Final safety fill.\n    finalizePlan(best.plan);\n\n    for (int i = 0; i < N; ++i) {\n        cout << best.plan.to[i][1] << ' ' << best.plan.to[i][0] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ull = unsigned long long;\n\nstatic const ll INFLL = (1LL << 62);\nstatic const int MAXN = 800;\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<int> exs, eys;\nvector<vector<ll>> dist2Mat;\nvector<double> densityScore;\nvector<int> densityOrder;\n\nint queries_used = 0;\n\nstruct BuiltGroup {\n    vector<int> cities;\n    vector<pair<int,int>> edges;\n};\n\null hilbertOrder(int x, int y) {\n    ull d = 0;\n    for (int s = 1 << 14; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += (ull)s * (ull)s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = s * 2 - 1 - x;\n                y = s * 2 - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\ninline ll d2(int a, int b) {\n    return dist2Mat[a][b];\n}\n\nstruct PrimRes {\n    vector<int> parent;\n    vector<ll> best;\n};\n\nPrimRes primParents(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    PrimRes res;\n    res.parent.assign(k, -1);\n    res.best.assign(k, INFLL);\n    if (k == 0) return res;\n    vector<char> used(k, 0);\n    res.best[0] = 0;\n\n    for (int it = 0; it < k; ++it) {\n        int v = -1;\n        for (int i = 0; i < k; ++i) {\n            if (!used[i] && (v == -1 || res.best[i] < res.best[v])) v = i;\n        }\n        used[v] = 1;\n        int a = nodes[v];\n        for (int to = 0; to < k; ++to) if (!used[to]) {\n            ll w = d2(a, nodes[to]);\n            if (w < res.best[to]) {\n                res.best[to] = w;\n                res.parent[to] = v;\n            }\n        }\n    }\n    return res;\n}\n\ndouble mstCostVec(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    if (k <= 1) return 0.0;\n    auto res = primParents(nodes);\n    double cost = 0.0;\n    for (int i = 1; i < k; ++i) cost += sqrt((double)res.best[i]);\n    return cost;\n}\n\nvector<pair<int,int>> primTree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    vector<pair<int,int>> edges;\n    if (k <= 1) return edges;\n    auto res = primParents(nodes);\n    edges.reserve(k - 1);\n    for (int i = 1; i < k; ++i) {\n        int a = nodes[i], b = nodes[res.parent[i]];\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nvector<pair<int,int>> queryTree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    cout << \"? \" << k;\n    for (int v : nodes) cout << ' ' << v;\n    cout << '\\n' << flush;\n\n    ++queries_used;\n    vector<pair<int,int>> edges;\n    edges.reserve(k - 1);\n    for (int i = 0; i < k - 1; ++i) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nvector<int> buildMSTPreorder(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    if (k <= 2) return nodes;\n\n    auto res = primParents(nodes);\n    vector<vector<pair<ll,int>>> adj(k);\n    for (int i = 1; i < k; ++i) {\n        int p = res.parent[i];\n        ll w = res.best[i];\n        adj[i].push_back({w, p});\n        adj[p].push_back({w, i});\n    }\n\n    int root = 0;\n    ll bestSum = INFLL;\n    for (int i = 0; i < k; ++i) {\n        ll sum = 0;\n        for (int j = 0; j < k; ++j) if (i != j) sum += d2(nodes[i], nodes[j]);\n        if (sum < bestSum || (sum == bestSum && nodes[i] < nodes[root])) {\n            bestSum = sum;\n            root = i;\n        }\n    }\n\n    for (int i = 0; i < k; ++i) {\n        sort(adj[i].begin(), adj[i].end());\n    }\n\n    vector<int> order;\n    order.reserve(k);\n    vector<int> par(k, -1);\n    vector<int> st;\n    st.push_back(root);\n    par[root] = root;\n\n    while (!st.empty()) {\n        int v = st.back();\n        st.pop_back();\n        order.push_back(nodes[v]);\n        for (int i = (int)adj[v].size() - 1; i >= 0; --i) {\n            int to = adj[v][i].second;\n            if (to == par[v]) continue;\n            par[to] = v;\n            st.push_back(to);\n        }\n    }\n    return order;\n}\n\nvector<vector<int>> splitChunks(const vector<int>& ord) {\n    int n = (int)ord.size();\n    vector<vector<int>> chunks;\n    if (n <= L) {\n        chunks.push_back(ord);\n        return chunks;\n    }\n\n    int p = 0, rem = n;\n    while (rem > 0) {\n        int take = min(L, rem);\n        if (rem > L && rem - take == 1) take--;\n        chunks.emplace_back(ord.begin() + p, ord.begin() + p + take);\n        p += take;\n        rem -= take;\n    }\n    return chunks;\n}\n\nvector<vector<ll>> computeChunkWeights(\n    const vector<vector<int>>& chunks,\n    vector<vector<pair<int,int>>>* bestPair = nullptr\n) {\n    int c = (int)chunks.size();\n    vector<vector<ll>> w(c, vector<ll>(c, INFLL));\n    if (bestPair) bestPair->assign(c, vector<pair<int,int>>(c, {INT_MAX, INT_MAX}));\n\n    for (int i = 0; i < c; ++i) {\n        for (int j = i + 1; j < c; ++j) {\n            ll bestW = INFLL;\n            pair<int,int> bestP = {INT_MAX, INT_MAX};\n            for (int a : chunks[i]) {\n                for (int b : chunks[j]) {\n                    ll d = d2(a, b);\n                    pair<int,int> p = (a < b ? make_pair(a, b) : make_pair(b, a));\n                    if (d < bestW || (d == bestW && p < bestP)) {\n                        bestW = d;\n                        bestP = p;\n                    }\n                }\n            }\n            w[i][j] = w[j][i] = bestW;\n            if (bestPair) {\n                (*bestPair)[i][j] = (*bestPair)[j][i] = bestP;\n            }\n        }\n    }\n    return w;\n}\n\ndouble estimateOrderCost(const vector<int>& ord) {\n    int n = (int)ord.size();\n    if (n <= 1) return 0.0;\n    if (n <= L) return mstCostVec(ord);\n\n    auto chunks = splitChunks(ord);\n    double cost = 0.0;\n    for (auto& ch : chunks) cost += mstCostVec(ch);\n\n    auto w = computeChunkWeights(chunks, nullptr);\n    int c = (int)chunks.size();\n    vector<ll> best(c, INFLL);\n    vector<char> used(c, 0);\n    best[0] = 0;\n\n    for (int it = 0; it < c; ++it) {\n        int v = -1;\n        for (int i = 0; i < c; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (best[v] != 0) cost += sqrt((double)best[v]);\n        for (int to = 0; to < c; ++to) if (!used[to]) {\n            if (w[v][to] < best[to]) best[to] = w[v][to];\n        }\n    }\n    return cost;\n}\n\nvector<pair<int,int>> buildChunkMSTEdges(const vector<vector<int>>& chunks) {\n    vector<pair<int,int>> edges;\n    int c = (int)chunks.size();\n    if (c <= 1) return edges;\n\n    vector<vector<pair<int,int>>> bestPair;\n    auto w = computeChunkWeights(chunks, &bestPair);\n\n    vector<ll> best(c, INFLL);\n    vector<int> parent(c, -1);\n    vector<char> used(c, 0);\n    best[0] = 0;\n\n    for (int it = 0; it < c; ++it) {\n        int v = -1;\n        for (int i = 0; i < c; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (parent[v] != -1) edges.push_back(bestPair[v][parent[v]]);\n        for (int to = 0; to < c; ++to) if (!used[to]) {\n            if (w[v][to] < best[to]) {\n                best[to] = w[v][to];\n                parent[to] = v;\n            }\n        }\n    }\n    return edges;\n}\n\nvector<int> growCluster(int seed, int targetSize, const vector<char>& used) {\n    vector<int> cluster;\n    cluster.reserve(targetSize);\n    vector<char> inCluster(N, 0);\n    vector<ll> mind(N, INFLL);\n\n    cluster.push_back(seed);\n    inCluster[seed] = 1;\n    for (int i = 0; i < N; ++i) {\n        if (!used[i] && !inCluster[i]) mind[i] = d2(seed, i);\n    }\n\n    while ((int)cluster.size() < targetSize) {\n        int best = -1;\n        for (int i = 0; i < N; ++i) {\n            if (used[i] || inCluster[i]) continue;\n            if (best == -1 ||\n                mind[i] < mind[best] ||\n                (mind[i] == mind[best] && densityScore[i] < densityScore[best]) ||\n                (mind[i] == mind[best] && densityScore[i] == densityScore[best] && i < best)) {\n                best = i;\n            }\n        }\n        if (best == -1) break;\n        cluster.push_back(best);\n        inCluster[best] = 1;\n        for (int i = 0; i < N; ++i) {\n            if (used[i] || inCluster[i]) continue;\n            ll w = d2(best, i);\n            if (w < mind[i]) mind[i] = w;\n        }\n    }\n    return cluster;\n}\n\nvector<vector<int>> buildDensityGreedyPartition() {\n    vector<vector<int>> groups(M);\n    vector<char> used(N, 0);\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n\n    for (int gi : order) {\n        int s = G[gi];\n\n        if (s == 1) {\n            int seed = -1;\n            for (int v : densityOrder) if (!used[v]) { seed = v; break; }\n            if (seed == -1) seed = 0;\n            used[seed] = 1;\n            groups[gi] = {seed};\n            continue;\n        }\n\n        vector<int> seeds;\n        int seedLimit = min(5, s);\n        for (int v : densityOrder) {\n            if (!used[v]) {\n                seeds.push_back(v);\n                if ((int)seeds.size() >= seedLimit) break;\n            }\n        }\n        if (seeds.empty()) {\n            for (int i = 0; i < N; ++i) if (!used[i]) { seeds.push_back(i); break; }\n        }\n\n        double bestScore = 1e100;\n        vector<int> bestCluster;\n        for (int seed : seeds) {\n            auto cluster = growCluster(seed, s, used);\n            if ((int)cluster.size() != s) continue;\n            double score = mstCostVec(cluster);\n            if (score < bestScore) {\n                bestScore = score;\n                bestCluster = move(cluster);\n            }\n        }\n\n        if ((int)bestCluster.size() != s) {\n            // Fallback: just take the first s unused cities.\n            bestCluster.clear();\n            for (int v : densityOrder) {\n                if (!used[v]) {\n                    bestCluster.push_back(v);\n                    if ((int)bestCluster.size() == s) break;\n                }\n            }\n        }\n\n        for (int v : bestCluster) used[v] = 1;\n        groups[gi] = move(bestCluster);\n    }\n\n    return groups;\n}\n\nvector<vector<int>> buildContiguousPartition(const vector<int>& cityOrder, const vector<int>& groupOrder) {\n    vector<vector<int>> groups(M);\n    int p = 0;\n    for (int gi : groupOrder) {\n        groups[gi].assign(cityOrder.begin() + p, cityOrder.begin() + p + G[gi]);\n        p += G[gi];\n    }\n    return groups;\n}\n\nbool validatePartition(const vector<vector<int>>& groups) {\n    if ((int)groups.size() != M) return false;\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < M; ++i) {\n        if ((int)groups[i].size() != G[i]) return false;\n        for (int v : groups[i]) {\n            if (v < 0 || v >= N) return false;\n            if (++cnt[v] != 1) return false;\n        }\n    }\n    for (int v = 0; v < N; ++v) if (cnt[v] != 1) return false;\n    return true;\n}\n\ndouble evalPartition(const vector<vector<int>>& groups) {\n    double cost = 0.0;\n    for (const auto& g : groups) cost += mstCostVec(g);\n    return cost;\n}\n\nvector<int> chooseBestLocalOrder(const vector<int>& group) {\n    int k = (int)group.size();\n    if (k <= 1) return group;\n    if (k <= L) return group;\n\n    vector<vector<int>> cands;\n\n    auto add = [&](vector<int> v) {\n        cands.push_back(move(v));\n    };\n\n    add(group);\n    {\n        vector<int> v = group;\n        reverse(v.begin(), v.end());\n        add(move(v));\n    }\n\n    auto addSort = [&](auto cmp) {\n        vector<int> v = group;\n        sort(v.begin(), v.end(), cmp);\n        add(move(v));\n    };\n\n    addSort([&](int a, int b) {\n        if (exs[a] != exs[b]) return exs[a] < exs[b];\n        if (eys[a] != eys[b]) return eys[a] < eys[b];\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        if (eys[a] != eys[b]) return eys[a] < eys[b];\n        if (exs[a] != exs[b]) return exs[a] < exs[b];\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        ll sa = (ll)exs[a] + eys[a];\n        ll sb = (ll)exs[b] + eys[b];\n        if (sa != sb) return sa < sb;\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        ll da = (ll)exs[a] - eys[a];\n        ll db = (ll)exs[b] - eys[b];\n        if (da != db) return da < db;\n        return a < b;\n    });\n\n    for (int o = 0; o < 8; ++o) {\n        addSort([&](int a, int b) {\n            ull ka, kb;\n            {\n                int x = exs[a], y = eys[a];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                ka = hilbertOrder(x, y);\n            }\n            {\n                int x = exs[b], y = eys[b];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                kb = hilbertOrder(x, y);\n            }\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n    }\n\n    {\n        vector<int> v = buildMSTPreorder(group);\n        add(move(v));\n        vector<int> w = cands.back();\n        reverse(w.begin(), w.end());\n        add(move(w));\n    }\n\n    double best = 1e100;\n    vector<int> bestOrd = group;\n    for (auto& cand : cands) {\n        double sc = estimateOrderCost(cand);\n        if (sc < best) {\n            best = sc;\n            bestOrd = cand;\n        }\n    }\n    return bestOrd;\n}\n\nBuiltGroup buildGroupTree(const vector<int>& group) {\n    BuiltGroup res;\n    int k = (int)group.size();\n    if (k == 0) return res;\n\n    res.cities = chooseBestLocalOrder(group);\n\n    if (k == 1) return res;\n\n    if (k == 2) {\n        int a = res.cities[0], b = res.cities[1];\n        if (a > b) swap(a, b);\n        res.edges.push_back({a, b});\n        return res;\n    }\n\n    if (k <= L) {\n        if (queries_used < Q) res.edges = queryTree(res.cities);\n        else res.edges = primTree(res.cities);\n        if ((int)res.edges.size() != k - 1) res.edges = primTree(res.cities);\n        return res;\n    }\n\n    auto chunks = splitChunks(res.cities);\n\n    for (auto& ch : chunks) {\n        int s = (int)ch.size();\n        if (s == 1) continue;\n        if (s == 2) {\n            int a = ch[0], b = ch[1];\n            if (a > b) swap(a, b);\n            res.edges.push_back({a, b});\n        } else {\n            vector<pair<int,int>> got;\n            if (queries_used < Q) got = queryTree(ch);\n            else got = primTree(ch);\n            if ((int)got.size() != s - 1) got = primTree(ch);\n            res.edges.insert(res.edges.end(), got.begin(), got.end());\n        }\n    }\n\n    if (chunks.size() > 1) {\n        auto cross = buildChunkMSTEdges(chunks);\n        res.edges.insert(res.edges.end(), cross.begin(), cross.end());\n    }\n\n    if ((int)res.edges.size() != k - 1) {\n        res.edges = primTree(res.cities);\n    }\n\n    return res;\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    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    exs.resize(N);\n    eys.resize(N);\n    for (int i = 0; i < N; ++i) {\n        exs[i] = lx[i] + rx[i];\n        eys[i] = ly[i] + ry[i];\n    }\n\n    dist2Mat.assign(N, vector<ll>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i; j < N; ++j) {\n            ll dx = (ll)exs[i] - exs[j];\n            ll dy = (ll)eys[i] - eys[j];\n            ll d = dx * dx + dy * dy;\n            dist2Mat[i][j] = dist2Mat[j][i] = d;\n        }\n    }\n\n    // Density score: sum of the nearest few estimated distances.\n    int K = min(12, N - 1);\n    densityScore.assign(N, 0.0);\n    for (int i = 0; i < N; ++i) {\n        vector<ll> ds;\n        ds.reserve(N - 1);\n        for (int j = 0; j < N; ++j) if (i != j) ds.push_back(dist2Mat[i][j]);\n        nth_element(ds.begin(), ds.begin() + K, ds.end());\n        double s = 0.0;\n        for (int t = 0; t < K; ++t) s += sqrt((double)ds[t]);\n        densityScore[i] = s;\n    }\n\n    densityOrder.resize(N);\n    iota(densityOrder.begin(), densityOrder.end(), 0);\n    sort(densityOrder.begin(), densityOrder.end(), [&](int a, int b) {\n        if (densityScore[a] != densityScore[b]) return densityScore[a] < densityScore[b];\n        return a < b;\n    });\n\n    // Build candidate city orders.\n    vector<vector<int>> cityOrders;\n\n    auto addOrder = [&](vector<int> ord) {\n        cityOrders.push_back(move(ord));\n    };\n\n    auto makeSorted = [&](auto cmp) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), cmp);\n        return ord;\n    };\n\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            if (eys[a] != eys[b]) return eys[a] < eys[b];\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            if (eys[a] != eys[b]) return eys[a] < eys[b];\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            ll sa = (ll)exs[a] + eys[a];\n            ll sb = (ll)exs[b] + eys[b];\n            if (sa != sb) return sa < sb;\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            ll da = (ll)exs[a] - eys[a];\n            ll db = (ll)exs[b] - eys[b];\n            if (da != db) return da < db;\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        addOrder(densityOrder);\n        auto r = densityOrder;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        vector<int> all(N);\n        iota(all.begin(), all.end(), 0);\n        auto ord = buildMSTPreorder(all);\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    for (int o = 0; o < 8; ++o) {\n        auto ord = makeSorted([&](int a, int b) {\n            ull ka, kb;\n            {\n                int x = exs[a], y = eys[a];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                ka = hilbertOrder(x, y);\n            }\n            {\n                int x = exs[b], y = eys[b];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                kb = hilbertOrder(x, y);\n            }\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n        addOrder(ord);\n    }\n\n    vector<int> groupOrderOrig(M), groupOrderAsc(M), groupOrderDesc(M);\n    iota(groupOrderOrig.begin(), groupOrderOrig.end(), 0);\n    groupOrderAsc = groupOrderOrig;\n    groupOrderDesc = groupOrderOrig;\n    sort(groupOrderAsc.begin(), groupOrderAsc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n    sort(groupOrderDesc.begin(), groupOrderDesc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n\n    vector<vector<int>> groupOrders = {\n        groupOrderOrig, groupOrderAsc, groupOrderDesc\n    };\n\n    // Candidate partitions.\n    vector<vector<int>> fallback = buildContiguousPartition(cityOrders[0], groupOrders[0]);\n    vector<vector<int>> bestGroups = fallback;\n    double bestEval = evalPartition(bestGroups);\n\n    for (const auto& ord : cityOrders) {\n        for (const auto& gOrd : groupOrders) {\n            auto groups = buildContiguousPartition(ord, gOrd);\n            if (!validatePartition(groups)) continue;\n            double val = evalPartition(groups);\n            if (val < bestEval) {\n                bestEval = val;\n                bestGroups = move(groups);\n            }\n        }\n    }\n\n    auto dens = buildDensityGreedyPartition();\n    if (validatePartition(dens)) {\n        double val = evalPartition(dens);\n        if (val < bestEval) {\n            bestEval = val;\n            bestGroups = move(dens);\n        }\n    }\n\n    if (!validatePartition(bestGroups)) {\n        bestGroups = fallback;\n    }\n\n    // Build trees for each group.\n    vector<BuiltGroup> built(M);\n    for (int i = 0; i < M; ++i) {\n        built[i] = buildGroupTree(bestGroups[i]);\n        if ((int)built[i].edges.size() != G[i] - 1) {\n            built[i].cities = bestGroups[i];\n            built[i].edges = primTree(bestGroups[i]);\n        }\n    }\n\n    // Final sanity check before output.\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < M; ++i) {\n        if ((int)built[i].cities.size() != G[i]) {\n            built = {};\n            break;\n        }\n        for (int v : built[i].cities) {\n            if (v < 0 || v >= N) {\n                built = {};\n                break;\n            }\n            cnt[v]++;\n        }\n        if (built.empty()) break;\n    }\n    bool ok = !built.empty();\n    if (ok) {\n        for (int v = 0; v < N; ++v) if (cnt[v] != 1) ok = false;\n    }\n    if (!ok) {\n        bestGroups = fallback;\n        built.assign(M, {});\n        for (int i = 0; i < M; ++i) {\n            built[i] = buildGroupTree(bestGroups[i]);\n            if ((int)built[i].edges.size() != G[i] - 1) {\n                built[i].cities = bestGroups[i];\n                built[i].edges = primTree(bestGroups[i]);\n            }\n        }\n    }\n\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < (int)built[i].cities.size(); ++j) {\n            if (j) cout << ' ';\n            cout << built[i].cities[j];\n        }\n        cout << '\\n';\n        for (auto [a, b] : built[i].edges) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 20;\nstatic constexpr int MAXV = MAXN * MAXN;\nstatic constexpr double UTIL_WEIGHT = 0.7;\n\nstruct BFSState {\n    array<int, MAXV> dist;\n    array<int, MAXV> pre;\n    array<char, MAXV> pact;\n    array<char, MAXV> pdir;\n};\n\nstruct Board {\n    int N;\n    array<array<int, MAXN>, MAXN> b{};\n};\n\nint N, M;\nvector<pair<int,int>> pts;\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\ninline bool inside(int r, int c) {\n    return 0 <= r && r < N && 0 <= c && c < N;\n}\n\nint slide_dest(const Board& bd, int r, int c, int d) {\n    while (true) {\n        int nr = r + dr[d], nc = c + dc[d];\n        if (!inside(nr, nc) || bd.b[nr][nc]) break;\n        r = nr;\n        c = nc;\n    }\n    return r * N + c;\n}\n\nBFSState bfs_all(const Board& bd, int s) {\n    BFSState st;\n    st.dist.fill(-1);\n    st.pre.fill(-1);\n    st.pact.fill(0);\n    st.pdir.fill(0);\n\n    queue<int> q;\n    st.dist[s] = 0;\n    st.pre[s] = -2;\n    q.push(s);\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        int r = u / N, c = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move\n            {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (inside(nr, nc) && !bd.b[nr][nc]) {\n                    int v = nr * N + nc;\n                    if (st.dist[v] == -1) {\n                        st.dist[v] = st.dist[u] + 1;\n                        st.pre[v] = u;\n                        st.pact[v] = 'M';\n                        st.pdir[v] = dch[d];\n                        q.push(v);\n                    }\n                }\n            }\n            // Slide\n            {\n                int v = slide_dest(bd, r, c, d);\n                if (v != u && st.dist[v] == -1) {\n                    st.dist[v] = st.dist[u] + 1;\n                    st.pre[v] = u;\n                    st.pact[v] = 'S';\n                    st.pdir[v] = dch[d];\n                    q.push(v);\n                }\n            }\n        }\n    }\n    return st;\n}\n\nvector<pair<char,char>> reconstruct_path(const BFSState& st, int s, int t) {\n    vector<pair<char,char>> path;\n    if (st.dist[t] == -1) return path;\n    for (int v = t; v != s; v = st.pre[v]) {\n        path.push_back({st.pact[v], st.pdir[v]});\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nstruct Candidate {\n    double score = 1e100;\n    int pathLen = INT_MAX;\n    int cost = INT_MAX;\n    double util = -1e100;\n    vector<pair<int,int>> blocks;\n    vector<pair<char,char>> path;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    pts.resize(M);\n    for (int i = 0; i < M; ++i) cin >> pts[i].first >> pts[i].second;\n\n    Board bd;\n    bd.N = N;\n\n    int cur = pts[0].first * N + pts[0].second;\n\n    for (int k = 0; k < M - 1; ++k) {\n        int r = pts[k].first, c = pts[k].second;\n        int nxt = pts[k + 1].first * N + pts[k + 1].second;\n\n        // Compute lookahead utility for each possible new wall direction.\n        // Future targets are k+2 ... M-1.\n        double sideUtil[4] = {0, 0, 0, 0};\n\n        for (int j = k + 2; j < M; ++j) {\n            int tr = pts[j].first, tc = pts[j].second;\n            if (tr == r) {\n                if (tc < c) {\n                    // Right wall helps future targets on the left.\n                    sideUtil[3] += 1.0 + (N - 1 - c) / 10.0;\n                } else if (tc > c) {\n                    // Left wall helps future targets on the right.\n                    sideUtil[2] += 1.0 + c / 10.0;\n                }\n            }\n            if (tc == c) {\n                if (tr < r) {\n                    // Down wall helps future targets above.\n                    sideUtil[1] += 1.0 + (N - 1 - r) / 10.0;\n                } else if (tr > r) {\n                    // Up wall helps future targets below.\n                    sideUtil[0] += 1.0 + r / 10.0;\n                }\n            }\n        }\n\n        vector<int> candDirs;\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (inside(nr, nc) && bd.b[nr][nc] == 0) candDirs.push_back(d);\n        }\n\n        Candidate best;\n\n        int m = (int)candDirs.size();\n        for (int mask = 0; mask < (1 << m); ++mask) {\n            Board temp = bd;\n            vector<pair<int,int>> addBlocks;\n            addBlocks.reserve(4);\n\n            int cost = 0;\n            double util = 0.0;\n            bool ok = true;\n\n            for (int i = 0; i < m; ++i) {\n                if ((mask >> i) & 1) {\n                    int d = candDirs[i];\n                    int nr = r + dr[d], nc = c + dc[d];\n                    temp.b[nr][nc] = 1;\n                    addBlocks.push_back({nr, nc});\n                    ++cost;\n                    util += sideUtil[d];\n                }\n            }\n\n            // Exact reachability check on the modified board.\n            BFSState st = bfs_all(temp, cur);\n            if (st.dist[nxt] == -1) continue;\n\n            bool reachableAll = true;\n            for (int j = k + 1; j < M; ++j) {\n                int id = pts[j].first * N + pts[j].second;\n                if (st.dist[id] == -1) {\n                    reachableAll = false;\n                    break;\n                }\n            }\n            if (!reachableAll) continue;\n\n            vector<pair<char,char>> path = reconstruct_path(st, cur, nxt);\n            if (path.empty() && cur != nxt) continue;\n\n            int L = (int)path.size();\n            double score = (double)L + cost - UTIL_WEIGHT * util;\n\n            if (score + 1e-12 < best.score ||\n                (abs(score - best.score) <= 1e-12 &&\n                 (L < best.pathLen ||\n                  (L == best.pathLen && cost < best.cost)))) {\n                best.score = score;\n                best.pathLen = L;\n                best.cost = cost;\n                best.util = util;\n                best.blocks = std::move(addBlocks);\n                best.path = std::move(path);\n            }\n        }\n\n        if (best.blocks.empty() && best.path.empty()) {\n            // Extremely safe fallback: no new blocks, recompute on current board.\n            BFSState st = bfs_all(bd, cur);\n            best.path = reconstruct_path(st, cur, nxt);\n            best.blocks.clear();\n        }\n\n        // Apply chosen blocks.\n        for (auto [br, bc] : best.blocks) {\n            bd.b[br][bc] = 1;\n            cout << 'A' << ' ' << dch[(br == r - 1 ? 0 : br == r + 1 ? 1 : bc == c - 1 ? 2 : 3)] << '\\n';\n        }\n\n        // Emit the movement path.\n        for (auto [a, d] : best.path) {\n            cout << a << ' ' << d << '\\n';\n        }\n\n        cur = nxt;\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int B = 10000;\n\nstruct Rect {\n    int x1 = 0, y1 = 0, x2 = 0, y2 = 0;\n};\n\nstruct Cand {\n    int orient;   // 0: vertical, 1: horizontal\n    int cut;\n    int span;\n    double score;\n};\n\nstruct Config {\n    double rawWeight;     // blend between raw target and feasibility-aware target\n    int radius;           // nearby cut search radius\n    int optimizeRounds;   // top-down refinement rounds\n    int rootKEachOrient;  // root candidates per orientation\n    bool randomize;       // add tiny noise / diversify\n    double noise;         // noise scale\n};\n\nstruct Result {\n    vector<Rect> rects;\n    double score = -1e100;\n};\n\nstruct Stats {\n    long long sumR = 0;\n    int minx = 0, maxx = 0, miny = 0, maxy = 0;\n};\n\nstruct Node {\n    int left = -1, right = -1;\n    int orient = -1; // 0 vertical, 1 horizontal\n    int cut = 0;\n    int id = -1;     // leaf company id\n\n    int cnt = 0;\n    long long sumR = 0;\n    int minx = 0, maxx = 0, miny = 0, maxy = 0;\n};\n\nclass Engine {\npublic:\n    const vector<int>& xs;\n    const vector<int>& ys;\n    const vector<long long>& rs;\n    Config cfg;\n    mt19937_64 rng;\n    vector<Node> nodes;\n    chrono::steady_clock::time_point startTime;\n    double timeLimit;\n\n    Engine(const vector<int>& xs_, const vector<int>& ys_, const vector<long long>& rs_,\n           Config cfg_, uint64_t seed,\n           chrono::steady_clock::time_point start_, double timeLimit_)\n        : xs(xs_), ys(ys_), rs(rs_), cfg(cfg_), rng(seed), startTime(start_), timeLimit(timeLimit_) {\n        nodes.reserve(2 * xs.size() + 5);\n    }\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n    }\n\n    double rnd01() {\n        return (double)(rng() >> 11) * (1.0 / (1ULL << 53));\n    }\n\n    static inline int clampInt(int v, int lo, int hi) {\n        return max(lo, min(hi, v));\n    }\n\n    static inline double satScore(long long area, long long target) {\n        long long mn = min(area, target), mx = max(area, target);\n        double t = (double)mn / (double)mx;\n        return 1.0 - (1.0 - t) * (1.0 - t);\n    }\n\n    Stats calcStats(const vector<int>& ids) const {\n        Stats s;\n        s.sumR = 0;\n        s.minx = s.maxx = xs[ids[0]];\n        s.miny = s.maxy = ys[ids[0]];\n        for (int id : ids) {\n            s.sumR += rs[id];\n            s.minx = min(s.minx, xs[id]);\n            s.maxx = max(s.maxx, xs[id]);\n            s.miny = min(s.miny, ys[id]);\n            s.maxy = max(s.maxy, ys[id]);\n        }\n        return s;\n    }\n\n    bool splitByCut(const vector<int>& ids, const Rect& box, int orient, int cut,\n                    vector<int>& L, vector<int>& R, Rect& boxL, Rect& boxR) const {\n        L.clear();\n        R.clear();\n        L.reserve(ids.size());\n        R.reserve(ids.size());\n\n        if (orient == 0) {\n            for (int id : ids) (xs[id] < cut ? L : R).push_back(id);\n            if (L.empty() || R.empty()) return false;\n            boxL = {box.x1, box.y1, cut, box.y2};\n            boxR = {cut, box.y1, box.x2, box.y2};\n        } else {\n            for (int id : ids) (ys[id] < cut ? L : R).push_back(id);\n            if (L.empty() || R.empty()) return false;\n            boxL = {box.x1, box.y1, box.x2, cut};\n            boxR = {box.x1, cut, box.x2, box.y2};\n        }\n        return true;\n    }\n\n    bool splitMedian(const vector<int>& ids, const Rect& box, bool vertical,\n                     vector<int>& L, vector<int>& R, Rect& boxL, Rect& boxR) const {\n        vector<int> ord = ids;\n        if (vertical) {\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                return a < b;\n            });\n        } else {\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (ys[a] != ys[b]) return ys[a] < ys[b];\n                if (xs[a] != xs[b]) return xs[a] < xs[b];\n                return a < b;\n            });\n        }\n\n        auto coord = [&](int id) { return vertical ? xs[id] : ys[id]; };\n\n        int m = (int)ord.size();\n        int mid = m / 2 - 1;\n        if (mid < 0) mid = 0;\n        while (mid + 1 < m && coord(ord[mid]) == coord(ord[mid + 1])) ++mid;\n        if (mid + 1 >= m) mid = m / 2 - 1;\n        if (mid < 0) mid = 0;\n\n        int cut = coord(ord[mid]) + 1;\n        int lo = vertical ? box.x1 + 1 : box.y1 + 1;\n        int hi = vertical ? box.x2 - 1 : box.y2 - 1;\n        if (lo > hi) return false;\n        cut = clampInt(cut, lo, hi);\n\n        return splitByCut(ids, box, vertical ? 0 : 1, cut, L, R, boxL, boxR);\n    }\n\n    vector<Cand> genCandidates(const vector<int>& ids, const Rect& box, const Stats& st, int depth) {\n        vector<Cand> cands;\n        int m = (int)ids.size();\n        if (m <= 1) return cands;\n\n        auto process = [&](bool vertical) {\n            vector<int> ord = ids;\n            if (vertical) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (xs[a] != xs[b]) return xs[a] < xs[b];\n                    if (ys[a] != ys[b]) return ys[a] < ys[b];\n                    return a < b;\n                });\n            } else {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (ys[a] != ys[b]) return ys[a] < ys[b];\n                    if (xs[a] != xs[b]) return xs[a] < xs[b];\n                    return a < b;\n                });\n            }\n\n            vector<long long> prefSum(m);\n            vector<int> prefMinX(m), prefMaxX(m), prefMinY(m), prefMaxY(m);\n            vector<int> sufMinX(m), sufMaxX(m), sufMinY(m), sufMaxY(m);\n\n            prefSum[0] = rs[ord[0]];\n            prefMinX[0] = prefMaxX[0] = xs[ord[0]];\n            prefMinY[0] = prefMaxY[0] = ys[ord[0]];\n            for (int i = 1; i < m; ++i) {\n                prefSum[i] = prefSum[i - 1] + rs[ord[i]];\n                prefMinX[i] = min(prefMinX[i - 1], xs[ord[i]]);\n                prefMaxX[i] = max(prefMaxX[i - 1], xs[ord[i]]);\n                prefMinY[i] = min(prefMinY[i - 1], ys[ord[i]]);\n                prefMaxY[i] = max(prefMaxY[i - 1], ys[ord[i]]);\n            }\n\n            sufMinX[m - 1] = sufMaxX[m - 1] = xs[ord[m - 1]];\n            sufMinY[m - 1] = sufMaxY[m - 1] = ys[ord[m - 1]];\n            for (int i = m - 2; i >= 0; --i) {\n                sufMinX[i] = min(sufMinX[i + 1], xs[ord[i]]);\n                sufMaxX[i] = max(sufMaxX[i + 1], xs[ord[i]]);\n                sufMinY[i] = min(sufMinY[i + 1], ys[ord[i]]);\n                sufMaxY[i] = max(sufMaxY[i + 1], ys[ord[i]]);\n            }\n\n            auto coord = [&](int id) { return vertical ? xs[id] : ys[id]; };\n            int span = vertical ? (box.x2 - box.x1) : (box.y2 - box.y1);\n            int base = vertical ? box.x1 : box.y1;\n            int lineLen = vertical ? (box.y2 - box.y1) : (box.x2 - box.x1);\n\n            for (int i = 0; i + 1 < m; ++i) {\n                if (coord(ord[i]) == coord(ord[i + 1])) continue;\n\n                long long TL = prefSum[i];\n                long long TR = st.sumR - TL;\n                if (TL <= 0 || TR <= 0) continue;\n\n                int lo = vertical ? max(box.x1 + 1, coord(ord[i]) + 1)\n                                  : max(box.y1 + 1, coord(ord[i]) + 1);\n                int hi = vertical ? min(box.x2 - 1, coord(ord[i + 1]))\n                                  : min(box.y2 - 1, coord(ord[i + 1]));\n                if (lo > hi) continue;\n\n                long long bboxL = vertical\n                    ? 1LL * (prefMaxX[i] - prefMinX[i] + 1) * lineLen\n                    : 1LL * span * (prefMaxY[i] - prefMinY[i] + 1);\n                long long bboxR = vertical\n                    ? 1LL * (sufMaxX[i + 1] - sufMinX[i + 1] + 1) * lineLen\n                    : 1LL * span * (sufMaxY[i + 1] - sufMinY[i + 1] + 1);\n\n                long long needL = max(TL, bboxL);\n                long long needR = max(TR, bboxR);\n\n                double rawShare = (double)TL / (double)st.sumR;\n                double needShare = (double)needL / (double)(needL + needR);\n                double blendShare = cfg.rawWeight * rawShare + (1.0 - cfg.rawWeight) * needShare;\n\n                int centers[3] = {\n                    base + (int)llround(span * rawShare),\n                    base + (int)llround(span * needShare),\n                    base + (int)llround(span * blendShare)\n                };\n\n                auto addCut = [&](int cut) {\n                    if (cut < lo || cut > hi) return;\n                    long long areaL = 1LL * (cut - base) * lineLen;\n                    long long areaR = 1LL * span * lineLen - areaL;\n                    if (areaL <= 0 || areaR <= 0) return;\n\n                    double local = satScore(areaL, TL) + satScore(areaR, TR);\n                    double need = satScore(areaL, needL) + satScore(areaR, needR);\n                    double w = min(0.55, 0.12 + 0.35 / (depth + 1.0));\n                    double score = local * (1.0 - w) + need * w - 1e-9 * fabs((double)cut - (base + span * blendShare));\n                    if (cfg.randomize) score += cfg.noise * (rnd01() - 0.5);\n                    cands.push_back({vertical ? 0 : 1, cut, hi - lo, score});\n                };\n\n                if (hi - lo + 1 <= 64 || m <= 12) {\n                    for (int c = lo; c <= hi; ++c) addCut(c);\n                } else {\n                    addCut(lo);\n                    addCut(hi);\n                    addCut((lo + hi) / 2);\n                    int rad = max(1, cfg.radius - depth / 2);\n                    for (int cc = 0; cc < 3; ++cc) {\n                        for (int d = -rad; d <= rad; ++d) addCut(centers[cc] + d);\n                    }\n                }\n            }\n        };\n\n        process(true);\n        process(false);\n\n        sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n            if (fabs(a.score - b.score) > 1e-15) return a.score > b.score;\n            if (a.span != b.span) return a.span > b.span;\n            if (a.orient != b.orient) return a.orient < b.orient;\n            return a.cut < b.cut;\n        });\n\n        vector<Cand> uniq;\n        uniq.reserve(cands.size());\n        for (auto &c : cands) {\n            if (uniq.empty() || uniq.back().orient != c.orient || uniq.back().cut != c.cut) {\n                uniq.push_back(c);\n            } else if (c.score > uniq.back().score) {\n                uniq.back() = c;\n            }\n        }\n\n        sort(uniq.begin(), uniq.end(), [&](const Cand& a, const Cand& b) {\n            if (fabs(a.score - b.score) > 1e-15) return a.score > b.score;\n            if (a.span != b.span) return a.span > b.span;\n            if (a.orient != b.orient) return a.orient < b.orient;\n            return a.cut < b.cut;\n        });\n\n        if ((int)uniq.size() > 48) uniq.resize(48);\n        return uniq;\n    }\n\n    bool medianRootCandidate(const vector<int>& ids, const Rect& box, Cand& out) {\n        bool found = false;\n        Cand best;\n\n        auto tryOri = [&](bool vertical) {\n            vector<int> L, R;\n            Rect boxL, boxR;\n            if (!splitMedian(ids, box, vertical, L, R, boxL, boxR)) return;\n\n            Stats LS = calcStats(L);\n            Stats RS = calcStats(R);\n            long long areaL = 1LL * (boxL.x2 - boxL.x1) * (boxL.y2 - boxL.y1);\n            long long areaR = 1LL * (boxR.x2 - boxR.x1) * (boxR.y2 - boxR.y1);\n\n            Cand c;\n            c.orient = vertical ? 0 : 1;\n            c.cut = vertical ? boxL.x2 : boxL.y2;\n            c.span = 0;\n            c.score = satScore(areaL, LS.sumR) + satScore(areaR, RS.sumR);\n\n            if (!found || c.score > best.score) {\n                best = c;\n                found = true;\n            }\n        };\n\n        tryOri(true);\n        tryOri(false);\n\n        if (found) out = best;\n        return found;\n    }\n\n    int build(const vector<int>& ids, const Rect& box, int depth, const Cand* forcedRoot = nullptr) {\n        if ((int)ids.size() == 1) {\n            Stats st = calcStats(ids);\n            Node nd;\n            nd.id = ids[0];\n            nd.cnt = 1;\n            nd.sumR = st.sumR;\n            nd.minx = st.minx;\n            nd.maxx = st.maxx;\n            nd.miny = st.miny;\n            nd.maxy = st.maxy;\n            int idx = (int)nodes.size();\n            nodes.push_back(nd);\n            return idx;\n        }\n\n        Stats st = calcStats(ids);\n\n        Cand chosen;\n        bool haveChosen = false;\n\n        if (depth == 0 && forcedRoot != nullptr) {\n            chosen = *forcedRoot;\n            vector<int> L, R;\n            Rect boxL, boxR;\n            if (splitByCut(ids, box, chosen.orient, chosen.cut, L, R, boxL, boxR)) {\n                haveChosen = true;\n            }\n        }\n\n        if (!haveChosen) {\n            vector<Cand> cands = genCandidates(ids, box, st, depth);\n            if (cands.empty()) return buildFallback(ids, box, depth);\n\n            chosen = cands[0];\n            if (cfg.randomize && cands.size() > 1 && rnd01() < 0.18) {\n                int take = min<int>(3, (int)cands.size());\n                chosen = cands[(int)(rng() % take)];\n            }\n        }\n\n        vector<int> L, R;\n        Rect boxL, boxR;\n        if (!splitByCut(ids, box, chosen.orient, chosen.cut, L, R, boxL, boxR)) {\n            return buildFallback(ids, box, depth);\n        }\n\n        int lch = build(L, boxL, depth + 1, nullptr);\n        int rch = build(R, boxR, depth + 1, nullptr);\n\n        Node nd;\n        nd.left = lch;\n        nd.right = rch;\n        nd.orient = chosen.orient;\n        nd.cut = chosen.cut;\n        nd.cnt = (int)ids.size();\n        nd.sumR = st.sumR;\n        nd.minx = st.minx;\n        nd.maxx = st.maxx;\n        nd.miny = st.miny;\n        nd.maxy = st.maxy;\n\n        int idx = (int)nodes.size();\n        nodes.push_back(nd);\n        return idx;\n    }\n\n    int buildFallback(const vector<int>& ids, const Rect& box, int depth) {\n        if ((int)ids.size() == 1) {\n            Stats st = calcStats(ids);\n            Node nd;\n            nd.id = ids[0];\n            nd.cnt = 1;\n            nd.sumR = st.sumR;\n            nd.minx = st.minx;\n            nd.maxx = st.maxx;\n            nd.miny = st.miny;\n            nd.maxy = st.maxy;\n            int idx = (int)nodes.size();\n            nodes.push_back(nd);\n            return idx;\n        }\n\n        vector<int> L, R;\n        Rect boxL, boxR;\n        bool ok = false;\n\n        if (box.x2 - box.x1 >= box.y2 - box.y1) {\n            ok = splitMedian(ids, box, true, L, R, boxL, boxR) ||\n                 splitMedian(ids, box, false, L, R, boxL, boxR);\n        } else {\n            ok = splitMedian(ids, box, false, L, R, boxL, boxR) ||\n                 splitMedian(ids, box, true, L, R, boxL, boxR);\n        }\n\n        if (!ok) {\n            int W = box.x2 - box.x1;\n            int H = box.y2 - box.y1;\n            if (W >= 2) {\n                int cut = clampInt(box.x1 + max(1, W / 2), box.x1 + 1, box.x2 - 1);\n                ok = splitByCut(ids, box, 0, cut, L, R, boxL, boxR);\n            }\n            if (!ok && H >= 2) {\n                int cut = clampInt(box.y1 + max(1, H / 2), box.y1 + 1, box.y2 - 1);\n                ok = splitByCut(ids, box, 1, cut, L, R, boxL, boxR);\n            }\n        }\n\n        if (!ok) {\n            // Extremely defensive fallback.\n            Stats st = calcStats(ids);\n            Node nd;\n            nd.id = ids[0];\n            nd.cnt = 1;\n            nd.sumR = st.sumR;\n            nd.minx = st.minx;\n            nd.maxx = st.maxx;\n            nd.miny = st.miny;\n            nd.maxy = st.maxy;\n            int idx = (int)nodes.size();\n            nodes.push_back(nd);\n            return idx;\n        }\n\n        int lch = build(L, boxL, depth + 1, nullptr);\n        int rch = build(R, boxR, depth + 1, nullptr);\n\n        Stats st = calcStats(ids);\n        Node nd;\n        nd.left = lch;\n        nd.right = rch;\n        nd.orient = (boxL.x2 == boxR.x1 ? 0 : 1);\n        nd.cut = (nd.orient == 0 ? boxL.x2 : boxL.y2);\n        nd.cnt = (int)ids.size();\n        nd.sumR = st.sumR;\n        nd.minx = st.minx;\n        nd.maxx = st.maxx;\n        nd.miny = st.miny;\n        nd.maxy = st.maxy;\n\n        int idx = (int)nodes.size();\n        nodes.push_back(nd);\n        return idx;\n    }\n\n    double eval(int v, const Rect& box) const {\n        const Node& nd = nodes[v];\n        if (nd.id != -1) {\n            long long area = 1LL * (box.x2 - box.x1) * (box.y2 - box.y1);\n            return satScore(area, rs[nd.id]);\n        }\n        if (nd.orient == 0) {\n            Rect L{box.x1, box.y1, nd.cut, box.y2};\n            Rect R{nd.cut, box.y1, box.x2, box.y2};\n            return eval(nd.left, L) + eval(nd.right, R);\n        } else {\n            Rect L{box.x1, box.y1, box.x2, nd.cut};\n            Rect R{box.x1, nd.cut, box.x2, box.y2};\n            return eval(nd.left, L) + eval(nd.right, R);\n        }\n    }\n\n    void materialize(int v, const Rect& box, vector<Rect>& out) const {\n        const Node& nd = nodes[v];\n        if (nd.id != -1) {\n            out[nd.id] = box;\n            return;\n        }\n        if (nd.orient == 0) {\n            materialize(nd.left,  Rect{box.x1, box.y1, nd.cut, box.y2}, out);\n            materialize(nd.right, Rect{nd.cut, box.y1, box.x2, box.y2}, out);\n        } else {\n            materialize(nd.left,  Rect{box.x1, box.y1, box.x2, nd.cut}, out);\n            materialize(nd.right, Rect{box.x1, nd.cut, box.x2, box.y2}, out);\n        }\n    }\n\n    vector<int> genOptCuts(int v, const Rect& box, int depth) const {\n        const Node& nd = nodes[v];\n        if (nd.id != -1) return {};\n\n        const Node& L = nodes[nd.left];\n        const Node& R = nodes[nd.right];\n\n        int lo, hi;\n        if (nd.orient == 0) {\n            lo = max(box.x1 + 1, L.maxx + 1);\n            hi = min(box.x2 - 1, R.minx);\n        } else {\n            lo = max(box.y1 + 1, L.maxy + 1);\n            hi = min(box.y2 - 1, R.miny);\n        }\n        if (lo > hi) return {};\n\n        int W = box.x2 - box.x1;\n        int H = box.y2 - box.y1;\n        long long TL = L.sumR;\n        long long TR = R.sumR;\n        long long T = TL + TR;\n\n        long long bboxL = 1LL * (L.maxx - L.minx + 1) * (L.maxy - L.miny + 1);\n        long long bboxR = 1LL * (R.maxx - R.minx + 1) * (R.maxy - R.miny + 1);\n\n        int span = (nd.orient == 0 ? W : H);\n        int base = (nd.orient == 0 ? box.x1 : box.y1);\n\n        double rawShare = (double)TL / (double)T;\n        double needShare = (double)max<long long>(TL, bboxL) /\n                           (double)(max<long long>(TL, bboxL) + max<long long>(TR, bboxR));\n        double blendShare = cfg.rawWeight * rawShare + (1.0 - cfg.rawWeight) * needShare;\n\n        int centers[4] = {\n            nd.cut,\n            base + (int)llround(span * rawShare),\n            base + (int)llround(span * needShare),\n            base + (int)llround(span * blendShare)\n        };\n\n        vector<int> cuts;\n        auto add = [&](int c) {\n            if (c < lo || c > hi) return;\n            cuts.push_back(c);\n        };\n\n        if (hi - lo + 1 <= 80 || nd.cnt <= 12) {\n            for (int c = lo; c <= hi; ++c) cuts.push_back(c);\n        } else {\n            add(lo);\n            add(hi);\n            add((lo + hi) / 2);\n            int rad = max(1, cfg.radius + 1 - depth / 2);\n            for (int cc = 0; cc < 4; ++cc) {\n                for (int d = -rad; d <= rad; ++d) add(centers[cc] + d);\n            }\n        }\n\n        sort(cuts.begin(), cuts.end());\n        cuts.erase(unique(cuts.begin(), cuts.end()), cuts.end());\n        return cuts;\n    }\n\n    bool optimizeNode(int v, const Rect& box, int depth) {\n        if (elapsed() > timeLimit) return false;\n        Node& nd = nodes[v];\n        if (nd.id != -1) return false;\n\n        bool changed = false;\n        vector<int> cuts = genOptCuts(v, box, depth);\n\n        if (!cuts.empty()) {\n            double best = eval(v, box);\n            int bestCut = nd.cut;\n\n            for (int c : cuts) {\n                if (c == nd.cut) continue;\n                int old = nd.cut;\n                nd.cut = c;\n                double sc = eval(v, box);\n                if (sc > best + 1e-12) {\n                    best = sc;\n                    bestCut = c;\n                }\n                nd.cut = old;\n            }\n\n            if (bestCut != nd.cut) {\n                nd.cut = bestCut;\n                changed = true;\n            }\n        }\n\n        Rect Lbox, Rbox;\n        if (nd.orient == 0) {\n            Lbox = {box.x1, box.y1, nd.cut, box.y2};\n            Rbox = {nd.cut, box.y1, box.x2, box.y2};\n        } else {\n            Lbox = {box.x1, box.y1, box.x2, nd.cut};\n            Rbox = {box.x1, nd.cut, box.x2, box.y2};\n        }\n\n        changed |= optimizeNode(nd.left, Lbox, depth + 1);\n        changed |= optimizeNode(nd.right, Rbox, depth + 1);\n\n        return changed;\n    }\n\n    bool validate(const vector<Rect>& rects) const {\n        for (int i = 0; i < (int)rects.size(); ++i) {\n            const Rect& r = rects[i];\n            if (!(0 <= r.x1 && r.x1 < r.x2 && r.x2 <= B &&\n                  0 <= r.y1 && r.y1 < r.y2 && r.y2 <= B)) return false;\n            if (!(r.x1 <= xs[i] && xs[i] + 1 <= r.x2 &&\n                  r.y1 <= ys[i] && ys[i] + 1 <= r.y2)) return false;\n        }\n\n        for (int i = 0; i < (int)rects.size(); ++i) {\n            for (int j = i + 1; j < (int)rects.size(); ++j) {\n                int xL = max(rects[i].x1, rects[j].x1);\n                int xR = min(rects[i].x2, rects[j].x2);\n                int yB = max(rects[i].y1, rects[j].y1);\n                int yT = min(rects[i].y2, rects[j].y2);\n                if (xL < xR && yB < yT) return false;\n            }\n        }\n        return true;\n    }\n\n    double scoreRects(const vector<Rect>& rects) const {\n        double sum = 0.0;\n        for (int i = 0; i < (int)rects.size(); ++i) {\n            long long area = 1LL * (rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1);\n            sum += satScore(area, rs[i]);\n        }\n        return sum;\n    }\n\n    Result runAttempt(uint64_t seed) {\n        uint64_t s = seed ^ 0x9e3779b97f4a7c15ULL;\n        if (cfg.randomize) {\n            s ^= (s << 7);\n            s ^= (s >> 9);\n        }\n        rng.seed(s);\n\n        Config localCfg = cfg;\n        if (cfg.randomize) {\n            auto jitter = [&]() -> double { return 0.85 + 0.30 * rnd01(); };\n            localCfg.rawWeight *= jitter();\n            localCfg.radius = max(1, localCfg.radius + (int)(rng() % 3) - 1);\n            for (int i = 0; i < 3; ++i) {\n                (void)i;\n            }\n            localCfg.noise = max(1e-12, localCfg.noise * jitter());\n        }\n\n        vector<int> ids(xs.size());\n        iota(ids.begin(), ids.end(), 0);\n\n        // Build a root tree by trying a few root candidates.\n        Stats st = calcStats(ids);\n        vector<Cand> rootCands = genCandidates(ids, Rect{0, 0, B, B}, st, 0);\n\n        vector<Cand> rootAttempts;\n        set<pair<int, int>> used;\n\n        auto addRoot = [&](const Cand& c) {\n            pair<int, int> key{c.orient, c.cut};\n            if (used.insert(key).second) rootAttempts.push_back(c);\n        };\n\n        for (int o = 0; o < 2; ++o) {\n            int cnt = 0;\n            for (const auto& c : rootCands) {\n                if (c.orient != o) continue;\n                addRoot(c);\n                if (++cnt >= localCfg.rootKEachOrient) break;\n            }\n        }\n\n        Cand med;\n        if (medianRootCandidate(ids, Rect{0, 0, B, B}, med)) addRoot(med);\n\n        if (rootAttempts.empty() && !rootCands.empty()) addRoot(rootCands[0]);\n\n        sort(rootAttempts.begin(), rootAttempts.end(), [&](const Cand& a, const Cand& b) {\n            if (fabs(a.score - b.score) > 1e-15) return a.score > b.score;\n            if (a.orient != b.orient) return a.orient < b.orient;\n            return a.cut < b.cut;\n        });\n\n        Result best;\n        best.score = -1e100;\n\n        int rootLimit = min<int>(3, (int)rootAttempts.size());\n        if (!localCfg.randomize) rootLimit = min<int>(max(1, localCfg.rootKEachOrient), (int)rootAttempts.size());\n\n        for (int i = 0; i < rootLimit; ++i) {\n            if (elapsed() > timeLimit) break;\n\n            const Cand& rootCand = rootAttempts[i];\n            nodes.clear();\n            nodes.reserve(2 * ids.size() + 5);\n\n            int root = build(ids, Rect{0, 0, B, B}, 0, &rootCand);\n\n            for (int round = 0; round < localCfg.optimizeRounds; ++round) {\n                if (elapsed() > timeLimit) break;\n                bool changed = optimizeNode(root, Rect{0, 0, B, B}, 0);\n                if (!changed) break;\n            }\n\n            vector<Rect> rects(ids.size());\n            materialize(root, Rect{0, 0, B, B}, rects);\n\n            if (!validate(rects)) continue;\n\n            double sc = scoreRects(rects);\n            if (sc > best.score) {\n                best.score = sc;\n                best.rects = std::move(rects);\n            }\n        }\n\n        if (best.rects.empty()) {\n            // Fallback: a safe median-based construction.\n            nodes.clear();\n            nodes.reserve(2 * ids.size() + 5);\n            int root = build(ids, Rect{0, 0, B, B}, 0, nullptr);\n            for (int round = 0; round < localCfg.optimizeRounds; ++round) {\n                if (elapsed() > timeLimit) break;\n                bool changed = optimizeNode(root, Rect{0, 0, B, B}, 0);\n                if (!changed) break;\n            }\n            vector<Rect> rects(ids.size());\n            materialize(root, Rect{0, 0, B, B}, rects);\n            if (validate(rects)) {\n                best.rects = std::move(rects);\n                best.score = scoreRects(best.rects);\n            }\n        }\n\n        return best;\n    }\n};\n\nstruct SolvedInstance {\n    vector<Rect> rects;\n    double score = -1e100;\n};\n\nSolvedInstance solveOrientation(const vector<int>& xs, const vector<int>& ys, const vector<long long>& rs,\n                                 double timeLimit, uint64_t seedBase) {\n    vector<Config> configs = {\n        {0.70, 4, 3, 6, false, 0.0},\n        {0.62, 5, 3, 6, true, 1e-8},\n        {0.78, 4, 4, 8, true, 2e-8},\n    };\n\n    auto start = chrono::steady_clock::now();\n    SolvedInstance best;\n\n    for (int t = 0; t < (int)configs.size(); ++t) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > timeLimit) break;\n\n        Engine eng(xs, ys, rs, configs[t], seedBase + 1000003ULL * (uint64_t)(t + 1), start, timeLimit);\n        Result res = eng.runAttempt(seedBase + 99991ULL * (uint64_t)(t + 7));\n        if (!res.rects.empty() && res.score > best.score) {\n            best.score = res.score;\n            best.rects = std::move(res.rects);\n        }\n    }\n\n    if (best.rects.empty()) {\n        best.rects.assign(xs.size(), Rect{0, 0, B, B});\n        best.score = 0.0;\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<int> xs(n), ys(n);\n    vector<long long> rs(n);\n    for (int i = 0; i < n; ++i) cin >> xs[i] >> ys[i] >> rs[i];\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n\n    // Split the time budget between original and transposed coordinates.\n    double halfBudget = 2.25;\n\n    // Original orientation\n    SolvedInstance orig = solveOrientation(xs, ys, rs, halfBudget, baseSeed ^ 0x12345678ULL);\n\n    // Transposed orientation\n    vector<int> xt = ys, yt = xs;\n    SolvedInstance tr = solveOrientation(xt, yt, rs, halfBudget, baseSeed ^ 0x9e3779b97f4a7c15ULL);\n\n    // Map transposed rectangles back.\n    vector<Rect> trBack;\n    trBack.reserve(n);\n    for (const auto& r : tr.rects) {\n        trBack.push_back(Rect{r.y1, r.x1, r.y2, r.x2});\n    }\n\n    auto scoreRects = [&](const vector<Rect>& rects) -> double {\n        double sum = 0.0;\n        for (int i = 0; i < n; ++i) {\n            long long area = 1LL * (rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1);\n            long long mn = min(area, rs[i]), mx = max(area, rs[i]);\n            double t = (double)mn / (double)mx;\n            sum += 1.0 - (1.0 - t) * (1.0 - t);\n        }\n        return sum;\n    };\n\n    vector<Rect> best = orig.rects;\n    double bestScore = scoreRects(best);\n\n    double scTr = scoreRects(trBack);\n    if (scTr > bestScore) {\n        bestScore = scTr;\n        best = std::move(trBack);\n    }\n\n    for (int i = 0; i < n; ++i) {\n        cout << best[i].x1 << ' ' << best[i].y1 << ' '\n             << best[i].x2 << ' ' << best[i].y2 << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 50;\nstatic constexpr int W = 50;\nstatic constexpr int N = H * W;\nstatic constexpr int WORDS = (N + 63) / 64;\n\nstruct State {\n    array<uint64_t, WORDS> vis{};\n    int pos = 0;\n    int score = 0;\n    int parent = -1;\n    char mv = 0;\n    int prio = 0;\n};\n\nstruct Cand {\n    int next = -1;\n    char mv = '?';\n    int val = 0;\n    int r1 = 0;\n    int r2 = 0;\n    int fut = 0;\n    int dens = 0;\n    int key = 0;\n};\n\nstruct Mode {\n    int wR2, wR1, wF, wV, wD;\n    int prioMul;\n    int noise;      // percentage for randomized completion\n    int beamDepth;\n    int beamWidth;\n    int finishK;\n};\n\nstruct Result {\n    string path;\n    int score = -1;\n};\n\nint si, sj;\nint tileId[H][W];\nint valGrid[H][W];\n\nint tileOf[N];\nint valueOf[N];\nint densityScore[N];\n\nint adjCnt[N];\nint adjTo[N][4];\nchar adjMv[N][4];\n\ninline int idOf(int r, int c) { return r * W + c; }\n\ninline bool visited(const array<uint64_t, WORDS>& vis, int tid) {\n    return (vis[tid >> 6] >> (tid & 63)) & 1ULL;\n}\ninline void setVisited(array<uint64_t, WORDS>& vis, int tid) {\n    vis[tid >> 6] |= (1ULL << (tid & 63));\n}\n\nstatic inline bool candBetter(const Cand& a, const Cand& b) {\n    if (a.key != b.key) return a.key > b.key;\n    if (a.r2 != b.r2) return a.r2 > b.r2;\n    if (a.r1 != b.r1) return a.r1 > b.r1;\n    if (a.val != b.val) return a.val > b.val;\n    return a.next < b.next;\n}\n\nstatic inline bool nodeBetter(const State& a, const State& b) {\n    if (a.prio != b.prio) return a.prio > b.prio;\n    if (a.score != b.score) return a.score > b.score;\n    return a.pos < b.pos;\n}\n\ninline void applyMove(State& st, int nxt) {\n    st.pos = nxt;\n    st.score += valueOf[nxt];\n    setVisited(st.vis, tileOf[nxt]);\n}\n\nint makeCandidates(const State& st, const Mode& m, Cand out[4]) {\n    int cnt = 0;\n    int curTid = tileOf[st.pos];\n\n    for (int k = 0; k < adjCnt[st.pos]; ++k) {\n        int nxt = adjTo[st.pos][k];\n        int nxtTid = tileOf[nxt];\n        if (visited(st.vis, nxtTid)) continue;\n\n        int directTid[8], directVal[8], directCnt = 0;\n        int reachTid[20], reachVal[20], reachCnt = 0;\n\n        auto addTo = [&](int tid, int val, int tids[], int vals[], int& c) {\n            if (tid == curTid || tid == nxtTid || visited(st.vis, tid)) return;\n            for (int i = 0; i < c; ++i) {\n                if (tids[i] == tid) {\n                    vals[i] = max(vals[i], val);\n                    return;\n                }\n            }\n            tids[c] = tid;\n            vals[c] = val;\n            ++c;\n        };\n\n        for (int e = 0; e < adjCnt[nxt]; ++e) {\n            int x = adjTo[nxt][e];\n            int tx = tileOf[x];\n            addTo(tx, valueOf[x], directTid, directVal, directCnt);\n            addTo(tx, valueOf[x], reachTid, reachVal, reachCnt);\n\n            for (int ee = 0; ee < adjCnt[x]; ++ee) {\n                int y = adjTo[x][ee];\n                int ty = tileOf[y];\n                addTo(ty, valueOf[y], reachTid, reachVal, reachCnt);\n            }\n        }\n\n        sort(reachVal, reachVal + reachCnt, greater<int>());\n        int fut = 0;\n        for (int i = 0; i < min(4, reachCnt); ++i) fut += reachVal[i];\n\n        int dens = densityScore[nxt] / 20;\n        int key = m.wR2 * reachCnt\n                + m.wR1 * directCnt\n                + m.wF  * fut\n                + m.wV  * valueOf[nxt]\n                + m.wD  * dens;\n\n        out[cnt++] = {nxt, adjMv[st.pos][k], valueOf[nxt], directCnt, reachCnt, fut, dens, key};\n    }\n\n    if (cnt == 0) return 0;\n\n    // If there exists a move with positive immediate mobility, discard dead-end moves.\n    bool hasGood = false;\n    for (int i = 0; i < cnt; ++i) {\n        if (out[i].r1 > 0) {\n            hasGood = true;\n            break;\n        }\n    }\n    if (hasGood) {\n        int j = 0;\n        for (int i = 0; i < cnt; ++i) {\n            if (out[i].r1 > 0) out[j++] = out[i];\n        }\n        cnt = j;\n    }\n\n    sort(out, out + cnt, candBetter);\n    return cnt;\n}\n\nstring reconstructPath(const vector<State>& pool, int idx) {\n    string s;\n    while (idx != -1 && pool[idx].parent != -1) {\n        s.push_back(pool[idx].mv);\n        idx = pool[idx].parent;\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nResult completeFrom(State st, string path, const Mode& m, mt19937_64& rng,\n                    chrono::steady_clock::time_point deadline) {\n    while (chrono::steady_clock::now() < deadline) {\n        Cand cand[4];\n        int cnt = makeCandidates(st, m, cand);\n        if (cnt == 0) break;\n\n        int choose = 0;\n        if (m.noise > 0 && cnt > 1 && (int)(rng() % 100) < m.noise) {\n            int minKey = cand[cnt - 1].key;\n            int w[4];\n            int sum = 0;\n            for (int i = 0; i < cnt; ++i) {\n                w[i] = max(1, cand[i].key - minKey + 1);\n                sum += w[i];\n            }\n            uint64_t r = rng() % sum;\n            int acc = 0;\n            for (int i = 0; i < cnt; ++i) {\n                acc += w[i];\n                if (r < (uint64_t)acc) {\n                    choose = i;\n                    break;\n                }\n            }\n        }\n\n        applyMove(st, cand[choose].next);\n        path.push_back(cand[choose].mv);\n    }\n    return {path, st.score};\n}\n\nResult runAttempt(const Mode& m, uint64_t seed, chrono::steady_clock::time_point deadline) {\n    mt19937_64 rng(seed);\n\n    vector<State> pool;\n    pool.reserve(120000);\n\n    State root;\n    int start = idOf(si, sj);\n    root.pos = start;\n    root.score = valueOf[start];\n    setVisited(root.vis, tileOf[start]);\n    root.parent = -1;\n    root.mv = 0;\n    root.prio = root.score;\n    pool.push_back(root);\n\n    vector<int> beam = {0};\n    int bestTerminal = -1;\n\n    for (int depth = 0; depth < m.beamDepth; ++depth) {\n        if (chrono::steady_clock::now() >= deadline) break;\n\n        vector<int> nxt;\n        nxt.reserve(beam.size() * 4 + 8);\n\n        for (int idx : beam) {\n            Cand cand[4];\n            int cnt = makeCandidates(pool[idx], m, cand);\n            if (cnt == 0) {\n                if (bestTerminal == -1 || pool[idx].score > pool[bestTerminal].score) {\n                    bestTerminal = idx;\n                }\n                continue;\n            }\n\n            for (int i = 0; i < cnt; ++i) {\n                State ch = pool[idx];\n                applyMove(ch, cand[i].next);\n                ch.parent = idx;\n                ch.mv = cand[i].mv;\n                int jitter = m.noise ? (int)(rng() % (2ULL * m.noise + 1)) - m.noise : 0;\n                ch.prio = ch.score + m.prioMul * cand[i].key + jitter;\n                pool.push_back(ch);\n                nxt.push_back((int)pool.size() - 1);\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        if ((int)nxt.size() > m.beamWidth) {\n            nth_element(nxt.begin(), nxt.begin() + m.beamWidth, nxt.end(),\n                        [&](int a, int b) {\n                            if (pool[a].prio != pool[b].prio) return pool[a].prio > pool[b].prio;\n                            if (pool[a].score != pool[b].score) return pool[a].score > pool[b].score;\n                            return a < b;\n                        });\n            nxt.resize(m.beamWidth);\n        }\n\n        beam.swap(nxt);\n    }\n\n    vector<int> selected;\n    auto addUnique = [&](int x) {\n        if (x < 0) return;\n        for (int y : selected) if (y == x) return;\n        selected.push_back(x);\n    };\n\n    sort(beam.begin(), beam.end(), [&](int a, int b) {\n        if (pool[a].prio != pool[b].prio) return pool[a].prio > pool[b].prio;\n        if (pool[a].score != pool[b].score) return pool[a].score > pool[b].score;\n        return a < b;\n    });\n\n    for (int i = 0; i < (int)beam.size() && i < m.finishK; ++i) addUnique(beam[i]);\n    if (bestTerminal != -1) addUnique(bestTerminal);\n\n    if (!beam.empty()) {\n        int bestScoreIdx = beam[0];\n        for (int idx : beam) {\n            if (pool[idx].score > pool[bestScoreIdx].score) bestScoreIdx = idx;\n        }\n        addUnique(bestScoreIdx);\n    } else {\n        addUnique(0);\n    }\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[start];\n\n    for (int idx : selected) {\n        if (chrono::steady_clock::now() >= deadline) break;\n\n        string path = reconstructPath(pool, idx);\n        State st = pool[idx];\n        Result r = completeFrom(st, path, m, rng, deadline);\n\n        if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) {\n            best = std::move(r);\n        }\n    }\n\n    return best;\n}\n\npair<bool, int> simulatePath(const string& path) {\n    State st;\n    int start = idOf(si, sj);\n    st.pos = start;\n    st.score = valueOf[start];\n    setVisited(st.vis, tileOf[start]);\n\n    for (char ch : path) {\n        int nxt = -1;\n        for (int k = 0; k < adjCnt[st.pos]; ++k) {\n            if (adjMv[st.pos][k] == ch) {\n                nxt = adjTo[st.pos][k];\n                break;\n            }\n        }\n        if (nxt == -1) return {false, -1};\n        int tid = tileOf[nxt];\n        if (visited(st.vis, tid)) return {false, -1};\n        applyMove(st, nxt);\n    }\n    return {true, st.score};\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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> tileId[i][j];\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) cin >> valGrid[i][j];\n    }\n\n    uint64_t baseSeed = 0x123456789abcdefULL;\n    auto mix = [&](uint64_t x) {\n        baseSeed = splitmix64(baseSeed ^ x);\n    };\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            tileOf[id] = tileId[i][j];\n            valueOf[id] = valGrid[i][j];\n            mix((uint64_t)tileId[i][j] << 32 ^ (uint64_t)valGrid[i][j] ^ (uint64_t)(i * 50 + j));\n        }\n    }\n    mix((uint64_t)si << 32 | (uint64_t)sj);\n\n    // adjacency\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = idOf(i, j);\n            adjCnt[id] = 0;\n            if (i > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i - 1, j);\n                adjMv[id][adjCnt[id]++] = 'U';\n            }\n            if (i + 1 < H) {\n                adjTo[id][adjCnt[id]] = idOf(i + 1, j);\n                adjMv[id][adjCnt[id]++] = 'D';\n            }\n            if (j > 0) {\n                adjTo[id][adjCnt[id]] = idOf(i, j - 1);\n                adjMv[id][adjCnt[id]++] = 'L';\n            }\n            if (j + 1 < W) {\n                adjTo[id][adjCnt[id]] = idOf(i, j + 1);\n                adjMv[id][adjCnt[id]++] = 'R';\n            }\n        }\n    }\n\n    // Local density: weighted sum in Manhattan radius 3\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int sum = 0;\n            for (int dr = -3; dr <= 3; ++dr) {\n                for (int dc = -3; dc <= 3; ++dc) {\n                    int d = abs(dr) + abs(dc);\n                    if (d > 3) continue;\n                    int ni = i + dr, nj = j + dc;\n                    if (ni < 0 || ni >= H || nj < 0 || nj >= W) continue;\n                    int w = 4 - d; // 4,3,2,1\n                    sum += w * valGrid[ni][nj];\n                }\n            }\n            densityScore[idOf(i, j)] = sum;\n        }\n    }\n\n    chrono::steady_clock::time_point startTime = chrono::steady_clock::now();\n    chrono::steady_clock::time_point deadline = startTime + chrono::milliseconds(1850);\n\n    vector<Mode> modes = {\n        // Strong mobility-first\n        {100, 35, 1, 0, 1, 4, 4, 260, 64, 8},\n        // Balanced\n        {70,  25, 3, 1, 2, 4, 6, 220, 72, 8},\n        // Value-balanced\n        {45,  18, 5, 4, 2, 4, 8, 200, 84, 10},\n        // Dense-area explorer\n        {60,  20, 2, 1, 4, 4, 7, 220, 80, 8},\n        // More exploratory\n        {30,  12, 6, 6, 1, 5, 12, 180, 96, 12},\n    };\n\n    Result best;\n    best.path = \"\";\n    best.score = valueOf[idOf(si, sj)];\n\n    int attempt = 0;\n    while (chrono::steady_clock::now() < deadline) {\n        const Mode& m = modes[attempt % (int)modes.size()];\n        uint64_t seed = splitmix64(baseSeed ^ (uint64_t)attempt * 0x9e3779b97f4a7c15ULL);\n        Result r = runAttempt(m, seed, deadline);\n\n        // Safety check\n        auto [ok, sc] = simulatePath(r.path);\n        if (ok) r.score = sc;\n        else r.path.clear(), r.score = valueOf[idOf(si, sj)];\n\n        if (r.score > best.score || (r.score == best.score && r.path.size() > best.path.size())) {\n            best = std::move(r);\n        }\n\n        ++attempt;\n    }\n\n    auto [ok, sc] = simulatePath(best.path);\n    if (!ok) {\n        best.path.clear();\n    }\n\n    cout << best.path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\n\nstatic constexpr double INIT_W = 5000.0;\nstatic constexpr double MIN_W = 1000.0;\nstatic constexpr double MAX_W = 9000.0;\n\nstatic constexpr double PSEUDO_W = 0.05;      // small prior for unseen edges in row/col fitting\nstatic constexpr double SEG_BLEND = 12.0;     // stronger smoothing from segment mean\nstatic constexpr double COV_BETA = 0.35;      // segment coverage contribution to uncertainty\nstatic constexpr double RISK0 = 180.0;        // uncertainty penalty\nstatic constexpr double RISK1 = 160.0;        // grows slightly over time\nstatic constexpr double STEP_PENALTY = 25.0;   // tiny penalty per step to avoid over-detours\nstatic constexpr double UPDATE_LR = 0.30;      // residual update rate\nstatic constexpr double EPS = 1e-9;\nstatic constexpr double INF = 1e100;\n\ndouble estH[N][N - 1], estV[N - 1][N];\nint cntH[N][N - 1], cntV[N - 1][N];\n\nstruct LineModel {\n    bool split = false;\n    int pos = -1; // [1..28]\n    double mean = INIT_W;\n    double left = INIT_W;\n    double right = INIT_W;\n};\n\nLineModel rowModel[N], colModel[N];\nint rowCov[N][2], colCov[N][2];\n\ndouble pcostH[N][N - 1], pcostV[N - 1][N];\ndouble puncH[N][N - 1], puncV[N - 1][N];\n\nmt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n\ninline double clampW(double x) {\n    return max(MIN_W, min(MAX_W, x));\n}\n\ninline int rowSegOf(int r, int c) {\n    return (rowModel[r].split && c >= rowModel[r].pos) ? 1 : 0;\n}\n\ninline int colSegOf(int c, int r) {\n    return (colModel[c].split && r >= colModel[c].pos) ? 1 : 0;\n}\n\ninline double rowSegMean(int r, int c) {\n    if (!rowModel[r].split) return rowModel[r].mean;\n    return (c < rowModel[r].pos ? rowModel[r].left : rowModel[r].right);\n}\n\ninline double colSegMean(int c, int r) {\n    if (!colModel[c].split) return colModel[c].mean;\n    return (r < colModel[c].pos ? colModel[c].left : colModel[c].right);\n}\n\ninline double edgeUncH(int r, int c) {\n    int s = rowSegOf(r, c);\n    return 1.0 / (1.0 + cntH[r][c] + COV_BETA * rowCov[r][s]);\n}\n\ninline double edgeUncV(int r, int c) {\n    int s = colSegOf(c, r);\n    return 1.0 / (1.0 + cntV[r][c] + COV_BETA * colCov[c][s]);\n}\n\ndouble globalMeanH() {\n    double sw = 0.0, sv = 0.0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            if (cntH[i][j] > 0) {\n                double w = sqrt((double)cntH[i][j]);\n                sw += w;\n                sv += w * estH[i][j];\n            }\n        }\n    }\n    return (sw > 0.0 ? sv / sw : INIT_W);\n}\n\ndouble globalMeanV() {\n    double sw = 0.0, sv = 0.0;\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (cntV[i][j] > 0) {\n                double w = sqrt((double)cntV[i][j]);\n                sw += w;\n                sv += w * estV[i][j];\n            }\n        }\n    }\n    return (sw > 0.0 ? sv / sw : INIT_W);\n}\n\nLineModel fitRow(int r, double gH) {\n    double pw[30] = {}, ps[30] = {}, pq[30] = {};\n    int po[30] = {};\n    double totW = 0.0, totS = 0.0, totQ = 0.0;\n    int obs = 0;\n\n    for (int c = 0; c < 29; ++c) {\n        bool seen = (cntH[r][c] > 0);\n        double w = seen ? (sqrt((double)cntH[r][c]) + PSEUDO_W) : PSEUDO_W;\n        double x = seen ? estH[r][c] : gH;\n\n        totW += w;\n        totS += w * x;\n        totQ += w * x * x;\n        obs += seen ? 1 : 0;\n\n        pw[c + 1] = pw[c] + w;\n        ps[c + 1] = ps[c] + w * x;\n        pq[c + 1] = pq[c] + w * x * x;\n        po[c + 1] = po[c] + (seen ? 1 : 0);\n    }\n\n    LineModel m;\n    if (totW <= 0.0) {\n        m.mean = gH;\n        return m;\n    }\n\n    m.mean = totS / totW;\n    if (obs < 6) return m;\n\n    double sse1 = max(0.0, totQ - totS * totS / totW);\n\n    double best2 = INF;\n    int bestPos = -1;\n    double bestL = m.mean, bestR = m.mean;\n\n    for (int cut = 1; cut < 29; ++cut) {\n        double wL = pw[cut], wR = totW - wL;\n        int oL = po[cut], oR = obs - oL;\n        if (oL < 2 || oR < 2) continue;\n        if (wL < 0.5 || wR < 0.5) continue;\n\n        double sL = ps[cut], sR = totS - sL;\n        double qL = pq[cut], qR = totQ - qL;\n        double sse2 = max(0.0, qL - sL * sL / wL) + max(0.0, qR - sR * sR / wR);\n\n        if (sse2 < best2) {\n            best2 = sse2;\n            bestPos = cut;\n            bestL = sL / wL;\n            bestR = sR / wR;\n        }\n    }\n\n    if (bestPos != -1) {\n        double gain = sse1 - best2;\n        if (gain > 1.5e5 && gain > 0.03 * sse1) {\n            m.split = true;\n            m.pos = bestPos;\n            m.left = bestL;\n            m.right = bestR;\n        }\n    }\n\n    return m;\n}\n\nLineModel fitCol(int c, double gV) {\n    double pw[30] = {}, ps[30] = {}, pq[30] = {};\n    int po[30] = {};\n    double totW = 0.0, totS = 0.0, totQ = 0.0;\n    int obs = 0;\n\n    for (int r = 0; r < 29; ++r) {\n        bool seen = (cntV[r][c] > 0);\n        double w = seen ? (sqrt((double)cntV[r][c]) + PSEUDO_W) : PSEUDO_W;\n        double x = seen ? estV[r][c] : gV;\n\n        totW += w;\n        totS += w * x;\n        totQ += w * x * x;\n        obs += seen ? 1 : 0;\n\n        pw[r + 1] = pw[r] + w;\n        ps[r + 1] = ps[r] + w * x;\n        pq[r + 1] = pq[r] + w * x * x;\n        po[r + 1] = po[r] + (seen ? 1 : 0);\n    }\n\n    LineModel m;\n    if (totW <= 0.0) {\n        m.mean = gV;\n        return m;\n    }\n\n    m.mean = totS / totW;\n    if (obs < 6) return m;\n\n    double sse1 = max(0.0, totQ - totS * totS / totW);\n\n    double best2 = INF;\n    int bestPos = -1;\n    double bestL = m.mean, bestR = m.mean;\n\n    for (int cut = 1; cut < 29; ++cut) {\n        double wL = pw[cut], wR = totW - wL;\n        int oL = po[cut], oR = obs - oL;\n        if (oL < 2 || oR < 2) continue;\n        if (wL < 0.5 || wR < 0.5) continue;\n\n        double sL = ps[cut], sR = totS - sL;\n        double qL = pq[cut], qR = totQ - qL;\n        double sse2 = max(0.0, qL - sL * sL / wL) + max(0.0, qR - sR * sR / wR);\n\n        if (sse2 < best2) {\n            best2 = sse2;\n            bestPos = cut;\n            bestL = sL / wL;\n            bestR = sR / wR;\n        }\n    }\n\n    if (bestPos != -1) {\n        double gain = sse1 - best2;\n        if (gain > 1.5e5 && gain > 0.03 * sse1) {\n            m.split = true;\n            m.pos = bestPos;\n            m.left = bestL;\n            m.right = bestR;\n        }\n    }\n\n    return m;\n}\n\nvoid rebuildModelsAndCosts(int q) {\n    double gH = globalMeanH();\n    double gV = globalMeanV();\n\n    for (int i = 0; i < N; ++i) rowModel[i] = fitRow(i, gH);\n    for (int j = 0; j < N; ++j) colModel[j] = fitCol(j, gV);\n\n    for (int i = 0; i < N; ++i) rowCov[i][0] = rowCov[i][1] = 0;\n    for (int j = 0; j < N; ++j) colCov[j][0] = colCov[j][1] = 0;\n\n    for (int i = 0; i < N; ++i) {\n        if (!rowModel[i].split) {\n            int cov = 0;\n            for (int j = 0; j < N - 1; ++j) if (cntH[i][j] > 0) ++cov;\n            rowCov[i][0] = cov;\n        } else {\n            for (int j = 0; j < N - 1; ++j) {\n                if (cntH[i][j] > 0) ++rowCov[i][j >= rowModel[i].pos ? 1 : 0];\n            }\n        }\n    }\n\n    for (int j = 0; j < N; ++j) {\n        if (!colModel[j].split) {\n            int cov = 0;\n            for (int i = 0; i < N - 1; ++i) if (cntV[i][j] > 0) ++cov;\n            colCov[j][0] = cov;\n        } else {\n            for (int i = 0; i < N - 1; ++i) {\n                if (cntV[i][j] > 0) ++colCov[j][i >= colModel[j].pos ? 1 : 0];\n            }\n        }\n    }\n\n    double risk = RISK0 + RISK1 * (double)q / 999.0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            double seg = rowSegMean(i, j);\n            if (cntH[i][j] == 0) estH[i][j] = seg;\n            int s = rowSegOf(i, j);\n            double unc = 1.0 / (1.0 + cntH[i][j] + COV_BETA * rowCov[i][s]);\n            puncH[i][j] = unc;\n            double base = (cntH[i][j] > 0)\n                ? (estH[i][j] * cntH[i][j] + seg * SEG_BLEND) / (cntH[i][j] + SEG_BLEND)\n                : seg;\n            pcostH[i][j] = base + risk * unc;\n        }\n    }\n\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            double seg = colSegMean(j, i);\n            if (cntV[i][j] == 0) estV[i][j] = seg;\n            int s = colSegOf(j, i);\n            double unc = 1.0 / (1.0 + cntV[i][j] + COV_BETA * colCov[j][s]);\n            puncV[i][j] = unc;\n            double base = (cntV[i][j] > 0)\n                ? (estV[i][j] * cntV[i][j] + seg * SEG_BLEND) / (cntV[i][j] + SEG_BLEND)\n                : seg;\n            pcostV[i][j] = base + risk * unc;\n        }\n    }\n}\n\nstruct Candidate {\n    string path;\n    double cost = INF;\n    double unc = INF;\n    double score = INF;\n};\n\nCandidate solveMonotone(int si, int sj, int ti, int tj) {\n    int dy = abs(ti - si);\n    int dx = abs(tj - sj);\n    int sv = (ti >= si ? 1 : -1);\n    int sh = (tj >= sj ? 1 : -1);\n\n    static double dpC[N][N];\n    static double dpU[N][N];\n    static char par[N][N];\n\n    for (int i = 0; i <= dy; ++i) {\n        for (int j = 0; j <= dx; ++j) {\n            dpC[i][j] = INF;\n            dpU[i][j] = INF;\n            par[i][j] = 0;\n        }\n    }\n    dpC[0][0] = 0.0;\n    dpU[0][0] = 0.0;\n\n    auto better = [&](double c1, double u1, double c2, double u2) -> bool {\n        if (c1 + EPS < c2) return true;\n        if (c2 + EPS < c1) return false;\n        return u1 + EPS < u2;\n    };\n\n    for (int i = 0; i <= dy; ++i) {\n        for (int j = 0; j <= dx; ++j) {\n            if (i == 0 && j == 0) continue;\n\n            double bestC = INF, bestU = INF;\n            char bestP = 0;\n\n            if (i > 0) {\n                int px = si + sv * (i - 1);\n                int py = sj + sh * j;\n                int ex = (sv == 1 ? px : px - 1);\n                int ey = py;\n                double candC = dpC[i - 1][j] + pcostV[ex][ey];\n                double candU = dpU[i - 1][j] + puncV[ex][ey];\n                if (better(candC, candU, bestC, bestU)) {\n                    bestC = candC;\n                    bestU = candU;\n                    bestP = (sv == 1 ? 'D' : 'U');\n                }\n            }\n\n            if (j > 0) {\n                int px = si + sv * i;\n                int py = sj + sh * (j - 1);\n                int ex = px;\n                int ey = (sh == 1 ? py : py - 1);\n                double candC = dpC[i][j - 1] + pcostH[ex][ey];\n                double candU = dpU[i][j - 1] + puncH[ex][ey];\n                if (better(candC, candU, bestC, bestU)) {\n                    bestC = candC;\n                    bestU = candU;\n                    bestP = (sh == 1 ? 'R' : 'L');\n                }\n            }\n\n            dpC[i][j] = bestC;\n            dpU[i][j] = bestU;\n            par[i][j] = bestP;\n        }\n    }\n\n    string path;\n    for (int i = dy, j = dx; i > 0 || j > 0; ) {\n        char c = par[i][j];\n        path.push_back(c);\n        if (c == 'D' || c == 'U') --i;\n        else --j;\n    }\n    reverse(path.begin(), path.end());\n\n    Candidate res;\n    res.path = path;\n    res.cost = dpC[dy][dx];\n    res.unc = dpU[dy][dx];\n    res.score = res.cost + STEP_PENALTY * (double)path.size();\n    return res;\n}\n\nCandidate solveDijkstra(int si, int sj, int ti, int tj) {\n    const int S = si * N + sj;\n    const int T = ti * N + tj;\n\n    static double dist[N * N];\n    static double du[N * N];\n    static int par[N * N];\n    static char pmove[N * N];\n\n    for (int i = 0; i < N * N; ++i) {\n        dist[i] = INF;\n        du[i] = INF;\n        par[i] = -1;\n        pmove[i] = 0;\n    }\n\n    priority_queue<tuple<double, double, int>, vector<tuple<double, double, int>>, greater<tuple<double, double, int>>> pq;\n\n    dist[S] = 0.0;\n    du[S] = 0.0;\n    pq.emplace(0.0, 0.0, S);\n\n    while (!pq.empty()) {\n        auto [d, uUnc, u] = pq.top();\n        pq.pop();\n\n        if (d > dist[u] + EPS) continue;\n        if (fabs(d - dist[u]) <= EPS && uUnc > du[u] + EPS) continue;\n        if (u == T) break;\n\n        int x = u / N;\n        int y = u % N;\n\n        // Up\n        if (x > 0) {\n            int v = (x - 1) * N + y;\n            double nd = d + pcostV[x - 1][y];\n            double nu = uUnc + puncV[x - 1][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'U';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Down\n        if (x + 1 < N) {\n            int v = (x + 1) * N + y;\n            double nd = d + pcostV[x][y];\n            double nu = uUnc + puncV[x][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'D';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Left\n        if (y > 0) {\n            int v = x * N + (y - 1);\n            double nd = d + pcostH[x][y - 1];\n            double nu = uUnc + puncH[x][y - 1];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'L';\n                pq.emplace(nd, nu, v);\n            }\n        }\n        // Right\n        if (y + 1 < N) {\n            int v = x * N + (y + 1);\n            double nd = d + pcostH[x][y];\n            double nu = uUnc + puncH[x][y];\n            if (nd + EPS < dist[v] || (fabs(nd - dist[v]) <= EPS && nu + EPS < du[v])) {\n                dist[v] = nd;\n                du[v] = nu;\n                par[v] = u;\n                pmove[v] = 'R';\n                pq.emplace(nd, nu, v);\n            }\n        }\n    }\n\n    string path;\n    for (int v = T; v != S; v = par[v]) path.push_back(pmove[v]);\n    reverse(path.begin(), path.end());\n\n    Candidate res;\n    res.path = path;\n    res.cost = dist[T];\n    res.unc = du[T];\n    res.score = res.cost + STEP_PENALTY * (double)path.size();\n    return res;\n}\n\nstruct Step {\n    bool isH;\n    int a, b;\n    double est;\n    double unc;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            estH[i][j] = INIT_W;\n            cntH[i][j] = 0;\n        }\n    }\n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            estV[i][j] = INIT_W;\n            cntV[i][j] = 0;\n        }\n    }\n\n    for (int q = 0; q < 1000; ++q) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        rebuildModelsAndCosts(q);\n\n        Candidate mono = solveMonotone(si, sj, ti, tj);\n        Candidate dijk = solveDijkstra(si, sj, ti, tj);\n\n        // Choose the route with the better adjusted score.\n        // The tiny step penalty suppresses over-detours.\n        Candidate chosen = mono;\n        if (dijk.score + 1e-9 < mono.score) chosen = dijk;\n\n        cout << chosen.path << '\\n' << flush;\n\n        long long obs;\n        if (!(cin >> obs)) return 0;\n\n        // Predict path length using direct edge estimates.\n        double pred = 0.0;\n        int x = si, y = sj;\n        vector<Step> steps;\n        steps.reserve(chosen.path.size());\n\n        for (char c : chosen.path) {\n            if (c == 'D') {\n                double est = estV[x][y];\n                double unc = puncV[x][y];\n                pred += est;\n                steps.push_back({false, x, y, est, unc});\n                ++x;\n            } else if (c == 'U') {\n                double est = estV[x - 1][y];\n                double unc = puncV[x - 1][y];\n                pred += est;\n                steps.push_back({false, x - 1, y, est, unc});\n                --x;\n            } else if (c == 'R') {\n                double est = estH[x][y];\n                double unc = puncH[x][y];\n                pred += est;\n                steps.push_back({true, x, y, est, unc});\n                ++y;\n            } else { // 'L'\n                double est = estH[x][y - 1];\n                double unc = puncH[x][y - 1];\n                pred += est;\n                steps.push_back({true, x, y - 1, est, unc});\n                --y;\n            }\n        }\n\n        double residual = (double)obs - pred;\n\n        // Cost-proportional, uncertainty-aware residual distribution.\n        // This behaves closer to multiplicative correction than uniform additive updates.\n        double sumW = 0.0;\n        for (auto &st : steps) {\n            double w = st.est * (0.25 + 0.75 * st.unc);\n            sumW += w;\n            st.unc = w; // reuse field as weight\n        }\n        if (sumW <= 0.0) sumW = 1.0;\n\n        for (auto &st : steps) {\n            double delta = UPDATE_LR * residual * (st.unc / sumW);\n            if (st.isH) {\n                estH[st.a][st.b] = clampW(estH[st.a][st.b] + delta);\n                ++cntH[st.a][st.b];\n            } else {\n                estV[st.a][st.b] = clampW(estV[st.a][st.b] + delta);\n                ++cntV[st.a][st.b];\n            }\n        }\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int CELLS = N * N;\nstatic constexpr int SIG = 8;\nstatic constexpr int MAXL = 12;\nstatic constexpr int MAXM = 800;\n\nstatic constexpr long long SAT_WEIGHT  = 3000000000LL;\nstatic constexpr long long BEST_WEIGHT = 20000LL;\n\nusing Board = array<int, CELLS>;\n\nstruct Word {\n    int len;\n    int weight; // len^2\n    array<int, MAXL> ch{};\n};\n\nstruct Place {\n    int sid;\n    int len;\n    int ori;   // 0 horizontal, 1 vertical\n    int line;\n    int st;\n};\n\nstruct State {\n    int sat = 0;\n    long long bestWeighted = 0;\n    long long supportSum = 0;\n};\n\nstatic int Ninput, M;\nstatic vector<Word> words;\nstatic vector<Place> places;\nstatic vector<vector<int>> wordPlaces;\nstatic vector<int> placeCnt;\nstatic vector<array<int, MAXL + 1>> freq;\nstatic vector<int> bestCnt;\n\nstatic array<array<int, SIG>, CELLS> supW{};\nstatic array<array<int, SIG>, CELLS> supLongW{};\nstatic array<array<vector<int>, SIG>, CELLS> cellByChar{};\nstatic array<array<int, SIG>, CELLS> supportOrder{};\nstatic vector<int> uncertaintyOrder;\nstatic vector<int> longOrder;\n\nstatic Board board;\nstatic State curState;\nstatic mt19937_64 rng((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\nstatic auto startTime = chrono::steady_clock::now();\n\nstatic inline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n}\n\nstatic inline int cid(int r, int c) { return r * N + c; }\n\ntemplate <class F>\nstatic inline void forEachCellOfPlace(int pid, F&& f) {\n    const Place& p = places[pid];\n    if (p.ori == 0) {\n        int c = p.st;\n        int base = p.line * N;\n        for (int t = 0; t < p.len; ++t) {\n            f(base + c);\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = p.st;\n        int c = p.line;\n        for (int t = 0; t < p.len; ++t) {\n            f(cid(r, c));\n            if (++r == N) r = 0;\n        }\n    }\n}\n\nstatic inline int countPlacement(const Board& b, int pid) {\n    const Place& p = places[pid];\n    const Word& w = words[p.sid];\n    int cnt = 0;\n    if (p.ori == 0) {\n        int c = p.st;\n        int base = p.line * N;\n        for (int t = 0; t < p.len; ++t) {\n            cnt += (b[base + c] == w.ch[t]);\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = p.st;\n        int c = p.line;\n        for (int t = 0; t < p.len; ++t) {\n            cnt += (b[cid(r, c)] == w.ch[t]);\n            if (++r == N) r = 0;\n        }\n    }\n    return cnt;\n}\n\ntemplate <class TA, class TB>\nstatic Board makeBoardFromWeighted(const TA& A, const TB& B, int wb) {\n    Board b{};\n    for (int i = 0; i < CELLS; ++i) {\n        int best = -1;\n        int bc = 0;\n        for (int c = 0; c < SIG; ++c) {\n            int sc = A[i][c] + wb * B[i][c];\n            if (sc > best || (sc == best && (rng() & 1ULL))) {\n                best = sc;\n                bc = c;\n            }\n        }\n        b[i] = bc;\n    }\n    return b;\n}\n\nstatic void overlayWord(Board& b, const Word& w, int line, int st, bool horiz) {\n    if (horiz) {\n        int c = st;\n        for (int t = 0; t < w.len; ++t) {\n            b[cid(line, c)] = w.ch[t];\n            if (++c == N) c = 0;\n        }\n    } else {\n        int r = st;\n        for (int t = 0; t < w.len; ++t) {\n            b[cid(r, line)] = w.ch[t];\n            if (++r == N) r = 0;\n        }\n    }\n}\n\nstatic Board makeSeededBoard(const Board& base, int shift, int seedCnt = 12) {\n    Board b = base;\n    seedCnt = min(seedCnt, M);\n    for (int i = 0; i < seedCnt; ++i) {\n        int sid = longOrder[(i + shift) % M];\n        bool horiz = ((i + shift) & 1) == 0;\n        int line = (i * 3 + shift * 7) % N;\n        int st = int(rng() % N);\n        overlayWord(b, words[sid], line, st, horiz);\n    }\n    return b;\n}\n\nstatic Board makeRandomBoard() {\n    Board b{};\n    for (int i = 0; i < CELLS; ++i) b[i] = int(rng() & 7ULL);\n    return b;\n}\n\nstatic void mutateBoard(Board& b, int cnt) {\n    int lim = min(120, CELLS);\n    for (int i = 0; i < cnt; ++i) {\n        int idx = uncertaintyOrder[int(rng() % lim)];\n        int cur = b[idx];\n        int alt = cur;\n        for (int t = 0; t < 4 && alt == cur; ++t) {\n            int k = int(rng() % 4);\n            alt = supportOrder[idx][k];\n        }\n        if (alt == cur) alt = (cur + 1) & 7;\n        b[idx] = alt;\n    }\n}\n\nstatic void recomputeAll(const Board& b) {\n    placeCnt.assign(places.size(), 0);\n    freq.assign(M, array<int, MAXL + 1>{});\n    bestCnt.assign(M, 0);\n\n    curState = {};\n    for (int i = 0; i < CELLS; ++i) curState.supportSum += supW[i][b[i]];\n\n    for (int pid = 0; pid < (int)places.size(); ++pid) {\n        int c = countPlacement(b, pid);\n        placeCnt[pid] = c;\n        freq[places[pid].sid][c]++;\n    }\n\n    for (int sid = 0; sid < M; ++sid) {\n        int len = words[sid].len;\n        int best = 0;\n        for (int k = len; k >= 0; --k) {\n            if (freq[sid][k] > 0) {\n                best = k;\n                break;\n            }\n        }\n        bestCnt[sid] = best;\n        curState.sat += (best == len);\n        curState.bestWeighted += 1LL * best * words[sid].weight;\n    }\n}\n\nstatic inline bool betterState(const State& a, const State& b) {\n    if (a.sat != b.sat) return a.sat > b.sat;\n    if (a.bestWeighted != b.bestWeighted) return a.bestWeighted > b.bestWeighted;\n    return a.supportSum > b.supportSum;\n}\n\nstatic long long evalMove(int idx, int cand) {\n    int old = board[idx];\n    if (old == cand) return 0;\n\n    static int diff[MAXM][MAXL + 1];\n    static int seen[MAXM];\n    static int token = 1;\n    ++token;\n\n    static vector<int> touched;\n    touched.clear();\n    touched.reserve(M);\n\n    auto touch = [&](int sid) {\n        if (seen[sid] != token) {\n            seen[sid] = token;\n            memset(diff[sid], 0, sizeof(int) * (words[sid].len + 1));\n            touched.push_back(sid);\n        }\n    };\n\n    auto add = [&](int pid, int delta) {\n        int sid = places[pid].sid;\n        touch(sid);\n        int pc = placeCnt[pid];\n        diff[sid][pc]--;\n        diff[sid][pc + delta]++;\n    };\n\n    for (int pid : cellByChar[idx][old]) add(pid, -1);\n    for (int pid : cellByChar[idx][cand]) add(pid, +1);\n\n    long long dSat = 0, dBest = 0;\n    for (int sid : touched) {\n        int len = words[sid].len;\n        int oldBest = bestCnt[sid];\n        int newBest = 0;\n        for (int k = len; k >= 0; --k) {\n            if (freq[sid][k] + diff[sid][k] > 0) {\n                newBest = k;\n                break;\n            }\n        }\n        dBest += 1LL * (newBest - oldBest) * words[sid].weight;\n        dSat += (newBest == len) - (oldBest == len);\n    }\n\n    long long dSup = 1LL * supW[idx][cand] - supW[idx][old];\n    return dSat * SAT_WEIGHT + dBest * BEST_WEIGHT + dSup;\n}\n\nstatic void applyMove(int idx, int cand) {\n    int old = board[idx];\n    if (old == cand) return;\n\n    static int seen[MAXM];\n    static int token = 1;\n    ++token;\n\n    static vector<int> touched;\n    touched.clear();\n    touched.reserve(M);\n\n    auto touch = [&](int sid) {\n        if (seen[sid] != token) {\n            seen[sid] = token;\n            touched.push_back(sid);\n        }\n    };\n\n    auto upd = [&](const vector<int>& lst, int delta) {\n        for (int pid : lst) {\n            int sid = places[pid].sid;\n            touch(sid);\n            int pc = placeCnt[pid];\n            freq[sid][pc]--;\n            int npc = pc + delta;\n            freq[sid][npc]++;\n            placeCnt[pid] = npc;\n        }\n    };\n\n    upd(cellByChar[idx][old], -1);\n    upd(cellByChar[idx][cand], +1);\n\n    board[idx] = cand;\n    curState.supportSum += 1LL * supW[idx][cand] - supW[idx][old];\n\n    for (int sid : touched) {\n        int len = words[sid].len;\n        int oldBest = bestCnt[sid];\n        int newBest = 0;\n        for (int k = len; k >= 0; --k) {\n            if (freq[sid][k] > 0) {\n                newBest = k;\n                break;\n            }\n        }\n        bestCnt[sid] = newBest;\n        curState.bestWeighted += 1LL * (newBest - oldBest) * words[sid].weight;\n        curState.sat += (newBest == len) - (oldBest == len);\n    }\n}\n\nstatic void emStep(int minLen, int gap) {\n    static long long votes[CELLS][SIG];\n    memset(votes, 0, sizeof(votes));\n\n    for (int sid = 0; sid < M; ++sid) {\n        if (words[sid].len < minLen) continue;\n        int mx = bestCnt[sid];\n        if (mx < 2) continue;\n        int thr = max(1, mx - gap);\n\n        const Word& w = words[sid];\n        for (int pid : wordPlaces[sid]) {\n            int c = placeCnt[pid];\n            if (c < thr) continue;\n\n            long long wt = 1LL * w.weight * (c + 1) * (c + 1);\n            if (c == mx) wt *= 4;\n            if (c == w.len) wt *= 8;\n\n            const Place& p = places[pid];\n            if (p.ori == 0) {\n                int pos = p.st;\n                int base = p.line * N;\n                for (int t = 0; t < p.len; ++t) {\n                    votes[base + pos][w.ch[t]] += wt;\n                    if (++pos == N) pos = 0;\n                }\n            } else {\n                int pos = p.st;\n                int col = p.line;\n                for (int t = 0; t < p.len; ++t) {\n                    votes[cid(pos, col)][w.ch[t]] += wt;\n                    if (++pos == N) pos = 0;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < CELLS; ++i) {\n        int cur = board[i];\n        long long bestV = votes[i][cur] + 1; // inertia\n        int bestC = cur;\n        for (int c = 0; c < SIG; ++c) {\n            if (votes[i][c] > bestV) {\n                bestV = votes[i][c];\n                bestC = c;\n            }\n        }\n        board[i] = bestC;\n    }\n\n    recomputeAll(board);\n}\n\nstatic bool greedySweep(bool reverseOrder) {\n    bool changed = false;\n    if (!reverseOrder) {\n        for (int idx : uncertaintyOrder) {\n            int cur = board[idx];\n            long long bestDelta = 0;\n            int bestCand = cur;\n            for (int c = 0; c < SIG; ++c) {\n                if (c == cur) continue;\n                long long d = evalMove(idx, c);\n                if (d > bestDelta) {\n                    bestDelta = d;\n                    bestCand = c;\n                }\n            }\n            if (bestCand != cur && bestDelta > 0) {\n                applyMove(idx, bestCand);\n                changed = true;\n            }\n        }\n    } else {\n        for (int it = CELLS - 1; it >= 0; --it) {\n            int idx = uncertaintyOrder[it];\n            int cur = board[idx];\n            long long bestDelta = 0;\n            int bestCand = cur;\n            for (int c = 0; c < SIG; ++c) {\n                if (c == cur) continue;\n                long long d = evalMove(idx, c);\n                if (d > bestDelta) {\n                    bestDelta = d;\n                    bestCand = c;\n                }\n            }\n            if (bestCand != cur && bestDelta > 0) {\n                applyMove(idx, bestCand);\n                changed = true;\n            }\n        }\n    }\n    return changed;\n}\n\nstatic int pruneCurrentBoard(Board& outBoard, bitset<CELLS>& outKeep) {\n    vector<vector<int>> fullByWord(M);\n    for (int sid = 0; sid < M; ++sid) {\n        for (int pid : wordPlaces[sid]) {\n            if (placeCnt[pid] == words[sid].len) fullByWord[sid].push_back(pid);\n        }\n        if (fullByWord[sid].empty()) return -1;\n    }\n\n    auto attempt = [&](vector<int> order) -> pair<int, bitset<CELLS>> {\n        bitset<CELLS> keep;\n        keep.reset();\n\n        for (int sid : order) {\n            const auto& cand = fullByWord[sid];\n            int bestPid = cand[0];\n            int bestAdd = INT_MAX;\n\n            for (int pid : cand) {\n                int add = 0;\n                forEachCellOfPlace(pid, [&](int cell) {\n                    if (!keep.test(cell)) ++add;\n                });\n                if (add < bestAdd) {\n                    bestAdd = add;\n                    bestPid = pid;\n                    if (bestAdd == 0) break;\n                }\n            }\n\n            forEachCellOfPlace(bestPid, [&](int cell) {\n                keep.set(cell);\n            });\n        }\n\n        int dots = CELLS - (int)keep.count();\n        return {dots, keep};\n    };\n\n    int bestDots = -1;\n    bitset<CELLS> bestKeep;\n\n    {\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            if (fullByWord[a].size() != fullByWord[b].size()) return fullByWord[a].size() < fullByWord[b].size();\n            if (words[a].len != words[b].len) return words[a].len > words[b].len;\n            return a < b;\n        });\n        auto res = attempt(order);\n        bestDots = res.first;\n        bestKeep = res.second;\n    }\n    {\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            if (words[a].len != words[b].len) return words[a].len > words[b].len;\n            if (fullByWord[a].size() != fullByWord[b].size()) return fullByWord[a].size() < fullByWord[b].size();\n            return a < b;\n        });\n        auto res = attempt(order);\n        if (res.first > bestDots) {\n            bestDots = res.first;\n            bestKeep = res.second;\n        }\n    }\n    {\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        auto res = attempt(order);\n        if (res.first > bestDots) {\n            bestDots = res.first;\n            bestKeep = res.second;\n        }\n    }\n\n    outBoard = board;\n    outKeep = bestKeep;\n    return bestDots;\n}\n\nstatic void outputBoard(const Board& b, const bitset<CELLS>* keep = nullptr) {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int x = b[cid(r, c)];\n            if (keep && !keep->test(cid(r, c))) cout << '.';\n            else cout << char('A' + x);\n        }\n        cout << '\\n';\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> Ninput >> M;\n\n    words.resize(M);\n    for (int i = 0; i < M; ++i) {\n        string s;\n        cin >> s;\n        words[i].len = (int)s.size();\n        words[i].weight = words[i].len * words[i].len;\n        for (int j = 0; j < words[i].len; ++j) words[i].ch[j] = s[j] - 'A';\n    }\n\n    longOrder.resize(M);\n    iota(longOrder.begin(), longOrder.end(), 0);\n    sort(longOrder.begin(), longOrder.end(), [&](int a, int b) {\n        if (words[a].len != words[b].len) return words[a].len > words[b].len;\n        return a < b;\n    });\n\n    places.reserve((size_t)M * N * N * 2);\n    wordPlaces.assign(M, {});\n    for (int sid = 0; sid < M; ++sid) wordPlaces[sid].reserve(N * N * 2);\n\n    // Build placements and support tables.\n    for (int sid = 0; sid < M; ++sid) {\n        const Word& w = words[sid];\n        for (int ori = 0; ori < 2; ++ori) {\n            for (int line = 0; line < N; ++line) {\n                for (int st = 0; st < N; ++st) {\n                    int pid = (int)places.size();\n                    places.push_back(Place{sid, w.len, ori, line, st});\n                    wordPlaces[sid].push_back(pid);\n\n                    if (ori == 0) {\n                        int c = st;\n                        for (int t = 0; t < w.len; ++t) {\n                            ++supW[cid(line, c)][w.ch[t]];\n                            if (w.len >= 7) ++supLongW[cid(line, c)][w.ch[t]];\n                            if (++c == N) c = 0;\n                        }\n                    } else {\n                        int r = st;\n                        for (int t = 0; t < w.len; ++t) {\n                            ++supW[cid(r, line)][w.ch[t]];\n                            if (w.len >= 7) ++supLongW[cid(r, line)][w.ch[t]];\n                            if (++r == N) r = 0;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < CELLS; ++i) {\n        for (int c = 0; c < SIG; ++c) {\n            cellByChar[i][c].reserve(max(1, supW[i][c]));\n        }\n    }\n\n    for (int pid = 0; pid < (int)places.size(); ++pid) {\n        const Place& p = places[pid];\n        const Word& w = words[p.sid];\n        if (p.ori == 0) {\n            int c = p.st;\n            int base = p.line * N;\n            for (int t = 0; t < p.len; ++t) {\n                cellByChar[base + c][w.ch[t]].push_back(pid);\n                if (++c == N) c = 0;\n            }\n        } else {\n            int r = p.st;\n            int col = p.line;\n            for (int t = 0; t < p.len; ++t) {\n                cellByChar[cid(r, col)][w.ch[t]].push_back(pid);\n                if (++r == N) r = 0;\n            }\n        }\n    }\n\n    for (int i = 0; i < CELLS; ++i) {\n        array<pair<int, int>, SIG> arr;\n        for (int c = 0; c < SIG; ++c) arr[c] = {supW[i][c], c};\n        sort(arr.begin(), arr.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n        for (int c = 0; c < SIG; ++c) supportOrder[i][c] = arr[c].second;\n        int gap = arr[0].first - arr[1].first;\n        if (i == 0) {\n            uncertaintyOrder.assign(CELLS, 0);\n        }\n        uncertaintyOrder[i] = i;\n    }\n\n    vector<int> gapVal(CELLS);\n    for (int i = 0; i < CELLS; ++i) {\n        array<pair<int, int>, SIG> arr;\n        for (int c = 0; c < SIG; ++c) arr[c] = {supW[i][c], c};\n        sort(arr.begin(), arr.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n        gapVal[i] = arr[0].first - arr[1].first;\n    }\n    sort(uncertaintyOrder.begin(), uncertaintyOrder.end(), [&](int a, int b) {\n        if (gapVal[a] != gapVal[b]) return gapVal[a] < gapVal[b];\n        return a < b;\n    });\n\n    Board supportBoard = makeBoardFromWeighted(supW, supLongW, 0);\n    Board comboBoard = makeBoardFromWeighted(supW, supLongW, 3);\n    Board longBoard = makeBoardFromWeighted(supLongW, supW, 0);\n\n    board = supportBoard;\n    recomputeAll(board);\n\n    State bestState = curState;\n    Board bestBoard = board;\n\n    auto saveBest = [&]() {\n        if (betterState(curState, bestState)) {\n            bestState = curState;\n            bestBoard = board;\n        }\n    };\n\n    Board bestPrunedBoard;\n    bitset<CELLS> bestKeep;\n    int bestDots = -1;\n    bool havePruned = false;\n\n    auto tryPruneIfFull = [&]() {\n        if (curState.sat != M) return;\n        Board outBoard;\n        bitset<CELLS> outKeep;\n        int dots = pruneCurrentBoard(outBoard, outKeep);\n        if (dots >= 0 && dots > bestDots) {\n            bestDots = dots;\n            bestPrunedBoard = outBoard;\n            bestKeep = outKeep;\n            havePruned = true;\n        }\n    };\n\n    int restarts = 0;\n    while (elapsed() < 2.85 && restarts < 5) {\n        Board start;\n        if (restarts == 0) {\n            start = makeSeededBoard(supportBoard, 0, 12);\n        } else if (restarts == 1) {\n            start = makeSeededBoard(comboBoard, 1, 12);\n        } else if (restarts == 2) {\n            start = bestBoard;\n            mutateBoard(start, max(6, 18 - bestState.sat / 40));\n            start = makeSeededBoard(start, 2, 10);\n        } else if (restarts == 3) {\n            start = makeSeededBoard(longBoard, 3, 12);\n            mutateBoard(start, 10);\n        } else {\n            start = makeRandomBoard();\n            start = makeSeededBoard(start, 4, 12);\n        }\n\n        board = start;\n        recomputeAll(board);\n        saveBest();\n        tryPruneIfFull();\n        if (havePruned && elapsed() > 2.90) break;\n\n        if (curState.sat != M && elapsed() < 2.90) {\n            emStep(6, 0);\n            saveBest();\n            tryPruneIfFull();\n        }\n        if (curState.sat != M && elapsed() < 2.90) {\n            greedySweep(false);\n            saveBest();\n            recomputeAll(board); // keep state absolutely consistent before next phase\n            saveBest();\n            tryPruneIfFull();\n        }\n        if (curState.sat != M && elapsed() < 2.90) {\n            emStep(4, 1);\n            saveBest();\n            tryPruneIfFull();\n        }\n        if (curState.sat != M && elapsed() < 2.90) {\n            greedySweep(true);\n            saveBest();\n            recomputeAll(board);\n            saveBest();\n            tryPruneIfFull();\n        }\n\n        if (curState.sat != M && elapsed() < 2.75) {\n            Board kick = board;\n            mutateBoard(kick, bestState.sat < M / 2 ? 18 : 8);\n            board = kick;\n            recomputeAll(board);\n            saveBest();\n            if (curState.sat != M && elapsed() < 2.90) {\n                greedySweep(false);\n                saveBest();\n                recomputeAll(board);\n                saveBest();\n                tryPruneIfFull();\n            }\n        }\n\n        ++restarts;\n    }\n\n    if (bestState.sat == M && !havePruned) {\n        board = bestBoard;\n        recomputeAll(board);\n        Board outBoard;\n        bitset<CELLS> outKeep;\n        int dots = pruneCurrentBoard(outBoard, outKeep);\n        if (dots >= 0) {\n            bestPrunedBoard = outBoard;\n            bestKeep = outKeep;\n            bestDots = dots;\n            havePruned = true;\n        }\n    }\n\n    if (havePruned) {\n        outputBoard(bestPrunedBoard, &bestKeep);\n    } else {\n        outputBoard(bestBoard, nullptr);\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INF = (1LL << 60);\n\nstruct HSeg { int row, l, r; };\nstruct VSeg { int col, u, d; };\n\nstatic const int di[4] = {-1, 1, 0, 0};\nstatic const int dj[4] = {0, 0, -1, 1};\nstatic const char dc[4] = {'U', 'D', 'L', 'R'};\nstatic const int invd[4] = {1, 0, 3, 2};\n\nstruct Solver {\n    int N, si, sj, M, start;\n    vector<string> grid;\n    vector<int> wt, rowOf, colOf;\n    vector<char> road;\n    vector<int> hOf, vOf;\n    vector<vector<int>> hCells, vCells;\n    vector<HSeg> hsegs;\n    vector<VSeg> vsegs;\n    vector<vector<pair<int,int>>> adjCell, revAdjCell;\n    vector<int> roadCells;\n\n    void read_input() {\n        cin >> N >> si >> sj;\n        grid.resize(N);\n        for (int i = 0; i < N; ++i) cin >> grid[i];\n\n        M = N * N;\n        start = si * N + sj;\n\n        wt.assign(M, 0);\n        rowOf.assign(M, 0);\n        colOf.assign(M, 0);\n        road.assign(M, 0);\n        hOf.assign(M, -1);\n        vOf.assign(M, -1);\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                int id = i * N + j;\n                rowOf[id] = i;\n                colOf[id] = j;\n                if (grid[i][j] != '#') {\n                    road[id] = 1;\n                    wt[id] = grid[i][j] - '0';\n                    roadCells.push_back(id);\n                }\n            }\n        }\n\n        adjCell.assign(M, {});\n        revAdjCell.assign(M, {});\n        for (int id = 0; id < M; ++id) {\n            if (!road[id]) continue;\n            int i = rowOf[id], j = colOf[id];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int to = ni * N + nj;\n                if (!road[to]) continue;\n                // Original: id -> to costs wt[to]\n                adjCell[id].push_back({to, wt[to]});\n                // Reverse: to -> id costs wt[id]\n                revAdjCell[to].push_back({id, wt[id]});\n            }\n        }\n\n        // Horizontal segments on even rows\n        for (int i = 0; i < N; i += 2) {\n            int j = 0;\n            while (j < N) {\n                while (j < N && !road[i * N + j]) ++j;\n                if (j >= N) break;\n                int l = j;\n                vector<int> cells;\n                while (j < N && road[i * N + j]) {\n                    cells.push_back(i * N + j);\n                    ++j;\n                }\n                int r = j - 1;\n                int sid = (int)hsegs.size();\n                hsegs.push_back({i, l, r});\n                hCells.push_back(cells);\n                for (int x : cells) hOf[x] = sid;\n            }\n        }\n\n        // Vertical segments on even cols\n        for (int j = 0; j < N; j += 2) {\n            int i = 0;\n            while (i < N) {\n                while (i < N && !road[i * N + j]) ++i;\n                if (i >= N) break;\n                int u = i;\n                vector<int> cells;\n                while (i < N && road[i * N + j]) {\n                    cells.push_back(i * N + j);\n                    ++i;\n                }\n                int d = i - 1;\n                int sid = (int)vsegs.size();\n                vsegs.push_back({j, u, d});\n                vCells.push_back(cells);\n                for (int x : cells) vOf[x] = sid;\n            }\n        }\n    }\n\n    void dijkstraCells(int src, const vector<vector<pair<int,int>>>& g,\n                       vector<ll>& dist, vector<int>& parent) const {\n        int V = (int)g.size();\n        dist.assign(V, INF);\n        parent.assign(V, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[src] = 0;\n        parent[src] = src;\n        pq.push({0, src});\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            for (auto [v, w] : g[u]) {\n                ll nd = d + w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n\n    string reverseRoute(const string& s) const {\n        string t;\n        t.reserve(s.size());\n        for (int i = (int)s.size() - 1; i >= 0; --i) {\n            char c = s[i];\n            if (c == 'U') t.push_back('D');\n            else if (c == 'D') t.push_back('U');\n            else if (c == 'L') t.push_back('R');\n            else if (c == 'R') t.push_back('L');\n        }\n        return t;\n    }\n\n    pair<bool, ll> simulate(const string& s) const {\n        int ci = si, cj = sj;\n        vector<char> covH(hsegs.size(), 0), covV(vsegs.size(), 0);\n        int covered = 0;\n\n        auto cover = [&](int id) {\n            int h = hOf[id];\n            if (h != -1 && !covH[h]) {\n                covH[h] = 1;\n                ++covered;\n            }\n            int v = vOf[id];\n            if (v != -1 && !covV[v]) {\n                covV[v] = 1;\n                ++covered;\n            }\n        };\n\n        cover(start);\n        ll cost = 0;\n\n        for (char c : s) {\n            int d = -1;\n            if (c == 'U') d = 0;\n            else if (c == 'D') d = 1;\n            else if (c == 'L') d = 2;\n            else if (c == 'R') d = 3;\n            else return {false, 0};\n\n            int ni = ci + di[d], nj = cj + dj[d];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) return {false, 0};\n            int nid = ni * N + nj;\n            if (!road[nid]) return {false, 0};\n\n            ci = ni;\n            cj = nj;\n            cost += wt[nid];\n            cover(nid);\n        }\n\n        if (ci != si || cj != sj) return {false, 0};\n        if (covered != (int)hsegs.size() + (int)vsegs.size()) return {false, 0};\n        return {true, cost};\n    }\n\n    string buildGreedy(int mode) const {\n        struct Tune {\n            array<long double, 3> bonus;\n            array<long double, 3> retCoef;\n            array<long double, 3> pickAlpha;\n        };\n\n        static const Tune tunes[3] = {\n            // aggressive\n            {{24.0L, 18.0L, 13.0L}, {0.02L, 0.05L, 0.10L}, {0.00L, 0.03L, 0.06L}},\n            // balanced\n            {{18.0L, 14.0L, 10.0L}, {0.05L, 0.10L, 0.18L}, {0.05L, 0.10L, 0.15L}},\n            // return-aware\n            {{15.0L, 12.0L, 9.0L},  {0.12L, 0.22L, 0.35L}, {0.12L, 0.25L, 0.40L}}\n        };\n\n        const Tune& cfg = tunes[mode];\n\n        vector<ll> distBack;\n        vector<int> dummy;\n        dijkstraCells(start, revAdjCell, distBack, dummy);\n\n        auto returnCost = [&](int id) -> ll { return distBack[id]; };\n\n        vector<char> covH(hsegs.size(), 0), covV(vsegs.size(), 0);\n        int coveredCnt = 0;\n        auto coverCell = [&](int id) {\n            int h = hOf[id];\n            if (h != -1 && !covH[h]) {\n                covH[h] = 1;\n                ++coveredCnt;\n            }\n            int v = vOf[id];\n            if (v != -1 && !covV[v]) {\n                covV[v] = 1;\n                ++coveredCnt;\n            }\n        };\n        coverCell(start);\n\n        vector<ll> dist;\n        vector<int> parent;\n        vector<int> seenH(hsegs.size(), 0), seenV(vsegs.size(), 0);\n        int stamp = 1;\n\n        int current = start;\n        string route;\n        route.reserve(40000);\n\n        auto appendPath = [&](const vector<int>& path) {\n            int prev = current;\n            for (int id : path) {\n                int pi = rowOf[prev], pj = colOf[prev];\n                int i = rowOf[id], j = colOf[id];\n                if (i == pi - 1 && j == pj) route.push_back('U');\n                else if (i == pi + 1 && j == pj) route.push_back('D');\n                else if (i == pi && j == pj - 1) route.push_back('L');\n                else if (i == pi && j == pj + 1) route.push_back('R');\n                coverCell(id);\n                prev = id;\n            }\n            current = prev;\n        };\n\n        int totalSeg = (int)hsegs.size() + (int)vsegs.size();\n        vector<int> candidates, bestPrefix, tmpPath;\n        vector<int> candMark(M, 0);\n        int candStamp = 1;\n\n        while (coveredCnt < totalSeg) {\n            dijkstraCells(current, adjCell, dist, parent);\n\n            int rem = totalSeg - coveredCnt;\n            int phase = (rem * 3 > totalSeg * 2 ? 0 : (rem * 3 > totalSeg ? 1 : 2));\n\n            candidates.clear();\n            ++candStamp;\n\n            auto addCand = [&](int id) {\n                if (id < 0 || id >= M) return;\n                if (!road[id]) return;\n                if (candMark[id] == candStamp) return;\n                candMark[id] = candStamp;\n                candidates.push_back(id);\n            };\n\n            auto considerCells = [&](const vector<int>& cells) {\n                if (cells.empty()) return;\n                int bestDistCell = -1, bestTradeCell = -1;\n                ll bestDist = INF;\n                long double bestTrade = 1e100L;\n\n                for (int id : cells) {\n                    if (dist[id] >= INF / 2) continue;\n\n                    if (bestDistCell == -1 || dist[id] < bestDist ||\n                        (dist[id] == bestDist && returnCost(id) < returnCost(bestDistCell))) {\n                        bestDist = dist[id];\n                        bestDistCell = id;\n                    }\n\n                    long double trade = (long double)dist[id] + cfg.pickAlpha[phase] * (long double)returnCost(id);\n                    if (bestTradeCell == -1 || trade < bestTrade - 1e-12L ||\n                        (fabsl(trade - bestTrade) <= 1e-12L && dist[id] < dist[bestTradeCell])) {\n                        bestTrade = trade;\n                        bestTradeCell = id;\n                    }\n                }\n\n                if (bestDistCell != -1) addCand(bestDistCell);\n                if (bestTradeCell != -1) addCand(bestTradeCell);\n                addCand(cells[(int)cells.size() / 2]);\n            };\n\n            for (int i = 0; i < (int)hsegs.size(); ++i) if (!covH[i]) considerCells(hCells[i]);\n            for (int i = 0; i < (int)vsegs.size(); ++i) if (!covV[i]) considerCells(vCells[i]);\n\n            if (candidates.empty()) break;\n\n            long double bestScore = -1e100L;\n            int bestGain = -1;\n            ll bestPrefixCost = INF;\n            ll bestReturn = INF;\n            bestPrefix.clear();\n\n            for (int cand : candidates) {\n                if (dist[cand] >= INF / 2) continue;\n\n                tmpPath.clear();\n                int x = cand;\n                bool ok = true;\n                while (x != current) {\n                    if (x < 0 || x >= M || parent[x] == -1) {\n                        ok = false;\n                        break;\n                    }\n                    tmpPath.push_back(x);\n                    x = parent[x];\n                }\n                if (!ok || tmpPath.empty()) continue;\n                reverse(tmpPath.begin(), tmpPath.end());\n\n                ++stamp;\n                ll prefCost = 0;\n                int gain = 0;\n                int lastPos = -1;\n                ll lastPrefixCost = 0;\n                int lastEnd = -1;\n\n                for (int pos = 0; pos < (int)tmpPath.size(); ++pos) {\n                    int id = tmpPath[pos];\n                    prefCost += wt[id];\n\n                    int add = 0;\n                    int h = hOf[id];\n                    if (h != -1 && !covH[h] && seenH[h] != stamp) {\n                        seenH[h] = stamp;\n                        ++add;\n                    }\n                    int v = vOf[id];\n                    if (v != -1 && !covV[v] && seenV[v] != stamp) {\n                        seenV[v] = stamp;\n                        ++add;\n                    }\n                    if (add) {\n                        gain += add;\n                        lastPos = pos;\n                        lastPrefixCost = prefCost;\n                        lastEnd = id;\n                    }\n                }\n\n                if (gain == 0) continue;\n\n                long double score = cfg.bonus[phase] * (long double)gain\n                                  - (long double)lastPrefixCost\n                                  - cfg.retCoef[phase] * (long double)returnCost(lastEnd);\n\n                if (score > bestScore + 1e-12L ||\n                    (fabsl(score - bestScore) <= 1e-12L &&\n                     (gain > bestGain ||\n                      (gain == bestGain && (lastPrefixCost < bestPrefixCost ||\n                                            (lastPrefixCost == bestPrefixCost &&\n                                             returnCost(lastEnd) < bestReturn)))))) {\n                    bestScore = score;\n                    bestGain = gain;\n                    bestPrefixCost = lastPrefixCost;\n                    bestReturn = returnCost(lastEnd);\n                    bestPrefix.assign(tmpPath.begin(), tmpPath.begin() + lastPos + 1);\n                }\n            }\n\n            if (bestPrefix.empty()) {\n                bool found = false;\n                for (int cand : candidates) {\n                    tmpPath.clear();\n                    int x = cand;\n                    bool ok = true;\n                    while (x != current) {\n                        if (x < 0 || x >= M || parent[x] == -1) {\n                            ok = false;\n                            break;\n                        }\n                        tmpPath.push_back(x);\n                        x = parent[x];\n                    }\n                    if (ok && !tmpPath.empty()) {\n                        reverse(tmpPath.begin(), tmpPath.end());\n                        bestPrefix = tmpPath;\n                        found = true;\n                        break;\n                    }\n                }\n                if (!found) break;\n            }\n\n            appendPath(bestPrefix);\n        }\n\n        if (current != start) {\n            dijkstraCells(current, adjCell, dist, parent);\n            vector<int> back;\n            int x = start;\n            while (x != current) {\n                if (x < 0 || x >= M || parent[x] == -1) {\n                    back.clear();\n                    break;\n                }\n                back.push_back(x);\n                x = parent[x];\n            }\n            if (!back.empty()) {\n                reverse(back.begin(), back.end());\n                appendPath(back);\n            }\n        }\n\n        return route;\n    }\n\n    string buildPostman() const {\n        struct Edge {\n            int u, v;\n            int cost;\n            string moves;\n        };\n\n        vector<int> deg(M, 0);\n        for (int id = 0; id < M; ++id) if (road[id]) deg[id] = (int)adjCell[id].size();\n\n        vector<char> isNode(M, 0);\n        vector<int> nodeCells;\n        for (int id = 0; id < M; ++id) {\n            if (!road[id]) continue;\n            bool node = false;\n            if (id == start) node = true;\n            else if (deg[id] != 2) node = true;\n            else {\n                int a = adjCell[id][0].first;\n                int b = adjCell[id][1].first;\n                if (!(rowOf[a] == rowOf[b] || colOf[a] == colOf[b])) node = true;\n            }\n            if (node) {\n                isNode[id] = 1;\n                nodeCells.push_back(id);\n            }\n        }\n\n        vector<int> nodeId(M, -1);\n        for (int i = 0; i < (int)nodeCells.size(); ++i) nodeId[nodeCells[i]] = i;\n        int K = (int)nodeCells.size();\n        if (K == 0 || nodeId[start] == -1) return \"\";\n\n        auto step = [&](int id, int d) -> int {\n            int ni = rowOf[id] + di[d];\n            int nj = colOf[id] + dj[d];\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) return -1;\n            return ni * N + nj;\n        };\n\n        vector<array<char, 4>> usedStep(M);\n        for (auto &a : usedStep) a.fill(0);\n\n        vector<Edge> edges;\n        vector<vector<pair<int,int>>> g(K); // node graph: to, edgeId\n\n        for (int s : nodeCells) {\n            for (int d = 0; d < 4; ++d) {\n                int nxt = step(s, d);\n                if (nxt < 0 || !road[nxt] || usedStep[s][d]) continue;\n\n                int cur = s;\n                int prev = s;\n                int dir = d;\n                int cell = nxt;\n                int cost = 0;\n                string moves;\n\n                while (true) {\n                    usedStep[cur][dir] = 1;\n                    usedStep[cell][invd[dir]] = 1;\n\n                    moves.push_back(dc[dir]);\n                    cost += wt[cell];\n\n                    prev = cur;\n                    cur = cell;\n                    if (isNode[cur]) break;\n\n                    int nd = -1, nc = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int t = step(cur, d2);\n                        if (t < 0 || !road[t] || t == prev) continue;\n                        nd = d2;\n                        nc = t;\n                        break;\n                    }\n                    if (nd == -1) break;\n                    dir = nd;\n                    cell = nc;\n                }\n\n                int a = nodeId[s];\n                int b = nodeId[cur];\n                int eid = (int)edges.size();\n                edges.push_back({a, b, cost, moves});\n                if (a == b) {\n                    g[a].push_back({b, eid});\n                    g[a].push_back({b, eid});\n                } else {\n                    g[a].push_back({b, eid});\n                    g[b].push_back({a, eid});\n                }\n            }\n        }\n\n        vector<int> odd;\n        for (int i = 0; i < K; ++i) {\n            if ((int)g[i].size() % 2 == 1) odd.push_back(i);\n        }\n        int O = (int)odd.size();\n\n        vector<vector<int>> parV(O, vector<int>(K, -1));\n        vector<vector<int>> parE(O, vector<int>(K, -1));\n        vector<vector<ll>> dmat(O, vector<ll>(O, INF));\n\n        auto dijkstraNode = [&](int src, vector<ll>& dist, vector<int>& pV, vector<int>& pE) {\n            dist.assign(K, INF);\n            pV.assign(K, -1);\n            pE.assign(K, -1);\n            priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n            dist[src] = 0;\n            pV[src] = src;\n            pq.push({0, src});\n            while (!pq.empty()) {\n                auto [d, u] = pq.top();\n                pq.pop();\n                if (d != dist[u]) continue;\n                for (auto [v, eid] : g[u]) {\n                    ll nd = d + edges[eid].cost;\n                    if (nd < dist[v]) {\n                        dist[v] = nd;\n                        pV[v] = u;\n                        pE[v] = eid;\n                        pq.push({nd, v});\n                    }\n                }\n            }\n        };\n\n        for (int i = 0; i < O; ++i) {\n            vector<ll> dist;\n            dijkstraNode(odd[i], dist, parV[i], parE[i]);\n            for (int j = 0; j < O; ++j) dmat[i][j] = dist[odd[j]];\n        }\n\n        auto makePairsExact = [&]() -> vector<pair<int,int>> {\n            int full = (1 << O) - 1;\n            vector<ll> dp(1 << O, INF);\n            vector<int> preMask(1 << O, -1), pickI(1 << O, -1), pickJ(1 << O, -1);\n            dp[0] = 0;\n\n            for (int mask = 0; mask <= full; ++mask) {\n                if (dp[mask] >= INF / 2) continue;\n                int i = 0;\n                while (i < O && (mask & (1 << i))) ++i;\n                if (i == O) continue;\n                for (int j = i + 1; j < O; ++j) {\n                    if (mask & (1 << j)) continue;\n                    int nm = mask | (1 << i) | (1 << j);\n                    ll nd = dp[mask] + dmat[i][j];\n                    if (nd < dp[nm]) {\n                        dp[nm] = nd;\n                        preMask[nm] = mask;\n                        pickI[nm] = i;\n                        pickJ[nm] = j;\n                    }\n                }\n            }\n\n            vector<pair<int,int>> ps;\n            int mask = full;\n            while (mask) {\n                int i = pickI[mask], j = pickJ[mask];\n                if (i < 0 || j < 0) break;\n                ps.push_back({i, j});\n                mask = preMask[mask];\n            }\n            return ps;\n        };\n\n        auto pairByOrder = [&](const vector<int>& order) -> vector<pair<int,int>> {\n            vector<char> used(O, 0);\n            vector<pair<int,int>> ps;\n            for (int x : order) {\n                if (used[x]) continue;\n                used[x] = 1;\n                int bestY = -1;\n                ll best = INF;\n                for (int y = 0; y < O; ++y) {\n                    if (used[y] || y == x) continue;\n                    if (dmat[x][y] < best) {\n                        best = dmat[x][y];\n                        bestY = y;\n                    }\n                }\n                if (bestY != -1) {\n                    used[bestY] = 1;\n                    ps.push_back({x, bestY});\n                }\n            }\n            return ps;\n        };\n\n        vector<pair<int,int>> bestPairs;\n        ll bestPairCost = INF;\n\n        if (O == 0) {\n            bestPairs.clear();\n            bestPairCost = 0;\n        } else if (O <= 18) {\n            bestPairs = makePairsExact();\n            bestPairCost = 0;\n            for (auto [a, b] : bestPairs) bestPairCost += dmat[a][b];\n        } else {\n            vector<int> base(O);\n            iota(base.begin(), base.end(), 0);\n\n            vector<vector<int>> orders;\n            orders.push_back(base);\n\n            auto rev = base;\n            reverse(rev.begin(), rev.end());\n            orders.push_back(rev);\n\n            auto shuf = base;\n            mt19937 rng(712367 + N * 10007 + si * 1009 + sj * 9176);\n            shuffle(shuf.begin(), shuf.end(), rng);\n            orders.push_back(shuf);\n\n            auto byScore = base;\n            sort(byScore.begin(), byScore.end(), [&](int a, int b) {\n                ll sa = 0, sb = 0;\n                for (int t = 0; t < O; ++t) {\n                    if (a != t) sa += min(dmat[a][t], (ll)1e9);\n                    if (b != t) sb += min(dmat[b][t], (ll)1e9);\n                }\n                return sa < sb;\n            });\n            orders.push_back(byScore);\n\n            for (const auto& ord : orders) {\n                auto ps = pairByOrder(ord);\n                ll c = 0;\n                for (auto [a, b] : ps) c += dmat[a][b];\n                if (c < bestPairCost) {\n                    bestPairCost = c;\n                    bestPairs = ps;\n                }\n            }\n\n            if (bestPairs.empty()) bestPairs = pairByOrder(base);\n        }\n\n        vector<int> dup(edges.size(), 0);\n        for (auto [a, b] : bestPairs) {\n            if (a < 0 || b < 0) continue;\n            int v = odd[b];\n            while (v != odd[a]) {\n                int eid = parE[a][v];\n                if (eid < 0) break;\n                dup[eid]++;\n                v = parV[a][v];\n            }\n        }\n\n        struct UseEdge {\n            int u, v, orig;\n        };\n\n        vector<UseEdge> uses;\n        vector<vector<pair<int,int>>> mg(K);\n\n        for (int eid = 0; eid < (int)edges.size(); ++eid) {\n            int cnt = 1 + dup[eid];\n            for (int k = 0; k < cnt; ++k) {\n                int uid = (int)uses.size();\n                uses.push_back({edges[eid].u, edges[eid].v, eid});\n                if (edges[eid].u == edges[eid].v) {\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                } else {\n                    mg[edges[eid].u].push_back({edges[eid].v, uid});\n                    mg[edges[eid].v].push_back({edges[eid].u, uid});\n                }\n            }\n        }\n\n        vector<int> it(K, 0), stV, stE, stRev;\n        vector<char> usedUse(uses.size(), 0);\n        vector<pair<int,int>> circuit;\n\n        stV.push_back(nodeId[start]);\n\n        while (!stV.empty()) {\n            int v = stV.back();\n            auto &adj = mg[v];\n            while (it[v] < (int)adj.size() && usedUse[adj[it[v]].second]) ++it[v];\n            if (it[v] == (int)adj.size()) {\n                stV.pop_back();\n                if (!stE.empty()) {\n                    circuit.push_back({stE.back(), stRev.back()});\n                    stE.pop_back();\n                    stRev.pop_back();\n                }\n            } else {\n                auto [to, uid] = adj[it[v]++];\n                if (usedUse[uid]) continue;\n                usedUse[uid] = 1;\n                bool rev = (v != uses[uid].u);\n                stV.push_back(to);\n                stE.push_back(uid);\n                stRev.push_back(rev ? 1 : 0);\n            }\n        }\n\n        reverse(circuit.begin(), circuit.end());\n\n        auto invertMove = [&](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        string route;\n        route.reserve(40000);\n        for (auto [uid, rev] : circuit) {\n            const auto &e = edges[uses[uid].orig];\n            if (!rev) {\n                route += e.moves;\n            } else {\n                for (int i = (int)e.moves.size() - 1; i >= 0; --i) {\n                    route.push_back(invertMove(e.moves[i]));\n                }\n            }\n        }\n\n        return route;\n    }\n\n    string buildCoverageTour() const {\n        vector<ll> distFwd, distBack;\n        vector<int> dummy;\n        dijkstraCells(start, adjCell, distFwd, dummy);\n        dijkstraCells(start, revAdjCell, distBack, dummy);\n\n        // Segment weights: short segments are harder to cover by alternatives,\n        // so they get higher importance.\n        vector<long double> wH(hsegs.size()), wV(vsegs.size());\n        for (int i = 0; i < (int)hsegs.size(); ++i) {\n            long double len = (long double)hCells[i].size();\n            wH[i] = 1.0L / sqrtl(len);\n        }\n        for (int i = 0; i < (int)vsegs.size(); ++i) {\n            long double len = (long double)vCells[i].size();\n            wV[i] = 1.0L / sqrtl(len);\n        }\n\n        vector<char> covH(hsegs.size(), 0), covV(vsegs.size(), 0), picked(M, 0);\n        int coveredCnt = 0;\n        int totalSeg = (int)hsegs.size() + (int)vsegs.size();\n\n        auto coverCell = [&](int id) {\n            int h = hOf[id];\n            if (h != -1 && !covH[h]) {\n                covH[h] = 1;\n                ++coveredCnt;\n            }\n            int v = vOf[id];\n            if (v != -1 && !covV[v]) {\n                covV[v] = 1;\n                ++coveredCnt;\n            }\n        };\n\n        vector<int> selected;\n        selected.push_back(start);\n        picked[start] = 1;\n        coverCell(start);\n\n        while (coveredCnt < totalSeg) {\n            int best = -1;\n            int bestGainCnt = -1;\n            ll bestRT = INF;\n            long double bestScore = -1e100L;\n\n            int rem = totalSeg - coveredCnt;\n            int phase = (rem * 3 > totalSeg * 2 ? 0 : (rem * 3 > totalSeg ? 1 : 2));\n            const long double gainW[3] = {260.0L, 190.0L, 130.0L};\n            const long double costW[3] = {1.00L, 1.10L, 1.25L};\n\n            for (int id : roadCells) {\n                if (picked[id]) continue;\n\n                long double gain = 0;\n                int gainCnt = 0;\n                int h = hOf[id];\n                int v = vOf[id];\n                if (h != -1 && !covH[h]) {\n                    gain += wH[h];\n                    ++gainCnt;\n                }\n                if (v != -1 && !covV[v]) {\n                    gain += wV[v];\n                    ++gainCnt;\n                }\n                if (gainCnt == 0) continue;\n\n                ll rt = distFwd[id] + distBack[id];\n                long double score = gainW[phase] * gain - costW[phase] * (long double)rt;\n                if (gainCnt == 2) score += 0.15L;\n\n                if (score > bestScore + 1e-12L ||\n                    (fabsl(score - bestScore) <= 1e-12L &&\n                     (gainCnt > bestGainCnt || (gainCnt == bestGainCnt && rt < bestRT)))) {\n                    bestScore = score;\n                    bestGainCnt = gainCnt;\n                    bestRT = rt;\n                    best = id;\n                }\n            }\n\n            if (best == -1) break;\n            picked[best] = 1;\n            selected.push_back(best);\n            coverCell(best);\n        }\n\n        if (coveredCnt < totalSeg) return \"\";\n\n        // Prune redundant selected cells.\n        vector<int> cntH(hsegs.size(), 0), cntV(vsegs.size(), 0);\n        for (int id : selected) {\n            if (hOf[id] != -1) ++cntH[hOf[id]];\n            if (vOf[id] != -1) ++cntV[vOf[id]];\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = 1; i < (int)selected.size(); ++i) { // keep start\n                int id = selected[i];\n                bool removable = true;\n                int h = hOf[id], v = vOf[id];\n                if (h != -1 && cntH[h] <= 1) removable = false;\n                if (v != -1 && cntV[v] <= 1) removable = false;\n                if (!removable) continue;\n\n                if (h != -1) --cntH[h];\n                if (v != -1) --cntV[v];\n                selected.erase(selected.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n\n        int m = (int)selected.size();\n        if (m <= 1) return \"\";\n\n        vector<vector<ll>> D(m, vector<ll>(m, INF));\n        vector<vector<int>> parentFrom(m);\n\n        vector<ll> dist;\n        vector<int> par;\n        for (int i = 0; i < m; ++i) {\n            dijkstraCells(selected[i], adjCell, dist, par);\n            parentFrom[i] = par;\n            for (int j = 0; j < m; ++j) D[i][j] = dist[selected[j]];\n        }\n\n        vector<int> nodeGain(m, 0);\n        for (int i = 0; i < m; ++i) {\n            nodeGain[i] = (hOf[selected[i]] != -1) + (vOf[selected[i]] != -1);\n        }\n\n        auto costOf = [&](const vector<int>& ord) -> ll {\n            ll s = 0;\n            for (int i = 0; i + 1 < (int)ord.size(); ++i) s += D[ord[i]][ord[i + 1]];\n            return s;\n        };\n\n        auto improveOrder = [&](vector<int>& ord) {\n            if ((int)ord.size() <= 3) return;\n            for (int iter = 0; iter < 2; ++iter) {\n                ll cur = costOf(ord);\n                ll best = cur;\n                vector<int> bestOrd = ord;\n                int L = (int)ord.size();\n\n                // Relocation\n                for (int i = 1; i + 1 < L; ++i) {\n                    vector<int> base;\n                    base.reserve(L - 1);\n                    for (int k = 0; k < L; ++k) {\n                        if (k == i) continue;\n                        base.push_back(ord[k]);\n                    }\n                    for (int p = 1; p < (int)base.size(); ++p) {\n                        vector<int> cand = base;\n                        cand.insert(cand.begin() + p, ord[i]);\n                        ll c = costOf(cand);\n                        if (c < best) {\n                            best = c;\n                            bestOrd = cand;\n                        }\n                    }\n                }\n\n                // Swap\n                for (int i = 1; i + 1 < L; ++i) {\n                    for (int j = i + 1; j + 1 < L; ++j) {\n                        vector<int> cand = ord;\n                        swap(cand[i], cand[j]);\n                        ll c = costOf(cand);\n                        if (c < best) {\n                            best = c;\n                            bestOrd = cand;\n                        }\n                    }\n                }\n\n                if (best < cur) ord = bestOrd;\n                else break;\n            }\n        };\n\n        auto buildNN = [&](uint32_t seed, bool randomize) -> vector<int> {\n            mt19937 rng(seed);\n            vector<int> ord = {0};\n            vector<char> used(m, 0);\n            used[0] = 1;\n            int cur = 0;\n\n            while ((int)ord.size() < m) {\n                int best = -1;\n                long double bestVal = 1e100L;\n                for (int x = 1; x < m; ++x) if (!used[x]) {\n                    long double val = (long double)D[cur][x]\n                                    + 0.12L * (long double)D[x][0]\n                                    - 0.20L * (long double)nodeGain[x];\n                    if (randomize) {\n                        val += ((long double)(rng() & 1023) / 1023.0L - 0.5L) * 0.03L;\n                    }\n                    if (best == -1 || val < bestVal) {\n                        bestVal = val;\n                        best = x;\n                    }\n                }\n                if (best == -1) break;\n                used[best] = 1;\n                ord.push_back(best);\n                cur = best;\n            }\n            ord.push_back(0);\n            return ord;\n        };\n\n        auto buildInsertion = [&](bool farthest) -> vector<int> {\n            vector<int> ord = {0};\n            vector<char> used(m, 0);\n            used[0] = 1;\n\n            int seed = -1;\n            long double seedVal = farthest ? -1e100L : 1e100L;\n            for (int x = 1; x < m; ++x) {\n                long double val = (long double)D[0][x] + (long double)D[x][0]\n                                - 0.20L * (long double)nodeGain[x];\n                if ((!farthest && val < seedVal) || (farthest && val > seedVal)) {\n                    seedVal = val;\n                    seed = x;\n                }\n            }\n            if (seed == -1) return {0, 0};\n\n            ord.push_back(seed);\n            ord.push_back(0);\n            used[seed] = 1;\n\n            while ((int)ord.size() < m + 1) {\n                int choose = -1;\n                int choosePos = -1;\n                long double bestMetric = farthest ? -1e100L : 1e100L;\n\n                for (int x = 1; x < m; ++x) if (!used[x]) {\n                    ll bestDelta = INF;\n                    int bestP = -1;\n                    for (int p = 1; p < (int)ord.size(); ++p) {\n                        ll delta = D[ord[p - 1]][x] + D[x][ord[p]] - D[ord[p - 1]][ord[p]];\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestP = p;\n                        }\n                    }\n                    long double metric = (long double)bestDelta - 0.20L * (long double)nodeGain[x];\n                    if (!farthest) {\n                        if (choose == -1 || metric < bestMetric) {\n                            bestMetric = metric;\n                            choose = x;\n                            choosePos = bestP;\n                        }\n                    } else {\n                        if (choose == -1 || metric > bestMetric) {\n                            bestMetric = metric;\n                            choose = x;\n                            choosePos = bestP;\n                        }\n                    }\n                }\n\n                if (choose == -1) break;\n                ord.insert(ord.begin() + choosePos, choose);\n                used[choose] = 1;\n            }\n\n            return ord;\n        };\n\n        auto buildExact = [&]() -> vector<int> {\n            int n = m - 1;\n            int full = (1 << n) - 1;\n            vector<vector<ll>> dp(1 << n, vector<ll>(n, INF));\n            vector<vector<int>> preMask(1 << n, vector<int>(n, -1));\n            vector<vector<int>> preLast(1 << n, vector<int>(n, -1));\n\n            for (int i = 0; i < n; ++i) {\n                dp[1 << i][i] = D[0][i + 1];\n            }\n\n            for (int mask = 0; mask <= full; ++mask) {\n                for (int last = 0; last < n; ++last) {\n                    if (!(mask & (1 << last))) continue;\n                    if (dp[mask][last] >= INF / 2) continue;\n                    for (int nxt = 0; nxt < n; ++nxt) {\n                        if (mask & (1 << nxt)) continue;\n                        int nm = mask | (1 << nxt);\n                        ll nd = dp[mask][last] + D[last + 1][nxt + 1];\n                        if (nd < dp[nm][nxt]) {\n                            dp[nm][nxt] = nd;\n                            preMask[nm][nxt] = mask;\n                            preLast[nm][nxt] = last;\n                        }\n                    }\n                }\n            }\n\n            int bestLast = -1;\n            ll best = INF;\n            for (int last = 0; last < n; ++last) {\n                ll c = dp[full][last] + D[last + 1][0];\n                if (c < best) {\n                    best = c;\n                    bestLast = last;\n                }\n            }\n\n            vector<int> rev;\n            int mask = full, last = bestLast;\n            while (mask) {\n                rev.push_back(last + 1);\n                int pm = preMask[mask][last];\n                int pl = preLast[mask][last];\n                mask = pm;\n                last = pl;\n            }\n            reverse(rev.begin(), rev.end());\n\n            vector<int> ord = {0};\n            for (int x : rev) ord.push_back(x);\n            ord.push_back(0);\n            return ord;\n        };\n\n        vector<vector<int>> orders;\n        if (m <= 18) {\n            orders.push_back(buildExact());\n        } else {\n            orders.push_back(buildNN(712367u + (uint32_t)N * 10007u + (uint32_t)si * 1009u + (uint32_t)sj * 9176u, false));\n            orders.push_back(buildNN(998244353u ^ (uint32_t)(N * 911 + si * 131 + sj * 719), true));\n            orders.push_back(buildInsertion(false));\n            orders.push_back(buildInsertion(true));\n\n            vector<int> byRound(m);\n            iota(byRound.begin(), byRound.end(), 0);\n            sort(byRound.begin() + 1, byRound.end(), [&](int a, int b) {\n                ll ra = D[0][a] + D[a][0];\n                ll rb = D[0][b] + D[b][0];\n                if (ra != rb) return ra < rb;\n                return nodeGain[a] > nodeGain[b];\n            });\n            byRound.push_back(0);\n            orders.push_back(byRound);\n        }\n\n        vector<int> bestOrd;\n        ll bestCost = INF;\n        for (auto ord : orders) {\n            if (ord.size() < 2) continue;\n            improveOrder(ord);\n            ll c = costOf(ord);\n            if (c < bestCost) {\n                bestCost = c;\n                bestOrd = ord;\n            }\n        }\n\n        if (bestOrd.empty()) return \"\";\n\n        string ans;\n        ans.reserve(40000);\n\n        for (int i = 0; i + 1 < (int)bestOrd.size(); ++i) {\n            int srcIdx = bestOrd[i];\n            int dstIdx = bestOrd[i + 1];\n            int src = selected[srcIdx];\n            int dst = selected[dstIdx];\n\n            const vector<int>& parLocal = parentFrom[srcIdx];\n            vector<int> path;\n            int x = dst;\n            while (x != src) {\n                if (x < 0 || x >= M || parLocal[x] == -1) return \"\";\n                path.push_back(x);\n                x = parLocal[x];\n            }\n            reverse(path.begin(), path.end());\n\n            int prev = src;\n            for (int id : path) {\n                int pi = rowOf[prev], pj = colOf[prev];\n                int ii = rowOf[id], jj = colOf[id];\n                if (ii == pi - 1 && jj == pj) ans.push_back('U');\n                else if (ii == pi + 1 && jj == pj) ans.push_back('D');\n                else if (ii == pi && jj == pj - 1) ans.push_back('L');\n                else if (ii == pi && jj == pj + 1) ans.push_back('R');\n                prev = id;\n            }\n        }\n\n        return ans;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.read_input();\n\n    vector<string> candidates;\n\n    string g0 = solver.buildGreedy(0);\n    string g1 = solver.buildGreedy(1);\n    string g2 = solver.buildGreedy(2);\n    string p = solver.buildPostman();\n    string c = solver.buildCoverageTour();\n\n    candidates.push_back(g0);\n    candidates.push_back(solver.reverseRoute(g0));\n    candidates.push_back(g1);\n    candidates.push_back(solver.reverseRoute(g1));\n    candidates.push_back(g2);\n    candidates.push_back(solver.reverseRoute(g2));\n    candidates.push_back(p);\n    candidates.push_back(solver.reverseRoute(p));\n    candidates.push_back(c);\n    candidates.push_back(solver.reverseRoute(c));\n\n    string best;\n    ll bestCost = INF;\n    size_t bestLen = numeric_limits<size_t>::max();\n    bool hasBest = false;\n\n    for (const auto& r : candidates) {\n        auto [ok, cost] = solver.simulate(r);\n        if (!ok) continue;\n        if (!hasBest || cost < bestCost || (cost == bestCost && r.size() < bestLen)) {\n            hasBest = true;\n            bestCost = cost;\n            bestLen = r.size();\n            best = r;\n        }\n    }\n\n    if (!hasBest && !candidates.empty()) best = candidates[0];\n    cout << best << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 1000;\nstatic const double INIT_SKILL = 5.0;\nstatic const double INF_D = 1e100;\nstatic const double DUMMY_COST = 1e9;\n\nstruct TaskNode {\n    long long pr;\n    int id;\n};\n\nstruct TaskCmp {\n    bool operator()(const TaskNode& a, const TaskNode& b) const {\n        if (a.pr != b.pr) return a.pr < b.pr; // max-heap\n        return a.id > b.id;\n    }\n};\n\nvector<int> hungarian_min_cost(const vector<vector<double>>& a) {\n    int n = (int)a.size();\n    vector<double> u(n + 1), v(n + 1), minv(n + 1);\n    vector<int> p(n + 1), way(n + 1);\n\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        fill(minv.begin(), minv.end(), INF_D);\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            double delta = INF_D;\n            int j1 = 0;\n\n            for (int j = 1; j <= n; ++j) {\n                if (used[j]) continue;\n                double cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n\n            for (int j = 0; j <= n; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0 != 0);\n    }\n\n    vector<int> ans(n, -1);\n    for (int j = 1; j <= n; ++j) {\n        if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    }\n    return ans;\n}\n\nstatic inline double expected_duration(double w) {\n    double s = 0.0;\n    for (int r = -3; r <= 3; ++r) s += max(1.0, w + (double)r);\n    return s / 7.0;\n}\n\nstatic inline double expected_grad(double w) {\n    double g = 0.0;\n    for (int r = -3; r <= 3; ++r) {\n        if (w + (double)r > 1.0) g += 1.0;\n    }\n    return g / 7.0;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<vector<int>> d(N, vector<int>(K));\n    vector<long long> sumd(N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            cin >> d[i][k];\n            sumd[i] += d[i][k];\n        }\n    }\n\n    vector<vector<int>> succ(N);\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        succ[u].push_back(v);\n        indeg[v]++;\n    }\n\n    // Static task priority: critical path length + depth tie-break.\n    vector<long long> crit(N, 0), priorityVal(N, 0);\n    vector<int> depth(N, 1);\n    for (int i = N - 1; i >= 0; --i) {\n        long long bestCrit = 0;\n        int bestDepth = 0;\n        for (int v : succ[i]) {\n            bestCrit = max(bestCrit, crit[v]);\n            bestDepth = max(bestDepth, depth[v]);\n        }\n        crit[i] = sumd[i] + bestCrit;\n        depth[i] = bestDepth + 1;\n        priorityVal[i] = crit[i] * 1000LL + depth[i];\n    }\n\n    priority_queue<TaskNode, vector<TaskNode>, TaskCmp> pq;\n    for (int i = 0; i < N; ++i) {\n        if (indeg[i] == 0) pq.push({priorityVal[i], i});\n    }\n\n    // Worker model.\n    vector<vector<double>> skill(M, vector<double>(K, INIT_SKILL));\n    vector<int> obsCnt(M, 0);\n    vector<int> runningTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    auto predict_cost = [&](int mem, int task) -> double {\n        double w = 0.0;\n        for (int k = 0; k < K; ++k) {\n            double diff = (double)d[task][k] - skill[mem][k];\n            if (diff > 0) w += diff;\n        }\n        return expected_duration(w);\n    };\n\n    auto update_skill = [&](int mem, int task, int dur) {\n        double w = 0.0;\n        vector<double> gap(K, 0.0);\n        for (int k = 0; k < K; ++k) {\n            double diff = (double)d[task][k] - skill[mem][k];\n            if (diff > 0) {\n                gap[k] = diff;\n                w += diff;\n            }\n        }\n\n        double pred = expected_duration(w);\n        double err = (double)dur - pred; // positive => predicted too short => reduce skill\n        err = max(-4.0, min(4.0, err));\n\n        double g = expected_grad(w);\n        double lr = 0.5 / sqrt((double)obsCnt[mem] + 1.0);\n\n        if (w > 1e-9) {\n            double step = lr * err * g;\n            for (int k = 0; k < K; ++k) {\n                if (gap[k] <= 0.0) continue;\n                skill[mem][k] -= step * (gap[k] / w);\n                if (skill[mem][k] < 0.0) skill[mem][k] = 0.0;\n                if (skill[mem][k] > 100.0) skill[mem][k] = 100.0;\n            }\n        } else {\n            // If current estimate says the task is a perfect fit, but it still took longer,\n            // slightly lower all skills to escape the flat region.\n            if (err > 0.0) {\n                double dec = lr * err / max(1, K);\n                for (int k = 0; k < K; ++k) {\n                    skill[mem][k] = max(0.0, skill[mem][k] - dec);\n                }\n            }\n        }\n\n        ++obsCnt[mem];\n    };\n\n    int day = 1;\n    while (true) {\n        vector<int> freeWorkers;\n        freeWorkers.reserve(M);\n        for (int j = 0; j < M; ++j) {\n            if (runningTask[j] == -1) freeWorkers.push_back(j);\n        }\n\n        vector<pair<int, int>> outPairs;\n\n        if (!freeWorkers.empty() && !pq.empty()) {\n            int W = (int)freeWorkers.size();\n            int take = min<int>((int)pq.size(), W);\n\n            vector<TaskNode> selected;\n            selected.reserve(take);\n            for (int i = 0; i < take; ++i) {\n                selected.push_back(pq.top());\n                pq.pop();\n            }\n\n            int L = (int)selected.size();\n            if (L > 0) {\n                int n = W;\n                vector<vector<double>> mat(n, vector<double>(n, 0.0));\n\n                for (int r = 0; r < W; ++r) {\n                    int mem = freeWorkers[r];\n                    for (int c = 0; c < L; ++c) {\n                        int task = selected[c].id;\n                        mat[r][c] = predict_cost(mem, task);\n                    }\n                    for (int c = L; c < n; ++c) {\n                        mat[r][c] = 0.0; // dummy tasks\n                    }\n                }\n\n                vector<int> assign = hungarian_min_cost(mat);\n\n                for (int r = 0; r < W; ++r) {\n                    int c = assign[r];\n                    if (0 <= c && c < L) {\n                        int mem = freeWorkers[r];\n                        int task = selected[c].id;\n                        runningTask[mem] = task;\n                        startDay[mem] = day;\n                        outPairs.push_back({mem, task});\n                    }\n                }\n            }\n        }\n\n        cout << outPairs.size();\n        for (auto &p : outPairs) {\n            cout << ' ' << (p.first + 1) << ' ' << (p.second + 1);\n        }\n        cout << '\\n' << flush;\n\n        int cnt;\n        if (!(cin >> cnt)) return 0;\n        if (cnt == -1) return 0;\n\n        vector<int> finished(cnt);\n        for (int i = 0; i < cnt; ++i) cin >> finished[i];\n\n        for (int x : finished) {\n            int mem = x - 1;\n            int task = runningTask[mem];\n            if (task < 0) continue;\n\n            int dur = day - startDay[mem] + 1;\n            update_skill(mem, task, dur);\n\n            runningTask[mem] = -1;\n            startDay[mem] = -1;\n\n            for (int v : succ[task]) {\n                if (--indeg[v] == 0) {\n                    pq.push({priorityVal[v], v});\n                }\n            }\n        }\n\n        ++day;\n    }\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int N = 1000;\nstatic constexpr ll INFLL = (1LL << 60);\n\nstruct Pt {\n    int x, y;\n};\n\nstruct Order {\n    Pt p, q;\n    ll pq, op, oq;\n    ll mx2, my2;\n};\n\nstruct Event {\n    int id;\n    int type; // 0 = pickup, 1 = delivery\n};\n\nstruct InsInfo {\n    ll best = INFLL;\n    ll second = INFLL;\n    int i = 0, j = 0;\n    bool same = true;\n};\n\nstruct State {\n    ll cost = INFLL;\n    vector<Event> seq;\n    array<char, N> used{};\n};\n\nstruct Cand {\n    vector<int> sel;\n    int scoreId = -1;\n    Pt anchor{400, 400};\n    ll proxy = 0;\n    ll quickCost = INFLL;\n};\n\nstatic constexpr Pt OFFICE{400, 400};\n\nvector<Order> ord(N);\nvector<vector<ll>> scoreVecs;\nvector<Pt> scoreAnchors;\n\nstatic chrono::steady_clock::time_point gStart;\nstatic inline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - gStart).count();\n}\n\nstatic inline ll absl(ll x) { return x >= 0 ? x : -x; }\nstatic inline ll md(const Pt& a, const Pt& b) {\n    return absl((ll)a.x - b.x) + absl((ll)a.y - b.y);\n}\nstatic inline Pt pointOf(const Event& e) {\n    return e.type == 0 ? ord[e.id].p : ord[e.id].q;\n}\nstatic inline ll directCost(int id) {\n    return ord[id].op + ord[id].pq + ord[id].oq;\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\nstatic vector<Pt> buildPts(const vector<Event>& seq) {\n    vector<Pt> pts;\n    pts.reserve(seq.size() + 2);\n    pts.push_back(OFFICE);\n    for (const auto& e : seq) pts.push_back(pointOf(e));\n    pts.push_back(OFFICE);\n    return pts;\n}\n\nstatic ll routeCostPts(const vector<Pt>& pts) {\n    ll c = 0;\n    for (int i = 0; i + 1 < (int)pts.size(); ++i) c += md(pts[i], pts[i + 1]);\n    return c;\n}\n\nstatic ll seqCost(const vector<Event>& seq) {\n    return routeCostPts(buildPts(seq));\n}\n\nstatic InsInfo bestInsertPts(const vector<Pt>& pts, int id) {\n    int m = (int)pts.size() - 2;\n    const Pt& P = ord[id].p;\n    const Pt& Q = ord[id].q;\n\n    InsInfo res;\n    for (int i = 0; i <= m; ++i) {\n        ll e0 = md(pts[i], pts[i + 1]);\n\n        ll sameDelta = md(pts[i], P) + ord[id].pq + md(Q, pts[i + 1]) - e0;\n        if (sameDelta < res.best) {\n            res.second = res.best;\n            res.best = sameDelta;\n            res.i = i;\n            res.j = i;\n            res.same = true;\n        } else if (sameDelta < res.second) {\n            res.second = sameDelta;\n        }\n\n        ll left = md(pts[i], P) + md(P, pts[i + 1]) - e0;\n        for (int j = i + 1; j <= m; ++j) {\n            ll e1 = md(pts[j], pts[j + 1]);\n            ll delta = left + md(pts[j], Q) + md(Q, pts[j + 1]) - e1;\n            if (delta < res.best) {\n                res.second = res.best;\n                res.best = delta;\n                res.i = i;\n                res.j = j;\n                res.same = false;\n            } else if (delta < res.second) {\n                res.second = delta;\n            }\n        }\n    }\n    return res;\n}\n\nstatic void applyInsert(vector<Event>& seq, const InsInfo& ins, int id) {\n    seq.insert(seq.begin() + ins.i, Event{id, 0});\n    if (ins.same) {\n        seq.insert(seq.begin() + ins.i + 1, Event{id, 1});\n    } else {\n        seq.insert(seq.begin() + ins.j + 1, Event{id, 1});\n    }\n}\n\nstatic vector<Event> removeOrderSeq(const vector<Event>& seq, int id) {\n    vector<Event> res;\n    res.reserve(seq.size() - 2);\n    for (const auto& e : seq) if (e.id != id) res.push_back(e);\n    return res;\n}\n\nstatic vector<int> selectedIds(const array<char, N>& used) {\n    vector<int> ids;\n    for (int i = 0; i < N; ++i) if (used[i]) ids.push_back(i);\n    return ids;\n}\n\nstatic vector<int> selectTop50(const vector<ll>& score) {\n    vector<int> ids(N);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int a, int b) {\n        if (score[a] != score[b]) return score[a] < score[b];\n        return a < b;\n    });\n    ids.resize(50);\n    sort(ids.begin(), ids.end());\n    return ids;\n}\n\nstatic string keyOfSel(const vector<int>& sel) {\n    string s;\n    s.reserve(sel.size() * 6);\n    for (int x : sel) {\n        s += to_string(x);\n        s.push_back(',');\n    }\n    return s;\n}\n\nstatic vector<int> orderByScore(const vector<int>& sel, int sid, bool desc) {\n    vector<int> ords = sel;\n    const auto& sc = scoreVecs[sid];\n    sort(ords.begin(), ords.end(), [&](int a, int b) {\n        if (sc[a] != sc[b]) return desc ? (sc[a] > sc[b]) : (sc[a] < sc[b]);\n        return a < b;\n    });\n    return ords;\n}\n\nstatic vector<int> orderByPQ(const vector<int>& sel, bool desc) {\n    vector<int> ords = sel;\n    sort(ords.begin(), ords.end(), [&](int a, int b) {\n        if (ord[a].pq != ord[b].pq) return desc ? (ord[a].pq > ord[b].pq) : (ord[a].pq < ord[b].pq);\n        return a < b;\n    });\n    return ords;\n}\n\nstatic vector<int> orderByAngle(const vector<int>& sel, Pt anchor) {\n    vector<pair<double,int>> tmp;\n    tmp.reserve(sel.size());\n    for (int id : sel) {\n        double x = (double)ord[id].mx2 * 0.5 - anchor.x;\n        double y = (double)ord[id].my2 * 0.5 - anchor.y;\n        tmp.push_back({atan2(y, x), id});\n    }\n    sort(tmp.begin(), tmp.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n    vector<int> ords;\n    ords.reserve(sel.size());\n    for (auto& t : tmp) ords.push_back(t.second);\n    return ords;\n}\n\nstatic State buildInsertionState(const vector<int>& sel, const vector<int>& order) {\n    State st;\n    st.used.fill(0);\n    for (int id : sel) st.used[id] = 1;\n\n    st.seq.clear();\n    st.seq.reserve(100);\n\n    for (int id : order) {\n        vector<Pt> pts = buildPts(st.seq);\n        InsInfo ins = bestInsertPts(pts, id);\n        applyInsert(st.seq, ins, id);\n    }\n    st.cost = seqCost(st.seq);\n    return st;\n}\n\nstatic State buildRegretState(const vector<int>& sel, int startMode, uint64_t seed) {\n    State st;\n    st.used.fill(0);\n    for (int id : sel) st.used[id] = 1;\n\n    vector<int> rem = sel;\n    vector<pair<ll,int>> d;\n    d.reserve(rem.size());\n    for (int id : rem) d.push_back({directCost(id), id});\n    sort(d.begin(), d.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n\n    int first = d[0].second;\n    if (startMode == 1) {\n        int k = min(8, (int)d.size());\n        uint64_t r = splitmix64(seed);\n        first = d[r % k].second;\n    }\n\n    st.seq.push_back({first, 0});\n    st.seq.push_back({first, 1});\n    st.cost = directCost(first);\n\n    rem.erase(find(rem.begin(), rem.end(), first));\n\n    while (!rem.empty()) {\n        vector<Pt> pts = buildPts(st.seq);\n\n        ll bestReg = -INFLL;\n        ll bestDelta = INFLL;\n        ll bestDirect = INFLL;\n        int choose = -1;\n        InsInfo chooseIns;\n\n        for (int id : rem) {\n            InsInfo ins = bestInsertPts(pts, id);\n            ll sec = (ins.second >= INFLL / 4 ? INFLL / 4 : ins.second);\n            ll reg = sec - ins.best;\n            ll dir = directCost(id);\n            if (reg > bestReg ||\n                (reg == bestReg && (ins.best < bestDelta ||\n                 (ins.best == bestDelta && dir < bestDirect)))) {\n                bestReg = reg;\n                bestDelta = ins.best;\n                bestDirect = dir;\n                choose = id;\n                chooseIns = ins;\n            }\n        }\n\n        applyInsert(st.seq, chooseIns, choose);\n        st.cost += chooseIns.best;\n        rem.erase(find(rem.begin(), rem.end(), choose));\n    }\n\n    st.cost = seqCost(st.seq);\n    return st;\n}\n\nstatic void optimizeAdj(State& st) {\n    for (int iter = 0; iter < 50; ++iter) {\n        bool improved = false;\n        int m = (int)st.seq.size();\n        for (int i = 0; i + 1 < m; ++i) {\n            if (st.seq[i].id == st.seq[i + 1].id) continue;\n            Pt prev = (i == 0 ? OFFICE : pointOf(st.seq[i - 1]));\n            Pt a = pointOf(st.seq[i]);\n            Pt b = pointOf(st.seq[i + 1]);\n            Pt nxt = (i + 2 == m ? OFFICE : pointOf(st.seq[i + 2]));\n\n            ll before = md(prev, a) + md(a, b) + md(b, nxt);\n            ll after  = md(prev, b) + md(b, a) + md(a, nxt);\n\n            if (after < before) {\n                swap(st.seq[i], st.seq[i + 1]);\n                st.cost += after - before;\n                improved = true;\n                break;\n            }\n        }\n        if (!improved) break;\n    }\n}\n\nstatic bool pairBestImprove(State& st) {\n    vector<int> ids = selectedIds(st.used);\n    ll bestCost = st.cost;\n    int bestId = -1;\n    InsInfo bestIns;\n    vector<Event> bestReduced;\n\n    for (int id : ids) {\n        vector<Event> reduced = removeOrderSeq(st.seq, id);\n        vector<Pt> pts = buildPts(reduced);\n        ll redCost = routeCostPts(pts);\n        InsInfo ins = bestInsertPts(pts, id);\n        ll nc = redCost + ins.best;\n        if (nc < bestCost) {\n            bestCost = nc;\n            bestId = id;\n            bestIns = ins;\n            bestReduced = std::move(reduced);\n        }\n    }\n\n    if (bestId == -1) return false;\n\n    st.seq = std::move(bestReduced);\n    applyInsert(st.seq, bestIns, bestId);\n    st.cost = bestCost;\n    return true;\n}\n\nstatic vector<int> buildPool(const vector<vector<int>>& rankLists,\n                             const vector<int>& rankIds,\n                             const array<char, N>& used,\n                             int perLimit,\n                             int maxSize) {\n    vector<int> pool;\n    pool.reserve(maxSize);\n    array<char, N> seen{};\n    seen.fill(0);\n\n    for (int rid : rankIds) {\n        int cnt = 0;\n        for (int id : rankLists[rid]) {\n            if (used[id] || seen[id]) continue;\n            seen[id] = 1;\n            pool.push_back(id);\n            if (++cnt == perLimit) break;\n        }\n    }\n\n    if ((int)pool.size() > maxSize) pool.resize(maxSize);\n    return pool;\n}\n\nstatic bool swapBestImprove(State& st,\n                            const vector<vector<int>>& rankLists,\n                            const vector<int>& rankIds) {\n    vector<int> ids = selectedIds(st.used);\n    vector<pair<ll,int>> gain;\n    gain.reserve(ids.size());\n\n    for (int id : ids) {\n        vector<Event> reduced = removeOrderSeq(st.seq, id);\n        ll redCost = seqCost(reduced);\n        gain.push_back({st.cost - redCost, id});\n    }\n\n    sort(gain.begin(), gain.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    vector<int> pool = buildPool(rankLists, rankIds, st.used, 20, 40);\n    if (pool.empty()) return false;\n\n    int Kremove = min(10, (int)gain.size());\n    int Kadd = min(30, (int)pool.size());\n\n    ll bestCost = st.cost;\n    int bestRem = -1, bestAdd = -1;\n    InsInfo bestIns;\n    vector<Event> bestReduced;\n\n    for (int t = 0; t < Kremove; ++t) {\n        int remId = gain[t].second;\n        vector<Event> reduced = removeOrderSeq(st.seq, remId);\n        vector<Pt> pts = buildPts(reduced);\n        ll redCost = routeCostPts(pts);\n\n        for (int k = 0; k < Kadd; ++k) {\n            int addId = pool[k];\n            if (st.used[addId]) continue;\n            InsInfo ins = bestInsertPts(pts, addId);\n            ll nc = redCost + ins.best;\n            if (nc < bestCost) {\n                bestCost = nc;\n                bestRem = remId;\n                bestAdd = addId;\n                bestIns = ins;\n                bestReduced = reduced;\n            }\n        }\n    }\n\n    if (bestRem == -1) return false;\n\n    st.seq = std::move(bestReduced);\n    applyInsert(st.seq, bestIns, bestAdd);\n    st.used[bestRem] = 0;\n    st.used[bestAdd] = 1;\n    st.cost = bestCost;\n    return true;\n}\n\nstatic void fullImprove(State& st,\n                        const vector<vector<int>>& rankLists,\n                        const vector<int>& rankIds) {\n    optimizeAdj(st);\n\n    for (int round = 0; round < 3; ++round) {\n        if (elapsed() > 1.85) break;\n        bool changed = false;\n\n        for (int t = 0; t < 8; ++t) {\n            if (elapsed() > 1.85) break;\n            if (!pairBestImprove(st)) break;\n            changed = true;\n            optimizeAdj(st);\n        }\n\n        for (int t = 0; t < 3; ++t) {\n            if (elapsed() > 1.85) break;\n            if (!swapBestImprove(st, rankLists, rankIds)) break;\n            changed = true;\n            optimizeAdj(st);\n\n            for (int r = 0; r < 5; ++r) {\n                if (elapsed() > 1.85) break;\n                if (!pairBestImprove(st)) break;\n                changed = true;\n                optimizeAdj(st);\n            }\n        }\n\n        optimizeAdj(st);\n        if (!changed) break;\n    }\n\n    st.cost = seqCost(st.seq);\n}\n\nstatic ll quickEvalCandidate(const Cand& c) {\n    vector<int> ord1 = orderByScore(c.sel, c.scoreId, true);\n    vector<int> ord2 = orderByPQ(c.sel, true);\n    State s1 = buildInsertionState(c.sel, ord1);\n    State s2 = buildInsertionState(c.sel, ord2);\n    return min(s1.cost, s2.cost);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    gStart = chrono::steady_clock::now();\n\n    for (int i = 0; i < N; ++i) {\n        cin >> ord[i].p.x >> ord[i].p.y >> ord[i].q.x >> ord[i].q.y;\n        ord[i].pq = md(ord[i].p, ord[i].q);\n        ord[i].op = md(ord[i].p, OFFICE);\n        ord[i].oq = md(ord[i].q, OFFICE);\n        ord[i].mx2 = ord[i].p.x + ord[i].q.x;\n        ord[i].my2 = ord[i].p.y + ord[i].q.y;\n    }\n\n    vector<Pt> anchors;\n    for (int x : {0, 200, 400, 600, 800}) {\n        for (int y : {0, 200, 400, 600, 800}) {\n            anchors.push_back({x, y});\n        }\n    }\n\n    mt19937_64 rng(712367821ULL);\n    vector<int> perm(N);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    for (int k = 0; k < 12; ++k) {\n        int id = perm[k];\n        anchors.push_back({\n            (ord[id].p.x + ord[id].q.x) / 2,\n            (ord[id].p.y + ord[id].q.y) / 2\n        });\n    }\n\n    auto addScoreVec = [&](vector<ll>&& sc, Pt anchor) -> int {\n        scoreVecs.push_back(std::move(sc));\n        scoreAnchors.push_back(anchor);\n        return (int)scoreVecs.size() - 1;\n    };\n\n    // Anchor-based score vectors\n    for (const auto& a : anchors) {\n        for (ll lam : {0LL, 1LL, 3LL}) {\n            vector<ll> s0(N), s1(N), s2(N);\n            for (int i = 0; i < N; ++i) {\n                ll dp = md(ord[i].p, a);\n                ll dq = md(ord[i].q, a);\n                ll mid = absl(ord[i].mx2 - 2LL * a.x) + absl(ord[i].my2 - 2LL * a.y);\n                s0[i] = mid + lam * ord[i].pq;\n                s1[i] = max(dp, dq) + lam * ord[i].pq;\n                s2[i] = dp + dq + 2LL * lam * ord[i].pq;\n            }\n            addScoreVec(std::move(s0), a);\n            addScoreVec(std::move(s1), a);\n            addScoreVec(std::move(s2), a);\n        }\n    }\n\n    // Global score vectors\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = ord[i].op + ord[i].oq + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = max(ord[i].op, ord[i].oq) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = absl(ord[i].mx2 - 800) + absl(ord[i].my2 - 800) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = absl(ord[i].mx2 - ord[i].my2) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = absl(ord[i].mx2 + ord[i].my2 - 1600) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n    {\n        vector<ll> sc(N);\n        for (int i = 0; i < N; ++i) sc[i] = min(ord[i].op, ord[i].oq) + ord[i].pq;\n        addScoreVec(std::move(sc), OFFICE);\n    }\n\n    int S = (int)scoreVecs.size();\n\n    // Build rank lists for swap pool.\n    vector<vector<int>> rankLists(S);\n    for (int sid = 0; sid < S; ++sid) {\n        vector<int> ids(N);\n        iota(ids.begin(), ids.end(), 0);\n        sort(ids.begin(), ids.end(), [&](int a, int b) {\n            if (scoreVecs[sid][a] != scoreVecs[sid][b]) return scoreVecs[sid][a] < scoreVecs[sid][b];\n            return a < b;\n        });\n        rankLists[sid] = std::move(ids);\n    }\n\n    // Candidate generation.\n    vector<Cand> cands;\n    unordered_set<string> seen;\n    seen.reserve(256);\n\n    for (int sid = 0; sid < S; ++sid) {\n        vector<int> sel = selectTop50(scoreVecs[sid]);\n        string key = keyOfSel(sel);\n        if (seen.insert(key).second) {\n            ll proxy = 0;\n            for (int id : sel) proxy += scoreVecs[sid][id];\n            cands.push_back({sel, sid, scoreAnchors[sid], proxy, INFLL});\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.proxy != b.proxy) return a.proxy < b.proxy;\n        return a.scoreId < b.scoreId;\n    });\n    if ((int)cands.size() > 100) cands.resize(100);\n\n    // Quick evaluation.\n    for (auto& c : cands) {\n        if (elapsed() > 1.85) break;\n        c.quickCost = quickEvalCandidate(c);\n    }\n\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.quickCost != b.quickCost) return a.quickCost < b.quickCost;\n        return a.scoreId < b.scoreId;\n    });\n\n    int REFINE = min(5, (int)cands.size());\n    State globalBest;\n    globalBest.cost = INFLL;\n\n    for (int i = 0; i < REFINE; ++i) {\n        if (elapsed() > 1.85) break;\n        const Cand& c = cands[i];\n\n        vector<int> rankIds = {c.scoreId, S - 7, S - 6, S - 5, S - 4, S - 3, S - 2, S - 1};\n        sort(rankIds.begin(), rankIds.end());\n        rankIds.erase(unique(rankIds.begin(), rankIds.end()), rankIds.end());\n\n        vector<State> vars;\n        vars.reserve(5);\n        vars.push_back(buildInsertionState(c.sel, orderByScore(c.sel, c.scoreId, true)));\n        vars.push_back(buildInsertionState(c.sel, orderByScore(c.sel, c.scoreId, false)));\n        vars.push_back(buildInsertionState(c.sel, orderByPQ(c.sel, true)));\n        vars.push_back(buildInsertionState(c.sel, orderByAngle(c.sel, c.anchor)));\n        vars.push_back(buildRegretState(c.sel, 0, splitmix64(123456789ULL ^ (uint64_t)c.scoreId * 1000003ULL)));\n\n        sort(vars.begin(), vars.end(), [&](const State& a, const State& b) {\n            return a.cost < b.cost;\n        });\n\n        for (int k = 0; k < (int)vars.size() && k < 2; ++k) {\n            if (elapsed() > 1.85) break;\n            State st = vars[k];\n            fullImprove(st, rankLists, rankIds);\n            if (st.cost < globalBest.cost) globalBest = std::move(st);\n        }\n    }\n\n    // Fallback.\n    if (globalBest.cost == INFLL && !cands.empty()) {\n        const Cand& c = cands[0];\n        globalBest = buildInsertionState(c.sel, orderByScore(c.sel, c.scoreId, true));\n        globalBest.cost = seqCost(globalBest.seq);\n    }\n\n    vector<int> chosen = selectedIds(globalBest.used);\n    sort(chosen.begin(), chosen.end());\n\n    vector<Pt> pts = buildPts(globalBest.seq);\n\n    cout << 50;\n    for (int id : chosen) cout << ' ' << (id + 1);\n    cout << '\\n';\n\n    cout << pts.size();\n    for (const auto& p : pts) cout << ' ' << p.x << ' ' << p.y;\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        iota(p.begin(), p.end(), 0);\n        sz.assign(n, 1);\n    }\n    int find(int x) {\n        if (p[x] == x) return x;\n        return p[x] = find(p[x]);\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstatic inline int rounded_dist(int x1, int y1, int x2, int y2) {\n    long long dx = (long long)x1 - x2;\n    long long dy = (long long)y1 - y2;\n    long long s = dx * dx + dy * dy;\n    return (int)llround(sqrt((long double)s));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; ++i) cin >> x[i] >> y[i];\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> edges[i].u >> edges[i].v;\n        edges[i].d = rounded_dist(\n            x[edges[i].u], y[edges[i].u],\n            x[edges[i].v], y[edges[i].v]\n        );\n    }\n\n    // Build the backbone tree by Kruskal on d.\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (edges[a].d != edges[b].d) return edges[a].d < edges[b].d;\n        return a < b;\n    });\n\n    vector<char> is_base(M, 0);\n    DSU dsu_build(N);\n    int base_cnt = 0;\n    for (int id : ord) {\n        if (dsu_build.unite(edges[id].u, edges[id].v)) {\n            is_base[id] = 1;\n            ++base_cnt;\n        }\n    }\n\n    // Tree structure of the backbone.\n    vector<vector<pair<int,int>>> g(N);\n    for (int id = 0; id < M; ++id) {\n        if (!is_base[id]) continue;\n        int u = edges[id].u, v = edges[id].v;\n        g[u].push_back({v, id});\n        g[v].push_back({u, id});\n    }\n\n    vector<int> parent(N, -1), depth(N, 0), pedge(N, -1);\n    {\n        stack<int> st;\n        st.push(0);\n        parent[0] = 0;\n        while (!st.empty()) {\n            int v = st.top();\n            st.pop();\n            for (auto [to, id] : g[v]) {\n                if (to == parent[v]) continue;\n                parent[to] = v;\n                depth[to] = depth[v] + 1;\n                pedge[to] = id;\n                st.push(to);\n            }\n        }\n    }\n\n    DSU dsu(N);\n    vector<char> base_seen(M, 0);\n\n    int seen_base_cnt = 0;\n    int extra_cnt = 0;\n    constexpr int EXTRA_LIMIT = 120;\n\n    auto evaluate_path = [&](int u, int v) {\n        int best_d = -1;\n        int best_id = -1;\n        int cnt_future = 0;\n\n        auto consider_edge = [&](int id) {\n            if (id < 0) return;\n            if (!base_seen[id]) {\n                ++cnt_future;\n                if (edges[id].d > best_d) {\n                    best_d = edges[id].d;\n                    best_id = id;\n                }\n            }\n        };\n\n        while (depth[u] > depth[v]) {\n            consider_edge(pedge[u]);\n            u = parent[u];\n        }\n        while (depth[v] > depth[u]) {\n            consider_edge(pedge[v]);\n            v = parent[v];\n        }\n        while (u != v) {\n            consider_edge(pedge[u]);\n            consider_edge(pedge[v]);\n            u = parent[u];\n            v = parent[v];\n        }\n        return tuple<int,int,int>(best_d, best_id, cnt_future);\n    };\n\n    for (int i = 0; i < M; ++i) {\n        int l;\n        cin >> l;\n\n        bool take = false;\n\n        if (is_base[i]) {\n            base_seen[i] = 1;\n            ++seen_base_cnt;\n\n            // Always keep backbone edges if they still connect components.\n            if (dsu.unite(edges[i].u, edges[i].v)) {\n                take = true;\n            }\n        } else {\n            // Conservative extra-edge policy.\n            if (extra_cnt < EXTRA_LIMIT && seen_base_cnt < base_cnt) {\n                if (dsu.find(edges[i].u) != dsu.find(edges[i].v)) {\n                    auto [best_d, best_id, cnt_future] = evaluate_path(edges[i].u, edges[i].v);\n\n                    // Only consider if there is still a future backbone edge on the path.\n                    if (best_d >= 30 && best_id != -1) {\n                        double thr = 1.10\n                                   + 0.02 * min(cnt_future, 5)\n                                   + 0.04 * (double)(base_cnt - seen_base_cnt) / base_cnt;\n\n                        if (best_d >= 50)  thr += 0.03;\n                        if (best_d >= 100) thr += 0.04;\n                        if (best_d >= 200) thr += 0.04;\n                        thr = min(thr, 1.38);\n\n                        if ((double)l <= thr * (double)best_d) {\n                            if (dsu.unite(edges[i].u, edges[i].v)) {\n                                take = true;\n                                ++extra_cnt;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        cout << (take ? 1 : 0) << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstatic const int B = 30;\n\nstruct Candidate {\n    bool horizontal;\n    int line;       // row if horizontal, column if vertical\n    int side;       // -1 or +1\n    int variant;    // segment partition variant\n    int area = 0;\n    int petCount = 0;\n    int nearRisk = 0;\n    int prepTurns = 0;\n    long double score = -1e100L;\n    vector<pair<int,int>> segs; // intervals [l, r] on the barrier line\n};\n\nstatic inline int manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nstatic inline int clampi(int v, int l, int r) {\n    return max(l, min(r, v));\n}\n\nstatic bool feasibleMatching(\n    const vector<vector<int>>& cost,\n    int T,\n    vector<int>& matchHumanToSeg\n) {\n    int n = (int)cost.size();\n    vector<int> matchSegToHuman(n, -1);\n\n    function<bool(int, vector<int>&)> dfs = [&](int h, vector<int>& seen) -> bool {\n        for (int s = 0; s < n; ++s) {\n            if (cost[h][s] > T || seen[s]) continue;\n            seen[s] = 1;\n            if (matchSegToHuman[s] == -1 || dfs(matchSegToHuman[s], seen)) {\n                matchSegToHuman[s] = h;\n                return true;\n            }\n        }\n        return false;\n    };\n\n    for (int h = 0; h < n; ++h) {\n        vector<int> seen(n, 0);\n        if (!dfs(h, seen)) return false;\n    }\n\n    matchHumanToSeg.assign(n, -1);\n    for (int s = 0; s < n; ++s) {\n        matchHumanToSeg[matchSegToHuman[s]] = s;\n    }\n    return true;\n}\n\nstatic int minmaxMatching(\n    const vector<vector<int>>& cost,\n    vector<int>& matchHumanToSeg\n) {\n    int n = (int)cost.size();\n    int lo = 0, hi = 60;\n    while (lo < hi) {\n        int mid = (lo + hi) / 2;\n        vector<int> tmp;\n        if (feasibleMatching(cost, mid, tmp)) hi = mid;\n        else lo = mid + 1;\n    }\n    feasibleMatching(cost, lo, matchHumanToSeg);\n    return lo;\n}\n\nstatic vector<pair<int,int>> buildSegments(int M, int variant) {\n    int L = 30;\n    int base = L / M, rem = L % M;\n    vector<int> len(M, base);\n\n    if (variant == 0) {\n        for (int i = 0; i < rem; ++i) len[i]++;\n    } else if (variant == 1) {\n        for (int i = M - rem; i < M; ++i) len[i]++;\n    } else {\n        int st = (M - rem) / 2;\n        for (int i = 0; i < rem; ++i) len[st + i]++;\n    }\n\n    vector<pair<int,int>> segs;\n    int cur = 1;\n    for (int i = 0; i < M; ++i) {\n        segs.push_back({cur, cur + len[i] - 1});\n        cur += len[i];\n    }\n    return segs;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Point> pets(N);\n    vector<int> ptype(N);\n    vector<vector<int>> petOcc(B + 1, vector<int>(B + 1, 0));\n\n    for (int i = 0; i < N; ++i) {\n        cin >> pets[i].x >> pets[i].y >> ptype[i];\n        petOcc[pets[i].x][pets[i].y]++;\n    }\n\n    int M;\n    cin >> M;\n    vector<Point> humans(M);\n    for (int i = 0; i < M; ++i) cin >> humans[i].x >> humans[i].y;\n\n    vector<vector<int>> ps(B + 1, vector<int>(B + 1, 0));\n    for (int i = 1; i <= B; ++i) {\n        for (int j = 1; j <= B; ++j) {\n            ps[i][j] = petOcc[i][j] + ps[i - 1][j] + ps[i][j - 1] - ps[i - 1][j - 1];\n        }\n    }\n\n    auto sumRect = [&](int r1, int c1, int r2, int c2) -> int {\n        r1 = clampi(r1, 1, B);\n        c1 = clampi(c1, 1, B);\n        r2 = clampi(r2, 1, B);\n        c2 = clampi(c2, 1, B);\n        if (r1 > r2 || c1 > c2) return 0;\n        return ps[r2][c2] - ps[r1 - 1][c2] - ps[r2][c1 - 1] + ps[r1 - 1][c1 - 1];\n    };\n\n    auto buildCostMatrix = [&](bool horizontal, int line, int side, const vector<pair<int,int>>& segs) {\n        int n = M;\n        vector<vector<int>> cost(n, vector<int>(n, 0));\n        int sideCoord = line + side;\n\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                auto [l, r] = segs[j];\n                int d = 0;\n                if (horizontal) {\n                    d = abs(humans[i].x - sideCoord) + min(abs(humans[i].y - l), abs(humans[i].y - r));\n                } else {\n                    d = abs(humans[i].y - sideCoord) + min(abs(humans[i].x - l), abs(humans[i].x - r));\n                }\n                cost[i][j] = d;\n            }\n        }\n        return cost;\n    };\n\n    auto evaluate = [&](bool horizontal, int line, int side, int variant) -> optional<Candidate> {\n        Candidate cand;\n        cand.horizontal = horizontal;\n        cand.line = line;\n        cand.side = side;\n        cand.variant = variant;\n\n        // Final reachable region\n        if (horizontal) {\n            if (side == -1) {\n                cand.area = (line - 1) * B;\n                cand.petCount = sumRect(1, 1, line - 1, B);\n            } else {\n                cand.area = (B - line) * B;\n                cand.petCount = sumRect(line + 1, 1, B, B);\n            }\n        } else {\n            if (side == -1) {\n                cand.area = (line - 1) * B;\n                cand.petCount = sumRect(1, 1, B, line - 1);\n            } else {\n                cand.area = (B - line) * B;\n                cand.petCount = sumRect(1, line + 1, B, B);\n            }\n        }\n\n        if (cand.area <= 0) return nullopt;\n\n        // Risk near the barrier line itself\n        int risk = 0;\n        for (auto &p : pets) {\n            int d = horizontal ? abs(p.x - line) : abs(p.y - line);\n            if (d <= 2) risk += (3 - d); // d=0 -> 3, d=1 -> 2, d=2 -> 1\n        }\n        cand.nearRisk = risk;\n\n        cand.segs = buildSegments(M, variant);\n\n        // Build cost matrix and estimate prep time by min-max matching\n        auto cost = buildCostMatrix(horizontal, line, side, cand.segs);\n        vector<int> matchHumanToSeg;\n        cand.prepTurns = minmaxMatching(cost, matchHumanToSeg);\n\n        long double raw = (long double)cand.area * exp2l(-(long double)cand.petCount);\n        long double timeFactor = expl(-0.02L * (long double)cand.prepTurns);\n        long double riskFactor = 1.0L / (1.0L + 0.15L * (long double)cand.nearRisk);\n        cand.score = raw * timeFactor * riskFactor;\n\n        return cand;\n    };\n\n    optional<Candidate> best;\n\n    auto better = [&](const Candidate& a, const Candidate& b) {\n        const long double EPS = 1e-15L;\n        if (fabsl(a.score - b.score) > EPS) return a.score > b.score;\n        if (a.prepTurns != b.prepTurns) return a.prepTurns < b.prepTurns;\n        if (a.nearRisk != b.nearRisk) return a.nearRisk < b.nearRisk;\n        if (a.petCount != b.petCount) return a.petCount < b.petCount;\n        return a.area > b.area;\n    };\n\n    for (int line = 2; line <= 29; ++line) {\n        for (int side : {-1, +1}) {\n            for (int variant = 0; variant < 3; ++variant) {\n                auto cand = evaluate(true, line, side, variant);\n                if (!cand) continue;\n                if (!best || better(*cand, *best)) best = *cand;\n            }\n        }\n    }\n    for (int line = 2; line <= 29; ++line) {\n        for (int side : {-1, +1}) {\n            for (int variant = 0; variant < 3; ++variant) {\n                auto cand = evaluate(false, line, side, variant);\n                if (!cand) continue;\n                if (!best || better(*cand, *best)) best = *cand;\n            }\n        }\n    }\n\n    if (!best) {\n        for (int turn = 0; turn < 300; ++turn) {\n            cout << string(M, '.') << '\\n' << flush;\n            for (int i = 0; i < N; ++i) {\n                string s;\n                cin >> s;\n            }\n        }\n        return 0;\n    }\n\n    Candidate cand = *best;\n    int sideCoord = cand.line + cand.side;\n\n    // Recompute assignment for chosen candidate\n    auto cost = buildCostMatrix(cand.horizontal, cand.line, cand.side, cand.segs);\n    vector<int> matchHumanToSeg;\n    minmaxMatching(cost, matchHumanToSeg);\n\n    struct Builder {\n        int seg = -1;\n        Point start{};\n        Point pos{};\n        int cur = 0;       // current column (horizontal) or row (vertical)\n        int l = 0, r = 0;\n        int dir = 0;       // +1 or -1\n        bool horizontal = true;\n        bool needWall = true;\n        bool done = false;\n        int built = 0;\n    };\n\n    vector<Builder> builders(M);\n    for (int h = 0; h < M; ++h) {\n        int s = matchHumanToSeg[h];\n        auto [l, r] = cand.segs[s];\n        int dL, dR;\n        if (cand.horizontal) {\n            dL = abs(humans[h].x - sideCoord) + abs(humans[h].y - l);\n            dR = abs(humans[h].x - sideCoord) + abs(humans[h].y - r);\n            builders[h].horizontal = true;\n            builders[h].l = l;\n            builders[h].r = r;\n            if (dL <= dR) {\n                builders[h].start = {sideCoord, l};\n                builders[h].pos = builders[h].start;\n                builders[h].cur = l;\n                builders[h].dir = +1;\n            } else {\n                builders[h].start = {sideCoord, r};\n                builders[h].pos = builders[h].start;\n                builders[h].cur = r;\n                builders[h].dir = -1;\n            }\n        } else {\n            dL = abs(humans[h].x - l) + abs(humans[h].y - sideCoord);\n            dR = abs(humans[h].x - r) + abs(humans[h].y - sideCoord);\n            builders[h].horizontal = false;\n            builders[h].l = l;\n            builders[h].r = r;\n            if (dL <= dR) {\n                builders[h].start = {l, sideCoord};\n                builders[h].pos = builders[h].start;\n                builders[h].cur = l;\n                builders[h].dir = +1;\n            } else {\n                builders[h].start = {r, sideCoord};\n                builders[h].pos = builders[h].start;\n                builders[h].cur = r;\n                builders[h].dir = -1;\n            }\n        }\n    }\n\n    vector<Point> curHumans = humans;\n    vector<vector<int>> humanOcc(B + 1, vector<int>(B + 1, 0));\n\n    auto rebuildHumanOcc = [&]() {\n        for (int i = 1; i <= B; ++i) fill(humanOcc[i].begin(), humanOcc[i].end(), 0);\n        for (auto &p : curHumans) humanOcc[p.x][p.y]++;\n    };\n    rebuildHumanOcc();\n\n    auto inBoard = [&](int x, int y) -> bool {\n        return 1 <= x && x <= B && 1 <= y && y <= B;\n    };\n\n    auto safeToWall = [&](const Point& q) -> bool {\n        if (!inBoard(q.x, q.y)) return false;\n        if (humanOcc[q.x][q.y] > 0) return false;\n        if (petOcc[q.x][q.y] > 0) return false;\n        static int dx[4] = {-1, 1, 0, 0};\n        static int dy[4] = {0, 0, -1, 1};\n        for (int dir = 0; dir < 4; ++dir) {\n            int nx = q.x + dx[dir], ny = q.y + dy[dir];\n            if (inBoard(nx, ny) && petOcc[nx][ny] > 0) return false;\n        }\n        return true;\n    };\n\n    auto moveToward = [&](Point& p, const Point& t) -> char {\n        if (p.x < t.x) { ++p.x; return 'D'; }\n        if (p.x > t.x) { --p.x; return 'U'; }\n        if (p.y < t.y) { ++p.y; return 'R'; }\n        if (p.y > t.y) { --p.y; return 'L'; }\n        return '.';\n    };\n\n    for (int turn = 0; turn < 300; ++turn) {\n        string out(M, '.');\n        vector<Point> nextHumans = curHumans;\n\n        if (turn < cand.prepTurns) {\n            // Travel phase: move everyone to the assigned segment endpoint.\n            for (int i = 0; i < M; ++i) {\n                out[i] = moveToward(nextHumans[i], builders[i].start);\n            }\n        } else {\n            // Build phase: each human builds its own segment.\n            for (int i = 0; i < M; ++i) {\n                if (builders[i].done) {\n                    out[i] = '.';\n                    continue;\n                }\n\n                if (builders[i].needWall) {\n                    Point q;\n                    if (cand.horizontal) q = {cand.line, builders[i].cur};\n                    else q = {builders[i].cur, cand.line};\n\n                    if (safeToWall(q)) {\n                        out[i] = cand.horizontal\n                            ? (cand.side == -1 ? 'd' : 'u')\n                            : (cand.side == -1 ? 'r' : 'l');\n                        builders[i].built++;\n                        if (builders[i].built >= (builders[i].r - builders[i].l + 1)) {\n                            builders[i].done = true;\n                        } else {\n                            builders[i].needWall = false;\n                        }\n                    } else {\n                        out[i] = '.';\n                    }\n                } else {\n                    out[i] = cand.horizontal\n                        ? (builders[i].dir == +1 ? 'R' : 'L')\n                        : (builders[i].dir == +1 ? 'D' : 'U');\n                    if (cand.horizontal) nextHumans[i].y += builders[i].dir;\n                    else nextHumans[i].x += builders[i].dir;\n                    builders[i].cur += builders[i].dir;\n                    builders[i].needWall = true;\n                }\n            }\n        }\n\n        cout << out << '\\n' << flush;\n\n        curHumans = nextHumans;\n        rebuildHumanOcc();\n\n        vector<string> mv(N);\n        for (int i = 0; i < N; ++i) cin >> mv[i];\n\n        for (int i = 0; i < N; ++i) {\n            int x = pets[i].x, y = pets[i].y;\n            for (char ch : mv[i]) {\n                if (ch == 'U') --x;\n                else if (ch == 'D') ++x;\n                else if (ch == 'L') --y;\n                else if (ch == 'R') ++y;\n            }\n            pets[i] = {x, y};\n        }\n\n        for (int i = 1; i <= B; ++i) fill(petOcc[i].begin(), petOcc[i].end(), 0);\n        for (auto &p : pets) petOcc[p.x][p.y]++;\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int MAXL = 200;\nstatic constexpr double EPS = 1e-12;\n\nusing Dist = array<double, N>;\n\n// ---------------- Global input / board ----------------\nint si, sj, ti, tj;\ndouble p, qprob;\nvector<string> hwall(20), vwall(19);\n\n// ---------------- Global helpers ----------------\nint startPos, goalPos;\nint moveTo[4][N];\nint distGoal[N];\nint c2d[256];\nchar dch[4] = {'U', 'D', 'L', 'R'};\n\nchrono::steady_clock::time_point startTime;\n\ninline bool timeOver() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count() > 1.85;\n}\n\ninline int id(int i, int j) { return i * W + j; }\ninline pair<int, int> coord(int x) { return {x / W, x % W}; }\n\nbool open_move(int pos, int dir) {\n    int i = pos / W, j = pos % W;\n    if (dir == 0) return i > 0 && vwall[i - 1][j] == '0';\n    if (dir == 1) return i + 1 < H && vwall[i][j] == '0';\n    if (dir == 2) return j > 0 && hwall[i][j - 1] == '0';\n    if (dir == 3) return j + 1 < W && hwall[i][j] == '0';\n    return false;\n}\n\nchar invDir(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 c;\n}\n\nstring reversePath(const string& s) {\n    string t;\n    t.reserve(s.size());\n    for (int i = (int)s.size() - 1; i >= 0; --i) t.push_back(invDir(s[i]));\n    return t;\n}\n\nstring fullify(const string& s) {\n    if (s.empty()) return string(MAXL, 'R');\n    if ((int)s.size() >= MAXL) return s.substr(0, MAXL);\n    string res;\n    res.reserve(MAXL);\n    while ((int)res.size() < MAXL) {\n        int take = min<int>(MAXL - (int)res.size(), (int)s.size());\n        res.append(s.data(), take);\n    }\n    return res;\n}\n\nstring repeatToLen(const string& pat, int L = MAXL) {\n    if (pat.empty() || L <= 0) return \"\";\n    string res;\n    res.reserve(L);\n    for (int i = 0; i < L; ++i) res.push_back(pat[i % (int)pat.size()]);\n    return res;\n}\n\nstring concat2(const string& a, const string& b) {\n    string s;\n    s.reserve(min(MAXL, (int)a.size() + (int)b.size()));\n    s += a;\n    s += b;\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n    return s;\n}\n\nstring concat3(const string& a, const string& b, const string& c) {\n    string s;\n    s.reserve(min(MAXL, (int)a.size() + (int)b.size() + (int)c.size()));\n    s += a;\n    s += b;\n    s += c;\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n    return s;\n}\n\nstring stretchRuns(const string& s, const vector<int>& sched) {\n    if (s.empty()) return \"\";\n\n    vector<pair<char, int>> runs;\n    for (char c : s) {\n        if (!runs.empty() && runs.back().first == c) runs.back().second++;\n        else runs.push_back({c, 1});\n    }\n\n    string out;\n    out.reserve(MAXL);\n\n    int R = (int)runs.size();\n    int K = (int)sched.size();\n\n    for (int i = 0; i < R && (int)out.size() < MAXL; ++i) {\n        int idx = min(K - 1, (int)((1LL * i * K) / max(1, R)));\n        int factor = max(1, sched[idx]);\n        int rep = runs[i].second * factor;\n        rep = min(rep, MAXL - (int)out.size());\n        out.append(rep, runs[i].first);\n    }\n\n    if (out.empty()) out = s;\n    if ((int)out.size() < MAXL) {\n        string base = out;\n        while ((int)out.size() < MAXL) {\n            int take = min<int>(MAXL - (int)out.size(), (int)base.size());\n            out.append(base.data(), take);\n        }\n    }\n\n    if ((int)out.size() > MAXL) out.resize(MAXL);\n    return out;\n}\n\nstring randomRunString(mt19937_64& rng) {\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    auto pick = [&]() -> char {\n        double x = uni(rng);\n        if (x < 0.35) return 'D';\n        if (x < 0.70) return 'R';\n        if (x < 0.85) return 'U';\n        return 'L';\n    };\n\n    string s;\n    s.reserve(MAXL);\n    char cur = pick();\n    while ((int)s.size() < MAXL) {\n        int run = 1 + (int)(rng() % 6);\n        for (int k = 0; k < run && (int)s.size() < MAXL; ++k) s.push_back(cur);\n        if ((int)s.size() < MAXL && uni(rng) > 0.55) cur = pick();\n    }\n    return s;\n}\n\n// ---------------- Best-prefix extraction ----------------\npair<string, double> bestPrefixOfString(const string& s) {\n    if (s.empty()) return {\"\", 0.0};\n\n    array<double, N> cur{}, nxt{};\n    cur.fill(0.0);\n    nxt.fill(0.0);\n    cur[startPos] = 1.0;\n\n    double score = 0.0;\n    double bestScore = 0.0;\n    int bestLen = 1;\n\n    for (int t = 0; t < (int)s.size(); ++t) {\n        if (cur[goalPos] > 1.0 - 1e-14) break;\n\n        int dir = c2d[(unsigned char)s[t]];\n        if (dir < 0) return {\"\", 0.0};\n\n        nxt.fill(0.0);\n        double reward = 401.0 - (t + 1);\n\n        for (int pos = 0; pos < N; ++pos) {\n            double pr = cur[pos];\n            if (pr == 0.0) continue;\n\n            if (pos == goalPos) {\n                nxt[goalPos] += pr;\n                continue;\n            }\n\n            nxt[pos] += pr * p;\n            int np = moveTo[dir][pos];\n            if (np == goalPos) {\n                score += pr * qprob * reward;\n                nxt[goalPos] += pr * qprob;\n            } else {\n                nxt[np] += pr * qprob;\n            }\n        }\n\n        cur.swap(nxt);\n\n        if (score > bestScore + EPS || (fabs(score - bestScore) <= EPS && t + 1 < bestLen)) {\n            bestScore = score;\n            bestLen = t + 1;\n        }\n    }\n\n    return {s.substr(0, bestLen), bestScore};\n}\n\n// ---------------- Exact evaluation ----------------\ndouble evalExact(const string& s) {\n    if (s.empty()) return 0.0;\n\n    array<double, N> cur{}, nxt{};\n    cur.fill(0.0);\n    nxt.fill(0.0);\n    cur[startPos] = 1.0;\n\n    double score = 0.0;\n    for (int t = 0; t < (int)s.size(); ++t) {\n        if (cur[goalPos] > 1.0 - 1e-14) break;\n\n        int dir = c2d[(unsigned char)s[t]];\n        if (dir < 0) return 0.0;\n\n        nxt.fill(0.0);\n        double reward = 401.0 - (t + 1);\n\n        for (int pos = 0; pos < N; ++pos) {\n            double pr = cur[pos];\n            if (pr == 0.0) continue;\n\n            if (pos == goalPos) {\n                nxt[goalPos] += pr;\n                continue;\n            }\n\n            nxt[pos] += pr * p;\n            int np = moveTo[dir][pos];\n            if (np == goalPos) {\n                score += pr * qprob * reward;\n                nxt[goalPos] += pr * qprob;\n            } else {\n                nxt[np] += pr * qprob;\n            }\n        }\n        cur.swap(nxt);\n    }\n\n    return score;\n}\n\n// ---------------- Forward / backward DP for local search ----------------\nvoid computeFB(const string& s, vector<Dist>& F, vector<Dist>& B, vector<double>& pref, double& score) {\n    int L = (int)s.size();\n    F.assign(L + 1, Dist{});\n    B.assign(L + 1, Dist{});\n    pref.assign(L + 1, 0.0);\n    for (auto& x : F) x.fill(0.0);\n    for (auto& x : B) x.fill(0.0);\n\n    F[0][startPos] = 1.0;\n    score = 0.0;\n    Dist nxt{};\n\n    for (int t = 0; t < L; ++t) {\n        int dir = c2d[(unsigned char)s[t]];\n        nxt.fill(0.0);\n        double reward = 401.0 - (t + 1);\n\n        for (int pos = 0; pos < N; ++pos) {\n            double pr = F[t][pos];\n            if (pr == 0.0) continue;\n\n            if (pos == goalPos) {\n                nxt[goalPos] += pr;\n                continue;\n            }\n\n            nxt[pos] += pr * p;\n            int np = moveTo[dir][pos];\n            if (np == goalPos) {\n                score += pr * qprob * reward;\n                nxt[goalPos] += pr * qprob;\n            } else {\n                nxt[np] += pr * qprob;\n            }\n        }\n        F[t + 1] = nxt;\n        pref[t + 1] = score;\n    }\n\n    for (int t = L - 1; t >= 0; --t) {\n        int dir = c2d[(unsigned char)s[t]];\n        double reward = 401.0 - (t + 1);\n        for (int pos = 0; pos < N; ++pos) {\n            if (pos == goalPos) {\n                B[t][pos] = 0.0;\n                continue;\n            }\n            double val = p * B[t + 1][pos];\n            int np = moveTo[dir][pos];\n            val += qprob * (np == goalPos ? reward : B[t + 1][np]);\n            B[t][pos] = val;\n        }\n    }\n}\n\ndouble evalSingleReplace(const vector<Dist>& F, const vector<Dist>& B, const vector<double>& pref, int t, int dir) {\n    double reward = 401.0 - (t + 1);\n    double res = pref[t];\n\n    for (int pos = 0; pos < N; ++pos) {\n        double pr = F[t][pos];\n        if (pr == 0.0 || pos == goalPos) continue;\n        int np = moveTo[dir][pos];\n        res += pr * (p * B[t + 1][pos] + qprob * (np == goalPos ? reward : B[t + 1][np]));\n    }\n    return res;\n}\n\ndouble evalBlock2Replace(const vector<Dist>& F, const vector<Dist>& B, const vector<double>& pref,\n                         int t, int d1, int d2) {\n    double r1 = 401.0 - (t + 1);\n    double r2 = 401.0 - (t + 2);\n    double res = pref[t];\n\n    for (int pos = 0; pos < N; ++pos) {\n        double pr = F[t][pos];\n        if (pr == 0.0 || pos == goalPos) continue;\n\n        {\n            int n2 = moveTo[d2][pos];\n            res += pr * p * (p * B[t + 2][pos] + qprob * (n2 == goalPos ? r2 : B[t + 2][n2]));\n        }\n\n        {\n            int n1 = moveTo[d1][pos];\n            if (n1 == goalPos) {\n                res += pr * qprob * r1;\n            } else {\n                int n2 = moveTo[d2][n1];\n                res += pr * qprob * (p * B[t + 2][n1] + qprob * (n2 == goalPos ? r2 : B[t + 2][n2]));\n            }\n        }\n    }\n    return res;\n}\n\n// ---------------- Path generation ----------------\nbool bfsPath(pair<int, int> A, pair<int, int> B, const array<int, 4>& order, int mask, string& out) {\n    int s = id(A.first, A.second);\n    int g = id(B.first, B.second);\n    if (s == g) {\n        out.clear();\n        return true;\n    }\n\n    vector<int> dist(N, -1), par(N, -1);\n    vector<char> pch(N, '?');\n    queue<int> q;\n    dist[s] = 0;\n    q.push(s);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == g) break;\n        for (int d : order) {\n            if (!(mask & (1 << d))) continue;\n            int nv = moveTo[d][v];\n            if (nv == v || dist[nv] != -1) continue;\n            dist[nv] = dist[v] + 1;\n            par[nv] = v;\n            pch[nv] = dch[d];\n            q.push(nv);\n        }\n    }\n\n    if (dist[g] == -1) return false;\n\n    string res;\n    for (int cur = g; cur != s; cur = par[cur]) res.push_back(pch[cur]);\n    reverse(res.begin(), res.end());\n    if ((int)res.size() > MAXL) res.resize(MAXL);\n    out = std::move(res);\n    return true;\n}\n\nstring dijkstraPath(pair<int, int> A, pair<int, int> B, const array<int, 4>& order, int mask, int turnPenalty, int devWeight) {\n    int s = id(A.first, A.second);\n    int g = id(B.first, B.second);\n    if (s == g) return \"\";\n\n    auto sid = [&](int pos, int prev) { return pos * 5 + prev; };\n\n    const long long INF = (1LL << 60);\n    int S = N * 5;\n    vector<long long> dist(S, INF);\n    vector<int> par(S, -1);\n    vector<char> pch(S, '?');\n\n    int st = sid(s, 4);\n    dist[st] = 0;\n    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;\n    pq.push({0, st});\n\n    while (!pq.empty()) {\n        auto [cd, cur] = pq.top();\n        pq.pop();\n        if (cd != dist[cur]) continue;\n\n        int pos = cur / 5;\n        int prev = cur % 5;\n\n        for (int d : order) {\n            if (!(mask & (1 << d))) continue;\n            int np = moveTo[d][pos];\n            if (np == pos) continue;\n\n            auto [ni, nj] = coord(np);\n            long long nd = cd + 1000;\n            if (prev != 4 && prev != d) nd += turnPenalty;\n            nd += 1LL * devWeight *\n                  llabs(1LL * (ni - A.first) * (B.second - A.second) -\n                        1LL * (nj - A.second) * (B.first - A.first));\n\n            int ns = sid(np, d);\n            if (nd < dist[ns]) {\n                dist[ns] = nd;\n                par[ns] = cur;\n                pch[ns] = dch[d];\n                pq.push({nd, ns});\n            }\n        }\n    }\n\n    int best = -1;\n    long long bestd = INF;\n    for (int prev = 0; prev < 4; ++prev) {\n        int gs = sid(g, prev);\n        if (dist[gs] < bestd) {\n            bestd = dist[gs];\n            best = gs;\n        }\n    }\n    if (best == -1 || bestd == INF) return \"\";\n\n    string res;\n    for (int cur = best; cur != st; cur = par[cur]) res.push_back(pch[cur]);\n    reverse(res.begin(), res.end());\n    if ((int)res.size() > MAXL) res.resize(MAXL);\n    return res;\n}\n\nvector<pair<int, int>> sampleWaypoints(double frac) {\n    int ci = (int)llround(si + (ti - si) * frac);\n    int cj = (int)llround(sj + (tj - sj) * frac);\n\n    vector<pair<int, int>> pts;\n    vector<pair<int, int>> cand = {\n        {ci, cj}, {ci + 1, cj}, {ci - 1, cj}, {ci, cj + 1}, {ci, cj - 1}\n    };\n\n    for (auto [i, j] : cand) {\n        i = max(0, min(19, i));\n        j = max(0, min(19, j));\n        pts.push_back({i, j});\n    }\n\n    sort(pts.begin(), pts.end());\n    pts.erase(unique(pts.begin(), pts.end()), pts.end());\n    return pts;\n}\n\n// ---------------- Candidate pooling ----------------\nstruct BaseCand {\n    string s;\n    double score = 0.0;\n    int fam = 0;\n};\n\nbool betterScore(double a, double b) {\n    return a > b + EPS;\n}\n\nvoid addUnique(vector<string>& pool, unordered_set<string>& seen, string s) {\n    if (s.empty()) return;\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n    if (seen.insert(s).second) pool.push_back(std::move(s));\n}\n\nvoid addExpandedForms(const string& raw, const vector<vector<int>>& schedules,\n                      unordered_set<string>& seen, vector<string>& pool) {\n    if (raw.empty()) return;\n\n    vector<string> forms = {\n        raw,\n        reversePath(raw),\n        concat2(raw, reversePath(raw)),\n        concat2(reversePath(raw), raw),\n        concat3(raw, reversePath(raw), raw),\n    };\n\n    for (const string& form0 : forms) {\n        if (form0.empty()) continue;\n        string f = fullify(form0);\n        addUnique(pool, seen, f);\n\n        auto bp = bestPrefixOfString(f).first;\n        if (!bp.empty()) {\n            addUnique(pool, seen, fullify(bp));\n            addUnique(pool, seen, fullify(concat2(bp, reversePath(bp))));\n        }\n\n        for (const auto& sch : schedules) {\n            string st = stretchRuns(f, sch);\n            addUnique(pool, seen, fullify(st));\n        }\n    }\n}\n\nvector<BaseCand> selectDiverseBases(vector<BaseCand> v, int perFam = 3, int totalLimit = 12) {\n    sort(v.begin(), v.end(), [](const BaseCand& a, const BaseCand& b) {\n        if (fabs(a.score - b.score) > EPS) return a.score > b.score;\n        return a.s < b.s;\n    });\n\n    vector<BaseCand> res;\n    unordered_set<string> used;\n    used.reserve(v.size() * 2 + 1);\n    array<int, 4> famCnt{};\n\n    for (int fam = 0; fam < 4; ++fam) {\n        for (const auto& c : v) {\n            if (c.fam != fam) continue;\n            if (famCnt[fam] >= perFam) break;\n            if (used.insert(c.s).second) {\n                res.push_back(c);\n                famCnt[fam]++;\n            }\n        }\n    }\n\n    for (const auto& c : v) {\n        if ((int)res.size() >= totalLimit) break;\n        if (used.insert(c.s).second) res.push_back(c);\n    }\n\n    return res;\n}\n\n// ---------------- Local optimization ----------------\nstring mutateFixedLength(const string& s, mt19937_64& rng) {\n    string t = s;\n    auto randChar = [&]() -> char { return dch[rng() % 4]; };\n\n    int op = (int)(rng() % 6);\n    if (op == 0) {\n        int pos = (int)(rng() % t.size());\n        t[pos] = randChar();\n    } else if (op == 1) {\n        int l = (int)(rng() % t.size());\n        int r = min<int>(t.size(), l + 1 + (int)(rng() % 8));\n        for (int i = l; i < r; ++i) t[i] = randChar();\n    } else if (op == 2) {\n        int i = (int)(rng() % t.size());\n        int j = (int)(rng() % t.size());\n        if (i != j) swap(t[i], t[j]);\n    } else if (op == 3) {\n        int l = (int)(rng() % t.size());\n        int r = (int)(rng() % t.size());\n        if (l > r) swap(l, r);\n        reverse(t.begin() + l, t.begin() + r + 1);\n    } else if (op == 4) {\n        int l = (int)(rng() % t.size());\n        int len = min<int>(t.size() - l, 2 + (int)(rng() % 10));\n        string pat = (rng() & 1) ? string(\"DR\") : string(\"RD\");\n        string rep;\n        rep.reserve(len);\n        while ((int)rep.size() < len) rep += pat;\n        rep.resize(len);\n        for (int i = 0; i < len; ++i) t[l + i] = rep[i];\n    } else {\n        int l = (int)(rng() % t.size());\n        int r = (int)(rng() % t.size());\n        if (l > r) swap(l, r);\n        if (l != r) rotate(t.begin() + l, t.begin() + ((l + r) / 2 + 1), t.begin() + r + 1);\n    }\n\n    if ((int)t.size() > MAXL) t.resize(MAXL);\n    return t;\n}\n\nstring crossover(const string& a, const string& b, mt19937_64& rng) {\n    string c = a;\n    int mode = (int)(rng() % 3);\n\n    if (mode == 0) {\n        int cut = (int)(rng() % MAXL);\n        for (int i = cut; i < MAXL; ++i) c[i] = b[i];\n    } else if (mode == 1) {\n        int block = 3 + (int)(rng() % 13);\n        bool takeA = true;\n        for (int i = 0; i < MAXL; i += block) {\n            const string& src = takeA ? a : b;\n            for (int j = 0; j < block && i + j < MAXL; ++j) c[i + j] = src[i + j];\n            takeA = !takeA;\n        }\n    } else {\n        int l = (int)(rng() % MAXL);\n        int r = (int)(rng() % MAXL);\n        if (l > r) swap(l, r);\n        for (int i = l; i <= r; ++i) c[i] = b[i];\n    }\n\n    return c;\n}\n\nstring optimizeString(string s) {\n    double curScore = evalExact(s);\n    vector<Dist> F, B;\n    vector<double> pref;\n\n    auto tryPrefixRepeat = [&]() {\n        auto bp = bestPrefixOfString(s).first;\n        if (bp.empty()) return;\n\n        string c1 = fullify(bp);\n        double sc1 = evalExact(c1);\n\n        string c2 = fullify(concat2(bp, reversePath(bp)));\n        double sc2 = evalExact(c2);\n\n        if (betterScore(sc1, curScore) && sc1 >= sc2) {\n            s = std::move(c1);\n            curScore = sc1;\n        } else if (betterScore(sc2, curScore)) {\n            s = std::move(c2);\n            curScore = sc2;\n        }\n    };\n\n    tryPrefixRepeat();\n\n    for (int round = 0; round < 4 && !timeOver(); ++round) {\n        double score = 0.0;\n        computeFB(s, F, B, pref, score);\n        curScore = score;\n\n        string bestS = s;\n        double bestScore = curScore;\n\n        // single-char replacement\n        for (int t = 0; t < (int)s.size(); ++t) {\n            int oldd = c2d[(unsigned char)s[t]];\n            for (int d = 0; d < 4; ++d) {\n                if (d == oldd) continue;\n                double val = evalSingleReplace(F, B, pref, t, d);\n                if (betterScore(val, bestScore)) {\n                    bestScore = val;\n                    bestS = s;\n                    bestS[t] = dch[d];\n                }\n            }\n        }\n\n        // two-char replacement\n        int step = (int)s.size() <= 120 ? 1 : 2;\n        for (int t = 0; t + 1 < (int)s.size(); t += step) {\n            for (int d1 = 0; d1 < 4; ++d1) {\n                for (int d2 = 0; d2 < 4; ++d2) {\n                    double val = evalBlock2Replace(F, B, pref, t, d1, d2);\n                    if (betterScore(val, bestScore)) {\n                        bestScore = val;\n                        bestS = s;\n                        bestS[t] = dch[d1];\n                        bestS[t + 1] = dch[d2];\n                    }\n                }\n            }\n        }\n\n        // sampled adjacent swaps\n        if (!timeOver()) {\n            for (int t = 0; t + 1 < (int)s.size(); t += 3) {\n                string cand = s;\n                swap(cand[t], cand[t + 1]);\n                double val = evalExact(cand);\n                if (betterScore(val, bestScore)) {\n                    bestScore = val;\n                    bestS = std::move(cand);\n                }\n            }\n        }\n\n        if (betterScore(bestScore, curScore)) {\n            s = std::move(bestS);\n            curScore = bestScore;\n            tryPrefixRepeat();\n        } else {\n            break;\n        }\n    }\n\n    // Random fixed-length hill-climbing / annealing\n    if (!timeOver()) {\n        uint64_t seed =\n            0x9e3779b97f4a7c15ULL ^\n            (uint64_t(si) << 1) ^ (uint64_t(sj) << 7) ^\n            (uint64_t(ti) << 13) ^ (uint64_t(tj) << 17) ^\n            (uint64_t)(p * 1000000.0) ^ (uint64_t)s.size();\n\n        mt19937_64 rng(seed);\n        double cur = evalExact(s);\n        double temp = 2.5;\n\n        for (int it = 0; it < 60 && !timeOver(); ++it) {\n            string t = mutateFixedLength(s, rng);\n            double val = evalExact(t);\n\n            bool accept = false;\n            if (val > cur + EPS) accept = true;\n            else {\n                double prob = exp((val - cur) / max(1e-6, temp));\n                double x = (rng() & 0xFFFF) / 65535.0;\n                if (x < prob) accept = true;\n            }\n\n            if (accept) {\n                s = std::move(t);\n                cur = val;\n            }\n            temp *= 0.96;\n        }\n\n        curScore = evalExact(s);\n        tryPrefixRepeat();\n    }\n\n    // Final exact polish\n    for (int round = 0; round < 2 && !timeOver(); ++round) {\n        double score = 0.0;\n        computeFB(s, F, B, pref, score);\n        curScore = score;\n\n        string bestS = s;\n        double bestScore = curScore;\n\n        for (int t = 0; t < (int)s.size(); ++t) {\n            int oldd = c2d[(unsigned char)s[t]];\n            for (int d = 0; d < 4; ++d) {\n                if (d == oldd) continue;\n                double val = evalSingleReplace(F, B, pref, t, d);\n                if (betterScore(val, bestScore)) {\n                    bestScore = val;\n                    bestS = s;\n                    bestS[t] = dch[d];\n                }\n            }\n        }\n\n        if (betterScore(bestScore, curScore)) {\n            s = std::move(bestS);\n            curScore = bestScore;\n        } else {\n            break;\n        }\n    }\n\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n    return s;\n}\n\n// ---------------- Main ----------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    startTime = chrono::steady_clock::now();\n\n    cin >> si >> sj >> ti >> tj >> p;\n    qprob = 1.0 - p;\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    startPos = id(si, sj);\n    goalPos = id(ti, tj);\n\n    for (int i = 0; i < 256; ++i) c2d[i] = -1;\n    c2d[(unsigned char)'U'] = 0;\n    c2d[(unsigned char)'D'] = 1;\n    c2d[(unsigned char)'L'] = 2;\n    c2d[(unsigned char)'R'] = 3;\n\n    for (int pos = 0; pos < N; ++pos) {\n        for (int d = 0; d < 4; ++d) {\n            if (open_move(pos, d)) {\n                auto [i, j] = coord(pos);\n                int ni = i + (d == 1) - (d == 0);\n                int nj = j + (d == 3) - (d == 2);\n                moveTo[d][pos] = id(ni, nj);\n            } else {\n                moveTo[d][pos] = pos;\n            }\n        }\n    }\n\n    // Distances from goal for heuristics\n    fill(distGoal, distGoal + N, -1);\n    {\n        queue<int> q;\n        distGoal[goalPos] = 0;\n        q.push(goalPos);\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int nv = moveTo[d][v];\n                if (nv == v || distGoal[nv] != -1) continue;\n                distGoal[nv] = distGoal[v] + 1;\n                q.push(nv);\n            }\n        }\n    }\n\n    array<array<int, 4>, 4> orders = {{\n        array<int, 4>{1, 3, 0, 2},\n        array<int, 4>{3, 1, 0, 2},\n        array<int, 4>{1, 3, 2, 0},\n        array<int, 4>{3, 1, 2, 0}\n    }};\n\n    vector<BaseCand> bases;\n    auto addBase = [&](int fam, string s) {\n        if (s.empty()) return;\n        if ((int)s.size() > MAXL) s.resize(MAXL);\n        BaseCand c;\n        c.s = std::move(s);\n        c.score = evalExact(c.s);\n        c.fam = fam;\n        bases.push_back(std::move(c));\n    };\n\n    // Family 0: shortest / turn-penalized paths\n    {\n        string s;\n        for (const auto& ord : orders) {\n            if (bfsPath({si, sj}, {ti, tj}, ord, 15, s)) addBase(0, s);\n            if (bfsPath({si, sj}, {ti, tj}, ord, (1 << 1) | (1 << 3), s)) addBase(0, s);\n\n            for (int tp : {0, 15, 60, 180}) {\n                for (int dw : {0, 1, 3}) {\n                    addBase(0, dijkstraPath({si, sj}, {ti, tj}, ord, 15, tp, dw));\n                    addBase(0, dijkstraPath({si, sj}, {ti, tj}, ord, (1 << 1) | (1 << 3), tp, dw));\n                }\n            }\n        }\n    }\n\n    // Family 1: waypoint concatenations\n    {\n        auto mids1 = sampleWaypoints(0.25);\n        auto mids2 = sampleWaypoints(0.50);\n        auto mids3 = sampleWaypoints(0.75);\n\n        vector<pair<int, int>> allmids;\n        allmids.insert(allmids.end(), mids1.begin(), mids1.end());\n        allmids.insert(allmids.end(), mids2.begin(), mids2.end());\n        allmids.insert(allmids.end(), mids3.begin(), mids3.end());\n        sort(allmids.begin(), allmids.end());\n        allmids.erase(unique(allmids.begin(), allmids.end()), allmids.end());\n\n        for (auto w : allmids) {\n            for (const auto& ord : orders) {\n                string a = dijkstraPath({si, sj}, w, ord, 15, 60, 2);\n                string b = dijkstraPath(w, {ti, tj}, ord, 15, 60, 2);\n                if (!a.empty() && !b.empty()) addBase(1, concat2(a, b));\n            }\n        }\n\n        for (auto w1 : mids1) {\n            for (auto w2 : mids3) {\n                for (const auto& ord : orders) {\n                    string a = dijkstraPath({si, sj}, w1, ord, 15, 60, 2);\n                    string b = dijkstraPath(w1, w2, ord, 15, 60, 2);\n                    string c = dijkstraPath(w2, {ti, tj}, ord, 15, 60, 2);\n                    if (!a.empty() && !b.empty() && !c.empty()) addBase(1, concat3(a, b, c));\n                }\n            }\n        }\n    }\n\n    // Family 2: periodic patterns\n    {\n        vector<string> pats = {\n            \"D\", \"R\", \"DR\", \"RD\", \"DDRR\", \"RRDD\", \"DRDR\", \"RDRD\",\n            \"DRDRDR\", \"RDRDRD\", \"DURD\", \"RDLU\", \"DLUR\", \"URDL\"\n        };\n        for (const string& pat : pats) addBase(2, repeatToLen(pat, MAXL));\n    }\n\n    // Family 3: random run-heavy strings\n    {\n        uint64_t seed =\n            0x9e3779b97f4a7c15ULL ^\n            (uint64_t(si) << 1) ^ (uint64_t(sj) << 7) ^\n            (uint64_t(ti) << 13) ^ (uint64_t(tj) << 17) ^\n            (uint64_t)(p * 1000000.0);\n\n        mt19937_64 rng(seed);\n        for (int i = 0; i < 8; ++i) addBase(3, randomRunString(rng));\n    }\n\n    if (bases.empty()) {\n        cout << string(MAXL, 'R') << '\\n';\n        return 0;\n    }\n\n    // Diverse subset\n    bases = selectDiverseBases(std::move(bases), 3, 12);\n\n    // Stretch schedules depending on p\n    vector<vector<int>> schedules;\n    if (p >= 0.40) {\n        schedules = {\n            {4, 4, 3, 3, 2, 2},\n            {4, 3, 3, 2, 2, 1},\n            {3, 3, 2, 2, 1, 1},\n            {2, 2, 2, 2, 2, 2}\n        };\n    } else if (p >= 0.25) {\n        schedules = {\n            {3, 3, 2, 2, 1, 1},\n            {3, 2, 2, 1, 1, 1},\n            {2, 2, 2, 1, 1, 1},\n            {2, 2, 1, 1, 1, 1}\n        };\n    } else {\n        schedules = {\n            {2, 2, 2, 1, 1, 1},\n            {2, 2, 1, 1, 1, 1},\n            {2, 1, 1, 1, 1, 1},\n            {1, 1, 1, 1, 1, 1}\n        };\n    }\n\n    // Build candidate pool\n    vector<string> pool;\n    unordered_set<string> seen;\n    pool.reserve(800);\n    seen.reserve(8000);\n\n    for (const auto& b : bases) {\n        addExpandedForms(b.s, schedules, seen, pool);\n    }\n\n    // Pairwise concatenations of strong bases\n    int K = min<int>(6, bases.size());\n    for (int i = 0; i < K; ++i) {\n        for (int j = 0; j < K; ++j) {\n            if (i == j) continue;\n            addExpandedForms(concat2(bases[i].s, bases[j].s), schedules, seen, pool);\n            addExpandedForms(concat3(bases[i].s, bases[j].s, bases[i].s), schedules, seen, pool);\n        }\n    }\n\n    if (pool.empty()) pool.push_back(string(MAXL, 'R'));\n\n    // Exact score all candidates\n    vector<pair<double, string>> scored;\n    scored.reserve(pool.size());\n    for (const auto& s : pool) scored.push_back({evalExact(s), s});\n\n    sort(scored.begin(), scored.end(), [](const auto& A, const auto& B) {\n        if (fabs(A.first - B.first) > EPS) return A.first > B.first;\n        return A.second.size() < B.second.size();\n    });\n\n    string bestAns = scored.empty() ? string(MAXL, 'R') : scored.front().second;\n    double bestScore = scored.empty() ? 0.0 : scored.front().first;\n\n    // Local optimization on the best few\n    int take = min<int>(8, scored.size());\n    vector<pair<double, string>> elite;\n    unordered_set<string> seenElite;\n    seenElite.reserve(128);\n\n    auto addElite = [&](const string& s) {\n        if (s.empty()) return;\n        if (seenElite.insert(s).second) {\n            elite.push_back({evalExact(s), s});\n            sort(elite.begin(), elite.end(), [](const auto& A, const auto& B) {\n                if (fabs(A.first - B.first) > EPS) return A.first > B.first;\n                return A.second < B.second;\n            });\n            if ((int)elite.size() > 24) elite.resize(24);\n        }\n    };\n\n    for (int i = 0; i < take && !timeOver(); ++i) {\n        string s = optimizeString(scored[i].second);\n        double sc = evalExact(s);\n        addElite(s);\n        if (betterScore(sc, bestScore)) {\n            bestScore = sc;\n            bestAns = s;\n        }\n\n        auto bp = bestPrefixOfString(s).first;\n        if (!bp.empty()) {\n            string c1 = fullify(bp);\n            string c2 = fullify(concat2(bp, reversePath(bp)));\n            double sc1 = evalExact(c1);\n            double sc2 = evalExact(c2);\n            addElite(c1);\n            addElite(c2);\n            if (betterScore(sc1, bestScore)) {\n                bestScore = sc1;\n                bestAns = c1;\n            }\n            if (betterScore(sc2, bestScore)) {\n                bestScore = sc2;\n                bestAns = c2;\n            }\n        }\n    }\n\n    // Genetic-style improvement\n    {\n        uint64_t seed =\n            0x123456789abcdefULL ^\n            (uint64_t(si) << 1) ^ (uint64_t(sj) << 7) ^\n            (uint64_t(ti) << 13) ^ (uint64_t(tj) << 17) ^\n            (uint64_t)(p * 1000000.0);\n\n        mt19937_64 rng(seed);\n\n        for (int it = 0; it < 80 && !timeOver(); ++it) {\n            if (elite.empty()) break;\n\n            int p1 = (int)(rng() % min<int>(elite.size(), 6));\n            int p2 = (int)(rng() % min<int>(elite.size(), 12));\n            string child = crossover(elite[p1].second, elite[p2].second, rng);\n\n            // Multiple mutations\n            int m = 1 + (int)(rng() % 3);\n            for (int k = 0; k < m; ++k) child = mutateFixedLength(child, rng);\n\n            // Occasional prefix-repeat injection\n            if ((rng() & 3) == 0) {\n                auto bp = bestPrefixOfString(child).first;\n                if (!bp.empty()) {\n                    string c1 = fullify(bp);\n                    string c2 = fullify(concat2(bp, reversePath(bp)));\n                    double sc1 = evalExact(c1);\n                    double sc2 = evalExact(c2);\n                    if (sc1 > sc2) child = c1;\n                    else child = c2;\n                }\n            }\n\n            double sc = evalExact(child);\n\n            if (sc > bestScore + EPS) {\n                string improved = optimizeString(child);\n                double sc2 = evalExact(improved);\n                if (sc2 > sc) {\n                    child = std::move(improved);\n                    sc = sc2;\n                }\n            }\n\n            if (betterScore(sc, bestScore)) {\n                bestScore = sc;\n                bestAns = child;\n            }\n\n            if ((int)elite.size() < 24 || sc > elite.back().first + EPS) {\n                addElite(child);\n            }\n\n            if ((it % 10) == 0 && !elite.empty()) {\n                // One local improvement on current elite leader\n                string lead = optimizeString(elite.front().second);\n                double ls = evalExact(lead);\n                addElite(lead);\n                if (ls > bestScore + EPS) {\n                    bestScore = ls;\n                    bestAns = lead;\n                }\n            }\n        }\n    }\n\n    // Final polish on the best answer\n    if (!timeOver()) {\n        string polished = optimizeString(bestAns);\n        double sc = evalExact(polished);\n        if (sc > bestScore + EPS) {\n            bestScore = sc;\n            bestAns = std::move(polished);\n        }\n    }\n\n    if ((int)bestAns.size() > MAXL) bestAns.resize(MAXL);\n    cout << bestAns << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int S = N * N;\nstatic constexpr int ST = S * 4;\n\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\nint baseTo[8][4] = {\n    {1, 0, -1, -1},\n    {3, -1, -1, 0},\n    {-1, -1, 3, 2},\n    {-1, 2, 1, -1},\n    {1, 0, 3, 2},\n    {3, 2, 1, 0},\n    {2, -1, 0, -1},\n    {-1, 3, -1, 1},\n};\n\nint nxtDir[8][4][4]; // nxtDir[t][rot][entry_dir] -> exit_dir, or -1\n\nusing RotArr = array<uint8_t, S>;\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 EvalResult {\n    long long score = -1;\n    int cycles = 0;\n    int l1 = 0, l2 = 0;\n    vector<int> hotCells;\n};\n\nint rotCorner[8][4];\nint rotPair[8][2];\n\nstatic inline bool better(const EvalResult& a, const EvalResult& b) {\n    if (a.score != b.score) return a.score > b.score;\n    if (a.cycles != b.cycles) return a.cycles > b.cycles;\n    if (a.l1 + a.l2 != b.l1 + b.l2) return a.l1 + a.l2 > b.l1 + b.l2;\n    if (a.l1 != b.l1) return a.l1 > b.l1;\n    return a.l2 > b.l2;\n}\n\nstatic inline void apply_sym(int sym, int i, int j, int& u, int& v) {\n    switch (sym) {\n        case 0: u = i; v = j; break;\n        case 1: u = i; v = N - 1 - j; break;\n        case 2: u = N - 1 - i; v = j; break;\n        case 3: u = N - 1 - i; v = N - 1 - j; break;\n        case 4: u = j; v = i; break;\n        case 5: u = j; v = N - 1 - i; break;\n        case 6: u = N - 1 - j; v = i; break;\n        case 7: u = N - 1 - j; v = N - 1 - i; break;\n    }\n}\n\nstatic inline int pattern_value(int pid, int u, int v, uint64_t seed) {\n    switch (pid) {\n        case 0: return u + v;\n        case 1: return u - v + 29;\n        case 2: return ((u & 1) << 1) | (v & 1);                 // 2x2 checkerboard\n        case 3: return (u / 2) * 4 + (v / 2);                    // 2x2 coarse\n        case 4: return (u / 3) * 4 + (v / 3);                    // 3x3 coarse\n        case 5: return min(min(u, 29 - u), min(v, 29 - v));      // border distance\n        case 6: return abs(u - 15) + abs(v - 15);                // center distance\n        case 7: return (int)(splitmix64(seed + (uint64_t)u * 10007ULL + (uint64_t)v * 10009ULL) & 1023ULL);\n    }\n    return u + v;\n}\n\nEvalResult evaluate(const RotArr& rot, const array<int, S>& tile) {\n    static int succ[ST];\n    static uint8_t vis[ST];\n    static int pos[ST];\n    static uint8_t mark[S];\n\n    memset(vis, 0, sizeof(vis));\n    memset(mark, 0, sizeof(mark));\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int base = (i * N + j) * 4;\n            int t = tile[i * N + j];\n            int r = rot[i * N + j];\n            for (int d = 0; d < 4; ++d) {\n                int d2 = nxtDir[t][r][d];\n                if (d2 < 0) {\n                    succ[base + d] = -1;\n                    continue;\n                }\n                int ni = i + di[d2];\n                int nj = j + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    succ[base + d] = -1;\n                    continue;\n                }\n                int nd = (d2 + 2) & 3;\n                succ[base + d] = (ni * N + nj) * 4 + nd;\n            }\n        }\n    }\n\n    vector<int> lens;\n    vector<vector<int>> cycStates;\n    vector<int> st;\n    st.reserve(ST);\n    lens.reserve(1024);\n    cycStates.reserve(1024);\n\n    for (int s = 0; s < ST; ++s) {\n        if (vis[s]) continue;\n        int cur = s;\n        st.clear();\n        while (cur != -1 && vis[cur] == 0) {\n            vis[cur] = 1;\n            pos[cur] = (int)st.size();\n            st.push_back(cur);\n            cur = succ[cur];\n        }\n        if (cur != -1 && vis[cur] == 1) {\n            vector<int> cyc(st.begin() + pos[cur], st.end());\n            lens.push_back((int)cyc.size());\n            cycStates.push_back(move(cyc));\n        }\n        for (int v : st) vis[v] = 2;\n    }\n\n    EvalResult res;\n    res.cycles = (int)lens.size();\n    if (res.cycles >= 1) {\n        vector<int> ord(res.cycles);\n        iota(ord.begin(), ord.end(), 0);\n        int top = min(4, res.cycles);\n        partial_sort(ord.begin(), ord.begin() + top, ord.end(), [&](int a, int b) {\n            if (lens[a] != lens[b]) return lens[a] > lens[b];\n            return a < b;\n        });\n\n        res.l1 = lens[ord[0]];\n        if (res.cycles >= 2) res.l2 = lens[ord[1]];\n        res.score = (res.cycles >= 2 ? 1LL * res.l1 * res.l2 : 0LL);\n\n        auto add_hot = [&](int cell) {\n            if (cell < 0 || cell >= S) return;\n            mark[cell] = 1;\n            int i = cell / N, j = cell % N;\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) mark[ni * N + nj] = 1;\n            }\n        };\n\n        for (int k = 0; k < top; ++k) {\n            for (int stid : cycStates[ord[k]]) {\n                add_hot(stid / 4);\n            }\n        }\n\n        for (int i = 0; i < S; ++i) if (mark[i]) res.hotCells.push_back(i);\n    }\n\n    return res;\n}\n\nRotArr make_candidate(const array<int, S>& tile, int pid, int sym, int mode, uint64_t seed) {\n    RotArr rot{};\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u, v;\n            apply_sym(sym, i, j, u, v);\n            int x = pattern_value(pid, u, v, seed);\n            int t = tile[i * N + j];\n\n            if (t <= 3) {\n                int kind;\n                if (mode == 0) kind = x & 3;\n                else kind = (x ^ (x >> 1)) & 3;\n                int r = rotCorner[t][kind];\n                if (r < 0) r = 0;\n                rot[i * N + j] = (uint8_t)r;\n            } else {\n                int kind;\n                if (mode == 0) kind = x & 1;\n                else kind = (x ^ (x >> 1)) & 1;\n                int r = rotPair[t][kind];\n                if (r < 0) r = 0;\n                rot[i * N + j] = (uint8_t)r;\n            }\n        }\n    }\n    return rot;\n}\n\nstatic inline int pick_cell(const vector<int>& hot, mt19937_64& rng) {\n    if (!hot.empty() && (rng() % 100) < 75) return hot[rng() % hot.size()];\n    return (int)(rng() % S);\n}\n\nbool try_best_cell(RotArr& cur, EvalResult& curEv, const array<int, S>& tile, int cell) {\n    uint8_t old = cur[cell];\n    uint8_t bestR = old;\n    EvalResult bestEv = curEv;\n\n    for (int r = 0; r < 4; ++r) {\n        if (r == old) continue;\n        cur[cell] = (uint8_t)r;\n        EvalResult ev = evaluate(cur, tile);\n        if (better(ev, bestEv)) {\n            bestEv = move(ev);\n            bestR = (uint8_t)r;\n        }\n    }\n\n    cur[cell] = bestR;\n    if (bestR != old) {\n        curEv = move(bestEv);\n        return true;\n    }\n    return false;\n}\n\nbool try_best_block(RotArr& cur, EvalResult& curEv, const array<int, S>& tile, int bi, int bj, mt19937_64& rng) {\n    RotArr bak = cur;\n    EvalResult bakEv = curEv;\n\n    array<int, 4> cells = {\n        bi * N + bj,\n        bi * N + (bj + 1),\n        (bi + 1) * N + bj,\n        (bi + 1) * N + (bj + 1)\n    };\n\n    bool changed = false;\n    for (int pass = 0; pass < 2; ++pass) {\n        shuffle(cells.begin(), cells.end(), rng);\n        for (int c : cells) {\n            changed |= try_best_cell(cur, curEv, tile, c);\n        }\n    }\n\n    if (!better(curEv, bakEv)) {\n        cur = bak;\n        curEv = bakEv;\n        return false;\n    }\n    return changed;\n}\n\nvoid local_search(RotArr& cur, EvalResult& curEv, const array<int, S>& tile,\n                  RotArr& globalBestRot, EvalResult& globalBestEv,\n                  chrono::steady_clock::time_point deadline, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    auto update_global = [&]() {\n        if (better(curEv, globalBestEv)) {\n            globalBestEv = curEv;\n            globalBestRot = cur;\n        }\n    };\n\n    // Initial greedy sweep on hot cells.\n    {\n        vector<int> ord = curEv.hotCells;\n        shuffle(ord.begin(), ord.end(), rng);\n        int lim = min<int>(60, ord.size());\n        for (int i = 0; i < lim; ++i) {\n            if (chrono::steady_clock::now() >= deadline) return;\n            try_best_cell(cur, curEv, tile, ord[i]);\n            update_global();\n        }\n    }\n\n    int stagnation = 0;\n    while (chrono::steady_clock::now() < deadline) {\n        if (stagnation > 150) {\n            // Restart from the best-known solution with a small random shake.\n            cur = globalBestRot;\n            curEv = globalBestEv;\n\n            for (int k = 0; k < 5; ++k) {\n                int c = (int)(rng() % S);\n                cur[c] = (uint8_t)(rng() & 3);\n            }\n            curEv = evaluate(cur, tile);\n            update_global();\n\n            stagnation = 0;\n            continue;\n        }\n\n        int mode = (int)(rng() % 100);\n        bool moved = false;\n\n        if (mode < 62) {\n            int cell = pick_cell(curEv.hotCells, rng);\n            moved = try_best_cell(cur, curEv, tile, cell);\n        } else if (mode < 90) {\n            int cell = pick_cell(curEv.hotCells, rng);\n            int i = cell / N, j = cell % N;\n            int bi = max(0, min(i - 1, N - 2));\n            int bj = max(0, min(j - 1, N - 2));\n            moved = try_best_block(cur, curEv, tile, bi, bj, rng);\n        } else {\n            // Random shake; accept sometimes even if worse to escape local minima.\n            RotArr bak = cur;\n            EvalResult bakEv = curEv;\n\n            if (!curEv.hotCells.empty() && (rng() % 100) < 70) {\n                int cell = curEv.hotCells[rng() % curEv.hotCells.size()];\n                int i = cell / N, j = cell % N;\n                int bi = max(0, min(i - 1, N - 2));\n                int bj = max(0, min(j - 1, N - 2));\n                for (int di2 = 0; di2 < 2; ++di2) {\n                    for (int dj2 = 0; dj2 < 2; ++dj2) {\n                        int c = (bi + di2) * N + (bj + dj2);\n                        cur[c] = (uint8_t)(rng() & 3);\n                    }\n                }\n            } else {\n                for (int k = 0; k < 4; ++k) {\n                    int c = (int)(rng() % S);\n                    cur[c] = (uint8_t)(rng() & 3);\n                }\n            }\n\n            curEv = evaluate(cur, tile);\n            if (better(curEv, bakEv) || (rng() % 250 == 0)) {\n                moved = true;\n            } else {\n                cur = bak;\n                curEv = bakEv;\n            }\n        }\n\n        update_global();\n        if (moved) stagnation = 0;\n        else ++stagnation;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    array<int, S> tile{};\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) tile[i * N + j] = s[j] - '0';\n    }\n\n    // Precompute rotations for each tile type / desired kind.\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            for (int d = 0; d < 4; ++d) {\n                int bd = (d + r) & 3; // world dir -> base dir\n                int be = baseTo[t][bd];\n                if (be < 0) nxtDir[t][r][d] = -1;\n                else nxtDir[t][r][d] = (be - r + 4) & 3;\n            }\n        }\n    }\n\n    for (int t = 0; t < 8; ++t) {\n        for (int k = 0; k < 4; ++k) rotCorner[t][k] = -1;\n        for (int k = 0; k < 2; ++k) rotPair[t][k] = -1;\n    }\n\n    auto corner_kind = [&](int a, int b) -> int {\n        if (a > b) swap(a, b);\n        if (a == 0 && b == 1) return 0; // left-up\n        if (a == 1 && b == 2) return 1; // up-right\n        if (a == 2 && b == 3) return 2; // right-down\n        if (a == 0 && b == 3) return 3; // left-down\n        return -1;\n    };\n    auto straight_kind = [&](int a, int b) -> int {\n        if (a > b) swap(a, b);\n        if (a == 0 && b == 2) return 0; // horizontal\n        if (a == 1 && b == 3) return 1; // vertical\n        return -1;\n    };\n\n    for (int t = 0; t < 8; ++t) {\n        for (int r = 0; r < 4; ++r) {\n            vector<pair<int,int>> prs;\n            for (int d = 0; d < 4; ++d) {\n                int e = nxtDir[t][r][d];\n                if (e != -1 && d < e) prs.push_back({d, e});\n            }\n            sort(prs.begin(), prs.end());\n\n            if (t <= 3 && prs.size() == 1) {\n                int k = corner_kind(prs[0].first, prs[0].second);\n                if (k >= 0 && rotCorner[t][k] == -1) rotCorner[t][k] = r;\n            } else if (t <= 5 && prs.size() == 2) {\n                int a = corner_kind(prs[0].first, prs[0].second);\n                int b = corner_kind(prs[1].first, prs[1].second);\n                if ((a == 0 && b == 2) || (a == 2 && b == 0)) {\n                    if (rotPair[t][0] == -1) rotPair[t][0] = r;\n                }\n                if ((a == 3 && b == 1) || (a == 1 && b == 3)) {\n                    if (rotPair[t][1] == -1) rotPair[t][1] = r;\n                }\n            } else if (t >= 6 && prs.size() == 1) {\n                int k = straight_kind(prs[0].first, prs[0].second);\n                if (k >= 0 && rotPair[t][k] == -1) rotPair[t][k] = r;\n            }\n        }\n    }\n\n    auto start = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85;\n\n    struct Node {\n        EvalResult ev;\n        RotArr rot;\n    };\n\n    vector<Node> nodes;\n    nodes.reserve(128);\n\n    // Diverse structured candidates.\n    for (int pid = 0; pid < 8; ++pid) {\n        for (int sym = 0; sym < 8; ++sym) {\n            for (int mode = 0; mode < 2; ++mode) {\n                uint64_t seed = splitmix64(0x123456789abcdef0ULL ^ (uint64_t)pid * 0x9e3779b97f4a7c15ULL ^\n                                           (uint64_t)sym * 0xbf58476d1ce4e5b9ULL ^ (uint64_t)mode * 0x94d049bb133111ebULL);\n                RotArr cand = make_candidate(tile, pid, sym, mode, seed);\n                EvalResult ev = evaluate(cand, tile);\n                nodes.push_back(Node{move(ev), move(cand)});\n            }\n        }\n    }\n\n    sort(nodes.begin(), nodes.end(), [&](const Node& a, const Node& b) {\n        return better(a.ev, b.ev);\n    });\n\n    RotArr globalBestRot = nodes.front().rot;\n    EvalResult globalBestEv = nodes.front().ev;\n\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    // Refine the top few candidates within remaining time.\n    int use = min<int>(3, nodes.size());\n    for (int k = 0; k < use; ++k) {\n        double rem = TIME_LIMIT - elapsed();\n        if (rem <= 0.01) break;\n        double slice = rem / (use - k);\n        auto deadline = chrono::steady_clock::now() +\n                        chrono::duration_cast<chrono::steady_clock::duration>(chrono::duration<double>(slice));\n\n        RotArr cur = nodes[k].rot;\n        EvalResult curEv = nodes[k].ev;\n\n        local_search(cur, curEv, tile, globalBestRot, globalBestEv, deadline,\n                     splitmix64(0xabcdef0123456789ULL ^ (uint64_t)k * 0x9e3779b97f4a7c15ULL));\n\n        if (better(curEv, globalBestEv)) {\n            globalBestEv = curEv;\n            globalBestRot = cur;\n        }\n        if (elapsed() > TIME_LIMIT) break;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cout << int(globalBestRot[i * N + j]);\n        }\n    }\n    cout << '\\n';\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXC = 100;\n\nstruct EvalRes {\n    int exact = 0;    // largest tree component size\n    int near = 0;     // almost-tree component potential\n    int largest = 0;  // largest connected component size\n    int goodDeg = 0;  // degree matches tile degree\n    int diffDeg = 0;  // sum of abs(deg - need)\n    int shape = 0;    // border/center heuristic\n};\n\nstruct Node {\n    array<uint8_t, MAXC> bd{};\n    int blank = -1;\n    uint64_t hash = 0;\n    EvalRes ev;\n    int parent = -1;\n    char move = '?';\n    int depth = 0; // depth from the start of this search\n};\n\nstruct SearchResult {\n    string path; // path from the original root, if used by caller\n    Node end;\n    long long score = 0;\n};\n\nint N, T;\nint cells, fullV;\n\nint adjPos[MAXC][4];\nuint64_t zob[MAXC][16];\nint pcnt[16];\nint shapeW[5][5];\n\nchar dirChar[4] = {'U', 'D', 'L', 'R'};\n\nchrono::steady_clock::time_point gStart;\ndouble gDeadline = 2.85;\n\ninline double elapsedSec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - gStart).count();\n}\n\ninline int parseHex(char c) {\n    if ('0' <= c && c <= '9') return c - '0';\n    return 10 + (c - 'a');\n}\n\ninline bool vecGreater(const array<int, 6>& a, const array<int, 6>& b) {\n    for (int i = 0; i < 6; ++i) {\n        if (a[i] != b[i]) return a[i] > b[i];\n    }\n    return false;\n}\n\ninline array<int, 6> modeKey(const EvalRes& e, int mode) {\n    if (mode == 0) {\n        return {e.exact, e.near, e.goodDeg, -e.diffDeg, e.shape, e.largest};\n    } else if (mode == 1) {\n        return {e.exact, e.shape, e.goodDeg, e.near, -e.diffDeg, e.largest};\n    } else {\n        return {e.exact, e.goodDeg, e.near, e.shape, -e.diffDeg, e.largest};\n    }\n}\n\ninline array<int, 6> partialKey(const EvalRes& e) {\n    return {e.exact, e.near, e.goodDeg, e.shape, -e.diffDeg, e.largest};\n}\n\ninline bool betterEvalMode(const EvalRes& a, const EvalRes& b, int mode) {\n    return vecGreater(modeKey(a, mode), modeKey(b, mode));\n}\n\ninline bool betterPartialScore(const EvalRes& a, const EvalRes& b) {\n    // Compare by actual judge score for partial states (depends only on exact).\n    if (a.exact != b.exact) return a.exact > b.exact;\n    return vecGreater(partialKey(a), partialKey(b));\n}\n\ninline long long partialScore(int exact) {\n    return (500000LL * exact + fullV / 2) / fullV;\n}\n\ninline long long fullScore(int totalLen) {\n    return llround(500000.0L * (2.0L - (long double)totalLen / (long double)T));\n}\n\ninline long long actualScore(const Node& n, int prefixLen) {\n    if (n.ev.exact == fullV) {\n        return fullScore(prefixLen + n.depth);\n    }\n    return partialScore(n.ev.exact);\n}\n\nEvalRes evaluate(const array<uint8_t, MAXC>& bd) {\n    int id[MAXC];\n    int V = 0;\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] != 0) id[i] = V++;\n        else id[i] = -1;\n    }\n\n    int deg[MAXC] = {};\n    int adj[MAXC][4];\n    int shape = 0;\n    int E = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int m = bd[idx];\n            if (!m) continue;\n\n            int ring = min(min(i, j), min(N - 1 - i, N - 1 - j));\n            if (ring > 4) ring = 4;\n            int need = pcnt[m];\n            int desired = min(4, ring + 1);\n            shape += shapeW[need][ring];\n\n            if (j + 1 < N) {\n                int idx2 = idx + 1;\n                int m2 = bd[idx2];\n                if (m2 && (m & 4) && (m2 & 1)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n            if (i + 1 < N) {\n                int idx2 = idx + N;\n                int m2 = bd[idx2];\n                if (m2 && (m & 8) && (m2 & 2)) {\n                    int a = id[idx], b = id[idx2];\n                    adj[a][deg[a]++] = b;\n                    adj[b][deg[b]++] = a;\n                    ++E;\n                }\n            }\n        }\n    }\n\n    bool vis[MAXC] = {};\n    int q[MAXC];\n\n    EvalRes res;\n    for (int s = 0; s < V; ++s) {\n        if (vis[s]) continue;\n\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n\n        int cnt = 0;\n        int sumdeg = 0;\n\n        while (head < tail) {\n            int x = q[head++];\n            ++cnt;\n            sumdeg += deg[x];\n            for (int k = 0; k < deg[x]; ++k) {\n                int y = adj[x][k];\n                if (!vis[y]) {\n                    vis[y] = true;\n                    q[tail++] = y;\n                }\n            }\n        }\n\n        int edges = sumdeg / 2;\n        int excess = edges - cnt + 1; // cycle rank of the component\n        res.largest = max(res.largest, cnt);\n        res.near = max(res.near, cnt - 2 * excess);\n        if (excess == 0) res.exact = max(res.exact, cnt);\n    }\n\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] == 0) continue;\n        res.goodDeg += 0; // placeholder, filled below\n    }\n\n    // Recompute degrees for local consistency metrics.\n    // (We keep this separate for clarity and because the board is tiny.)\n    memset(deg, 0, sizeof(deg));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int m = bd[idx];\n            if (!m) continue;\n            if (j + 1 < N) {\n                int idx2 = idx + 1;\n                int m2 = bd[idx2];\n                if (m2 && (m & 4) && (m2 & 1)) {\n                    ++deg[id[idx]];\n                    ++deg[id[idx2]];\n                }\n            }\n            if (i + 1 < N) {\n                int idx2 = idx + N;\n                int m2 = bd[idx2];\n                if (m2 && (m & 8) && (m2 & 2)) {\n                    ++deg[id[idx]];\n                    ++deg[id[idx2]];\n                }\n            }\n        }\n    }\n    for (int i = 0; i < cells; ++i) {\n        if (bd[i] == 0) continue;\n        int need = pcnt[bd[i]];\n        int d = deg[id[i]];\n        if (d == need) ++res.goodDeg;\n        res.diffDeg += abs(d - need);\n    }\n\n    res.shape = shape;\n    return res;\n}\n\nNode applyMove(const Node& cur, int dir, int parentId) {\n    Node nxt = cur;\n    int a = cur.blank;\n    int b = adjPos[a][dir];\n    uint8_t x = nxt.bd[a];\n    uint8_t y = nxt.bd[b];\n    nxt.hash ^= zob[a][x] ^ zob[a][y] ^ zob[b][y] ^ zob[b][x];\n    swap(nxt.bd[a], nxt.bd[b]);\n    nxt.blank = b;\n    nxt.parent = parentId;\n    nxt.move = dirChar[dir];\n    nxt.depth = cur.depth + 1;\n    nxt.ev = evaluate(nxt.bd);\n    return nxt;\n}\n\nstring buildPath(const vector<Node>& nodes, int id) {\n    string s;\n    while (id != -1 && nodes[id].parent != -1) {\n        s.push_back(nodes[id].move);\n        id = nodes[id].parent;\n    }\n    reverse(s.begin(), s.end());\n    return s;\n}\n\nstruct Cand {\n    int id;\n    array<int, 6> key;\n    array<int, 6> self;\n    uint32_t noise;\n};\n\nbool betterCand(const Cand& a, const Cand& b) {\n    if (vecGreater(a.key, b.key)) return true;\n    if (vecGreater(b.key, a.key)) return false;\n    if (vecGreater(a.self, b.self)) return true;\n    if (vecGreater(b.self, a.self)) return false;\n    return a.noise > b.noise;\n}\n\nSearchResult searchBeam(const Node& start, int prefixLen, int mode, int beamWidth, int depthLimit, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    vector<Node> nodes;\n    nodes.reserve((size_t)beamWidth * (size_t)depthLimit * 4 + 64);\n\n    Node root = start;\n    root.parent = -1;\n    root.move = '?';\n    root.depth = 0;\n    nodes.push_back(root);\n\n    vector<int> layer = {0};\n\n    unordered_set<uint64_t> seen;\n    seen.reserve((size_t)beamWidth * (size_t)depthLimit * 6 + 64);\n    seen.insert(root.hash);\n\n    int bestId = 0;\n    long long bestScore = actualScore(nodes[0], prefixLen);\n    array<int, 6> bestHeu = modeKey(nodes[0].ev, mode);\n\n    for (int depth = 0; depth < depthLimit; ++depth) {\n        if ((depth & 3) == 0 && elapsedSec() > gDeadline) break;\n\n        unordered_map<uint64_t, Cand> bestMap;\n        bestMap.reserve(layer.size() * 4 + 32);\n\n        int generated = 0;\n\n        for (int pid : layer) {\n            const Node cur = nodes[pid];\n\n            for (int dir = 0; dir < 4; ++dir) {\n                int nb = adjPos[cur.blank][dir];\n                if (nb == -1) continue;\n\n                Node child = applyMove(cur, dir, pid);\n                if (seen.count(child.hash)) continue;\n                seen.insert(child.hash);\n\n                int childId = (int)nodes.size();\n                nodes.push_back(child);\n\n                long long scChild = actualScore(nodes[childId], prefixLen);\n                array<int, 6> heuChild = modeKey(nodes[childId].ev, mode);\n\n                if (scChild > bestScore || (scChild == bestScore && vecGreater(heuChild, bestHeu))) {\n                    bestScore = scChild;\n                    bestId = childId;\n                    bestHeu = heuChild;\n                }\n\n                array<int, 6> bestKey = heuChild;\n\n                // One-step lookahead for ranking and possibly better actual-score samples.\n                for (int ndir = 0; ndir < 4; ++ndir) {\n                    int nnb = adjPos[child.blank][ndir];\n                    if (nnb == -1) continue;\n                    if (nnb == cur.blank) continue; // immediate backtrack\n\n                    Node grand = applyMove(child, ndir, childId);\n                    if (seen.count(grand.hash)) continue;\n\n                    array<int, 6> heuGrand = modeKey(grand.ev, mode);\n                    if (vecGreater(heuGrand, bestKey)) bestKey = heuGrand;\n\n                    long long scGrand = actualScore(grand, prefixLen);\n                    if (scGrand > bestScore || (scGrand == bestScore && vecGreater(heuGrand, bestHeu))) {\n                        int gid = (int)nodes.size();\n                        nodes.push_back(grand);\n                        bestScore = scGrand;\n                        bestId = gid;\n                        bestHeu = heuGrand;\n                    }\n                }\n\n                Cand cand{childId, bestKey, heuChild, (uint32_t)rng()};\n                auto it = bestMap.find(child.hash);\n                if (it == bestMap.end() || betterCand(cand, it->second)) {\n                    bestMap[child.hash] = cand;\n                }\n\n                ++generated;\n                if ((generated & 31) == 0 && elapsedSec() > gDeadline) break;\n            }\n\n            if (elapsedSec() > gDeadline) break;\n        }\n\n        if (bestMap.empty()) break;\n\n        vector<Cand> candVec;\n        candVec.reserve(bestMap.size());\n        for (auto& kv : bestMap) candVec.push_back(kv.second);\n\n        sort(candVec.begin(), candVec.end(), [](const Cand& a, const Cand& b) {\n            return betterCand(a, b);\n        });\n\n        if ((int)candVec.size() > beamWidth) candVec.resize(beamWidth);\n\n        layer.clear();\n        layer.reserve(candVec.size());\n        for (const auto& c : candVec) {\n            layer.push_back(c.id);\n        }\n    }\n\n    SearchResult res;\n    res.end = nodes[bestId];\n    res.path = buildPath(nodes, bestId);\n    res.score = bestScore;\n    return res;\n}\n\nSearchResult searchGreedy(const Node& start, int prefixLen, int mode, int maxSteps, uint64_t seed) {\n    mt19937_64 rng(seed);\n\n    Node cur = start;\n    cur.parent = -1;\n    cur.move = '?';\n    cur.depth = 0;\n\n    string path;\n    string bestPath;\n    Node best = cur;\n    long long bestScore = actualScore(cur, prefixLen);\n    array<int, 6> bestHeu = modeKey(cur.ev, mode);\n\n    unordered_set<uint64_t> seen;\n    seen.reserve((size_t)maxSteps * 4 + 32);\n    seen.insert(cur.hash);\n\n    int stagnation = 0;\n\n    for (int step = 0; step < maxSteps; ++step) {\n        if ((step & 7) == 0 && elapsedSec() > gDeadline) break;\n\n        struct GCand {\n            int dir;\n            Node st;\n            array<int, 6> key;\n            array<int, 6> self;\n            uint32_t noise;\n        };\n\n        vector<GCand> cands;\n        cands.reserve(4);\n\n        for (int dir = 0; dir < 4; ++dir) {\n            int nb = adjPos[cur.blank][dir];\n            if (nb == -1) continue;\n\n            Node child = applyMove(cur, dir, -1);\n            if (seen.count(child.hash)) continue;\n\n            array<int, 6> selfKey = modeKey(child.ev, mode);\n            array<int, 6> bestKey = selfKey;\n\n            for (int ndir = 0; ndir < 4; ++ndir) {\n                int nnb = adjPos[child.blank][ndir];\n                if (nnb == -1) continue;\n                if (nnb == cur.blank) continue;\n\n                Node grand = applyMove(child, ndir, -1);\n                if (seen.count(grand.hash)) continue;\n                array<int, 6> gk = modeKey(grand.ev, mode);\n                if (vecGreater(gk, bestKey)) bestKey = gk;\n            }\n\n            cands.push_back({dir, child, bestKey, selfKey, (uint32_t)rng()});\n        }\n\n        if (cands.empty()) break;\n\n        sort(cands.begin(), cands.end(), [](const GCand& a, const GCand& b) {\n            if (vecGreater(a.key, b.key)) return true;\n            if (vecGreater(b.key, a.key)) return false;\n            if (vecGreater(a.self, b.self)) return true;\n            if (vecGreater(b.self, a.self)) return false;\n            return a.noise > b.noise;\n        });\n\n        int pick = 0;\n        if ((int)cands.size() >= 2) {\n            uint32_t r = (uint32_t)rng();\n            if (r % 100 < 18) pick = 1;\n            if ((int)cands.size() >= 3 && r % 100 < 7) pick = 2;\n        }\n\n        cur = cands[pick].st;\n        path.push_back(dirChar[cands[pick].dir]);\n        seen.insert(cur.hash);\n\n        long long sc = actualScore(cur, prefixLen);\n        array<int, 6> heu = modeKey(cur.ev, mode);\n        if (sc > bestScore || (sc == bestScore && vecGreater(heu, bestHeu))) {\n            bestScore = sc;\n            best = cur;\n            bestPath = path;\n            bestHeu = heu;\n            stagnation = 0;\n        } else {\n            ++stagnation;\n        }\n\n        if (cur.ev.exact == fullV) {\n            // A full tree is valuable; continue only if it is still improving score.\n            long long fullSc = actualScore(cur, prefixLen);\n            if (fullSc >= bestScore) {\n                bestScore = fullSc;\n                best = cur;\n                bestPath = path;\n                bestHeu = heu;\n            }\n        }\n\n        if (stagnation > 50) break;\n    }\n\n    SearchResult res;\n    res.end = best;\n    res.path = bestPath;\n    res.score = bestScore;\n    return res;\n}\n\nstruct FinalCand {\n    string path;\n    Node end;\n    long long score;\n};\n\nbool betterFinal(const FinalCand& a, const FinalCand& b) {\n    if (a.score != b.score) return a.score > b.score;\n    if (a.end.ev.exact == fullV && b.end.ev.exact == fullV && a.path.size() != b.path.size()) {\n        return a.path.size() < b.path.size();\n    }\n    return a.path.size() < b.path.size();\n}\n\nuint64_t splitmix64(uint64_t& x) {\n    x += 0x9e3779b97f4a7c15ULL;\n    uint64_t z = x;\n    z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n    z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n    return z ^ (z >> 31);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    cells = N * N;\n    fullV = cells - 1;\n\n    vector<string> s(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n\n    for (int i = 0; i < 16; ++i) {\n        pcnt[i] = __builtin_popcount((unsigned)i);\n    }\n\n    // Mild shape heuristic: leaves on border, higher degree toward center.\n    for (int need = 1; need <= 4; ++need) {\n        for (int ring = 0; ring <= 4; ++ring) {\n            int desired = min(4, ring + 1);\n            shapeW[need][ring] = 8 - 2 * abs(need - desired);\n        }\n    }\n\n    Node root;\n    int blankPos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int v = parseHex(s[i][j]);\n            root.bd[idx] = (uint8_t)v;\n            if (v == 0) blankPos = idx;\n        }\n    }\n    root.blank = blankPos;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            adjPos[idx][0] = (i > 0 ? idx - N : -1);\n            adjPos[idx][1] = (i + 1 < N ? idx + N : -1);\n            adjPos[idx][2] = (j > 0 ? idx - 1 : -1);\n            adjPos[idx][3] = (j + 1 < N ? idx + 1 : -1);\n        }\n    }\n\n    uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();\n    uint64_t sm = seed ^ 0x123456789abcdef0ULL;\n    for (int i = 0; i < cells; ++i) {\n        for (int v = 0; v < 16; ++v) {\n            zob[i][v] = splitmix64(sm);\n        }\n    }\n\n    root.hash = 0;\n    for (int i = 0; i < cells; ++i) root.hash ^= zob[i][root.bd[i]];\n    root.ev = evaluate(root.bd);\n    root.parent = -1;\n    root.move = '?';\n    root.depth = 0;\n\n    gStart = chrono::steady_clock::now();\n    gDeadline = 2.85;\n\n    vector<FinalCand> finals;\n\n    auto addCand = [&](const SearchResult& r) {\n        finals.push_back({r.path, r.end, r.score});\n    };\n\n    // Stage 1: several diverse searches from the root.\n    {\n        int rootDepth = min(80, T);\n        int rootBeam = 120;\n        int rootGreedy = min(80, T);\n\n        uint64_t s1 = splitmix64(sm);\n        uint64_t s2 = splitmix64(sm);\n        uint64_t s3 = splitmix64(sm);\n        uint64_t s4 = splitmix64(sm);\n\n        SearchResult r1 = searchBeam(root, 0, 0, rootBeam, rootDepth, s1);\n        SearchResult r2 = searchBeam(root, 0, 1, rootBeam, rootDepth, s2);\n        SearchResult r3 = searchBeam(root, 0, 2, rootBeam, rootDepth, s3);\n        SearchResult r4 = searchGreedy(root, 0, 2, rootGreedy, s4);\n\n        addCand(r1);\n        addCand(r2);\n        addCand(r3);\n        addCand(r4);\n\n        if (elapsedSec() < gDeadline) {\n            vector<SearchResult> roots = {r1, r2, r3, r4};\n\n            // Pick promising partial states for refinement:\n            // sort by actual score (which is already path-aware for full states),\n            // then by remaining budget, then by heuristic quality.\n            struct Pick {\n                SearchResult r;\n                int remaining;\n                array<int, 6> pk;\n            };\n            vector<Pick> picks;\n            for (auto& rr : roots) {\n                if (rr.end.ev.exact == fullV) continue; // already full; keep as final candidate\n                int rem = T - (int)rr.path.size();\n                if (rem <= 0) continue;\n                picks.push_back({rr, rem, partialKey(rr.end.ev)});\n            }\n\n            sort(picks.begin(), picks.end(), [&](const Pick& a, const Pick& b) {\n                if (a.r.score != b.r.score) return a.r.score > b.r.score;\n                if (a.remaining != b.remaining) return a.remaining > b.remaining;\n                if (vecGreater(a.pk, b.pk)) return true;\n                if (vecGreater(b.pk, a.pk)) return false;\n                return a.r.path.size() < b.r.path.size();\n            });\n\n            vector<Pick> uniq;\n            unordered_set<uint64_t> used;\n            used.reserve(8);\n            for (auto& p : picks) {\n                if (used.insert(p.r.end.hash).second) uniq.push_back(p);\n                if ((int)uniq.size() >= 2) break;\n            }\n\n            if (!uniq.empty() && elapsedSec() < gDeadline) {\n                auto doRefine = [&](const Pick& p, int mode, int beamWidth, int depthCap, uint64_t seedX) {\n                    int rem = T - (int)p.r.path.size();\n                    if (rem <= 0) return;\n                    int lim = min(depthCap, rem);\n                    SearchResult ext = searchBeam(p.r.end, (int)p.r.path.size(), mode, beamWidth, lim, seedX);\n                    FinalCand fc;\n                    fc.path = p.r.path + ext.path;\n                    fc.end = ext.end;\n                    fc.score = ext.score;\n                    addCand(ext); // ext.score already includes prefixLen inside the search\n                    finals.push_back(fc);\n                };\n\n                // Refine the best candidate with both beam and greedy.\n                {\n                    const auto& p = uniq[0];\n                    uint64_t sa = splitmix64(sm);\n                    uint64_t sb = splitmix64(sm);\n                    int rem = T - (int)p.r.path.size();\n                    if (rem > 0) {\n                        int lim = min(160, rem);\n                        SearchResult ext1 = searchBeam(p.r.end, (int)p.r.path.size(), 0, 160, lim, sa);\n                        FinalCand fc1{p.r.path + ext1.path, ext1.end, ext1.score};\n                        finals.push_back(fc1);\n\n                        SearchResult ext2 = searchGreedy(p.r.end, (int)p.r.path.size(), 1, min(160, rem), sb);\n                        FinalCand fc2{p.r.path + ext2.path, ext2.end, ext2.score};\n                        finals.push_back(fc2);\n                    }\n                }\n\n                if (uniq.size() >= 2 && elapsedSec() < gDeadline) {\n                    const auto& p = uniq[1];\n                    uint64_t sc = splitmix64(sm);\n                    int rem = T - (int)p.r.path.size();\n                    if (rem > 0) {\n                        int lim = min(160, rem);\n                        SearchResult ext = searchBeam(p.r.end, (int)p.r.path.size(), 1, 160, lim, sc);\n                        FinalCand fc{p.r.path + ext.path, ext.end, ext.score};\n                        finals.push_back(fc);\n                    }\n                }\n            }\n        }\n    }\n\n    // Choose the best final candidate by the judge score.\n    if (finals.empty()) {\n        cout << '\\n';\n        return 0;\n    }\n\n    FinalCand best = finals[0];\n    for (int i = 1; i < (int)finals.size(); ++i) {\n        if (betterFinal(finals[i], best)) best = finals[i];\n    }\n\n    if ((int)best.path.size() > T) {\n        // Safety fallback: should not happen, but keep output legal.\n        best.path.resize(T);\n    }\n\n    cout << best.path << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ld = long double;\n\nstatic const ld PI = acosl(-1.0L);\nstatic const int MAXS = 101;\nstatic const int PAIR_CAP = 2601;\n\nint N, K;\narray<int, 11> A{};\nvector<int> X, Y;\nint totalAtt = 0;\n\nstruct Family {\n    int a = 0, b = 0; // primitive normal vector\n    ld ang = 0;\n    vector<ll> sortedVals;\n    vector<int> ord;\n    vector<ll> gapCut;\n    vector<int> gapLeft;\n};\n\nstruct Memo {\n    array<vector<vector<ll>>, 5> cuts;\n    array<vector<char>, 5> ready;\n    Memo() {\n        for (int m = 0; m < 5; m++) {\n            cuts[m].resize(MAXS + 1);\n            ready[m].assign(MAXS + 1, 0);\n        }\n    }\n};\n\nstruct Solution {\n    int score = -1;\n    int cuts = INT_MAX;\n    vector<int> fams;\n    vector<int> sizes;\n    vector<int> modes;\n};\n\nvector<Family> families;\nvector<Memo> memo;\nmap<pair<int,int>, int> famId;\nvector<vector<int>> countCache[5];\n\npair<int,int> canon(int a, int b) {\n    if (a == 0 && b == 0) return {0, 0};\n    int g = std::gcd(abs(a), abs(b));\n    a /= g;\n    b /= g;\n    if (b < 0 || (b == 0 && a < 0)) {\n        a = -a;\n        b = -b;\n    }\n    return {a, b};\n}\n\nll egcd(ll a, ll b, ll& x, ll& y) {\n    if (b == 0) {\n        x = 1;\n        y = 0;\n        return a;\n    }\n    ll x1, y1;\n    ll g = egcd(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\nstruct LineOut {\n    ll x1, y1, x2, y2;\n};\n\nLineOut makeLine(int a, int b, ll c) {\n    if (a == 0) {\n        ll y = c / b;\n        return {-1000000000LL, y, 1000000000LL, y};\n    }\n    if (b == 0) {\n        ll x = c / a;\n        return {x, -1000000000LL, x, 1000000000LL};\n    }\n\n    ll aa = llabs((ll)a), bb = llabs((ll)b);\n    ll x0, y0;\n    egcd(aa, bb, x0, y0); // aa*x0 + bb*y0 = 1\n\n    if (a < 0) x0 = -x0;\n    if (b < 0) y0 = -y0;\n\n    ll x = (ll)((__int128)x0 * c);\n    ll y = (ll)((__int128)y0 * c);\n\n    return {x, y, x + b, y - a};\n}\n\nFamily buildFamily(int a, int b) {\n    Family F;\n    F.a = a;\n    F.b = b;\n    F.ang = atan2l((ld)b, (ld)a);\n    if (F.ang < 0) F.ang += PI;\n\n    vector<ll> proj(N);\n    F.ord.resize(N);\n    for (int i = 0; i < N; i++) {\n        proj[i] = 1LL * a * X[i] + 1LL * b * Y[i];\n        F.ord[i] = i;\n    }\n\n    sort(F.ord.begin(), F.ord.end(), [&](int i, int j) {\n        if (proj[i] != proj[j]) return proj[i] < proj[j];\n        return i < j;\n    });\n\n    F.sortedVals.resize(N);\n    for (int i = 0; i < N; i++) F.sortedVals[i] = proj[F.ord[i]];\n\n    for (int i = 0; i + 1 < N; i++) {\n        if (F.sortedVals[i + 1] - F.sortedVals[i] >= 2) {\n            F.gapCut.push_back(F.sortedVals[i] + 1);\n            F.gapLeft.push_back(i + 1);\n        }\n    }\n\n    return F;\n}\n\nvector<int> buildCounts(int s, int total, int mode) {\n    if (total < s) return {};\n    if (s == 1) return vector<int>{total};\n\n    vector<int> cnt(s, 0);\n\n    if (mode == 0) {\n        int base = total / s;\n        int rem = total % s;\n        for (int i = 0; i < s; i++) cnt[i] = base + (i < rem);\n        return cnt;\n    }\n\n    vector<ld> w(s, 1.0L);\n    if (mode == 1) {\n        for (int i = 0; i < s; i++) w[i] = 1.0L + i;\n    } else if (mode == 2) {\n        for (int i = 0; i < s; i++) w[i] = 1.0L + (s - 1 - i);\n    } else if (mode == 3) {\n        ld mid = (ld)(s - 1) / 2.0L;\n        ld scale = max<ld>(1.0L, (ld)s / 6.0L);\n        for (int i = 0; i < s; i++) {\n            ld dist = fabsl((ld)i - mid);\n            w[i] = 1.0L + 5.0L * expl(-dist / scale);\n        }\n    } else if (mode == 4) {\n        for (int i = 0; i < s; i++) {\n            w[i] = (i % 2 == 0 ? 1.0L : 3.0L);\n        }\n    }\n\n    ld sumw = 0;\n    for (ld x : w) sumw += x;\n\n    vector<pair<ld,int>> frac;\n    int used = 0;\n    for (int i = 0; i < s; i++) {\n        ld ideal = (ld)total * w[i] / sumw;\n        int x = (int)floor(ideal + 1e-18L);\n        cnt[i] = x;\n        used += x;\n        frac.push_back({ideal - x, i});\n    }\n\n    int rem = total - used;\n    sort(frac.begin(), frac.end(), [&](const auto& p1, const auto& p2) {\n        if (fabsl(p1.first - p2.first) > 1e-18L) return p1.first > p2.first;\n        return p1.second < p2.second;\n    });\n\n    for (int i = 0; i < rem; i++) cnt[frac[i].second]++;\n\n    return cnt;\n}\n\nvector<ll> buildCuts(const Family& F, const vector<int>& cnt) {\n    int s = (int)cnt.size();\n    if (s == 1) return {};\n    if ((int)F.gapCut.size() < s - 1) return {};\n\n    vector<ll> cuts;\n    cuts.reserve(s - 1);\n\n    int start = 0;\n    int pref = 0;\n    for (int j = 0; j < s - 1; j++) {\n        pref += cnt[j];\n\n        int lo = start;\n        int hi = (int)F.gapCut.size() - 1 - ((s - 2) - j);\n        if (lo > hi) return {};\n\n        auto it = lower_bound(F.gapLeft.begin() + lo, F.gapLeft.begin() + hi + 1, pref);\n        int idx;\n        if (it == F.gapLeft.begin() + lo) {\n            idx = lo;\n        } else if (it == F.gapLeft.begin() + hi + 1) {\n            idx = hi;\n        } else {\n            int p = (int)(it - F.gapLeft.begin());\n            ll d0 = llabs((ll)F.gapLeft[p - 1] - pref);\n            ll d1 = llabs((ll)F.gapLeft[p] - pref);\n            idx = (d0 <= d1 ? p - 1 : p);\n        }\n\n        cuts.push_back(F.gapCut[idx]);\n        start = idx + 1;\n    }\n\n    return cuts;\n}\n\nconst vector<ll>& getCuts(int fid, int s, int mode) {\n    Memo& M = memo[fid];\n    if (!M.ready[mode][s]) {\n        M.cuts[mode][s] = buildCuts(families[fid], countCache[mode][s]);\n        M.ready[mode][s] = 1;\n    }\n    return M.cuts[mode][s];\n}\n\nvoid assignBinsTo(const Family& F, const vector<ll>& cuts, vector<int>& bin) {\n    bin.assign(N, 0);\n    int p = 0;\n    for (int b = 0; b < (int)cuts.size(); b++) {\n        while (p < N && F.sortedVals[p] < cuts[b]) {\n            bin[F.ord[p]] = b;\n            p++;\n        }\n    }\n    while (p < N) {\n        bin[F.ord[p]] = (int)cuts.size();\n        p++;\n    }\n}\n\nbool better(const Solution& a, const Solution& b) {\n    if (a.score != b.score) return a.score > b.score;\n    return a.cuts < b.cuts;\n}\n\nSolution evalSol(const vector<int>& fams, const vector<int>& sizes, const vector<int>& modes) {\n    Solution res;\n    res.fams = fams;\n    res.sizes = sizes;\n    res.modes = modes;\n\n    int t = (int)fams.size();\n    if (t == 0 || t > 2 || (int)sizes.size() != t || (int)modes.size() != t) return res;\n\n    int cutNum = 0;\n    long long prod = 1;\n    for (int i = 0; i < t; i++) {\n        int s = sizes[i];\n        int m = modes[i];\n        if (s < 1 || s > MAXS || s > N || m < 0 || m >= 5) return res;\n        cutNum += s - 1;\n        if (cutNum > K) return res;\n        if (prod > PAIR_CAP / s) return res;\n        prod *= s;\n    }\n    if (prod > PAIR_CAP) return res;\n\n    vector<vector<int>> bins(t);\n    for (int i = 0; i < t; i++) {\n        const vector<ll>& cuts = getCuts(fams[i], sizes[i], modes[i]);\n        if (sizes[i] > 1 && (int)cuts.size() != sizes[i] - 1) return res;\n        assignBinsTo(families[fams[i]], cuts, bins[i]);\n    }\n\n    vector<int> cell((int)prod, 0);\n    for (int p = 0; p < N; p++) {\n        int id = 0;\n        for (int i = 0; i < t; i++) {\n            id = id * sizes[i] + bins[i][p];\n        }\n        cell[id]++;\n    }\n\n    int hist[11] = {};\n    for (int v : cell) {\n        if (1 <= v && v <= 10) hist[v]++;\n    }\n\n    int score = 0;\n    for (int d = 1; d <= 10; d++) score += min(A[d], hist[d]);\n\n    res.score = score;\n    res.cuts = cutNum;\n    return res;\n}\n\nstatic const vector<int> SINGLE_SIZES = {\n    1,2,3,4,5,6,8,10,12,15,18,20,24,25,30,36,40,45,50,51,60,80,100,101\n};\n\nvector<int> buildProxyTargets() {\n    array<ll, 11> fact{};\n    fact[0] = 1;\n    for (int i = 1; i <= 10; i++) fact[i] = fact[i - 1] * i;\n\n    vector<pair<ld,int>> cand;\n    cand.reserve(PAIR_CAP);\n\n    for (int m = 1; m <= PAIR_CAP; m++) {\n        ld lambda = (ld)N / (ld)m;\n        ld e = expl(-lambda);\n        ld p = 1.0L;\n        ld proxy = 0.0L;\n        for (int d = 1; d <= 10; d++) {\n            p *= lambda;\n            ld expect = (ld)m * e * p / (ld)fact[d];\n            proxy += min((ld)A[d], expect);\n        }\n        cand.push_back({proxy, m});\n    }\n\n    sort(cand.begin(), cand.end(), [&](const auto& x, const auto& y) {\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n\n    vector<int> res;\n    auto add = [&](int x) {\n        x = max(1, min(PAIR_CAP, x));\n        if (find(res.begin(), res.end(), x) == res.end()) res.push_back(x);\n    };\n\n    for (int i = 0; i < (int)cand.size() && i < 6; i++) add(cand[i].second);\n    add(totalAtt);\n    add(N / 2);\n    add(N / 3);\n\n    if (res.empty()) res.push_back(max(1, min(PAIR_CAP, totalAtt)));\n    return res;\n}\n\nSolution searchSingle(int fid) {\n    Solution best;\n    for (int s : SINGLE_SIZES) {\n        if (s > N) continue;\n        for (int m = 0; m < 5; m++) {\n            Solution cand = evalSol({fid}, {s}, {m});\n            if (better(cand, best)) best = cand;\n        }\n    }\n    return best;\n}\n\nSolution searchPair(int f1, int f2, const Solution& seed1, const Solution& seed2, const vector<int>& proxyTargets) {\n    Solution best;\n\n    vector<int> targets;\n    auto addT = [&](int x) {\n        x = max(1, min(PAIR_CAP, x));\n        if (find(targets.begin(), targets.end(), x) == targets.end()) targets.push_back(x);\n    };\n\n    for (int i = 0; i < min<int>(4, proxyTargets.size()); i++) addT(proxyTargets[i]);\n    addT(totalAtt);\n    addT(N / 2);\n\n    vector<int> sCand;\n    auto addS = [&](int x) {\n        if (1 <= x && x <= N) sCand.push_back(x);\n    };\n\n    for (int s : SINGLE_SIZES) addS(s);\n    if (!seed1.sizes.empty()) for (int d = -2; d <= 2; d++) addS(seed1.sizes[0] + d);\n    if (!seed2.sizes.empty()) for (int d = -2; d <= 2; d++) addS(seed2.sizes[0] + d);\n\n    for (int T : targets) {\n        int r = (int)llround(sqrt((ld)T));\n        for (int d = -2; d <= 2; d++) addS(r + d);\n    }\n\n    sort(sCand.begin(), sCand.end());\n    sCand.erase(unique(sCand.begin(), sCand.end()), sCand.end());\n\n    static const vector<pair<int,int>> modePairs = {\n        {0,0}, {1,0}, {0,1}, {1,1}, {2,0}, {0,2}, {3,3}, {4,0}, {0,4}\n    };\n\n    auto tryEval = [&](int s1, int s2, int m1, int m2) {\n        if (s1 < 1 || s2 < 1 || s1 > N || s2 > N) return;\n        if (s1 + s2 - 2 > K) return;\n        if (1LL * s1 * s2 > PAIR_CAP) return;\n\n        Solution a = evalSol({f1, f2}, {s1, s2}, {m1, m2});\n        if (better(a, best)) best = a;\n\n        Solution b = evalSol({f1, f2}, {s2, s1}, {m2, m1});\n        if (better(b, best)) best = b;\n    };\n\n    for (int T : targets) {\n        for (int s1 : sCand) {\n            int s2base = (int)llround((ld)T / (ld)s1);\n            for (int d = -1; d <= 1; d++) {\n                int s2 = s2base + d;\n                if (s2 < 1 || s2 > N) continue;\n                for (auto [m1, m2] : modePairs) {\n                    tryEval(s1, s2, m1, m2);\n                }\n            }\n        }\n    }\n\n    return best;\n}\n\nSolution refineSolution(Solution cur) {\n    if (cur.score < 0) return cur;\n\n    for (int iter = 0; iter < 2; iter++) {\n        Solution best = cur;\n        int t = (int)cur.fams.size();\n\n        if (t == 1) {\n            for (int ds = -4; ds <= 4; ds++) {\n                int ns = cur.sizes[0] + ds;\n                if (ns < 1 || ns > N) continue;\n                for (int m = 0; m < 5; m++) {\n                    Solution cand = evalSol(cur.fams, {ns}, {m});\n                    if (better(cand, best)) best = cand;\n                }\n            }\n        } else if (t == 2) {\n            for (int d1 = -2; d1 <= 2; d1++) {\n                for (int d2 = -2; d2 <= 2; d2++) {\n                    int ns1 = cur.sizes[0] + d1;\n                    int ns2 = cur.sizes[1] + d2;\n                    if (ns1 < 1 || ns2 < 1 || ns1 > N || ns2 > N) continue;\n                    if (ns1 + ns2 - 2 > K) continue;\n                    if (1LL * ns1 * ns2 > PAIR_CAP) continue;\n                    for (int m1 = 0; m1 < 5; m1++) {\n                        for (int m2 = 0; m2 < 5; m2++) {\n                            Solution cand = evalSol(cur.fams, {ns1, ns2}, {m1, m2});\n                            if (better(cand, best)) best = cand;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (better(best, cur)) cur = best;\n        else break;\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> K;\n    for (int d = 1; d <= 10; d++) {\n        cin >> A[d];\n        totalAtt += A[d];\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    for (int m = 0; m < 5; m++) {\n        countCache[m].resize(MAXS + 1);\n        for (int s = 1; s <= MAXS; s++) {\n            countCache[m][s] = buildCounts(s, N, m);\n        }\n    }\n\n    // Candidate orientations: small primitive normals + PCA direction.\n    set<pair<int,int>> seen;\n    vector<pair<int,int>> normals;\n\n    auto addNormal = [&](int a, int b) {\n        auto p = canon(a, b);\n        if (p.first == 0 && p.second == 0) return;\n        if (seen.insert(p).second) normals.push_back(p);\n    };\n\n    int B = 6;\n    for (int a = -B; a <= B; a++) {\n        for (int b = -B; b <= B; b++) {\n            if (a == 0 && b == 0) continue;\n            if (std::gcd(abs(a), abs(b)) != 1) continue;\n            addNormal(a, b);\n        }\n    }\n\n    // PCA-derived direction and its orthogonal.\n    {\n        ld mx = 0, my = 0;\n        for (int i = 0; i < N; i++) {\n            mx += X[i];\n            my += Y[i];\n        }\n        mx /= N;\n        my /= N;\n\n        ld cxx = 0, cyy = 0, cxy = 0;\n        for (int i = 0; i < N; i++) {\n            ld dx = X[i] - mx;\n            ld dy = Y[i] - my;\n            cxx += dx * dx;\n            cyy += dy * dy;\n            cxy += dx * dy;\n        }\n\n        ld theta = 0.5L * atan2l(2.0L * cxy, cxx - cyy);\n        int pa = (int)llround(cosl(theta) * 12.0L);\n        int pb = (int)llround(sinl(theta) * 12.0L);\n        if (pa == 0 && pb == 0) pa = 1;\n        addNormal(pa, pb);\n        addNormal(pb, -pa);\n    }\n\n    sort(normals.begin(), normals.end(), [&](auto& p1, auto& p2) {\n        ld a1 = atan2l((ld)p1.second, (ld)p1.first);\n        ld a2 = atan2l((ld)p2.second, (ld)p2.first);\n        if (a1 < 0) a1 += PI;\n        if (a2 < 0) a2 += PI;\n        if (a1 != a2) return a1 < a2;\n        return p1 < p2;\n    });\n\n    families.reserve(normals.size());\n    for (auto [a, b] : normals) {\n        auto it = famId.find({a, b});\n        if (it == famId.end()) {\n            int id = (int)families.size();\n            famId[{a, b}] = id;\n            families.push_back(buildFamily(a, b));\n        }\n    }\n\n    memo.resize(families.size());\n\n    // Single-family search.\n    vector<Solution> bestSingle(families.size());\n    for (int fid = 0; fid < (int)families.size(); fid++) {\n        bestSingle[fid] = searchSingle(fid);\n    }\n\n    Solution bestSol;\n    for (auto& s : bestSingle) {\n        if (better(s, bestSol)) bestSol = s;\n    }\n\n    // Select diverse families by angle bins.\n    vector<int> order(families.size());\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int i, int j) {\n        if (bestSingle[i].score != bestSingle[j].score) return bestSingle[i].score > bestSingle[j].score;\n        return families[i].ang < families[j].ang;\n    });\n\n    const int BINS = 4;\n    vector<int> picked(BINS, -1);\n    for (int fid : order) {\n        int bin = min(BINS - 1, (int)(families[fid].ang / PI * BINS));\n        if (bin < 0) bin = 0;\n        if (bin >= BINS) bin = BINS - 1;\n        if (picked[bin] == -1) picked[bin] = fid;\n    }\n\n    vector<int> selected;\n    vector<char> used(families.size(), 0);\n    for (int b = 0; b < BINS; b++) {\n        if (picked[b] != -1) {\n            selected.push_back(picked[b]);\n            used[picked[b]] = 1;\n        }\n    }\n    for (int fid : order) {\n        if ((int)selected.size() >= BINS) break;\n        if (!used[fid]) {\n            selected.push_back(fid);\n            used[fid] = 1;\n        }\n    }\n\n    vector<int> proxyTargets = buildProxyTargets();\n\n    // Pair search among selected diverse families.\n    for (int i = 0; i < (int)selected.size(); i++) {\n        for (int j = i + 1; j < (int)selected.size(); j++) {\n            Solution cand = searchPair(\n                selected[i], selected[j],\n                bestSingle[selected[i]], bestSingle[selected[j]],\n                proxyTargets\n            );\n            if (better(cand, bestSol)) bestSol = cand;\n        }\n    }\n\n    if (bestSol.score < 0) {\n        bestSol = evalSol({0}, {1}, {0});\n    }\n\n    bestSol = refineSolution(bestSol);\n\n    // Output.\n    vector<LineOut> lines;\n    for (int idx = 0; idx < (int)bestSol.fams.size(); idx++) {\n        int fid = bestSol.fams[idx];\n        int s = bestSol.sizes[idx];\n        int m = bestSol.modes[idx];\n        const vector<ll>& cuts = getCuts(fid, s, m);\n        for (ll c : cuts) {\n            lines.push_back(makeLine(families[fid].a, families[fid].b, c));\n        }\n    }\n\n    cout << lines.size() << '\\n';\n    for (auto& L : lines) {\n        cout << L.x1 << ' ' << L.y1 << ' ' << L.x2 << ' ' << L.y2 << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Cand {\n    array<int, 4> c{};\n    int bdL = 0, bdR = 0;\n    int sgL = 0, sgR = 0;\n    int perim = 0;\n};\n\nstruct StateInfo {\n    array<ll, 4> contrib{};\n    ll blockShare = 0;\n    int miss = -1;\n};\n\nstruct Node {\n    ll score;\n    int ver;\n    int cid;\n    bool operator<(const Node& other) const { return score < other.score; }\n};\n\nstruct Op {\n    array<int, 8> a{};\n};\n\nstruct Param {\n    ll A, B, C, D, E;\n    uint64_t seed;\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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto t0 = chrono::steady_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - t0).count();\n    };\n\n    int N, M;\n    cin >> N >> M;\n\n    const int V = N * N;\n    auto pid = [&](int x, int y) -> int { return x * N + y; };\n    auto decode = [&](int id) -> pair<int, int> { return {id / N, id % N}; };\n\n    const ll Cc = (N - 1) / 2;\n    vector<ll> wt(V);\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            ll dx = x - Cc, dy = y - Cc;\n            wt[pid(x, y)] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    vector<char> initOcc(V, 0);\n    ll initSum = 0;\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        int p = pid(x, y);\n        if (!initOcc[p]) {\n            initOcc[p] = 1;\n            initSum += wt[p];\n        }\n    }\n\n    // Initial prefix sums for quick filtering of illegal candidates.\n    vector<vector<int>> rowPref(N, vector<int>(N + 1, 0));\n    vector<vector<int>> colPref(N, vector<int>(N + 1, 0));\n    for (int y = 0; y < N; ++y) {\n        for (int x = 0; x < N; ++x) {\n            rowPref[y][x + 1] = rowPref[y][x] + initOcc[pid(x, y)];\n        }\n    }\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) {\n            colPref[x][y + 1] = colPref[x][y] + initOcc[pid(x, y)];\n        }\n    }\n\n    vector<int> d1Start(2 * N - 1), d2Start(2 * N - 1);\n    vector<vector<int>> d1Pref(2 * N - 1), d2Pref(2 * N - 1);\n\n    for (int diff = -(N - 1); diff <= N - 1; ++diff) {\n        int idx = diff + (N - 1);\n        int sx = max(0, diff);\n        int len = N - abs(diff);\n        d1Start[idx] = sx;\n        d1Pref[idx].assign(len + 1, 0);\n        for (int i = 0; i < len; ++i) {\n            int x = sx + i;\n            int y = x - diff;\n            d1Pref[idx][i + 1] = d1Pref[idx][i] + initOcc[pid(x, y)];\n        }\n    }\n    for (int s = 0; s <= 2 * N - 2; ++s) {\n        int sx = max(0, s - (N - 1));\n        int ex = min(N - 1, s);\n        int len = ex - sx + 1;\n        d2Start[s] = sx;\n        d2Pref[s].assign(len + 1, 0);\n        for (int i = 0; i < len; ++i) {\n            int x = sx + i;\n            int y = s - x;\n            d2Pref[s][i + 1] = d2Pref[s][i] + initOcc[pid(x, y)];\n        }\n    }\n\n    auto rowCnt = [&](int y, int l, int r) -> int {\n        if (l > r) return 0;\n        return rowPref[y][r + 1] - rowPref[y][l];\n    };\n    auto colCnt = [&](int x, int l, int r) -> int {\n        if (l > r) return 0;\n        return colPref[x][r + 1] - colPref[x][l];\n    };\n    auto d1Cnt = [&](int diff, int l, int r) -> int {\n        if (l > r) return 0;\n        int idx = diff + (N - 1);\n        int sx = d1Start[idx];\n        return d1Pref[idx][r - sx + 1] - d1Pref[idx][l - sx];\n    };\n    auto d2Cnt = [&](int sum, int l, int r) -> int {\n        if (l > r) return 0;\n        int sx = d2Start[sum];\n        return d2Pref[sum][r - sx + 1] - d2Pref[sum][l - sx];\n    };\n\n    const int H = N * (N - 1);\n    const int D = (N - 1) * (N - 1);\n    const int totalSeg = 2 * H + 2 * D;\n\n    auto hid = [&](int x, int y) -> int { return y * (N - 1) + x; };\n    auto vid = [&](int x, int y) -> int { return H + x * (N - 1) + y; };\n    auto pdiag = [&](int x, int y) -> int { return 2 * H + y * (N - 1) + x; };\n    auto ndiag = [&](int x, int y) -> int { return 2 * H + D + y * (N - 1) + x; };\n\n    vector<Cand> cands;\n    vector<uint16_t> bdPool, sgPool;\n    vector<vector<int>> cornerInc(V), boundaryInc(V), segInc(totalSeg);\n    vector<int> cornerDeg(V, 0);\n\n    vector<array<ll, 4>> initContrib;\n    vector<ll> initBlockShare;\n    vector<int> initCnt;\n    vector<int> initReadyMiss;\n\n    cands.reserve(800000);\n    initContrib.reserve(800000);\n    initBlockShare.reserve(800000);\n    initCnt.reserve(800000);\n    initReadyMiss.reserve(800000);\n    bdPool.reserve(5000000);\n    sgPool.reserve(5000000);\n\n    auto calcState = [&](int cid, const vector<char>& occ) -> StateInfo {\n        StateInfo st;\n        const Cand& cd = cands[cid];\n\n        int eidx[4];\n        ll ew[4];\n        int e = 0;\n        for (int i = 0; i < 4; ++i) {\n            if (!occ[cd.c[i]]) {\n                eidx[e] = i;\n                ew[e] = wt[cd.c[i]];\n                ++e;\n            }\n        }\n        if (e == 0) return st;\n\n        if (e == 1) {\n            st.contrib[eidx[0]] = 64LL * ew[0];\n            st.miss = cd.c[eidx[0]];\n        } else if (e == 2) {\n            st.contrib[eidx[0]] = 16LL * ew[1];\n            st.contrib[eidx[1]] = 16LL * ew[0];\n        } else if (e == 3) {\n            for (int t = 0; t < 3; ++t) {\n                ll mx = 0;\n                for (int u = 0; u < 3; ++u) {\n                    if (u == t) continue;\n                    mx = max(mx, ew[u]);\n                }\n                st.contrib[eidx[t]] = 4LL * mx;\n            }\n        } else {\n            for (int t = 0; t < 4; ++t) {\n                ll mx = 0;\n                for (int u = 0; u < 4; ++u) {\n                    if (u == t) continue;\n                    mx = max(mx, ew[u]);\n                }\n                st.contrib[eidx[t]] = mx;\n            }\n        }\n\n        ll total = 0;\n        for (ll v : st.contrib) total += v;\n        int blen = cd.bdR - cd.bdL;\n        st.blockShare = (blen > 0 ? max(1LL, (total + blen - 1) / blen) : 0);\n        return st;\n    };\n\n    auto addCandidate = [&](Cand&& cd, int cnt) {\n        if (cnt == 4) return;\n        int cid = (int)cands.size();\n        cands.push_back(std::move(cd));\n        initCnt.push_back(cnt);\n\n        for (int i = 0; i < 4; ++i) {\n            cornerInc[cands[cid].c[i]].push_back(cid);\n            cornerDeg[cands[cid].c[i]]++;\n        }\n        for (int i = cands[cid].bdL; i < cands[cid].bdR; ++i) {\n            boundaryInc[bdPool[i]].push_back(cid);\n        }\n        for (int i = cands[cid].sgL; i < cands[cid].sgR; ++i) {\n            segInc[sgPool[i]].push_back(cid);\n        }\n\n        StateInfo st = calcState(cid, initOcc);\n        initContrib.push_back(st.contrib);\n        initBlockShare.push_back(st.blockShare);\n        initReadyMiss.push_back(st.miss);\n    };\n\n    const int BAL = 15;\n    const int AX_LONG = 30;\n    const int DG_LONG_SUM = 30;\n    const int THIN_MIN = 2;\n\n    auto addAxisCand = [&](int x, int y, int w, int h) {\n        if (rowCnt(y, x + 1, x + w - 1) > 0) return;\n        if (rowCnt(y + h, x + 1, x + w - 1) > 0) return;\n        if (colCnt(x, y + 1, y + h - 1) > 0) return;\n        if (colCnt(x + w, y + 1, y + h - 1) > 0) return;\n\n        Cand cd;\n        cd.c = { pid(x, y), pid(x + w, y), pid(x + w, y + h), pid(x, y + h) };\n\n        int cnt = 0;\n        for (int i = 0; i < 4; ++i) cnt += initOcc[cd.c[i]];\n        if (cnt == 4) return;\n\n        cd.bdL = (int)bdPool.size();\n        for (int xx = x + 1; xx < x + w; ++xx) bdPool.push_back((uint16_t)pid(xx, y));\n        for (int yy = y + 1; yy < y + h; ++yy) bdPool.push_back((uint16_t)pid(x + w, yy));\n        for (int xx = x + w - 1; xx > x; --xx) bdPool.push_back((uint16_t)pid(xx, y + h));\n        for (int yy = y + h - 1; yy > y; --yy) bdPool.push_back((uint16_t)pid(x, yy));\n        cd.bdR = (int)bdPool.size();\n\n        cd.sgL = (int)sgPool.size();\n        for (int xx = x; xx < x + w; ++xx) sgPool.push_back((uint16_t)hid(xx, y));\n        for (int yy = y; yy < y + h; ++yy) sgPool.push_back((uint16_t)vid(x + w, yy));\n        for (int xx = x + w - 1; xx >= x; --xx) sgPool.push_back((uint16_t)hid(xx, y + h));\n        for (int yy = y + h - 1; yy >= y; --yy) sgPool.push_back((uint16_t)vid(x, yy));\n        cd.sgR = (int)sgPool.size();\n        cd.perim = cd.sgR - cd.sgL;\n\n        addCandidate(std::move(cd), cnt);\n    };\n\n    auto addDiagCand = [&](int x, int y, int a, int b) {\n        if (d1Cnt(x - y, x + 1, x + a - 1) > 0) return;\n        if (d2Cnt(x + y + 2 * a, x + a + 1, x + a + b - 1) > 0) return;\n        if (d1Cnt(x - y + 2 * b, x + b + 1, x + a + b - 1) > 0) return;\n        if (d2Cnt(x + y, x + 1, x + b - 1) > 0) return;\n\n        Cand cd;\n        cd.c = {\n            pid(x, y),\n            pid(x + a, y + a),\n            pid(x + a + b, y + a - b),\n            pid(x + b, y - b)\n        };\n\n        int cnt = 0;\n        for (int i = 0; i < 4; ++i) cnt += initOcc[cd.c[i]];\n        if (cnt == 4) return;\n\n        cd.bdL = (int)bdPool.size();\n        for (int t = 1; t < a; ++t) bdPool.push_back((uint16_t)pid(x + t, y + t));\n        for (int t = 1; t < b; ++t) bdPool.push_back((uint16_t)pid(x + a + t, y + a - t));\n        for (int t = 1; t < a; ++t) bdPool.push_back((uint16_t)pid(x + b + t, y - b + t));\n        for (int t = 1; t < b; ++t) bdPool.push_back((uint16_t)pid(x + t, y - t));\n        cd.bdR = (int)bdPool.size();\n\n        cd.sgL = (int)sgPool.size();\n        for (int t = 0; t < a; ++t) sgPool.push_back((uint16_t)pdiag(x + t, y + t));\n        for (int t = 0; t < b; ++t) sgPool.push_back((uint16_t)ndiag(x + a + t, y + a - t - 1));\n        for (int t = 0; t < a; ++t) sgPool.push_back((uint16_t)pdiag(x + b + t, y - b + t));\n        for (int t = 0; t < b; ++t) sgPool.push_back((uint16_t)ndiag(x + t, y - t - 1));\n        cd.sgR = (int)sgPool.size();\n        cd.perim = cd.sgR - cd.sgL;\n\n        addCandidate(std::move(cd), cnt);\n    };\n\n    // Build a rich but still manageable candidate pool.\n    for (int w = 1; w <= AX_LONG; ++w) {\n        for (int h = 1; h <= AX_LONG; ++h) {\n            bool keep = (w <= BAL && h <= BAL) || (min(w, h) <= THIN_MIN && max(w, h) <= AX_LONG);\n            if (!keep) continue;\n            for (int x = 0; x + w < N; ++x) {\n                for (int y = 0; y + h < N; ++y) {\n                    addAxisCand(x, y, w, h);\n                }\n            }\n        }\n    }\n\n    for (int a = 1; a <= DG_LONG_SUM - 1; ++a) {\n        for (int b = 1; a + b <= DG_LONG_SUM; ++b) {\n            bool keep = (a + b <= BAL) || (min(a, b) <= THIN_MIN && a + b <= DG_LONG_SUM);\n            if (!keep) continue;\n            for (int x = 0; x + a + b < N; ++x) {\n                for (int y = b; y + a < N; ++y) {\n                    addDiagCand(x, y, a, b);\n                }\n            }\n        }\n    }\n\n    const int Ccand = (int)cands.size();\n\n    vector<ll> initPot(V, 0), initBlock(V, 0);\n    for (int cid = 0; cid < Ccand; ++cid) {\n        const Cand& cd = cands[cid];\n        for (int i = 0; i < 4; ++i) {\n            int p = cd.c[i];\n            if (initContrib[cid][i]) initPot[p] += initContrib[cid][i];\n        }\n        for (int i = cd.bdL; i < cd.bdR; ++i) {\n            initBlock[bdPool[i]] += initBlockShare[cid];\n        }\n    }\n\n    auto simulate = [&](const Param& P) -> pair<ll, vector<Op>> {\n        vector<char> occ = initOcc;\n        vector<int> cnt = initCnt;\n        vector<char> alive(Ccand, 1);\n        vector<int> readyMiss = initReadyMiss;\n        vector<int> ver(Ccand, 0);\n        vector<array<ll, 4>> contrib = initContrib;\n        vector<ll> bshare = initBlockShare;\n        vector<ll> pot = initPot, block = initBlock;\n        vector<char> segUsed(totalSeg, 0);\n\n        vector<vector<int>> readyList(V);\n        for (int cid = 0; cid < Ccand; ++cid) {\n            if (readyMiss[cid] >= 0) readyList[readyMiss[cid]].push_back(cid);\n        }\n\n        vector<char> touchedMark(V, 0);\n        vector<int> touched;\n        touched.reserve(2048);\n\n        auto touch = [&](int p) {\n            if (!occ[p] && !touchedMark[p]) {\n                touchedMark[p] = 1;\n                touched.push_back(p);\n            }\n        };\n\n        auto removeCurrent = [&](int cid) {\n            const Cand& cd = cands[cid];\n            for (int i = 0; i < 4; ++i) {\n                ll v = contrib[cid][i];\n                if (!v) continue;\n                int p = cd.c[i];\n                pot[p] -= v;\n                touch(p);\n            }\n            if (bshare[cid] > 0) {\n                for (int i = cd.bdL; i < cd.bdR; ++i) {\n                    int p = bdPool[i];\n                    block[p] -= bshare[cid];\n                    touch(p);\n                }\n            }\n        };\n\n        auto addCurrent = [&](int cid) {\n            const Cand& cd = cands[cid];\n            for (int i = 0; i < 4; ++i) {\n                ll v = contrib[cid][i];\n                if (!v) continue;\n                int p = cd.c[i];\n                pot[p] += v;\n                touch(p);\n            }\n            if (bshare[cid] > 0) {\n                for (int i = cd.bdL; i < cd.bdR; ++i) {\n                    int p = bdPool[i];\n                    block[p] += bshare[cid];\n                    touch(p);\n                }\n            }\n        };\n\n        auto killCand = [&](int cid) {\n            if (!alive[cid]) return;\n            removeCurrent(cid);\n            alive[cid] = 0;\n            cnt[cid] = 4;\n            readyMiss[cid] = -1;\n            contrib[cid].fill(0);\n            bshare[cid] = 0;\n        };\n\n        auto scoreReady = [&](int cid) -> ll {\n            int p = readyMiss[cid];\n            ll s = P.A * wt[p] + P.B * pot[p] - P.C * block[p] - P.D * cands[cid].perim + P.E * cornerDeg[p];\n            s += (ll)(splitmix64(P.seed ^ ((uint64_t)cid * 0x9e3779b97f4a7c15ULL) ^ (uint64_t)p) % 11) - 5;\n            return s;\n        };\n\n        auto checkValid = [&](int cid) -> bool {\n            const Cand& cd = cands[cid];\n            for (int i = cd.bdL; i < cd.bdR; ++i) {\n                if (occ[bdPool[i]]) return false;\n            }\n            for (int i = cd.sgL; i < cd.sgR; ++i) {\n                if (segUsed[sgPool[i]]) return false;\n            }\n            return true;\n        };\n\n        priority_queue<Node> pq;\n        for (int cid = 0; cid < Ccand; ++cid) {\n            if (alive[cid] && cnt[cid] == 3 && readyMiss[cid] >= 0) {\n                ver[cid] = 1;\n                pq.push(Node{scoreReady(cid), ver[cid], cid});\n            }\n        }\n\n        vector<Op> ops;\n        ops.reserve(200000);\n        ll curSum = initSum;\n\n        vector<int> toRecalc, newReady;\n        toRecalc.reserve(64);\n        newReady.reserve(64);\n\n        while (!pq.empty()) {\n            if (elapsed() > 4.75) break;\n\n            Node cur = pq.top();\n            pq.pop();\n\n            int cid = cur.cid;\n            if (cur.ver != ver[cid]) continue;\n            if (!alive[cid] || cnt[cid] != 3) continue;\n\n            int miss = readyMiss[cid];\n            if (miss < 0 || occ[miss] || !checkValid(cid)) {\n                killCand(cid);\n                continue;\n            }\n\n            const Cand& cd = cands[cid];\n            int missIdx = -1;\n            for (int i = 0; i < 4; ++i) {\n                if (cd.c[i] == miss) {\n                    missIdx = i;\n                    break;\n                }\n            }\n            if (missIdx < 0) {\n                killCand(cid);\n                continue;\n            }\n\n            Op op;\n            for (int t = 0; t < 4; ++t) {\n                int p = cd.c[(missIdx + t) & 3];\n                auto [x, y] = decode(p);\n                op.a[2 * t] = x;\n                op.a[2 * t + 1] = y;\n            }\n            ops.push_back(op);\n            curSum += wt[miss];\n\n            toRecalc.clear();\n            newReady.clear();\n\n            // 1) Boundary conflict\n            for (int nid : boundaryInc[miss]) {\n                if (alive[nid]) killCand(nid);\n            }\n\n            // 2) Segment conflict\n            for (int i = cd.sgL; i < cd.sgR; ++i) {\n                int sid = sgPool[i];\n                if (segUsed[sid]) continue;\n                segUsed[sid] = 1;\n                for (int nid : segInc[sid]) {\n                    if (nid == cid) continue;\n                    if (alive[nid]) killCand(nid);\n                }\n            }\n\n            // 3) Occupy the new point\n            occ[miss] = 1;\n\n            // 4) Update candidates using miss as a corner\n            for (int nid : cornerInc[miss]) {\n                if (!alive[nid]) continue;\n                removeCurrent(nid);\n\n                if (cnt[nid] == 3) {\n                    alive[nid] = 0;\n                    cnt[nid] = 4;\n                    readyMiss[nid] = -1;\n                    contrib[nid].fill(0);\n                    bshare[nid] = 0;\n                    continue;\n                }\n\n                ++cnt[nid];\n                toRecalc.push_back(nid);\n            }\n\n            // 5) Recompute and re-add survivors\n            for (int nid : toRecalc) {\n                if (!alive[nid]) continue;\n                StateInfo st = calcState(nid, occ);\n                contrib[nid] = st.contrib;\n                bshare[nid] = st.blockShare;\n                readyMiss[nid] = st.miss;\n                addCurrent(nid);\n\n                if (cnt[nid] == 3 && readyMiss[nid] >= 0) {\n                    newReady.push_back(nid);\n                }\n            }\n\n            // 6) Requeue ready candidates whose score changed\n            for (int p : touched) {\n                if (!occ[p]) {\n                    for (int nid : readyList[p]) {\n                        if (!alive[nid] || cnt[nid] != 3 || readyMiss[nid] != p) continue;\n                        ++ver[nid];\n                        pq.push(Node{scoreReady(nid), ver[nid], nid});\n                    }\n                }\n                touchedMark[p] = 0;\n            }\n            touched.clear();\n\n            // 7) Add newly ready candidates\n            for (int nid : newReady) {\n                if (!alive[nid] || cnt[nid] != 3) continue;\n                int p = readyMiss[nid];\n                if (p < 0 || occ[p]) continue;\n                readyList[p].push_back(nid);\n                ++ver[nid];\n                pq.push(Node{scoreReady(nid), ver[nid], nid});\n            }\n        }\n\n        return {curSum, ops};\n    };\n\n    int simCount = 4;\n    if (Ccand > 1200000) simCount = 2;\n    else if (Ccand > 900000) simCount = 3;\n    if (elapsed() > 3.8) simCount = min(simCount, 1);\n    else if (elapsed() > 2.8) simCount = min(simCount, 2);\n\n    vector<Param> variants = {\n        {2600, 2, 1, 8, 1, 0x123456789abcdefULL},\n        {1800, 4, 2, 6, 1, 0x223456789abcdefULL},\n        {1200, 8, 4, 4, 2, 0x323456789abcdefULL},\n        {3000, 1, 1, 10, 1, 0x423456789abcdefULL}\n    };\n    variants.resize(simCount);\n\n    ll bestSum = -1;\n    vector<Op> bestOps;\n\n    for (int i = 0; i < simCount; ++i) {\n        if (elapsed() > 4.75) break;\n        auto [sum, ops] = simulate(variants[i]);\n        if (sum > bestSum || (sum == bestSum && ops.size() > bestOps.size())) {\n            bestSum = sum;\n            bestOps = move(ops);\n        }\n    }\n\n    cout << bestOps.size() << '\\n';\n    for (const auto& op : bestOps) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << op.a[i];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int CELLS = 100;\nstatic constexpr int COLORS = 3;\nstatic constexpr int EXACT_DEPTH = 4;\nstatic constexpr double DISCOUNT = 0.97;\n\nstruct Board {\n    array<uint8_t, CELLS> a{};\n};\n\nint F[CELLS];\nint tot[4];\nint prefCnt[CELLS + 1][4];\nint remainAfter[CELLS + 1][4];\ndouble futureWeight[CELLS + 1][4];\n\nint targetR[4], targetC[4];\nint targetDist[4][CELLS];\n\nint NB[CELLS][4];\nstatic constexpr char DIRS[4] = {'F', 'B', 'L', 'R'};\n\ninline void initNeighbors() {\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            NB[id][0] = (r + 1 < N ? (r + 1) * N + c : -1); // down\n            NB[id][1] = (r - 1 >= 0 ? (r - 1) * N + c : -1); // up\n            NB[id][2] = (c + 1 < N ? r * N + (c + 1) : -1);   // right\n            NB[id][3] = (c - 1 >= 0 ? r * N + (c - 1) : -1);  // left\n        }\n    }\n}\n\ninline int kthEmpty(const Board& b, int p) {\n    for (int i = 0; i < CELLS; ++i) {\n        if (b.a[i] == 0) {\n            --p;\n            if (p == 0) return i;\n        }\n    }\n    return -1;\n}\n\ninline int collectEmpties(const Board& b, int empties[]) {\n    int ec = 0;\n    for (int i = 0; i < CELLS; ++i) {\n        if (b.a[i] == 0) empties[ec++] = i;\n    }\n    return ec;\n}\n\ninline Board tilt(const Board& b, char d) {\n    Board r{};\n    r.a.fill(0);\n\n    if (d == 'L') {\n        for (int row = 0; row < N; ++row) {\n            int w = 0;\n            int base = row * N;\n            for (int c = 0; c < N; ++c) {\n                uint8_t v = b.a[base + c];\n                if (v) r.a[base + w++] = v;\n            }\n        }\n    } else if (d == 'R') {\n        for (int row = 0; row < N; ++row) {\n            int w = N - 1;\n            int base = row * N;\n            for (int c = N - 1; c >= 0; --c) {\n                uint8_t v = b.a[base + c];\n                if (v) r.a[base + w--] = v;\n            }\n        }\n    } else if (d == 'F') {\n        for (int c = 0; c < N; ++c) {\n            int w = 0;\n            for (int row = 0; row < N; ++row) {\n                uint8_t v = b.a[row * N + c];\n                if (v) r.a[w++ * N + c] = v;\n            }\n        }\n    } else { // 'B'\n        for (int c = 0; c < N; ++c) {\n            int w = N - 1;\n            for (int row = N - 1; row >= 0; --row) {\n                uint8_t v = b.a[row * N + c];\n                if (v) r.a[w-- * N + c] = v;\n            }\n        }\n    }\n    return r;\n}\n\ninline long long exactScore(const Board& b) {\n    bool vis[CELLS] = {};\n    int q[CELLS];\n    long long ans = 0;\n\n    for (int s = 0; s < CELLS; ++s) {\n        if (b.a[s] == 0 || vis[s]) continue;\n        uint8_t col = b.a[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            ++sz;\n            for (int k = 0; k < 4; ++k) {\n                int to = NB[v][k];\n                if (to != -1 && !vis[to] && b.a[to] == col) {\n                    vis[to] = true;\n                    q[tail++] = to;\n                }\n            }\n        }\n\n        ans += 1LL * sz * sz;\n    }\n    return ans;\n}\n\nstruct Info {\n    long long sumSq = 0;\n    int top[4][3]{};       // top[color][0..2]\n    int compCnt[4]{};      // components per color\n    int compSizeCell[CELLS]{};\n    long long rowSq[4]{};\n    long long colSq[4]{};\n    long long distSum[4]{};\n    int bboxArea[4]{};\n    int adj = 0;\n};\n\ninline void updTop(int t[3], int x) {\n    if (x > t[0]) {\n        t[2] = t[1];\n        t[1] = t[0];\n        t[0] = x;\n    } else if (x > t[1]) {\n        t[2] = t[1];\n        t[1] = x;\n    } else if (x > t[2]) {\n        t[2] = x;\n    }\n}\n\ninline Info analyze(const Board& b) {\n    Info info{};\n    bool vis[CELLS] = {};\n    int q[CELLS];\n    int compCells[CELLS];\n    int rowCnt[4][N] = {};\n    int colCnt[4][N] = {};\n\n    int minR[4], maxR[4], minC[4], maxC[4];\n    for (int c = 1; c <= 3; ++c) {\n        minR[c] = minC[c] = N;\n        maxR[c] = maxC[c] = -1;\n    }\n\n    for (int s = 0; s < CELLS; ++s) {\n        if (b.a[s] == 0 || vis[s]) continue;\n        uint8_t col = b.a[s];\n        int head = 0, tail = 0, cc = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        ++info.compCnt[col];\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            compCells[cc++] = v;\n            ++sz;\n\n            int r = v / N, c = v % N;\n            rowCnt[col][r]++;\n            colCnt[col][c]++;\n            info.distSum[col] += targetDist[col][v];\n            minR[col] = min(minR[col], r);\n            maxR[col] = max(maxR[col], r);\n            minC[col] = min(minC[col], c);\n            maxC[col] = max(maxC[col], c);\n\n            for (int k = 0; k < 4; ++k) {\n                int to = NB[v][k];\n                if (to != -1 && !vis[to] && b.a[to] == col) {\n                    vis[to] = true;\n                    q[tail++] = to;\n                }\n            }\n        }\n\n        info.sumSq += 1LL * sz * sz;\n        updTop(info.top[col], sz);\n        for (int i = 0; i < cc; ++i) info.compSizeCell[compCells[i]] = sz;\n    }\n\n    for (int c = 1; c <= 3; ++c) {\n        long long rs = 0, cs = 0;\n        for (int i = 0; i < N; ++i) {\n            rs += 1LL * rowCnt[c][i] * rowCnt[c][i];\n            cs += 1LL * colCnt[c][i] * colCnt[c][i];\n        }\n        info.rowSq[c] = rs;\n        info.colSq[c] = cs;\n\n        if (info.compCnt[c] == 0) {\n            info.bboxArea[c] = 0;\n        } else {\n            int h = maxR[c] - minR[c] + 1;\n            int w = maxC[c] - minC[c] + 1;\n            info.bboxArea[c] = h * w;\n        }\n    }\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            if (b.a[id] == 0) continue;\n            if (c + 1 < N && b.a[id + 1] == b.a[id]) ++info.adj;\n            if (r + 1 < N && b.a[id + N] == b.a[id]) ++info.adj;\n        }\n    }\n\n    return info;\n}\n\ninline double heuristicFromInfo(const Info& info, int idx) {\n    double s = (double)info.sumSq;\n\n    for (int c = 1; c <= 3; ++c) {\n        double rem = remainAfter[idx][c] + 0.25 * futureWeight[idx][c];\n        double top = info.top[c][0] + 0.65 * info.top[c][1] + 0.35 * info.top[c][2];\n        double avgDist = info.distSum[c] / max(1, tot[c]);\n\n        double pot = 1.4 * top;\n        pot += 0.012 * (double)(info.rowSq[c] + info.colSq[c]);\n        pot -= 0.10 * avgDist;\n        pot -= 0.25 * info.compCnt[c];\n        pot -= 0.02 * info.bboxArea[c];\n\n        s += rem * pot;\n    }\n\n    s += 0.04 * info.adj;\n    return s;\n}\n\ninline int findMarkerPos(const Board& b) {\n    for (int i = 0; i < CELLS; ++i) if (b.a[i] == 4) return i;\n    return -1;\n}\n\ninline double markerBonus(const Info& info, int pos, int color, int idx) {\n    if (pos < 0) return 0.0;\n    int r = pos / N, c = pos % N;\n    double imp = futureWeight[idx][color] / max(1, tot[color]);\n    double dist = abs(r - targetR[color]) + abs(c - targetC[color]);\n    return (0.75 + 2.5 * imp) * (double)info.compSizeCell[pos] - 0.12 * dist;\n}\n\ndouble exactValue(const Board& state, int idx);\n\ndouble scoreCurrentCandidate(const Board& afterCurrentTilt, int nextIdx) {\n    int empties[CELLS];\n    int ec = collectEmpties(afterCurrentTilt, empties);\n\n    if (100 - nextIdx <= EXACT_DEPTH) {\n        return exactValue(afterCurrentTilt, nextIdx);\n    }\n\n    double sum = 0.0;\n    for (int i = 0; i < ec; ++i) {\n        int pos = empties[i];\n\n        Board real = afterCurrentTilt;\n        real.a[pos] = (uint8_t)F[nextIdx];\n\n        Board mark = afterCurrentTilt;\n        mark.a[pos] = 4;\n\n        double best = -1e100;\n        for (char d : DIRS) {\n            Board u = tilt(real, d);\n            Board m = tilt(mark, d);\n            int mp = findMarkerPos(m);\n\n            Info info = analyze(u);\n            double v = heuristicFromInfo(info, nextIdx + 1);\n            v += markerBonus(info, mp, F[nextIdx], nextIdx + 1);\n\n            if (v > best) best = v;\n        }\n        sum += best;\n    }\n\n    return sum / ec;\n}\n\ndouble exactValue(const Board& state, int idx) {\n    if (idx >= CELLS) return (double)exactScore(state);\n\n    if (idx == CELLS - 1) {\n        int empties[CELLS];\n        int ec = collectEmpties(state, empties);\n        double sum = 0.0;\n        for (int i = 0; i < ec; ++i) {\n            Board t = state;\n            t.a[empties[i]] = (uint8_t)F[idx];\n            sum += (double)exactScore(t);\n        }\n        return sum / ec;\n    }\n\n    int empties[CELLS];\n    int ec = collectEmpties(state, empties);\n    double sum = 0.0;\n\n    for (int i = 0; i < ec; ++i) {\n        Board t = state;\n        t.a[empties[i]] = (uint8_t)F[idx];\n\n        double best = -1e100;\n        for (char d : DIRS) {\n            Board u = tilt(t, d);\n            double v = exactValue(u, idx + 1);\n            if (v > best) best = v;\n        }\n        sum += best;\n    }\n\n    return sum / ec;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    initNeighbors();\n\n    for (int i = 0; i < CELLS; ++i) cin >> F[i];\n\n    for (int i = 0; i < CELLS; ++i) {\n        for (int c = 1; c <= 3; ++c) prefCnt[i + 1][c] = prefCnt[i][c];\n        prefCnt[i + 1][F[i]]++;\n    }\n    for (int i = 0; i <= CELLS; ++i) {\n        for (int c = 1; c <= 3; ++c) {\n            remainAfter[i][c] = prefCnt[CELLS][c] - prefCnt[i][c];\n        }\n    }\n\n    for (int c = 1; c <= 3; ++c) futureWeight[CELLS][c] = 0.0;\n    for (int i = CELLS - 1; i >= 0; --i) {\n        for (int c = 1; c <= 3; ++c) futureWeight[i][c] = futureWeight[i + 1][c] * DISCOUNT;\n        futureWeight[i][F[i]] += 1.0;\n    }\n\n    vector<pair<int,int>> ord;\n    for (int c = 1; c <= 3; ++c) ord.push_back({tot[c], c});\n    sort(ord.begin(), ord.end(), [](const auto& x, const auto& y) {\n        if (x.first != y.first) return x.first > y.first;\n        return x.second < y.second;\n    });\n\n    int corners[3][2] = {{0, 0}, {0, 9}, {9, 0}};\n    for (int i = 0; i < 3; ++i) {\n        int color = ord[i].second;\n        targetR[color] = corners[i][0];\n        targetC[color] = corners[i][1];\n    }\n\n    for (int c = 1; c <= 3; ++c) {\n        for (int i = 0; i < CELLS; ++i) {\n            int r = i / N, col = i % N;\n            targetDist[c][i] = abs(r - targetR[c]) + abs(col - targetC[c]);\n        }\n    }\n\n    Board board{};\n\n    for (int t = 0; t < CELLS; ++t) {\n        int p;\n        cin >> p;\n\n        Board cur = board;\n        int pos = kthEmpty(cur, p);\n        cur.a[pos] = (uint8_t)F[t];\n\n        if (t == CELLS - 1) {\n            board = cur;\n            break;\n        }\n\n        int nextIdx = t + 1;\n        double bestScore = -1e100;\n        Board bestBoard = cur;\n        char bestDir = 'F';\n\n        for (char d : DIRS) {\n            Board real = tilt(cur, d);\n\n            double sc;\n            if (100 - nextIdx <= EXACT_DEPTH) {\n                sc = exactValue(real, nextIdx);\n            } else {\n                Info info = analyze(real);\n\n                Board mark = cur;\n                mark.a[pos] = 4;\n                Board markTilt = tilt(mark, d);\n                int markerPos = findMarkerPos(markTilt);\n\n                sc = scoreCurrentCandidate(real, nextIdx);\n                sc += 0.02 * heuristicFromInfo(info, nextIdx);\n                sc += markerBonus(info, markerPos, F[t], nextIdx);\n            }\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestBoard = real;\n                bestDir = d;\n            }\n        }\n\n        board = bestBoard;\n        cout << bestDir << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ld = long double;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr ld TINY = 1e-300L;\n\nstruct Cand {\n    vector<int> parts;      // sorted ascending\n    bool comp;              // false: union of cliques, true: complement\n    vector<ld> hist;        // expected noisy degree histogram\n    vector<ld> logHist;     // log(hist)\n    vector<ld> feat;        // for farthest-point selection\n    long long edge0 = 0;    // original edge count\n    long long tri0 = 0;     // original triangle count\n    ld triMean = 0;         // expected noisy triangle count\n    ld triVar = 1;          // approximate variance of noisy triangle count\n};\n\nstatic vector<vector<ld>> build_binom(int n, ld q) {\n    vector<vector<ld>> dp(n + 1, vector<ld>(n + 1, 0.0L));\n    dp[0][0] = 1.0L;\n    for (int i = 1; i <= n; ++i) {\n        dp[i][0] = dp[i - 1][0] * (1.0L - q);\n        for (int k = 1; k < i; ++k) {\n            dp[i][k] = dp[i - 1][k] * (1.0L - q) + dp[i - 1][k - 1] * q;\n        }\n        dp[i][i] = dp[i - 1][i - 1] * q;\n    }\n    return dp;\n}\n\nstatic string build_graph(const Cand& c, int N) {\n    array<int, MAXN> grp{};\n    int p = 0;\n    for (int i = 0; i < (int)c.parts.size(); ++i) {\n        for (int t = 0; t < c.parts[i]; ++t) grp[p++] = i;\n    }\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            bool same = (grp[i] == grp[j]);\n            bool e = c.comp ? !same : same;\n            s.push_back(e ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    ld eps;\n    cin >> M >> eps;\n\n    // N depends only on epsilon.\n    int N = 40 + (int)llround(125.0L * eps);\n    N = min(N, 100);\n\n    const long long totalPairs = 1LL * N * (N - 1) / 2;\n    const long long totalTri = 1LL * N * (N - 1) * (N - 2) / 6;\n\n    // Precompute degree distributions.\n    // r = original degree.\n    auto binStay = build_binom(N - 1, 1.0L - eps);\n    auto binFlip = build_binom(N - 1, eps);\n\n    vector<vector<ld>> degP(N, vector<ld>(N, 0.0L));\n    for (int r = 0; r < N; ++r) {\n        vector<ld> pmf(N, 0.0L);\n        int n1 = r;\n        int n0 = N - 1 - r;\n        for (int a = 0; a <= n1; ++a) {\n            ld pa = binStay[n1][a];\n            if (pa == 0.0L) continue;\n            for (int b = 0; b <= n0; ++b) {\n                pmf[a + b] += pa * binFlip[n0][b];\n            }\n        }\n        ld sum = 0.0L;\n        for (ld x : pmf) sum += x;\n        if (sum <= 0.0L) sum = 1.0L;\n        for (int d = 0; d < N; ++d) degP[r][d] = pmf[d] / sum;\n    }\n\n    auto make_candidate = [&](vector<int> parts, bool comp) -> Cand {\n        sort(parts.begin(), parts.end());\n        Cand c;\n        c.parts = parts;\n        c.comp = comp;\n\n        int k = (int)parts.size();\n        c.hist.assign(N, 0.0L);\n        c.logHist.assign(N, 0.0L);\n        c.feat.clear();\n        c.feat.reserve(N + 2);\n\n        long long same3 = 0; // sum C(s,3)\n        long long one1 = 0;  // sum C(s,2)*(N-s)\n        long long unionEdges = 0;\n\n        for (int s : parts) {\n            unionEdges += 1LL * s * (s - 1) / 2;\n            same3 += 1LL * s * (s - 1) * (s - 2) / 6;\n            one1 += 1LL * s * (s - 1) / 2 * (N - s);\n\n            int r = comp ? (N - s) : (s - 1);\n            ld w = (ld)s / (ld)N;\n            for (int d = 0; d < N; ++d) {\n                c.hist[d] += w * degP[r][d];\n            }\n        }\n\n        ld sumHist = 0.0L;\n        for (ld x : c.hist) sumHist += x;\n        if (sumHist <= 0.0L) sumHist = 1.0L;\n\n        for (int d = 0; d < N; ++d) {\n            c.hist[d] /= sumHist;\n            c.logHist[d] = logl(max(c.hist[d], TINY));\n            c.feat.push_back(sqrtl(max(c.hist[d], 0.0L)));\n        }\n\n        // Additional scalar features for selection.\n        c.edge0 = comp ? (totalPairs - unionEdges) : unionEdges;\n\n        if (!comp) {\n            long long zero = totalTri - same3 - one1;\n            long double p3 = powl(1.0L - eps, 3);\n            long double p1 = (1.0L - eps) * eps * eps;\n            long double p0 = eps * eps * eps;\n\n            c.tri0 = same3;\n            c.triMean = (ld)same3 * p3 + (ld)one1 * p1 + (ld)zero * p0;\n            c.triVar = (ld)same3 * p3 * (1.0L - p3)\n                     + (ld)one1 * p1 * (1.0L - p1)\n                     + (ld)zero * p0 * (1.0L - p0);\n        } else {\n            long long zero = same3;\n            long long two = one1;\n            long long three = totalTri - zero - two;\n\n            long double p0 = eps * eps * eps;\n            long double p2 = (1.0L - eps) * (1.0L - eps) * eps;\n            long double p3 = powl(1.0L - eps, 3);\n\n            c.tri0 = three;\n            c.triMean = (ld)zero * p0 + (ld)two * p2 + (ld)three * p3;\n            c.triVar = (ld)zero * p0 * (1.0L - p0)\n                     + (ld)two * p2 * (1.0L - p2)\n                     + (ld)three * p3 * (1.0L - p3);\n        }\n\n        // Inflate triangle variance a bit to avoid overconfidence.\n        c.triVar = max<ld>(1.0L, c.triVar * 2.0L);\n\n        c.feat.push_back((ld)c.edge0 / (ld)max<long long>(1, totalPairs) * 2.0L);\n        c.feat.push_back((ld)c.tri0 / (ld)max<long long>(1, totalTri) * 2.0L);\n        return c;\n    };\n\n    auto build_pool = [&](int step, int span) -> vector<Cand> {\n        vector<Cand> pool;\n        set<string> seen;\n\n        auto add = [&](const vector<int>& parts, bool comp) {\n            vector<int> p = parts;\n            sort(p.begin(), p.end());\n            string key;\n            key.reserve(32);\n            key.push_back(comp ? '1' : '0');\n            key.push_back(':');\n            for (int x : p) {\n                key += to_string(x);\n                key.push_back(',');\n            }\n            if (seen.insert(key).second) pool.push_back(make_candidate(p, comp));\n        };\n\n        int minS = max(4, N / 10);\n\n        // 2-partitions\n        {\n            int lo = max(minS, N / 2 - span);\n            int hi = min(N - minS, N / 2 + span);\n            for (int a = lo; a <= hi; a += step) {\n                int b = N - a;\n                if (a <= b && b >= minS) add({a, b}, false), add({a, b}, true);\n            }\n        }\n\n        // 3-partitions\n        {\n            int center = N / 3;\n            int loA = max(minS, center - span);\n            int hiA = min(N - 2 * minS, center + span);\n            for (int a = loA; a <= hiA; a += step) {\n                int loB = max(a, center - span);\n                int hiB = min(N - a - minS, center + span);\n                for (int b = loB; b <= hiB; b += step) {\n                    int c = N - a - b;\n                    if (c < b || c < minS) continue;\n                    add({a, b, c}, false);\n                    add({a, b, c}, true);\n                }\n            }\n        }\n\n        // 4-partitions\n        {\n            int center = N / 4;\n            int loA = max(minS, center - span);\n            int hiA = min(N - 3 * minS, center + span);\n            for (int a = loA; a <= hiA; a += step) {\n                int loB = max(a, center - span);\n                int hiB = min(N - a - 2 * minS, center + span);\n                for (int b = loB; b <= hiB; b += step) {\n                    int loC = max(b, center - span);\n                    int hiC = min(N - a - b - minS, center + span);\n                    for (int c = loC; c <= hiC; c += step) {\n                        int d = N - a - b - c;\n                        if (d < c || d < minS) continue;\n                        add({a, b, c, d}, false);\n                        add({a, b, c, d}, true);\n                    }\n                }\n            }\n        }\n\n        return pool;\n    };\n\n    int step = (N >= 70 ? 2 : 1);\n    int span = max(5, N / 6);\n\n    vector<Cand> pool = build_pool(step, span);\n    if ((int)pool.size() < M) {\n        pool = build_pool(1, span + max(4, N / 10));\n    }\n    if ((int)pool.size() < M) {\n        // Very rare fallback.\n        pool = build_pool(1, N / 3);\n    }\n\n    int P = (int)pool.size();\n\n    // Select a balanced seed.\n    int seed = 0;\n    ld bestVar = 1e100L;\n    for (int i = 0; i < P; ++i) {\n        if (pool[i].comp) continue;\n        ld mean = (ld)N / (ld)pool[i].parts.size();\n        ld var = 0.0L;\n        for (int s : pool[i].parts) {\n            ld d = (ld)s - mean;\n            var += d * d;\n        }\n        if (var < bestVar) {\n            bestVar = var;\n            seed = i;\n        }\n    }\n\n    auto dist = [&](const Cand& a, const Cand& b) -> ld {\n        ld s = 0.0L;\n        int D = (int)a.feat.size();\n        for (int i = 0; i < D; ++i) {\n            ld diff = a.feat[i] - b.feat[i];\n            s += diff * diff;\n        }\n        return s;\n    };\n\n    // Pairwise distances for farthest-point selection.\n    vector<vector<ld>> dmat(P, vector<ld>(P, 0.0L));\n    for (int i = 0; i < P; ++i) {\n        for (int j = i + 1; j < P; ++j) {\n            dmat[i][j] = dmat[j][i] = dist(pool[i], pool[j]);\n        }\n    }\n\n    vector<int> order;\n    vector<char> used(P, 0);\n    vector<ld> best(P, 1e100L);\n\n    order.push_back(seed);\n    used[seed] = 1;\n    for (int i = 0; i < P; ++i) best[i] = dmat[i][seed];\n\n    while ((int)order.size() < min(M, P)) {\n        int u = -1;\n        ld val = -1.0L;\n        for (int i = 0; i < P; ++i) {\n            if (used[i]) continue;\n            if (u == -1 || best[i] > val) {\n                u = i;\n                val = best[i];\n            }\n        }\n        if (u == -1) break;\n        order.push_back(u);\n        used[u] = 1;\n        for (int i = 0; i < P; ++i) {\n            if (!used[i]) best[i] = min(best[i], dmat[i][u]);\n        }\n    }\n\n    vector<Cand> chosen;\n    chosen.reserve(M);\n    for (int i = 0; i < M; ++i) {\n        chosen.push_back(pool[order[i % (int)order.size()]]);\n    }\n\n    // Output graphs.\n    cout << N << '\\n';\n    for (int i = 0; i < M; ++i) {\n        cout << build_graph(chosen[i], N) << '\\n';\n    }\n    cout.flush();\n\n    // Precompute a constant edge variance.\n    const ld edgeVar = max<ld>(1.0L, (ld)totalPairs * eps * (1.0L - eps));\n\n    // Decode 100 queries.\n    for (int q = 0; q < 100; ++q) {\n        string H;\n        cin >> H;\n\n        array<int, MAXN> deg{};\n        deg.fill(0);\n        array<array<unsigned char, MAXN>, MAXN> adj{};\n        int idx = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j, ++idx) {\n                if (H[idx] == '1') {\n                    adj[i][j] = adj[j][i] = 1;\n                    ++deg[i];\n                    ++deg[j];\n                }\n            }\n        }\n\n        long long edgeObs = 0;\n        array<int, MAXN> cnt{};\n        cnt.fill(0);\n        for (int i = 0; i < N; ++i) {\n            edgeObs += deg[i];\n            ++cnt[deg[i]];\n        }\n        edgeObs /= 2;\n\n        long long triObs = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) if (adj[i][j]) {\n                for (int k = j + 1; k < N; ++k) {\n                    if (adj[i][k] && adj[j][k]) ++triObs;\n                }\n            }\n        }\n\n        int bestId = 0;\n        ld bestScore = -1e100L;\n\n        for (int id = 0; id < M; ++id) {\n            const Cand& c = chosen[id];\n\n            ld score = 0.0L;\n\n            // Degree histogram likelihood.\n            for (int d = 0; d < N; ++d) {\n                if (cnt[d]) score += (ld)cnt[d] * c.logHist[d];\n            }\n\n            // Edge count Gaussian score.\n            ld edgeMean = (ld)totalPairs * eps + (1.0L - 2.0L * eps) * (ld)c.edge0;\n            ld de = (ld)edgeObs - edgeMean;\n            score -= de * de / (2.0L * edgeVar);\n\n            // Triangle count Gaussian score.\n            ld dt = (ld)triObs - c.triMean;\n            score -= dt * dt / (2.0L * c.triVar) + 0.5L * logl(c.triVar);\n\n            if (score > bestScore) {\n                bestScore = score;\n                bestId = id;\n            }\n        }\n\n        cout << bestId << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ld = long double;\n\nstatic constexpr int MAXD = 31;\nstatic constexpr int GRID = 20;\nstatic constexpr int CELLS = GRID * GRID;\nstatic constexpr ll INFLL = (1LL << 62);\n\nstruct Edge {\n    int u, v;\n    ll w;\n    int cell;\n    uint64_t morton;\n    ld rawImp = 0.0L;\n    ld normImp = 0.0L;\n};\n\nstruct Adj {\n    int to, id;\n};\n\nstatic inline ll sqdist(int x1, int y1, int x2, int y2) {\n    ll dx = (ll)x1 - x2;\n    ll dy = (ll)y1 - y2;\n    return dx * dx + dy * dy;\n}\n\nstatic inline uint32_t part1by1(uint32_t n) {\n    n &= 0x0000ffffu;\n    n = (n | (n << 8)) & 0x00FF00FFu;\n    n = (n | (n << 4)) & 0x0F0F0F0Fu;\n    n = (n | (n << 2)) & 0x33333333u;\n    n = (n | (n << 1)) & 0x55555555u;\n    return n;\n}\n\nstatic inline uint64_t mortonCode(int x, int y) {\n    return (uint64_t)part1by1((uint32_t)x) | ((uint64_t)part1by1((uint32_t)y) << 1);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<int> deg(N, 0);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        deg[u]++;\n        deg[v]++;\n    }\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    vector<vector<Adj>> g(N);\n    for (int i = 0; i < N; ++i) g[i].reserve(deg[i]);\n    for (int i = 0; i < M; ++i) {\n        g[edges[i].u].push_back({edges[i].v, i});\n        g[edges[i].v].push_back({edges[i].u, i});\n    }\n\n    // Capacity profile used only for initial balanced greedy assignment.\n    vector<int> cap(D, M / D);\n    for (int i = 0; i < M % D; ++i) cap[i]++;\n\n    // Spatial features for edges.\n    for (int i = 0; i < M; ++i) {\n        int mx = xs[edges[i].u] + xs[edges[i].v];\n        int my = ys[edges[i].u] + ys[edges[i].v];\n        int cx = min(GRID - 1, (mx * GRID) / 2001);\n        int cy = min(GRID - 1, (my * GRID) / 2001);\n        edges[i].cell = cx * GRID + cy;\n        edges[i].morton = mortonCode(mx, my);\n    }\n\n    vector<ld> invSqrtDeg(N);\n    for (int i = 0; i < N; ++i) invSqrtDeg[i] = 1.0L / sqrtl((ld)deg[i]);\n\n    // ---------- Source sampling ----------\n    int Simp = min(50, N - 4);   // for importance estimation\n    int Seval = 4;               // for candidate evaluation\n    int Stotal = Simp + Seval;\n\n    vector<int> sources;\n    sources.reserve(Stotal);\n\n    int first = 0;\n    for (int i = 1; i < N; ++i) if (deg[i] > deg[first]) first = i;\n    sources.push_back(first);\n\n    vector<ll> mind2(N, INFLL);\n    vector<char> used(N, false);\n    used[first] = true;\n    for (int v = 0; v < N; ++v) mind2[v] = sqdist(xs[v], ys[v], xs[first], ys[first]);\n\n    for (int t = 1; t < Stotal; ++t) {\n        int best = -1;\n        ll bestd = -1;\n        int bestDeg = -1;\n        for (int v = 0; v < N; ++v) if (!used[v]) {\n            if (mind2[v] > bestd || (mind2[v] == bestd && deg[v] > bestDeg)) {\n                best = v;\n                bestd = mind2[v];\n                bestDeg = deg[v];\n            }\n        }\n        sources.push_back(best);\n        used[best] = true;\n        for (int v = 0; v < N; ++v) if (!used[v]) {\n            mind2[v] = min(mind2[v], sqdist(xs[v], ys[v], xs[best], ys[best]));\n        }\n    }\n\n    // ---------- Edge importance estimation (weighted Brandes on sampled sources) ----------\n    vector<ld> edgeBC(M, 0.0L);\n    vector<ll> dist(N);\n    vector<ld> sigma(N), delta(N);\n    vector<vector<int>> predV(N), predE(N);\n    for (int v = 0; v < N; ++v) {\n        predV[v].reserve(deg[v] + 2);\n        predE[v].reserve(deg[v] + 2);\n    }\n    vector<int> order;\n    order.reserve(N);\n\n    auto brandesSource = [&](int s) {\n        fill(dist.begin(), dist.end(), INFLL);\n        fill(sigma.begin(), sigma.end(), 0.0L);\n        fill(delta.begin(), delta.end(), 0.0L);\n        for (int v = 0; v < N; ++v) {\n            predV[v].clear();\n            predE[v].clear();\n        }\n        order.clear();\n\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        sigma[s] = 1.0L;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n            order.push_back(v);\n\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                int eid = e.id;\n                ll nd = d + edges[eid].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n                    sigma[to] = sigma[v];\n                    predV[to].clear();\n                    predE[to].clear();\n                    predV[to].push_back(v);\n                    predE[to].push_back(eid);\n                } else if (nd == dist[to]) {\n                    sigma[to] += sigma[v];\n                    predV[to].push_back(v);\n                    predE[to].push_back(eid);\n                }\n            }\n        }\n\n        for (int idx = (int)order.size() - 1; idx >= 0; --idx) {\n            int w = order[idx];\n            if (sigma[w] == 0.0L) continue;\n            for (int k = 0; k < (int)predV[w].size(); ++k) {\n                int v = predV[w][k];\n                int eid = predE[w][k];\n                ld c = (sigma[v] / sigma[w]) * (1.0L + delta[w]);\n                edgeBC[eid] += c;\n                delta[v] += c;\n            }\n        }\n    };\n\n    for (int i = 0; i < Simp; ++i) brandesSource(sources[i]);\n\n    ld meanRaw = 0.0L;\n    for (int i = 0; i < M; ++i) {\n        edges[i].rawImp = sqrtl(edgeBC[i] / (2.0L * max(1, Simp)) + 1.0L);\n        edges[i].rawImp *= 1.0L + 0.03L * ((ld)edges[i].w / 1000000.0L);\n        meanRaw += edges[i].rawImp;\n    }\n    meanRaw /= max(1, M);\n    if (meanRaw <= 0) meanRaw = 1.0L;\n\n    for (int i = 0; i < M; ++i) {\n        edges[i].normImp = edges[i].rawImp / meanRaw;\n    }\n\n    // ---------- Evaluation sources ----------\n    vector<vector<ll>> baseDist(Seval, vector<ll>(N));\n    auto dijkstraPlain = [&](int s, vector<ll> &out) {\n        fill(out.begin(), out.end(), INFLL);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        out[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != out[v]) continue;\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                int eid = e.id;\n                ll nd = d + edges[eid].w;\n                if (nd < out[to]) {\n                    out[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n    for (int i = 0; i < Seval; ++i) {\n        dijkstraPlain(sources[Simp + i], baseDist[i]);\n    }\n\n    auto dijkstraSkipDay = [&](int s, const vector<int> &dayOf, int banDay, vector<ll> &out) {\n        fill(out.begin(), out.end(), INFLL);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        out[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != out[v]) continue;\n            for (const auto &e : g[v]) {\n                int to = e.to;\n                int eid = e.id;\n                if (dayOf[eid] == banDay) continue;\n                ll nd = d + edges[eid].w;\n                if (nd < out[to]) {\n                    out[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    };\n\n    // ---------- Deterministic order builders ----------\n    uint64_t baseSeed = 0x123456789abcdefULL\n                      ^ (uint64_t)N * 1000003ULL\n                      ^ (uint64_t)M * 10007ULL\n                      ^ (uint64_t)D * 1000000007ULL\n                      ^ (uint64_t)K * 1000000009ULL;\n\n    auto makeImportanceOrder = [&]() {\n        vector<pair<ld,int>> key(M);\n        for (int i = 0; i < M; ++i) key[i] = {-edges[i].rawImp, i};\n        sort(key.begin(), key.end());\n        vector<int> ord(M);\n        for (int i = 0; i < M; ++i) ord[i] = key[i].second;\n        return ord;\n    };\n\n    auto makeMortonOrder = [&]() {\n        vector<pair<uint64_t,int>> key(M);\n        for (int i = 0; i < M; ++i) key[i] = {edges[i].morton, i};\n        sort(key.begin(), key.end());\n        vector<int> ord(M);\n        for (int i = 0; i < M; ++i) ord[i] = key[i].second;\n        return ord;\n    };\n\n    auto makeDegreeBiasOrder = [&]() {\n        vector<pair<ld,int>> key(M);\n        for (int i = 0; i < M; ++i) {\n            ld s = edges[i].rawImp * (1.0L + 0.25L * (invSqrtDeg[edges[i].u] + invSqrtDeg[edges[i].v]));\n            key[i] = {-s, i};\n        }\n        sort(key.begin(), key.end());\n        vector<int> ord(M);\n        for (int i = 0; i < M; ++i) ord[i] = key[i].second;\n        return ord;\n    };\n\n    auto makeNoisyImportanceOrder = [&](uint64_t seed) {\n        mt19937_64 rng(seed);\n        vector<pair<ld,int>> key(M);\n        for (int i = 0; i < M; ++i) {\n            ld noise = ((ld)(rng() & ((1ULL << 53) - 1))) / ((ld)((1ULL << 53) - 1));\n            noise = noise * 2.0L - 1.0L; // [-1, 1]\n            ld s = edges[i].rawImp * (1.0L + 0.05L * noise);\n            key[i] = {-s, i};\n        }\n        sort(key.begin(), key.end());\n        vector<int> ord(M);\n        for (int i = 0; i < M; ++i) ord[i] = key[i].second;\n        return ord;\n    };\n\n    struct Params {\n        ld wV, wC, wDay, wCnt;\n    };\n\n    auto buildCandidate = [&](const vector<int> &ord, const Params &p) {\n        vector<array<ld, MAXD>> vLoad(N), cLoad(CELLS);\n        for (auto &a : vLoad) a.fill(0.0L);\n        for (auto &a : cLoad) a.fill(0.0L);\n\n        vector<ld> dayLoad(D, 0.0L);\n        vector<int> cnt(D, 0);\n        vector<int> ans(M, -1);\n\n        ld target = (ld)M / (ld)D;\n\n        auto addDelta = [&](int e, int d) -> ld {\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n            ld x = edges[e].normImp;\n            ld xu = x * invSqrtDeg[u];\n            ld xv = x * invSqrtDeg[v];\n\n            auto sq = [](ld z) { return z * z; };\n\n            ld delta = 0.0L;\n            delta += p.wV * (sq(vLoad[u][d] + xu) - sq(vLoad[u][d]));\n            delta += p.wV * (sq(vLoad[v][d] + xv) - sq(vLoad[v][d]));\n            delta += p.wC * (sq(cLoad[c][d] + x) - sq(cLoad[c][d]));\n            delta += p.wDay * (sq(dayLoad[d] + x - target) - sq(dayLoad[d] - target));\n            delta += p.wCnt * (sq((ld)cnt[d] + 1.0L - target) - sq((ld)cnt[d] - target));\n            return delta;\n        };\n\n        auto moveDelta = [&](int e, int a, int b) -> ld {\n            if (a == b) return 0.0L;\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n            ld x = edges[e].normImp;\n            ld xu = x * invSqrtDeg[u];\n            ld xv = x * invSqrtDeg[v];\n\n            auto sq = [](ld z) { return z * z; };\n\n            ld delta = 0.0L;\n            delta += p.wV * (sq(vLoad[u][a] - xu) + sq(vLoad[u][b] + xu)\n                           - sq(vLoad[u][a]) - sq(vLoad[u][b]));\n            delta += p.wV * (sq(vLoad[v][a] - xv) + sq(vLoad[v][b] + xv)\n                           - sq(vLoad[v][a]) - sq(vLoad[v][b]));\n            delta += p.wC * (sq(cLoad[c][a] - x) + sq(cLoad[c][b] + x)\n                           - sq(cLoad[c][a]) - sq(cLoad[c][b]));\n            delta += p.wDay * (sq(dayLoad[a] - x - target) + sq(dayLoad[b] + x - target)\n                             - sq(dayLoad[a] - target) - sq(dayLoad[b] - target));\n            delta += p.wCnt * (sq((ld)cnt[a] - 1.0L - target) + sq((ld)cnt[b] + 1.0L - target)\n                             - sq((ld)cnt[a] - target) - sq((ld)cnt[b] - target));\n            return delta;\n        };\n\n        auto applyMove = [&](int e, int a, int b) {\n            if (a == b) return;\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n            ld x = edges[e].normImp;\n            ld xu = x * invSqrtDeg[u];\n            ld xv = x * invSqrtDeg[v];\n\n            vLoad[u][a] -= xu; vLoad[u][b] += xu;\n            vLoad[v][a] -= xv; vLoad[v][b] += xv;\n            cLoad[c][a] -= x;   cLoad[c][b] += x;\n            dayLoad[a] -= x;    dayLoad[b] += x;\n            cnt[a]--;          cnt[b]++;\n            ans[e] = b;\n        };\n\n        // Initial balanced greedy assignment.\n        for (int e : ord) {\n            int bestD = -1;\n            ld best = numeric_limits<ld>::infinity();\n            for (int d = 0; d < D; ++d) {\n                if (cnt[d] >= cap[d]) continue;\n                ld sc = addDelta(e, d);\n                if (bestD == -1 || sc < best - 1e-18L || (fabsl(sc - best) <= 1e-18L && cnt[d] < cnt[bestD])) {\n                    best = sc;\n                    bestD = d;\n                }\n            }\n            if (bestD == -1) bestD = min_element(cnt.begin(), cnt.end()) - cnt.begin();\n            int u = edges[e].u, v = edges[e].v, c = edges[e].cell;\n            ld x = edges[e].normImp;\n            ld xu = x * invSqrtDeg[u];\n            ld xv = x * invSqrtDeg[v];\n            ans[e] = bestD;\n            vLoad[u][bestD] += xu;\n            vLoad[v][bestD] += xv;\n            cLoad[c][bestD] += x;\n            dayLoad[bestD] += x;\n            cnt[bestD]++;\n        }\n\n        // Local improvement by single-edge moves.\n        for (int pass = 0; pass < 2; ++pass) {\n            bool improved = false;\n            for (int e : ord) {\n                int a = ans[e];\n                int bestD = a;\n                ld bestDelta = 0.0L;\n                for (int b = 0; b < D; ++b) {\n                    if (b == a) continue;\n                    if (cnt[b] >= K) continue;\n                    ld dlt = moveDelta(e, a, b);\n                    if (dlt < bestDelta - 1e-18L ||\n                        (fabsl(dlt - bestDelta) <= 1e-18L && cnt[b] < cnt[bestD])) {\n                        bestDelta = dlt;\n                        bestD = b;\n                    }\n                }\n                if (bestD != a) {\n                    applyMove(e, a, bestD);\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n\n        return ans;\n    };\n\n    auto evaluate = [&](const vector<int> &dayOf) -> ll {\n        ll total = 0;\n        vector<ll> dist2(N);\n        for (int i = 0; i < Seval; ++i) {\n            int s = sources[Simp + i];\n            const auto &base = baseDist[i];\n            for (int d = 0; d < D; ++d) {\n                dijkstraSkipDay(s, dayOf, d, dist2);\n                for (int v = 0; v < N; ++v) {\n                    ll cur = (dist2[v] >= INFLL / 2 ? 1000000000LL : dist2[v]);\n                    total += cur - base[v];\n                }\n            }\n        }\n        return total;\n    };\n\n    // ---------- Candidate schedules ----------\n    vector<int> ordImp = makeImportanceOrder();\n    vector<int> ordMorton = makeMortonOrder();\n    vector<int> ordDegree = makeDegreeBiasOrder();\n    vector<int> ordNoise = makeNoisyImportanceOrder(baseSeed + 1234567ULL);\n\n    vector<Params> params = {\n        {1.00L, 0.25L, 0.12L, 0.05L},\n        {0.70L, 0.70L, 0.08L, 0.03L},\n        {1.15L, 0.18L, 0.18L, 0.05L},\n        {0.95L, 0.30L, 0.10L, 0.08L}\n    };\n\n    vector<vector<int>> candidates;\n    candidates.push_back(buildCandidate(ordImp,    params[0]));\n    candidates.push_back(buildCandidate(ordMorton, params[1]));\n    candidates.push_back(buildCandidate(ordDegree, params[2]));\n    candidates.push_back(buildCandidate(ordNoise,  params[3]));\n\n    vector<int> bestAns = candidates[0];\n    ll bestVal = evaluate(candidates[0]);\n\n    for (int i = 1; i < (int)candidates.size(); ++i) {\n        ll val = evaluate(candidates[i]);\n        if (val < bestVal) {\n            bestVal = val;\n            bestAns = candidates[i];\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        if (i) cout << ' ';\n        cout << bestAns[i] + 1;\n    }\n    cout << '\\n';\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXD = 14;\n\nusing Mat = array<array<unsigned char, MAXD>, MAXD>;\n\nstruct Rod {\n    int x, y, l, r;\n    int len() const { return r - l + 1; }\n};\n\nstruct Candidate {\n    vector<Rod> rods;\n    array<int, MAXD + 1> hist{};\n};\n\nstruct ObjData {\n    int D;\n    vector<string> f, r;\n    unsigned char runLen[2][MAXD][MAXD][MAXD]{}; // dir 0: z++, dir 1: z--\n};\n\nstruct PairInfo {\n    long double score;\n    int blocks;\n    int a, b;\n};\n\nstruct Preset {\n    long long runA, runB;\n    long long contA, contB;\n};\n\nstatic 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\nstatic void precompute_runlen(ObjData& obj) {\n    int D = obj.D;\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            for (int z = D - 1; z >= 0; --z) {\n                if (obj.f[z][x] == '1' && obj.r[z][y] == '1') {\n                    obj.runLen[0][z][x][y] = 1 + ((z + 1 < D) ? obj.runLen[0][z + 1][x][y] : 0);\n                }\n            }\n            for (int z = 0; z < D; ++z) {\n                if (obj.f[z][x] == '1' && obj.r[z][y] == '1') {\n                    obj.runLen[1][z][x][y] = 1 + ((z > 0) ? obj.runLen[1][z - 1][x][y] : 0);\n                }\n            }\n        }\n    }\n}\n\nstatic pair<long long, vector<int>> hungarian_min(const vector<vector<long long>>& a) {\n    int n = (int)a.size();\n    vector<long long> u(n + 1), v(n + 1);\n    vector<int> 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<long long> minv(n + 1, (1LL << 60));\n        vector<char> used(n + 1, false);\n\n        do {\n            used[j0] = true;\n            int i0 = p[j0];\n            long long delta = (1LL << 60);\n            int j1 = 0;\n            for (int j = 1; j <= n; ++j) if (!used[j]) {\n                long long cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n\n    vector<int> rowToCol(n);\n    for (int j = 1; j <= n; ++j) {\n        if (p[j] != 0) rowToCol[p[j] - 1] = j - 1;\n    }\n    long long minCost = -v[0];\n    return {minCost, rowToCol};\n}\n\nstatic Preset get_preset(int variant) {\n    if (variant == 0) return {120, 90, 60, 35};  // short / compact\n    if (variant == 1) return {160, 50, 90, 20};  // medium\n    return {220, 15, 120, 8};                    // long\n}\n\nstatic long long cell_noise(uint64_t baseSeed, int p, int variant, int dir, int swapEqual, int z, int x, int y) {\n    uint64_t h = baseSeed;\n    h ^= uint64_t(p + 1) * 10007ULL;\n    h ^= uint64_t(variant + 3) * 1009ULL;\n    h ^= uint64_t(dir + 7) * 313ULL;\n    h ^= uint64_t(swapEqual + 11) * 911ULL;\n    h ^= uint64_t(z + 1) * 1000003ULL;\n    h ^= uint64_t(x + 5) * 1000033ULL;\n    h ^= uint64_t(y + 9) * 1000037ULL;\n    return (long long)(splitmix64(h) % 5ULL) - 2LL; // [-2, 2]\n}\n\nstatic Candidate build_candidate(\n    const ObjData& obj,\n    int p,\n    int variant,\n    int dir,\n    bool swapEqual,\n    const array<long long, MAXD + 1>& target,\n    long long targetScale,\n    uint64_t baseSeed\n) {\n    int D = obj.D;\n    Preset pr = get_preset(variant);\n\n    vector<Mat> layers(D, Mat{});\n    array<array<int, MAXD>, MAXD> streak{};\n    for (int x = 0; x < D; ++x) for (int y = 0; y < D; ++y) streak[x][y] = 0;\n\n    for (int step = 0; step < D; ++step) {\n        int z = (dir == 0 ? step : D - 1 - step);\n\n        vector<int> xs, ys;\n        xs.reserve(D);\n        ys.reserve(D);\n        for (int x = 0; x < D; ++x) if (obj.f[z][x] == '1') xs.push_back(x);\n        for (int y = 0; y < D; ++y) if (obj.r[z][y] == '1') ys.push_back(y);\n\n        bool rowsAreX;\n        if ((int)xs.size() < (int)ys.size()) rowsAreX = true;\n        else if ((int)ys.size() < (int)xs.size()) rowsAreX = false;\n        else rowsAreX = !swapEqual;\n\n        const vector<int>& rows = rowsAreX ? xs : ys; // smaller side\n        const vector<int>& cols = rowsAreX ? ys : xs; // larger side\n        int m = (int)rows.size();\n        int k = (int)cols.size();\n\n        vector<vector<long long>> w(m, vector<long long>(k, 0));\n        vector<long long> bestExtraW(k, -(1LL << 60));\n        vector<int> bestExtraRow(k, -1);\n\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < k; ++j) {\n                int x = rowsAreX ? rows[i] : cols[j];\n                int y = rowsAreX ? cols[j] : rows[i];\n\n                int run = obj.runLen[dir][z][x][y];\n                int st = streak[x][y];\n\n                long long runTerm = pr.runA * min(run, p) - pr.runB * max(0, run - p);\n                long long contTerm;\n                if (st + 1 <= p) contTerm = pr.contA * (st + 1);\n                else contTerm = -pr.contB * (st + 1 - p);\n\n                long long val = runTerm + contTerm + targetScale * target[run];\n                val += cell_noise(baseSeed, p, variant, dir, (int)swapEqual, z, x, y);\n\n                w[i][j] = val;\n                if (val > bestExtraW[j] || (val == bestExtraW[j] && i < bestExtraRow[j])) {\n                    bestExtraW[j] = val;\n                    bestExtraRow[j] = i;\n                }\n            }\n        }\n\n        // Exact minimum edge cover by matching the smaller side to the larger side.\n        vector<vector<long long>> cost(k, vector<long long>(k, 0));\n        for (int i = 0; i < m; ++i) {\n            for (int j = 0; j < k; ++j) {\n                cost[i][j] = bestExtraW[j] - w[i][j];\n            }\n        }\n        auto [dummyCost, rowToCol] = hungarian_min(cost);\n        (void)dummyCost;\n\n        vector<int> colToRow(k, -1);\n        for (int i = 0; i < m; ++i) colToRow[rowToCol[i]] = i;\n\n        Mat cur{};\n        for (int j = 0; j < k; ++j) {\n            int i = colToRow[j];\n            int x, y;\n            if (i >= 0) {\n                if (rowsAreX) {\n                    x = rows[i];\n                    y = cols[j];\n                } else {\n                    x = cols[j];\n                    y = rows[i];\n                }\n            } else {\n                int bi = bestExtraRow[j];\n                if (rowsAreX) {\n                    x = rows[bi];\n                    y = cols[j];\n                } else {\n                    x = cols[j];\n                    y = rows[bi];\n                }\n            }\n            cur[x][y] = 1;\n        }\n\n        array<array<int, MAXD>, MAXD> nextStreak{};\n        for (int x = 0; x < D; ++x) {\n            for (int y = 0; y < D; ++y) {\n                if (cur[x][y]) nextStreak[x][y] = streak[x][y] + 1;\n                else nextStreak[x][y] = 0;\n            }\n        }\n        streak = nextStreak;\n        layers[z] = cur;\n    }\n\n    Candidate cand;\n    cand.hist.fill(0);\n\n    for (int x = 0; x < D; ++x) {\n        for (int y = 0; y < D; ++y) {\n            int s = -1;\n            for (int z = 0; z < D; ++z) {\n                if (layers[z][x][y]) {\n                    if (s == -1) s = z;\n                } else if (s != -1) {\n                    Rod rd{x, y, s, z - 1};\n                    cand.hist[rd.len()]++;\n                    cand.rods.push_back(rd);\n                    s = -1;\n                }\n            }\n            if (s != -1) {\n                Rod rd{x, y, s, D - 1};\n                cand.hist[rd.len()]++;\n                cand.rods.push_back(rd);\n            }\n        }\n    }\n\n    return cand;\n}\n\nstatic vector<int> make_base_pvals(int D) {\n    vector<int> pvals;\n    for (int p = 1; p <= D; ++p) pvals.push_back(p);\n    return pvals;\n}\n\nstatic array<long long, MAXD + 1> make_target_from_hist(const array<int, MAXD + 1>& hist, int D) {\n    array<long long, MAXD + 1> target{};\n    target.fill(0);\n\n    long long total = 0;\n    for (int L = 1; L <= D; ++L) total += hist[L];\n    if (total == 0) total = 1;\n\n    for (int L = 1; L <= D; ++L) {\n        long long sm = 3LL * hist[L];\n        if (L > 1) sm += hist[L - 1];\n        if (L < D) sm += hist[L + 1];\n\n        long long raw = sm * (2LL * L - 1) * 250LL / total;\n        raw = min(8000LL, raw);\n        target[L] = raw;\n    }\n    return target;\n}\n\nstatic vector<int> make_target_pvals(const array<long long, MAXD + 1>& target, int D) {\n    vector<pair<long long, int>> ord;\n    for (int L = 1; L <= D; ++L) ord.push_back({target[L], L});\n    sort(ord.begin(), ord.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    set<int> pset;\n    pset.insert(1);\n    pset.insert(D);\n    int take = min(3, D);\n    for (int i = 0; i < take; ++i) {\n        int L = ord[i].second;\n        for (int d = -1; d <= 1; ++d) {\n            int p = L + d;\n            if (1 <= p && p <= D) pset.insert(p);\n        }\n    }\n\n    vector<int> pvals(pset.begin(), pset.end());\n    return pvals;\n}\n\nstatic vector<Candidate> build_pool(\n    const ObjData& obj,\n    const vector<int>& pvals,\n    const array<long long, MAXD + 1>& target,\n    long long targetScale,\n    uint64_t baseSeed,\n    int roundTag\n) {\n    vector<Candidate> pool;\n    pool.reserve((int)pvals.size() * 3 * 2 * 2);\n\n    for (int p : pvals) {\n        for (int variant = 0; variant < 3; ++variant) {\n            for (int dir : {0, 1}) {\n                for (bool swapEqual : {false, true}) {\n                    uint64_t seed = baseSeed;\n                    seed ^= splitmix64((uint64_t)(roundTag + 1) * 1000003ULL);\n                    seed ^= splitmix64((uint64_t)(p + 1) * 10007ULL);\n                    seed ^= splitmix64((uint64_t)(variant + 3) * 1009ULL);\n                    seed ^= splitmix64((uint64_t)(dir + 7) * 313ULL);\n                    seed ^= splitmix64((uint64_t)(swapEqual ? 1 : 0) * 911ULL);\n\n                    pool.push_back(build_candidate(obj, p, variant, dir, swapEqual, target, targetScale, seed));\n                }\n            }\n        }\n    }\n    return pool;\n}\n\nstatic long double pair_score(const Candidate& A, const Candidate& B, int D) {\n    long double res = 0.0L;\n    for (int L = 1; L <= D; ++L) {\n        int k = min(A.hist[L], B.hist[L]);\n        res += (long double)k / (long double)L;\n        res += (long double)(A.hist[L] - k + B.hist[L] - k) * (long double)L;\n    }\n    return res;\n}\n\nstatic int pair_blocks(const Candidate& A, const Candidate& B, int D) {\n    int res = 0;\n    for (int L = 1; L <= D; ++L) res += max(A.hist[L], B.hist[L]);\n    return res;\n}\n\nstatic long long hist_distance(const Candidate& A1, const Candidate& B1, const Candidate& A2, const Candidate& B2, int D) {\n    long long d = 0;\n    for (int L = 1; L <= D; ++L) {\n        d += 1LL * (2 * L - 1) * (llabs((long long)A1.hist[L] - (long long)A2.hist[L]) +\n                                   llabs((long long)B1.hist[L] - (long long)B2.hist[L]));\n    }\n    return d;\n}\n\nstatic pair<int, int> choose_diverse_second(\n    const vector<PairInfo>& pairs,\n    const vector<Candidate>& poolA,\n    const vector<Candidate>& poolB,\n    int D,\n    int topK = 30\n) {\n    if (pairs.empty()) return {0, 0};\n    int bestIdx = 0;\n    long long bestDist = -1;\n\n    int lim = min(topK, (int)pairs.size());\n    for (int i = 0; i < lim; ++i) {\n        long long dist = hist_distance(\n            poolA[pairs[0].a], poolB[pairs[0].b],\n            poolA[pairs[i].a], poolB[pairs[i].b],\n            D\n        );\n        if (dist > bestDist) {\n            bestDist = dist;\n            bestIdx = i;\n        }\n    }\n    return {pairs[bestIdx].a, pairs[bestIdx].b};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    ObjData obj[2];\n    for (int t = 0; t < 2; ++t) {\n        obj[t].D = D;\n        obj[t].f.resize(D);\n        obj[t].r.resize(D);\n        for (int i = 0; i < D; ++i) cin >> obj[t].f[i];\n        for (int i = 0; i < D; ++i) cin >> obj[t].r[i];\n        precompute_runlen(obj[t]);\n    }\n\n    uint64_t baseSeed = 1469598103934665603ULL;\n    auto mix_str = [&](const string& s) {\n        for (unsigned char c : s) baseSeed = splitmix64(baseSeed ^ (uint64_t)c);\n    };\n    baseSeed = splitmix64(baseSeed ^ (uint64_t)D);\n    for (int t = 0; t < 2; ++t) {\n        for (auto& s : obj[t].f) mix_str(s);\n        for (auto& s : obj[t].r) mix_str(s);\n    }\n\n    // Round 0: base pools.\n    vector<int> baseP = make_base_pvals(D);\n    array<long long, MAXD + 1> zero{};\n    zero.fill(0);\n\n    vector<Candidate> basePool[2];\n    basePool[0] = build_pool(obj[0], baseP, zero, 0, baseSeed ^ 1111ULL, 0);\n    basePool[1] = build_pool(obj[1], baseP, zero, 0, baseSeed ^ 2222ULL, 0);\n\n    vector<PairInfo> basePairs;\n    basePairs.reserve(basePool[0].size() * basePool[1].size());\n\n    for (int i = 0; i < (int)basePool[0].size(); ++i) {\n        for (int j = 0; j < (int)basePool[1].size(); ++j) {\n            long double sc = pair_score(basePool[0][i], basePool[1][j], D);\n            int bl = pair_blocks(basePool[0][i], basePool[1][j], D);\n            basePairs.push_back({sc, bl, i, j});\n        }\n    }\n\n    sort(basePairs.begin(), basePairs.end(), [&](const PairInfo& a, const PairInfo& b) {\n        if (fabsl(a.score - b.score) > 1e-18L) return a.score < b.score;\n        return a.blocks < b.blocks;\n    });\n\n    PairInfo best0 = basePairs[0];\n    auto [secAIdx, secBIdx] = choose_diverse_second(basePairs, basePool[0], basePool[1], D);\n\n    // Round 1: target-guided pools from the best two base pairs.\n    array<long long, MAXD + 1> targetA0 = make_target_from_hist(basePool[1][best0.b].hist, D);\n    array<long long, MAXD + 1> targetB0 = make_target_from_hist(basePool[0][best0.a].hist, D);\n    array<long long, MAXD + 1> targetA1 = make_target_from_hist(basePool[1][secBIdx].hist, D);\n    array<long long, MAXD + 1> targetB1 = make_target_from_hist(basePool[0][secAIdx].hist, D);\n\n    vector<int> pA0 = make_target_pvals(targetA0, D);\n    vector<int> pB0 = make_target_pvals(targetB0, D);\n    vector<int> pA1 = make_target_pvals(targetA1, D);\n    vector<int> pB1 = make_target_pvals(targetB1, D);\n\n    vector<Candidate> poolA = basePool[0];\n    vector<Candidate> poolB = basePool[1];\n\n    auto add_pool = [&](vector<Candidate>& dst, const vector<Candidate>& src) {\n        dst.insert(dst.end(), src.begin(), src.end());\n    };\n\n    auto targA0 = build_pool(obj[0], pA0, targetA0, 1, baseSeed ^ 3333ULL, 1);\n    auto targB0 = build_pool(obj[1], pB0, targetB0, 1, baseSeed ^ 4444ULL, 1);\n    auto targA1 = build_pool(obj[0], pA1, targetA1, 1, baseSeed ^ 5555ULL, 2);\n    auto targB1 = build_pool(obj[1], pB1, targetB1, 1, baseSeed ^ 6666ULL, 2);\n\n    add_pool(poolA, targA0);\n    add_pool(poolA, targA1);\n    add_pool(poolB, targB0);\n    add_pool(poolB, targB1);\n\n    // Final exact search among all candidates.\n    int bestA = 0, bestB = 0;\n    long double bestScore = numeric_limits<long double>::infinity();\n    int bestBlocks = INT_MAX;\n\n    for (int i = 0; i < (int)poolA.size(); ++i) {\n        for (int j = 0; j < (int)poolB.size(); ++j) {\n            long double sc = pair_score(poolA[i], poolB[j], D);\n            int bl = pair_blocks(poolA[i], poolB[j], D);\n            if (sc + 1e-18L < bestScore || (fabsl(sc - bestScore) <= 1e-18L && bl < bestBlocks)) {\n                bestScore = sc;\n                bestBlocks = bl;\n                bestA = i;\n                bestB = j;\n            }\n        }\n    }\n\n    const Candidate& A = poolA[bestA];\n    const Candidate& B = poolB[bestB];\n\n    // Assign IDs: rods of the same length are congruent.\n    array<vector<int>, MAXD + 1> idxA, idxB;\n    for (int i = 0; i < (int)A.rods.size(); ++i) idxA[A.rods[i].len()].push_back(i);\n    for (int i = 0; i < (int)B.rods.size(); ++i) idxB[B.rods[i].len()].push_back(i);\n\n    vector<int> idA(A.rods.size(), 0), idB(B.rods.size(), 0);\n    int n = 0;\n\n    for (int L = 1; L <= D; ++L) {\n        int k = min((int)idxA[L].size(), (int)idxB[L].size());\n        for (int i = 0; i < k; ++i) {\n            ++n;\n            idA[idxA[L][i]] = n;\n            idB[idxB[L][i]] = n;\n        }\n        for (int i = k; i < (int)idxA[L].size(); ++i) {\n            ++n;\n            idA[idxA[L][i]] = n;\n        }\n        for (int i = k; i < (int)idxB[L].size(); ++i) {\n            ++n;\n            idB[idxB[L][i]] = n;\n        }\n    }\n\n    vector<int> outA(D * D * D, 0), outB(D * D * D, 0);\n\n    auto fill_out = [&](vector<int>& out, const vector<Rod>& rods, const vector<int>& ids) {\n        for (int i = 0; i < (int)rods.size(); ++i) {\n            int id = ids[i];\n            const Rod& rd = rods[i];\n            for (int z = rd.l; z <= rd.r; ++z) {\n                out[rd.x * D * D + rd.y * D + z] = id;\n            }\n        }\n    };\n\n    fill_out(outA, A.rods, idA);\n    fill_out(outB, B.rods, idB);\n\n    cout << 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    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << outB[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INFLL = (1LL << 60);\nstatic const ll PENALTY = 1000000000000LL;\nstatic const int MAXR = 5001;\n\nstruct Edge {\n    int u, v;\n    ll w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n + 1);\n        sz.assign(n + 1, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct ConnResult {\n    ll cost = 0;\n    vector<char> used;\n};\n\nstruct EvalResult {\n    vector<int> sel;\n    vector<int> rad;\n    vector<int> owner;\n    vector<int> bestDist;\n    vector<char> inSel;\n    vector<char> used;\n    ll cov = 0;\n    ll conn = 0;\n    ll total = INFLL;\n    int uncovered = 0;\n};\n\nstatic int N, M, K;\nstatic vector<int> xs, ys;\nstatic vector<int> ax, ay;\nstatic vector<Edge> edges;\n\nstatic vector<vector<ll>> distGraph;\nstatic vector<vector<int>> nxtHop;\nstatic vector<vector<int>> edgeId;\nstatic vector<vector<pair<int,ll>>> graphAdj;\nstatic vector<vector<int>> distSR;\nstatic vector<vector<int>> residentOrder;\n\nstatic vector<int> coverCnt;\nstatic vector<int> coverCntRes;\nstatic vector<ll> singleCost;\nstatic vector<int> singleOrder, coverOrder;\nstatic vector<int> minDistRes, hardOrder;\n\nstatic mt19937 rng(712367821);\nstatic auto startTime = chrono::steady_clock::now();\n\nstatic inline bool time_over() {\n    using namespace chrono;\n    return duration_cast<milliseconds>(chrono::steady_clock::now() - startTime).count() > 1850;\n}\n\nstatic int ceil_sqrt_ll(ll x) {\n    long double y = sqrt((long double)x);\n    int r = (int)y;\n    while ((ll)r * r < x) ++r;\n    while (r > 0 && (ll)(r - 1) * (ll)(r - 1) >= x) --r;\n    return r;\n}\n\nstatic vector<int> normalize_sel(vector<int> sel) {\n    if (find(sel.begin(), sel.end(), 1) == sel.end()) sel.push_back(1);\n    sort(sel.begin(), sel.end());\n    sel.erase(unique(sel.begin(), sel.end()), sel.end());\n    return sel;\n}\n\nstatic void add_path_edges(int a, int b, vector<char>& mark, vector<int>& cand) {\n    while (a != b) {\n        int c = nxtHop[a][b];\n        int id = edgeId[a][c];\n        if (!mark[id]) {\n            mark[id] = 1;\n            cand.push_back(id);\n        }\n        a = c;\n    }\n}\n\nstatic ll exact_steiner_cost(const vector<int>& terminals) {\n    int t = (int)terminals.size();\n    if (t <= 1) return 0;\n    if (t > 5) return INFLL;\n\n    int FULL = 1 << t;\n    vector<vector<ll>> dp(FULL, vector<ll>(N + 1, INFLL));\n\n    for (int i = 0; i < t; ++i) {\n        int mask = 1 << i;\n        for (int v = 1; v <= N; ++v) dp[mask][v] = distGraph[terminals[i]][v];\n    }\n\n    for (int mask = 1; mask < FULL; ++mask) {\n        int pc = __builtin_popcount((unsigned)mask);\n        if (pc > 1) {\n            vector<ll> ndp(N + 1, INFLL);\n            for (int sub = (mask - 1) & mask; sub; sub = (sub - 1) & mask) {\n                int other = mask ^ sub;\n                if (sub > other) continue;\n                for (int v = 1; v <= N; ++v) {\n                    if (dp[sub][v] >= INFLL / 4 || dp[other][v] >= INFLL / 4) continue;\n                    ndp[v] = min(ndp[v], dp[sub][v] + dp[other][v]);\n                }\n            }\n            dp[mask].swap(ndp);\n        }\n\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        for (int v = 1; v <= N; ++v) {\n            if (dp[mask][v] < INFLL / 4) pq.push({dp[mask][v], v});\n        }\n\n        vector<ll>& d = dp[mask];\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top();\n            pq.pop();\n            if (cd != d[u]) continue;\n            for (auto [v, w] : graphAdj[u]) {\n                ll nd = cd + w;\n                if (nd < d[v]) {\n                    d[v] = nd;\n                    pq.push({nd, v});\n                }\n            }\n        }\n    }\n\n    ll ans = INFLL;\n    for (int v = 1; v <= N; ++v) ans = min(ans, dp[FULL - 1][v]);\n    return ans;\n}\n\nstatic ConnResult reduce_candidate_edges(const vector<int>& candIds, const vector<char>& termMark, bool storeUsed) {\n    ConnResult res;\n    if (candIds.empty()) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<int> ids = candIds;\n    sort(ids.begin(), ids.end(), [&](int i, int j) {\n        if (edges[i].w != edges[j].w) return edges[i].w < edges[j].w;\n        return i < j;\n    });\n\n    DSU dsu(N);\n    vector<char> tree(M, 0);\n    ll cost = 0;\n    for (int id : ids) {\n        if (dsu.unite(edges[id].u, edges[id].v)) {\n            tree[id] = 1;\n            cost += edges[id].w;\n        }\n    }\n\n    int rootComp = -1;\n    for (int v = 1; v <= N; ++v) {\n        if (termMark[v]) {\n            rootComp = dsu.find(v);\n            break;\n        }\n    }\n    for (int v = 1; v <= N; ++v) {\n        if (termMark[v] && dsu.find(v) != rootComp) {\n            res.cost = INFLL;\n            if (storeUsed) res.used.assign(M, 0);\n            return res;\n        }\n    }\n\n    vector<vector<pair<int,int>>> adj(N + 1);\n    vector<int> deg(N + 1, 0);\n    for (int id = 0; id < M; ++id) {\n        if (!tree[id]) continue;\n        int u = edges[id].u, v = edges[id].v;\n        adj[u].push_back({v, id});\n        adj[v].push_back({u, id});\n        deg[u]++;\n        deg[v]++;\n    }\n\n    queue<int> q;\n    for (int v = 1; v <= N; ++v) if (!termMark[v] && deg[v] == 1) q.push(v);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (termMark[v] || deg[v] != 1) continue;\n\n        int rem = -1, to = -1;\n        for (auto [nx, id] : adj[v]) {\n            if (tree[id]) {\n                rem = id;\n                to = nx;\n                break;\n            }\n        }\n        if (rem == -1) continue;\n\n        tree[rem] = 0;\n        cost -= edges[rem].w;\n        deg[v]--;\n        deg[to]--;\n        if (!termMark[to] && deg[to] == 1) q.push(to);\n    }\n\n    res.cost = cost;\n    if (storeUsed) {\n        res.used.assign(M, 0);\n        for (int id = 0; id < M; ++id) if (tree[id]) res.used[id] = 1;\n    }\n    return res;\n}\n\nstatic ConnResult build_conn_mst(const vector<int>& terminals, bool storeUsed) {\n    ConnResult res;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<ll> bestD(t, INFLL);\n    vector<int> par(t, -1);\n    vector<char> used(t, 0);\n    bestD[0] = 0;\n    vector<pair<int,int>> termEdges;\n    termEdges.reserve(t - 1);\n\n    for (int it = 0; it < t; ++it) {\n        int x = -1;\n        ll bd = INFLL;\n        for (int i = 0; i < t; ++i) {\n            if (!used[i] && bestD[i] < bd) {\n                bd = bestD[i];\n                x = i;\n            }\n        }\n        used[x] = 1;\n        if (par[x] != -1) termEdges.push_back({terminals[x], terminals[par[x]]});\n        for (int y = 0; y < t; ++y) {\n            if (used[y]) continue;\n            ll d = distGraph[terminals[x]][terminals[y]];\n            if (d < bestD[y]) {\n                bestD[y] = d;\n                par[y] = x;\n            }\n        }\n    }\n\n    vector<char> termMark(N + 1, 0), mark(M, 0);\n    vector<int> cand;\n    for (int s : terminals) termMark[s] = 1;\n    for (auto [u, v] : termEdges) add_path_edges(u, v, mark, cand);\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_star(const vector<int>& terminals, int rootIdx, bool storeUsed) {\n    ConnResult res;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<char> termMark(N + 1, 0), mark(M, 0);\n    vector<int> cand;\n    for (int s : terminals) termMark[s] = 1;\n    int root = terminals[rootIdx];\n    for (int i = 0; i < t; ++i) {\n        if (i == rootIdx) continue;\n        add_path_edges(root, terminals[i], mark, cand);\n    }\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_hub(const vector<int>& terminals, int hub, bool storeUsed) {\n    ConnResult res;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<char> termMark(N + 1, 0), mark(M, 0);\n    vector<int> cand;\n    for (int s : terminals) termMark[s] = 1;\n    for (int s : terminals) add_path_edges(hub, s, mark, cand);\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_greedy(const vector<int>& terminals, int startIdx, bool storeUsed) {\n    ConnResult res;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        res.cost = 0;\n        if (storeUsed) res.used.assign(M, 0);\n        return res;\n    }\n\n    vector<char> termMark(N + 1, 0);\n    for (int s : terminals) termMark[s] = 1;\n\n    vector<char> inTree(N + 1, 0), done(t, 0), mark(M, 0);\n    vector<int> treeVerts;\n    treeVerts.reserve(N);\n\n    int start = terminals[startIdx];\n    inTree[start] = 1;\n    treeVerts.push_back(start);\n    done[startIdx] = 1;\n    int doneCnt = 1;\n\n    vector<int> cand;\n    while (doneCnt < t) {\n        ll bestD = INFLL;\n        int bestTi = -1, bestV = -1;\n\n        for (int i = 0; i < t; ++i) {\n            if (done[i]) continue;\n            int term = terminals[i];\n            for (int v : treeVerts) {\n                ll d = distGraph[v][term];\n                if (d < bestD) {\n                    bestD = d;\n                    bestTi = i;\n                    bestV = v;\n                }\n            }\n        }\n\n        int a = bestV;\n        int b = terminals[bestTi];\n        while (a != b) {\n            int c = nxtHop[a][b];\n            int id = edgeId[a][c];\n            if (!mark[id]) {\n                mark[id] = 1;\n                cand.push_back(id);\n            }\n            if (!inTree[c]) {\n                inTree[c] = 1;\n                treeVerts.push_back(c);\n            }\n            a = c;\n        }\n\n        if (!inTree[b]) {\n            inTree[b] = 1;\n            treeVerts.push_back(b);\n        }\n        done[bestTi] = 1;\n        ++doneCnt;\n    }\n\n    return reduce_candidate_edges(cand, termMark, storeUsed);\n}\n\nstatic ConnResult build_conn_best(const vector<int>& terminals, bool storeUsed) {\n    ConnResult best;\n    best.cost = INFLL;\n    int t = (int)terminals.size();\n    if (t <= 1) {\n        best.cost = 0;\n        if (storeUsed) best.used.assign(M, 0);\n        return best;\n    }\n\n    auto consider = [&](ConnResult cand) {\n        if (cand.cost < best.cost) best = std::move(cand);\n    };\n\n    consider(build_conn_mst(terminals, storeUsed));\n    consider(build_conn_star(terminals, 0, storeUsed));\n\n    int center = 0;\n    {\n        ll bestSum = INFLL;\n        for (int i = 0; i < t; ++i) {\n            ll s = 0;\n            for (int j = 0; j < t; ++j) s += distGraph[terminals[i]][terminals[j]];\n            if (s < bestSum) {\n                bestSum = s;\n                center = i;\n            }\n        }\n    }\n    consider(build_conn_star(terminals, center, storeUsed));\n\n    vector<pair<ll,int>> hubs;\n    hubs.reserve(N);\n    for (int v = 1; v <= N; ++v) {\n        ll s = 0;\n        for (int term : terminals) s += distGraph[v][term];\n        hubs.push_back({s, v});\n    }\n    sort(hubs.begin(), hubs.end(), [&](auto& a, auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n    consider(build_conn_hub(terminals, hubs[0].second, storeUsed));\n    if ((int)hubs.size() >= 2) consider(build_conn_hub(terminals, hubs[1].second, storeUsed));\n    if ((int)hubs.size() >= 3) consider(build_conn_hub(terminals, hubs[2].second, storeUsed));\n\n    if (t <= 25) {\n        consider(build_conn_greedy(terminals, 0, storeUsed));\n        consider(build_conn_greedy(terminals, center, storeUsed));\n    }\n\n    if (!storeUsed && t <= 5) {\n        ll exact = exact_steiner_cost(terminals);\n        if (exact < best.cost) {\n            best.cost = exact;\n            best.used.clear();\n        }\n    }\n\n    return best;\n}\n\nstatic int choose_medoid(const vector<int>& residents) {\n    int bestV = 1;\n    int bestMax = INT_MAX;\n    ll bestSum = INFLL;\n    ll bestRoot = INFLL;\n\n    for (int v = 1; v <= N; ++v) {\n        int mx = 0;\n        ll sum = 0;\n        for (int k : residents) {\n            int d = distSR[v][k];\n            mx = max(mx, d);\n            sum += d;\n            if (mx > bestMax) break;\n        }\n        if (mx < bestMax ||\n            (mx == bestMax && (sum < bestSum || (sum == bestSum && distGraph[1][v] < bestRoot)))) {\n            bestMax = mx;\n            bestSum = sum;\n            bestRoot = distGraph[1][v];\n            bestV = v;\n        }\n    }\n    return bestV;\n}\n\nstatic EvalResult core_eval(vector<int> selInput, bool storeUsed, bool improveResidents) {\n    EvalResult res;\n    vector<int> sel = normalize_sel(std::move(selInput));\n    int t = (int)sel.size();\n    res.sel = sel;\n\n    res.inSel.assign(N + 1, 0);\n    for (int s : sel) res.inSel[s] = 1;\n\n    res.rad.assign(t, 0);\n    res.owner.assign(K, -1);\n    res.bestDist.assign(K, INT_MAX);\n\n    vector<int> cnt(t, 0);\n    vector<int> freq(t * MAXR, 0);\n\n    for (int k : hardOrder) {\n        int bestJ = -1;\n        ll bestInc = INFLL;\n        int bestD = INT_MAX;\n        int bestRad = INT_MAX;\n\n        for (int j = 0; j < t; ++j) {\n            int d = distSR[sel[j]][k];\n            if (d > 5000) continue;\n            ll r = res.rad[j];\n            ll inc = 1LL * max<ll>(r, d) * max<ll>(r, d) - r * r;\n            if (bestJ == -1 || inc < bestInc || (inc == bestInc && (d < bestD || (d == bestD && (int)r < bestRad)))) {\n                bestInc = inc;\n                bestJ = j;\n                bestD = d;\n                bestRad = (int)r;\n            }\n        }\n\n        if (bestJ == -1) {\n            res.uncovered++;\n            continue;\n        }\n\n        res.owner[k] = bestJ;\n        res.bestDist[k] = bestD;\n        cnt[bestJ]++;\n        freq[bestJ * MAXR + bestD]++;\n        if (bestD > res.rad[bestJ]) res.rad[bestJ] = bestD;\n    }\n\n    if (improveResidents && res.uncovered == 0 && t <= 20) {\n        vector<int> residents;\n        residents.reserve(K);\n        for (int k = 0; k < K; ++k) if (res.owner[k] != -1) residents.push_back(k);\n        sort(residents.begin(), residents.end(), [&](int a, int b) {\n            return res.bestDist[a] > res.bestDist[b];\n        });\n\n        for (int k : residents) {\n            int a = res.owner[k];\n            int da = res.bestDist[k];\n            int oldRa = res.rad[a];\n            int newRa = oldRa;\n\n            if (da == oldRa && freq[a * MAXR + da] == 1) {\n                int x = oldRa - 1;\n                while (x > 0 && freq[a * MAXR + x] == 0) --x;\n                newRa = x;\n            }\n\n            ll bestDelta = 0;\n            int bestB = -1, bestDb = -1, bestNewRb = -1;\n\n            for (int b = 0; b < t; ++b) {\n                if (b == a) continue;\n                int db = distSR[sel[b]][k];\n                if (db > 5000) continue;\n                int oldRb = res.rad[b];\n                int newRb = max(oldRb, db);\n                ll delta = 1LL * newRa * newRa + 1LL * newRb * newRb\n                         - 1LL * oldRa * oldRa - 1LL * oldRb * oldRb;\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    bestB = b;\n                    bestDb = db;\n                    bestNewRb = newRb;\n                }\n            }\n\n            if (bestB != -1) {\n                int b = bestB;\n\n                freq[a * MAXR + da]--;\n                cnt[a]--;\n                if (cnt[a] == 0) {\n                    res.rad[a] = 0;\n                } else if (da == oldRa && freq[a * MAXR + oldRa] == 0) {\n                    int x = oldRa - 1;\n                    while (x > 0 && freq[a * MAXR + x] == 0) --x;\n                    res.rad[a] = x;\n                }\n\n                freq[b * MAXR + bestDb]++;\n                cnt[b]++;\n                res.rad[b] = max(res.rad[b], bestNewRb);\n\n                res.owner[k] = b;\n                res.bestDist[k] = bestDb;\n            }\n        }\n    }\n\n    vector<int> newSel, newRad;\n    vector<int> mp(t, -1);\n    for (int j = 0; j < t; ++j) {\n        if (sel[j] == 1 || cnt[j] > 0) {\n            mp[j] = (int)newSel.size();\n            newSel.push_back(sel[j]);\n            newRad.push_back(res.rad[j]);\n        }\n    }\n    for (int k = 0; k < K; ++k) {\n        if (res.owner[k] != -1) res.owner[k] = mp[res.owner[k]];\n    }\n    res.sel = std::move(newSel);\n    res.rad = std::move(newRad);\n\n    res.inSel.assign(N + 1, 0);\n    for (int s : res.sel) res.inSel[s] = 1;\n\n    res.cov = 0;\n    for (int r : res.rad) res.cov += 1LL * r * r;\n\n    ConnResult cr = build_conn_best(res.sel, storeUsed);\n    res.conn = cr.cost;\n    if (storeUsed) res.used = std::move(cr.used);\n\n    res.total = res.cov + res.conn + PENALTY * res.uncovered;\n    return res;\n}\n\nstatic EvalResult strong_eval(vector<int> sel, bool storeUsed) {\n    EvalResult cur = core_eval(std::move(sel), false, true);\n    EvalResult best = cur;\n\n    int rounds = 1;\n    if ((int)cur.sel.size() <= 10) rounds = 3;\n    else if ((int)cur.sel.size() <= 15) rounds = 2;\n\n    for (int it = 0; it < rounds && !time_over(); ++it) {\n        if (cur.uncovered > 0 || cur.sel.size() <= 1) break;\n\n        vector<vector<int>> groups(cur.sel.size());\n        for (int k = 0; k < K; ++k) {\n            if (cur.owner[k] != -1) groups[cur.owner[k]].push_back(k);\n        }\n\n        vector<int> ns;\n        ns.push_back(1);\n        for (int j = 0; j < (int)cur.sel.size(); ++j) {\n            if (groups[j].empty()) continue;\n            ns.push_back(choose_medoid(groups[j]));\n        }\n        ns = normalize_sel(std::move(ns));\n\n        if (ns == cur.sel) break;\n\n        EvalResult cand = core_eval(ns, false, true);\n        if (cand.total < best.total) best = cand;\n        if (cand.total < cur.total) cur = cand;\n        else break;\n    }\n\n    if (storeUsed) best = core_eval(best.sel, true, true);\n    return best;\n}\n\nstatic vector<int> make_kmeans_seed(int C, int startIdx) {\n    if (C <= 0) return {1};\n    C = min(C, K);\n\n    auto dist2p = [&](int i, int j) -> ll {\n        ll dx = (ll)ax[i] - ax[j];\n        ll dy = (ll)ay[i] - ay[j];\n        return dx * dx + dy * dy;\n    };\n\n    vector<int> centers;\n    centers.reserve(C);\n    startIdx %= K;\n    if (startIdx < 0) startIdx += K;\n    centers.push_back(startIdx);\n\n    vector<ll> mind2(K, INFLL);\n    for (int k = 0; k < K; ++k) mind2[k] = dist2p(k, startIdx);\n\n    for (int c = 1; c < C; ++c) {\n        int nxt = 0;\n        ll best = -1;\n        for (int k = 0; k < K; ++k) {\n            if (mind2[k] > best) {\n                best = mind2[k];\n                nxt = k;\n            }\n        }\n        centers.push_back(nxt);\n        for (int k = 0; k < K; ++k) mind2[k] = min(mind2[k], dist2p(k, nxt));\n    }\n\n    vector<pair<double,double>> cen(C);\n    for (int i = 0; i < C; ++i) cen[i] = {(double)ax[centers[i]], (double)ay[centers[i]]};\n\n    for (int it = 0; it < 3; ++it) {\n        vector<vector<int>> groups(C);\n        for (int k = 0; k < K; ++k) {\n            int bestc = 0;\n            long double bestd = 1e100;\n            for (int c = 0; c < C; ++c) {\n                long double dx = (long double)ax[k] - cen[c].first;\n                long double dy = (long double)ay[k] - cen[c].second;\n                long double d = dx * dx + dy * dy;\n                if (d < bestd) {\n                    bestd = d;\n                    bestc = c;\n                }\n            }\n            groups[bestc].push_back(k);\n        }\n\n        for (int c = 0; c < C; ++c) {\n            if (groups[c].empty()) continue;\n            long double sx = 0, sy = 0;\n            for (int k : groups[c]) {\n                sx += ax[k];\n                sy += ay[k];\n            }\n            cen[c] = {(double)(sx / groups[c].size()), (double)(sy / groups[c].size())};\n        }\n    }\n\n    vector<vector<int>> groups(C);\n    for (int k = 0; k < K; ++k) {\n        int bestc = 0;\n        long double bestd = 1e100;\n        for (int c = 0; c < C; ++c) {\n            long double dx = (long double)ax[k] - cen[c].first;\n            long double dy = (long double)ay[k] - cen[c].second;\n            long double d = dx * dx + dy * dy;\n            if (d < bestd) {\n                bestd = d;\n                bestc = c;\n            }\n        }\n        groups[bestc].push_back(k);\n    }\n\n    vector<int> chosen = {1};\n    for (int c = 0; c < C; ++c) {\n        if (groups[c].empty()) continue;\n        int bestV = 1;\n        int bestMax = INT_MAX;\n        ll bestSum = INFLL;\n        for (int v = 1; v <= N; ++v) {\n            int mx = 0;\n            ll sum = 0;\n            for (int k : groups[c]) {\n                int d = distSR[v][k];\n                mx = max(mx, d);\n                sum += d;\n                if (mx > bestMax) break;\n            }\n            if (mx < bestMax || (mx == bestMax && sum < bestSum)) {\n                bestMax = mx;\n                bestSum = sum;\n                bestV = v;\n            }\n        }\n        chosen.push_back(bestV);\n    }\n\n    sort(chosen.begin(), chosen.end());\n    chosen.erase(unique(chosen.begin(), chosen.end()), chosen.end());\n    if (find(chosen.begin(), chosen.end(), 1) == chosen.end()) chosen.push_back(1);\n    sort(chosen.begin(), chosen.end());\n    return chosen;\n}\n\nstatic vector<int> make_hard_seed() {\n    vector<int> seed = {1};\n    int L = min(120, K);\n    vector<int> cand(hardOrder.begin(), hardOrder.begin() + L);\n\n    auto dist2res = [&](int a, int b) -> ll {\n        ll dx = (ll)ax[a] - ax[b];\n        ll dy = (ll)ay[a] - ay[b];\n        return dx * dx + dy * dy;\n    };\n\n    vector<int> centers;\n    centers.push_back(cand[0]);\n    vector<ll> mind(cand.size(), INFLL);\n    for (int idx = 0; idx < (int)cand.size(); ++idx) mind[idx] = dist2res(cand[idx], cand[0]);\n\n    int need = min(4, L);\n    for (int it = 1; it < need; ++it) {\n        int best = cand[0];\n        ll bd = -1;\n        for (int idx = 0; idx < (int)cand.size(); ++idx) {\n            if (mind[idx] > bd) {\n                bd = mind[idx];\n                best = cand[idx];\n            }\n        }\n        centers.push_back(best);\n        for (int idx = 0; idx < (int)cand.size(); ++idx) {\n            mind[idx] = min(mind[idx], dist2res(cand[idx], best));\n        }\n    }\n\n    vector<vector<int>> groups(centers.size());\n    for (int k : cand) {\n        int bestc = 0;\n        ll bd = INFLL;\n        for (int c = 0; c < (int)centers.size(); ++c) {\n            ll d = dist2res(k, centers[c]);\n            if (d < bd) {\n                bd = d;\n                bestc = c;\n            }\n        }\n        groups[bestc].push_back(k);\n    }\n\n    vector<char> used(N + 1, 0);\n    used[1] = 1;\n    for (auto& g : groups) {\n        if (g.empty()) continue;\n        int bestV = 1;\n        int bestMax = INT_MAX;\n        ll bestSum = INFLL;\n        for (int v = 1; v <= N; ++v) {\n            int mx = 0;\n            ll sum = 0;\n            for (int k : g) {\n                int d = distSR[v][k];\n                mx = max(mx, d);\n                sum += d;\n                if (mx > bestMax) break;\n            }\n            if (mx < bestMax || (mx == bestMax && sum < bestSum)) {\n                bestMax = mx;\n                bestSum = sum;\n                bestV = v;\n            }\n        }\n        if (!used[bestV]) {\n            used[bestV] = 1;\n            seed.push_back(bestV);\n        }\n    }\n\n    return normalize_sel(std::move(seed));\n}\n\nstatic vector<int> make_cover_seed() {\n    vector<int> seed = {1};\n    vector<char> chosen(N + 1, 0);\n    chosen[1] = 1;\n    vector<char> covered(K, 0);\n\n    for (int step = 0; step < 5; ++step) {\n        int bestV = -1;\n        ll bestScore = -1;\n\n        for (int v = 2; v <= N; ++v) {\n            if (chosen[v]) continue;\n            ll score = 0;\n            for (int k = 0; k < K; ++k) {\n                if (covered[k]) continue;\n                int d = distSR[v][k];\n                if (d <= 5000) score += 5001 - d;\n            }\n            if (score > bestScore) {\n                bestScore = score;\n                bestV = v;\n            }\n        }\n\n        if (bestV == -1 || bestScore <= 0) break;\n        seed.push_back(bestV);\n        chosen[bestV] = 1;\n        for (int k = 0; k < K; ++k) {\n            if (!covered[k] && distSR[bestV][k] <= 5000) covered[k] = 1;\n        }\n    }\n\n    return normalize_sel(std::move(seed));\n}\n\nstatic vector<int> build_pool(const EvalResult& cur) {\n    vector<int> pool;\n    vector<char> seen(N + 1, 0);\n\n    auto addv = [&](int v) {\n        if (v < 1 || v > N || cur.inSel[v] || seen[v]) return;\n        seen[v] = 1;\n        pool.push_back(v);\n    };\n\n    if (cur.uncovered > 0) {\n        vector<int> unc;\n        for (int k = 0; k < K; ++k) if (cur.owner[k] == -1) unc.push_back(k);\n        sort(unc.begin(), unc.end(), [&](int a, int b) {\n            if (minDistRes[a] != minDistRes[b]) return minDistRes[a] > minDistRes[b];\n            return a < b;\n        });\n        for (int i = 0; i < (int)unc.size() && i < 6; ++i) {\n            int k = unc[i];\n            addv(residentOrder[k][0]);\n            if (N >= 2) addv(residentOrder[k][1]);\n            if (N >= 3) addv(residentOrder[k][2]);\n        }\n    } else {\n        vector<pair<int,int>> far;\n        far.reserve(K);\n        for (int k = 0; k < K; ++k) {\n            if (cur.owner[k] != -1) far.push_back({cur.bestDist[k], k});\n        }\n        sort(far.begin(), far.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n        for (int i = 0; i < (int)far.size() && i < 6; ++i) {\n            int k = far[i].second;\n            addv(residentOrder[k][0]);\n            if (N >= 2) addv(residentOrder[k][1]);\n            if (N >= 3) addv(residentOrder[k][2]);\n        }\n    }\n\n    for (int i = 0; i < (int)singleOrder.size() && i < 6; ++i) addv(singleOrder[i]);\n    for (int i = 0; i < (int)coverOrder.size() && i < 6; ++i) addv(coverOrder[i]);\n    return pool;\n}\n\nstatic EvalResult repair_coverage(EvalResult cur) {\n    while (!time_over() && cur.uncovered > 0) {\n        vector<int> pool = build_pool(cur);\n        EvalResult best = cur;\n        bool found = false;\n\n        for (int v : pool) {\n            vector<int> tmp = cur.sel;\n            tmp.push_back(v);\n            EvalResult cand = core_eval(std::move(tmp), false, false);\n            if (!found ||\n                cand.uncovered < best.uncovered ||\n                (cand.uncovered == best.uncovered && cand.total < best.total)) {\n                best = std::move(cand);\n                found = true;\n            }\n            if (time_over()) break;\n        }\n\n        if (!found || best.uncovered >= cur.uncovered) {\n            int bestV = -1;\n            int bestCov = -1;\n            ll bestTot = INFLL;\n\n            for (int v = 2; v <= N; ++v) {\n                if (cur.inSel[v]) continue;\n                int cov = 0;\n                for (int k = 0; k < K; ++k) {\n                    if (cur.owner[k] == -1 && distSR[v][k] <= 5000) cov++;\n                }\n                if (cov == 0) continue;\n                vector<int> tmp = cur.sel;\n                tmp.push_back(v);\n                EvalResult cand = core_eval(std::move(tmp), false, false);\n                if (cand.uncovered < cur.uncovered &&\n                    (cov > bestCov || (cov == bestCov && cand.total < bestTot))) {\n                    bestCov = cov;\n                    bestTot = cand.total;\n                    bestV = v;\n                    best = std::move(cand);\n                    found = true;\n                }\n                if (time_over()) break;\n            }\n\n            if (bestV == -1 && !found) break;\n        }\n\n        if (!found) break;\n        cur = std::move(best);\n    }\n    return cur;\n}\n\nstatic EvalResult search_from_seed(vector<int> seed) {\n    EvalResult cur = strong_eval(std::move(seed), false);\n\n    for (int iter = 0; iter < 4 && !time_over(); ++iter) {\n        if (cur.uncovered > 0) {\n            cur = repair_coverage(cur);\n            if (cur.uncovered > 0) break;\n        }\n\n        vector<int> pool = build_pool(cur);\n\n        vector<int> load(cur.sel.size(), 0);\n        for (int k = 0; k < K; ++k) if (cur.owner[k] != -1) load[cur.owner[k]]++;\n\n        vector<pair<ll, vector<int>>> top;\n        top.reserve(24);\n\n        auto push_candidate = [&](const vector<int>& sel) {\n            EvalResult fast = core_eval(sel, false, false);\n            top.push_back({fast.total, fast.sel});\n            sort(top.begin(), top.end(), [&](auto& a, auto& b) {\n                if (a.first != b.first) return a.first < b.first;\n                return a.second.size() < b.second.size();\n            });\n            if ((int)top.size() > 6) top.resize(6);\n        };\n\n        for (int v : pool) {\n            vector<int> tmp = cur.sel;\n            tmp.push_back(v);\n            push_candidate(tmp);\n            if (time_over()) break;\n        }\n\n        vector<pair<ll,int>> remList;\n        for (int i = 0; i < (int)cur.sel.size(); ++i) {\n            if (cur.sel[i] == 1) continue;\n            ll score = 1LL * cur.rad[i] + 1000LL * (100 - load[i]);\n            remList.push_back({score, i});\n        }\n        sort(remList.begin(), remList.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return cur.sel[a.second] < cur.sel[b.second];\n        });\n\n        for (int i = 0; i < (int)remList.size() && i < 4; ++i) {\n            int rem = remList[i].second;\n            vector<int> tmp;\n            for (int x : cur.sel) if (x != cur.sel[rem]) tmp.push_back(x);\n            push_candidate(tmp);\n            if (time_over()) break;\n        }\n\n        int remLim = min(3, (int)remList.size());\n        int addLim = min(4, (int)pool.size());\n        for (int i = 0; i < remLim; ++i) {\n            int rem = remList[i].second;\n            for (int j = 0; j < addLim; ++j) {\n                int add = pool[j];\n                if (cur.inSel[add]) continue;\n                vector<int> tmp;\n                for (int x : cur.sel) if (x != cur.sel[rem]) tmp.push_back(x);\n                tmp.push_back(add);\n                push_candidate(tmp);\n                if (time_over()) break;\n            }\n            if (time_over()) break;\n        }\n\n        EvalResult best = cur;\n        for (auto& [sc, sel] : top) {\n            EvalResult cand = strong_eval(sel, false);\n            if (cand.total < best.total) best = std::move(cand);\n            if (time_over()) break;\n        }\n\n        if (best.total < cur.total) cur = std::move(best);\n        else break;\n    }\n\n    for (int rep = 0; rep < 2 && !time_over(); ++rep) {\n        vector<int> load(cur.sel.size(), 0);\n        for (int k = 0; k < K; ++k) if (cur.owner[k] != -1) load[cur.owner[k]]++;\n\n        vector<pair<ll,int>> remList;\n        for (int i = 0; i < (int)cur.sel.size(); ++i) {\n            if (cur.sel[i] == 1) continue;\n            ll score = 1LL * cur.rad[i] + 1000LL * (100 - load[i]);\n            remList.push_back({score, i});\n        }\n        sort(remList.begin(), remList.end(), [&](auto& a, auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return cur.sel[a.second] < cur.sel[b.second];\n        });\n\n        bool improved = false;\n        EvalResult best = cur;\n        for (int i = 0; i < (int)remList.size() && i < 4; ++i) {\n            int rem = remList[i].second;\n            vector<int> tmp;\n            for (int x : cur.sel) if (x != cur.sel[rem]) tmp.push_back(x);\n            EvalResult cand = strong_eval(std::move(tmp), false);\n            if (cand.total < best.total) {\n                best = std::move(cand);\n                improved = true;\n            }\n            if (time_over()) break;\n        }\n        if (!improved) break;\n        cur = std::move(best);\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\n    xs.resize(N + 1);\n    ys.resize(N + 1);\n    for (int i = 1; i <= N; ++i) cin >> xs[i] >> ys[i];\n\n    edges.resize(M);\n    edgeId.assign(N + 1, vector<int>(N + 1, -1));\n    distGraph.assign(N + 1, vector<ll>(N + 1, INFLL));\n    nxtHop.assign(N + 1, vector<int>(N + 1, -1));\n    graphAdj.assign(N + 1, {});\n\n    for (int i = 1; i <= N; ++i) {\n        distGraph[i][i] = 0;\n        nxtHop[i][i] = i;\n    }\n\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        ll w;\n        cin >> u >> v >> w;\n        edges[j] = {u, v, w};\n        edgeId[u][v] = edgeId[v][u] = j;\n        if (w < distGraph[u][v]) {\n            distGraph[u][v] = distGraph[v][u] = w;\n            nxtHop[u][v] = v;\n            nxtHop[v][u] = u;\n        }\n        graphAdj[u].push_back({v, w});\n        graphAdj[v].push_back({u, w});\n    }\n\n    ax.resize(K);\n    ay.resize(K);\n    for (int i = 0; i < K; ++i) cin >> ax[i] >> ay[i];\n\n    for (int k = 1; k <= N; ++k) {\n        for (int i = 1; i <= N; ++i) {\n            if (distGraph[i][k] >= INFLL / 4) continue;\n            for (int j = 1; j <= N; ++j) {\n                if (distGraph[k][j] >= INFLL / 4) continue;\n                ll nd = distGraph[i][k] + distGraph[k][j];\n                if (nd < distGraph[i][j]) {\n                    distGraph[i][j] = nd;\n                    nxtHop[i][j] = nxtHop[i][k];\n                }\n            }\n        }\n    }\n\n    distSR.assign(N + 1, vector<int>(K, 0));\n    residentOrder.assign(K, vector<int>(N));\n    coverCnt.assign(N + 1, 0);\n\n    for (int v = 1; v <= N; ++v) {\n        for (int k = 0; k < K; ++k) {\n            ll dx = (ll)xs[v] - ax[k];\n            ll dy = (ll)ys[v] - ay[k];\n            ll d2 = dx * dx + dy * dy;\n            int d = ceil_sqrt_ll(d2);\n            distSR[v][k] = d;\n            if (d <= 5000) coverCnt[v]++;\n        }\n    }\n\n    minDistRes.assign(K, MAXR);\n    coverCntRes.assign(K, 0);\n    hardOrder.resize(K);\n    for (int k = 0; k < K; ++k) {\n        int mn = MAXR, cnt = 0;\n        for (int v = 1; v <= N; ++v) {\n            int d = distSR[v][k];\n            mn = min(mn, d);\n            if (d <= 5000) cnt++;\n        }\n        minDistRes[k] = mn;\n        coverCntRes[k] = cnt;\n        hardOrder[k] = k;\n    }\n    sort(hardOrder.begin(), hardOrder.end(), [&](int a, int b) {\n        if (minDistRes[a] != minDistRes[b]) return minDistRes[a] > minDistRes[b];\n        if (coverCntRes[a] != coverCntRes[b]) return coverCntRes[a] < coverCntRes[b];\n        return a < b;\n    });\n\n    for (int k = 0; k < K; ++k) {\n        iota(residentOrder[k].begin(), residentOrder[k].end(), 1);\n        sort(residentOrder[k].begin(), residentOrder[k].end(), [&](int a, int b) {\n            if (distSR[a][k] != distSR[b][k]) return distSR[a][k] < distSR[b][k];\n            return a < b;\n        });\n    }\n\n    singleCost.assign(N + 1, INFLL);\n    for (int v = 2; v <= N; ++v) {\n        EvalResult e = core_eval({1, v}, false, true);\n        singleCost[v] = e.total;\n    }\n\n    singleOrder.clear();\n    coverOrder.clear();\n    for (int v = 2; v <= N; ++v) {\n        singleOrder.push_back(v);\n        coverOrder.push_back(v);\n    }\n\n    sort(singleOrder.begin(), singleOrder.end(), [&](int a, int b) {\n        if (singleCost[a] != singleCost[b]) return singleCost[a] < singleCost[b];\n        if (coverCnt[a] != coverCnt[b]) return coverCnt[a] > coverCnt[b];\n        return a < b;\n    });\n\n    sort(coverOrder.begin(), coverOrder.end(), [&](int a, int b) {\n        if (coverCnt[a] != coverCnt[b]) return coverCnt[a] > coverCnt[b];\n        if (singleCost[a] != singleCost[b]) return singleCost[a] < singleCost[b];\n        return a < b;\n    });\n\n    auto make_kmeans_seed = [&](int C, int startIdx) {\n        if (C <= 0) return vector<int>{1};\n        C = min(C, K);\n\n        auto dist2p = [&](int i, int j) -> ll {\n            ll dx = (ll)ax[i] - ax[j];\n            ll dy = (ll)ay[i] - ay[j];\n            return dx * dx + dy * dy;\n        };\n\n        vector<int> centers;\n        centers.reserve(C);\n        startIdx %= K;\n        if (startIdx < 0) startIdx += K;\n        centers.push_back(startIdx);\n\n        vector<ll> mind2(K, INFLL);\n        for (int k = 0; k < K; ++k) mind2[k] = dist2p(k, startIdx);\n\n        for (int c = 1; c < C; ++c) {\n            int nxt = 0;\n            ll best = -1;\n            for (int k = 0; k < K; ++k) {\n                if (mind2[k] > best) {\n                    best = mind2[k];\n                    nxt = k;\n                }\n            }\n            centers.push_back(nxt);\n            for (int k = 0; k < K; ++k) mind2[k] = min(mind2[k], dist2p(k, nxt));\n        }\n\n        vector<pair<double,double>> cen(C);\n        for (int i = 0; i < C; ++i) cen[i] = {(double)ax[centers[i]], (double)ay[centers[i]]};\n\n        for (int it = 0; it < 3; ++it) {\n            vector<vector<int>> groups(C);\n            for (int k = 0; k < K; ++k) {\n                int bestc = 0;\n                long double bestd = 1e100;\n                for (int c = 0; c < C; ++c) {\n                    long double dx = (long double)ax[k] - cen[c].first;\n                    long double dy = (long double)ay[k] - cen[c].second;\n                    long double d = dx * dx + dy * dy;\n                    if (d < bestd) {\n                        bestd = d;\n                        bestc = c;\n                    }\n                }\n                groups[bestc].push_back(k);\n            }\n\n            for (int c = 0; c < C; ++c) {\n                if (groups[c].empty()) continue;\n                long double sx = 0, sy = 0;\n                for (int k : groups[c]) {\n                    sx += ax[k];\n                    sy += ay[k];\n                }\n                cen[c] = {(double)(sx / groups[c].size()), (double)(sy / groups[c].size())};\n            }\n        }\n\n        vector<vector<int>> groups(C);\n        for (int k = 0; k < K; ++k) {\n            int bestc = 0;\n            long double bestd = 1e100;\n            for (int c = 0; c < C; ++c) {\n                long double dx = (long double)ax[k] - cen[c].first;\n                long double dy = (long double)ay[k] - cen[c].second;\n                long double d = dx * dx + dy * dy;\n                if (d < bestd) {\n                    bestd = d;\n                    bestc = c;\n                }\n            }\n            groups[bestc].push_back(k);\n        }\n\n        vector<int> chosen = {1};\n        for (int c = 0; c < C; ++c) {\n            if (groups[c].empty()) continue;\n            int bestV = 1;\n            int bestMax = INT_MAX;\n            ll bestSum = INFLL;\n            for (int v = 1; v <= N; ++v) {\n                int mx = 0;\n                ll sum = 0;\n                for (int k : groups[c]) {\n                    int d = distSR[v][k];\n                    mx = max(mx, d);\n                    sum += d;\n                    if (mx > bestMax) break;\n                }\n                if (mx < bestMax || (mx == bestMax && sum < bestSum)) {\n                    bestMax = mx;\n                    bestSum = sum;\n                    bestV = v;\n                }\n            }\n            chosen.push_back(bestV);\n        }\n\n        sort(chosen.begin(), chosen.end());\n        chosen.erase(unique(chosen.begin(), chosen.end()), chosen.end());\n        if (find(chosen.begin(), chosen.end(), 1) == chosen.end()) chosen.push_back(1);\n        sort(chosen.begin(), chosen.end());\n        return chosen;\n    };\n\n    auto make_hard_seed = [&]() {\n        vector<int> seed = {1};\n        int L = min(120, K);\n        vector<int> cand(hardOrder.begin(), hardOrder.begin() + L);\n\n        auto dist2res = [&](int a, int b) -> ll {\n            ll dx = (ll)ax[a] - ax[b];\n            ll dy = (ll)ay[a] - ay[b];\n            return dx * dx + dy * dy;\n        };\n\n        vector<int> centers;\n        centers.push_back(cand[0]);\n        vector<ll> mind(cand.size(), INFLL);\n        for (int idx = 0; idx < (int)cand.size(); ++idx) mind[idx] = dist2res(cand[idx], cand[0]);\n\n        int need = min(4, L);\n        for (int it = 1; it < need; ++it) {\n            int best = cand[0];\n            ll bd = -1;\n            for (int idx = 0; idx < (int)cand.size(); ++idx) {\n                if (mind[idx] > bd) {\n                    bd = mind[idx];\n                    best = cand[idx];\n                }\n            }\n            centers.push_back(best);\n            for (int idx = 0; idx < (int)cand.size(); ++idx) {\n                mind[idx] = min(mind[idx], dist2res(cand[idx], best));\n            }\n        }\n\n        vector<vector<int>> groups(centers.size());\n        for (int k : cand) {\n            int bestc = 0;\n            ll bd = INFLL;\n            for (int c = 0; c < (int)centers.size(); ++c) {\n                ll d = dist2res(k, centers[c]);\n                if (d < bd) {\n                    bd = d;\n                    bestc = c;\n                }\n            }\n            groups[bestc].push_back(k);\n        }\n\n        vector<char> used(N + 1, 0);\n        used[1] = 1;\n        for (auto& g : groups) {\n            if (g.empty()) continue;\n            int bestV = 1;\n            int bestMax = INT_MAX;\n            ll bestSum = INFLL;\n            for (int v = 1; v <= N; ++v) {\n                int mx = 0;\n                ll sum = 0;\n                for (int k : g) {\n                    int d = distSR[v][k];\n                    mx = max(mx, d);\n                    sum += d;\n                    if (mx > bestMax) break;\n                }\n                if (mx < bestMax || (mx == bestMax && sum < bestSum)) {\n                    bestMax = mx;\n                    bestSum = sum;\n                    bestV = v;\n                }\n            }\n            if (!used[bestV]) {\n                used[bestV] = 1;\n                seed.push_back(bestV);\n            }\n        }\n\n        return normalize_sel(std::move(seed));\n    };\n\n    auto make_cover_seed = [&]() {\n        vector<int> seed = {1};\n        vector<char> chosen(N + 1, 0);\n        chosen[1] = 1;\n        vector<char> covered(K, 0);\n\n        for (int step = 0; step < 5; ++step) {\n            int bestV = -1;\n            ll bestScore = -1;\n\n            for (int v = 2; v <= N; ++v) {\n                if (chosen[v]) continue;\n                ll score = 0;\n                for (int k = 0; k < K; ++k) {\n                    if (covered[k]) continue;\n                    int d = distSR[v][k];\n                    if (d <= 5000) score += 5001 - d;\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestV = v;\n                }\n            }\n\n            if (bestV == -1 || bestScore <= 0) break;\n            seed.push_back(bestV);\n            chosen[bestV] = 1;\n            for (int k = 0; k < K; ++k) {\n                if (!covered[k] && distSR[bestV][k] <= 5000) covered[k] = 1;\n            }\n        }\n\n        return normalize_sel(std::move(seed));\n    };\n\n    vector<vector<int>> seeds;\n    if (!singleOrder.empty()) seeds.push_back(normalize_sel({1, singleOrder[0]}));\n\n    {\n        int L = min(6, (int)singleOrder.size());\n        ll bestT = INFLL;\n        vector<int> bestSel = {1};\n        for (int i = 0; i < L; ++i) {\n            for (int j = i + 1; j < L; ++j) {\n                vector<int> s = {1, singleOrder[i], singleOrder[j]};\n                EvalResult e = core_eval(s, false, true);\n                if (e.total < bestT) {\n                    bestT = e.total;\n                    bestSel = e.sel;\n                }\n                if (time_over()) break;\n            }\n            if (time_over()) break;\n        }\n        seeds.push_back(normalize_sel(bestSel));\n    }\n\n    {\n        vector<int> s = {1};\n        for (int i = 0; i < (int)coverOrder.size() && i < 4; ++i) s.push_back(coverOrder[i]);\n        seeds.push_back(normalize_sel(s));\n    }\n\n    seeds.push_back(normalize_sel(make_kmeans_seed(6, 0)));\n    seeds.push_back(make_hard_seed());\n    seeds.push_back(make_cover_seed());\n\n    {\n        vector<int> cand;\n        for (int i = 0; i < (int)singleOrder.size() && i < 6; ++i) cand.push_back(singleOrder[i]);\n        for (int i = 0; i < (int)coverOrder.size() && i < 6; ++i) cand.push_back(coverOrder[i]);\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        shuffle(cand.begin(), cand.end(), rng);\n        vector<int> s = {1};\n        for (int v : cand) {\n            s.push_back(v);\n            if ((int)s.size() >= 5) break;\n        }\n        seeds.push_back(normalize_sel(s));\n    }\n\n    {\n        vector<vector<int>> uniq;\n        for (auto s : seeds) {\n            s = normalize_sel(std::move(s));\n            bool dup = false;\n            for (auto& t : uniq) {\n                if (t == s) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) uniq.push_back(std::move(s));\n        }\n        seeds = std::move(uniq);\n    }\n\n    EvalResult bestOverall;\n    bestOverall.total = INFLL;\n\n    for (auto& seed : seeds) {\n        if (time_over()) break;\n        EvalResult cur = search_from_seed(seed);\n        if (cur.total < bestOverall.total) bestOverall = std::move(cur);\n    }\n\n    if (bestOverall.sel.empty() || bestOverall.uncovered > 0) {\n        vector<int> allSel;\n        for (int v = 1; v <= N; ++v) allSel.push_back(v);\n        bestOverall = core_eval(allSel, true, false);\n    } else {\n        bestOverall = core_eval(bestOverall.sel, true, true);\n        if (bestOverall.uncovered > 0) {\n            vector<int> allSel;\n            for (int v = 1; v <= N; ++v) allSel.push_back(v);\n            bestOverall = core_eval(allSel, true, false);\n        }\n    }\n\n    vector<int> P(N + 1, 0);\n    for (int i = 0; i < (int)bestOverall.sel.size(); ++i) P[bestOverall.sel[i]] = bestOverall.rad[i];\n\n    for (int i = 1; i <= N; ++i) {\n        if (i > 1) cout << ' ';\n        cout << P[i];\n    }\n    cout << '\\n';\n\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << (bestOverall.used.empty() ? 0 : (bestOverall.used[j] ? 1 : 0));\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * (N + 1) / 2; // 465\nstatic constexpr int LIMIT = 10000;\nstatic constexpr int INF = 1e9;\nstatic constexpr long long INFLL = (1LL << 60);\n\nstruct Move {\n    int x1, y1, x2, y2;\n};\n\nstruct Variant {\n    bool topDown;\n    uint64_t seed;\n    int lenBase, lenSlope;\n    int unlockBase, unlockSlope;\n    int penW, centerW, rowW;\n    int futureW, horizon;\n    int rootBeam, deepBeam;\n};\n\nstruct State {\n    array<int, V> board{};\n    array<int, V> pos{};\n    array<unsigned char, V> fixed{};\n    array<unsigned char, V> avail{};\n    array<unsigned char, V> parentCnt{};\n    array<unsigned char, V> childCnt{};\n};\n\nstruct BFSRes {\n    array<int, V> dist{};\n    array<int, V> par{};\n    array<int, V> pen{};\n};\n\nstruct Candidate {\n    int target = -1;\n    int len = INF;\n    int pen = INF;\n    int unlock = 0;\n    int center = 0;\n    int rowBias = 0;\n    long long local = INFLL;\n};\n\nstruct Choice {\n    int target = -1;\n    int len = INF;\n    long long local = INFLL;\n    long long score = INFLL;\n    vector<int> path;\n};\n\nstruct Result {\n    vector<Move> ops;\n    bool complete = false;\n    int placed = 0;\n};\n\narray<pair<int, int>, V> coord;\narray<int, V> centerDist;\narray<int, V> needParents;\narray<int, V> needChildren;\narray<array<unsigned char, V>, V> fullDist;\n\nvector<int> adj[V];\nvector<int> parentsList[V];\nvector<int> childrenList[V];\n\ninline int id(int x, int y) {\n    return x * (x + 1) / 2 + y;\n}\n\ninline int next_label(int num, bool topDown, int d = 1) {\n    return topDown ? (num + d) : (num - d);\n}\n\narray<int, V> mirror_board(const array<int, V>& b) {\n    array<int, V> m{};\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            m[id(x, y)] = b[id(x, x - y)];\n        }\n    }\n    return m;\n}\n\nvector<Move> mirror_moves(const vector<Move>& ops) {\n    vector<Move> res;\n    res.reserve(ops.size());\n    for (const auto& mv : ops) {\n        res.push_back({mv.x1, mv.x1 - mv.y1, mv.x2, mv.x2 - mv.y2});\n    }\n    return res;\n}\n\nResult mirror_result(const Result& r) {\n    Result res;\n    res.complete = r.complete;\n    res.placed = r.placed;\n    res.ops = mirror_moves(r.ops);\n    return res;\n}\n\ninline array<int, V> make_weights(const State& st, int num, bool topDown) {\n    array<int, V> w;\n    w.fill(0);\n\n    auto mark = [&](int label, int val) {\n        if (0 <= label && label < V) {\n            w[st.pos[label]] = val;\n        }\n    };\n\n    if (topDown) {\n        mark(num + 1, 128);\n        mark(num + 2, 64);\n        mark(num + 3, 32);\n        mark(num + 4, 16);\n    } else {\n        mark(num - 1, 128);\n        mark(num - 2, 64);\n        mark(num - 3, 32);\n        mark(num - 4, 16);\n    }\n    return w;\n}\n\ninline int transition_penalty(const State& st, const array<int, V>& weight, int v) {\n    return weight[v] + 1 + (V - st.board[v]) / 32;\n}\n\ninline bool better_parent(int a, int b, bool topDown) {\n    if (b == -1) return true;\n    if (coord[a].first != coord[b].first) {\n        if (topDown) return coord[a].first > coord[b].first; // deeper preferred\n        return coord[a].first < coord[b].first;              // shallower preferred\n    }\n    if (centerDist[a] != centerDist[b]) return centerDist[a] < centerDist[b];\n    if (coord[a].second != coord[b].second) return coord[a].second < coord[b].second;\n    return a < b;\n}\n\nBFSRes bfs_from(const State& st, int src, const array<int, V>& weight, bool topDown) {\n    BFSRes res;\n    res.dist.fill(-1);\n    res.par.fill(-1);\n    res.pen.fill(INF);\n\n    vector<int> q;\n    q.reserve(V);\n    q.push_back(src);\n    res.dist[src] = 0;\n    res.pen[src] = 0;\n\n    for (size_t head = 0; head < q.size(); ++head) {\n        int u = q[head];\n        for (int v : adj[u]) {\n            if (st.fixed[v] || res.dist[v] != -1) continue;\n            res.dist[v] = res.dist[u] + 1;\n            q.push_back(v);\n        }\n    }\n\n    for (int u : q) {\n        if (res.pen[u] == INF) continue;\n        for (int v : adj[u]) {\n            if (st.fixed[v]) continue;\n            if (res.dist[v] != res.dist[u] + 1) continue;\n\n            int cand = res.pen[u] + transition_penalty(st, weight, v);\n            if (cand < res.pen[v] || (cand == res.pen[v] && better_parent(u, res.par[v], topDown))) {\n                res.pen[v] = cand;\n                res.par[v] = u;\n            }\n        }\n    }\n\n    return res;\n}\n\nvector<int> build_path(int src, int tgt, const array<int, V>& par) {\n    vector<int> path;\n    for (int v = tgt;; v = par[v]) {\n        path.push_back(v);\n        if (v == src) break;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nvoid apply_path(State& st, const vector<int>& path, vector<Move>* ops) {\n    for (int i = 0; i + 1 < (int)path.size(); ++i) {\n        int a = path[i];\n        int b = path[i + 1];\n        int va = st.board[a];\n        int vb = st.board[b];\n        swap(st.board[a], st.board[b]);\n        st.pos[va] = b;\n        st.pos[vb] = a;\n        if (ops) {\n            ops->push_back({coord[a].first, coord[a].second, coord[b].first, coord[b].second});\n        }\n    }\n}\n\nvoid fix_cell(State& st, int t, bool topDown) {\n    st.fixed[t] = 1;\n    st.avail[t] = 0;\n\n    if (topDown) {\n        for (int c : childrenList[t]) {\n            if (st.fixed[c]) continue;\n            ++st.parentCnt[c];\n            if (!st.avail[c] && st.parentCnt[c] == needParents[c]) {\n                st.avail[c] = 1;\n            }\n        }\n    } else {\n        for (int p : parentsList[t]) {\n            if (st.fixed[p]) continue;\n            ++st.childCnt[p];\n            if (!st.avail[p] && st.childCnt[p] == needChildren[p]) {\n                st.avail[p] = 1;\n            }\n        }\n    }\n}\n\nint unlock_score(const State& st, int t, bool topDown) {\n    int sc = 0;\n    if (topDown) {\n        for (int c : childrenList[t]) {\n            if (st.fixed[c]) continue;\n            if (st.parentCnt[c] + 1 == needParents[c]) ++sc;\n        }\n    } else {\n        for (int p : parentsList[t]) {\n            if (st.fixed[p]) continue;\n            if (st.childCnt[p] + 1 == needChildren[p]) ++sc;\n        }\n    }\n    return sc;\n}\n\ninline int small_noise(uint64_t seed, int num, int target) {\n    uint64_t x = seed\n        ^ (uint64_t)(num + 1) * 0x9e3779b97f4a7c15ULL\n        ^ (uint64_t)(target + 7) * 0xbf58476d1ce4e5b9ULL;\n    x ^= x >> 30;\n    x *= 0xbf58476d1ce4e5b9ULL;\n    x ^= x >> 27;\n    x *= 0x94d049bb133111ebULL;\n    x ^= x >> 31;\n    return (int)(x % 3) - 1; // tiny deterministic tie-break\n}\n\nlong long local_score(const Candidate& c, const Variant& var, int placed, int num) {\n    int phase = (V > 1 ? placed * 100 / (V - 1) : 0);\n    int lenW = max(20, var.lenBase - var.lenSlope * phase / 100);\n    int unlockW = max(10, var.unlockBase + var.unlockSlope * (100 - phase) / 100);\n\n    return 1LL * lenW * c.len\n         + 1LL * var.penW * c.pen\n         - 1LL * unlockW * c.unlock\n         + 1LL * var.centerW * c.center\n         + 1LL * var.rowW * c.rowBias\n         + small_noise(var.seed, num, c.target);\n}\n\nlong long future_potential(const State& st, int num, const Variant& var) {\n    long long sum = 0;\n    for (int d = 1; d <= var.horizon; ++d) {\n        int label = next_label(num, var.topDown, d);\n        if (label < 0 || label >= V) break;\n\n        int src = st.pos[label];\n        int best = INF;\n        for (int a = 0; a < V; ++a) {\n            if (!st.avail[a]) continue;\n            best = min(best, (int)fullDist[src][a]);\n        }\n        if (best >= INF) return INFLL;\n        sum += 1LL * (var.horizon - d + 1) * best;\n    }\n    return sum;\n}\n\nvector<Candidate> build_candidates(const State& st, const BFSRes& bfs, bool topDown,\n                                   int placed, int num, const Variant& var) {\n    vector<Candidate> cand;\n    cand.reserve(V);\n\n    for (int t = 0; t < V; ++t) {\n        if (!st.avail[t] || st.fixed[t]) continue;\n        if (bfs.dist[t] == -1) continue;\n\n        Candidate c;\n        c.target = t;\n        c.len = bfs.dist[t];\n        c.pen = bfs.pen[t];\n        c.unlock = unlock_score(st, t, topDown);\n        c.center = centerDist[t];\n        c.rowBias = topDown ? coord[t].first : (N - 1 - coord[t].first);\n        c.local = local_score(c, var, placed, num);\n        cand.push_back(c);\n    }\n\n    return cand;\n}\n\nstatic bool cmp_local(const Candidate& a, const Candidate& b) {\n    if (a.local != b.local) return a.local < b.local;\n    if (a.len != b.len) return a.len < b.len;\n    if (a.unlock != b.unlock) return a.unlock > b.unlock;\n    if (a.pen != b.pen) return a.pen < b.pen;\n    return a.target < b.target;\n}\n\nstatic bool cmp_len(const Candidate& a, const Candidate& b) {\n    if (a.len != b.len) return a.len < b.len;\n    if (a.local != b.local) return a.local < b.local;\n    if (a.unlock != b.unlock) return a.unlock > b.unlock;\n    if (a.pen != b.pen) return a.pen < b.pen;\n    return a.target < b.target;\n}\n\nstatic bool cmp_unlock(const Candidate& a, const Candidate& b) {\n    if (a.unlock != b.unlock) return a.unlock > b.unlock;\n    if (a.local != b.local) return a.local < b.local;\n    if (a.len != b.len) return a.len < b.len;\n    if (a.pen != b.pen) return a.pen < b.pen;\n    return a.target < b.target;\n}\n\nstatic bool cmp_pen(const Candidate& a, const Candidate& b) {\n    if (a.pen != b.pen) return a.pen < b.pen;\n    if (a.local != b.local) return a.local < b.local;\n    if (a.len != b.len) return a.len < b.len;\n    if (a.unlock != b.unlock) return a.unlock > b.unlock;\n    return a.target < b.target;\n}\n\nvector<int> shortlist_indices(const vector<Candidate>& cand, int limit) {\n    vector<int> ord(cand.size());\n    iota(ord.begin(), ord.end(), 0);\n\n    vector<int> picked;\n    picked.reserve(limit);\n    vector<char> usedTarget(V, 0);\n\n    auto add_from = [&](auto cmp, int k) {\n        if ((int)picked.size() >= limit || k <= 0 || ord.empty()) return;\n        vector<int> tmp = ord;\n        k = min(k, (int)tmp.size());\n        if (k < (int)tmp.size()) {\n            partial_sort(tmp.begin(), tmp.begin() + k, tmp.end(),\n                         [&](int a, int b) { return cmp(cand[a], cand[b]); });\n        } else {\n            sort(tmp.begin(), tmp.end(),\n                 [&](int a, int b) { return cmp(cand[a], cand[b]); });\n        }\n        for (int i = 0; i < k && (int)picked.size() < limit; ++i) {\n            int t = cand[tmp[i]].target;\n            if (!usedTarget[t]) {\n                usedTarget[t] = 1;\n                picked.push_back(tmp[i]);\n            }\n        }\n    };\n\n    add_from(cmp_local, 4);\n    add_from(cmp_len, 2);\n    add_from(cmp_unlock, 1);\n    add_from(cmp_pen, 1);\n\n    if ((int)picked.size() < limit) {\n        sort(ord.begin(), ord.end(), [&](int a, int b) { return cmp_local(cand[a], cand[b]); });\n        for (int idx : ord) {\n            int t = cand[idx].target;\n            if (!usedTarget[t]) {\n                usedTarget[t] = 1;\n                picked.push_back(idx);\n                if ((int)picked.size() == limit) break;\n            }\n        }\n    }\n\n    return picked;\n}\n\nChoice choose_greedy(const State& st, int num, int placed, int usedOps, const Variant& var) {\n    Choice best;\n    auto bfs = bfs_from(st, st.pos[num], make_weights(st, num, var.topDown), var.topDown);\n    auto cand = build_candidates(st, bfs, var.topDown, placed, num, var);\n\n    bool found = false;\n    tuple<long long, int, int, int, int> bestKey;\n\n    for (const auto& c : cand) {\n        if (usedOps + c.len > LIMIT) continue;\n        auto key = make_tuple(c.local, c.len, -c.unlock, c.pen, c.target);\n        if (!found || key < bestKey) {\n            found = true;\n            bestKey = key;\n            best.target = c.target;\n            best.len = c.len;\n            best.local = c.local;\n            best.score = c.local;\n        }\n    }\n\n    if (!found) return best;\n    best.path = build_path(st.pos[num], best.target, bfs.par);\n    return best;\n}\n\nChoice choose_move(const State& st, int num, int placed, int usedOps, const Variant& var, int depth) {\n    if (depth <= 1) return choose_greedy(st, num, placed, usedOps, var);\n\n    auto bfs = bfs_from(st, st.pos[num], make_weights(st, num, var.topDown), var.topDown);\n    auto cand = build_candidates(st, bfs, var.topDown, placed, num, var);\n    if (cand.empty()) return choose_greedy(st, num, placed, usedOps, var);\n\n    int beam = (depth >= 3 ? var.rootBeam : var.deepBeam);\n    auto idxs = shortlist_indices(cand, beam);\n    if (idxs.empty()) return choose_greedy(st, num, placed, usedOps, var);\n\n    Choice best;\n    bool found = false;\n\n    for (int idx : idxs) {\n        const Candidate& c = cand[idx];\n        if (usedOps + c.len > LIMIT) continue;\n\n        vector<int> path = build_path(st.pos[num], c.target, bfs.par);\n\n        State s1 = st;\n        apply_path(s1, path, nullptr);\n        fix_cell(s1, c.target, var.topDown);\n\n        long long total = c.local;\n        total += 1LL * var.futureW * future_potential(s1, num, var);\n\n        int nxt = next_label(num, var.topDown, 1);\n        if (0 <= nxt && nxt < V) {\n            Choice child = choose_move(s1, nxt, placed + 1, usedOps + c.len, var, depth - 1);\n            if (child.target == -1) continue;\n            total += child.score;\n        }\n\n        if (!found || total < best.score ||\n            (total == best.score && (c.local < best.local ||\n             (c.local == best.local && (c.len < best.len ||\n              (c.len == best.len && c.target < best.target)))))) {\n            found = true;\n            best.target = c.target;\n            best.len = c.len;\n            best.local = c.local;\n            best.score = total;\n            best.path = move(path);\n        }\n    }\n\n    if (!found) return choose_greedy(st, num, placed, usedOps, var);\n    return best;\n}\n\nResult run_variant(const array<int, V>& initBoard, const Variant& var, int depth) {\n    State st;\n    for (int i = 0; i < V; ++i) {\n        st.fixed[i] = 0;\n        st.avail[i] = 0;\n        st.parentCnt[i] = 0;\n        st.childCnt[i] = 0;\n    }\n\n    for (int i = 0; i < V; ++i) {\n        st.board[i] = initBoard[i];\n        st.pos[initBoard[i]] = i;\n    }\n\n    if (var.topDown) {\n        st.avail[id(0, 0)] = 1;\n    } else {\n        for (int y = 0; y < N; ++y) {\n            st.avail[id(N - 1, y)] = 1;\n        }\n    }\n\n    vector<Move> ops;\n    ops.reserve(LIMIT);\n\n    int placed = 0;\n    for (; placed < V && (int)ops.size() < LIMIT; ++placed) {\n        int num = var.topDown ? placed : (V - 1 - placed);\n\n        Choice ch = choose_move(st, num, placed, (int)ops.size(), var, depth);\n        if (ch.target == -1) break;\n\n        if ((int)ops.size() + ch.len > LIMIT) {\n            ch = choose_greedy(st, num, placed, (int)ops.size(), var);\n            if (ch.target == -1 || (int)ops.size() + ch.len > LIMIT) break;\n        }\n\n        apply_path(st, ch.path, &ops);\n        fix_cell(st, ch.target, var.topDown);\n    }\n\n    Result res;\n    res.ops = move(ops);\n    res.complete = (placed == V);\n    res.placed = placed;\n    return res;\n}\n\nResult solve_instance(const array<int, V>& initBoard, bool topDown, uint64_t seed) {\n    Variant var;\n    var.topDown = topDown;\n    var.seed = seed;\n    var.lenBase = 120;\n    var.lenSlope = 35;\n    var.unlockBase = 100;\n    var.unlockSlope = 25;\n    var.penW = 3;\n    var.centerW = 1;\n    var.rowW = 2;\n    var.futureW = 2;\n    var.horizon = 6;\n    var.rootBeam = 8;\n    var.deepBeam = 5;\n\n    Result exact = run_variant(initBoard, var, 3);\n    if (!exact.complete) {\n        Result greedy = run_variant(initBoard, var, 1);\n        if (greedy.complete || greedy.placed > exact.placed ||\n            (greedy.placed == exact.placed && greedy.ops.size() < exact.ops.size())) {\n            exact = move(greedy);\n        }\n    }\n    return exact;\n}\n\nbool better_result(const Result& a, const Result& b) {\n    if (a.complete != b.complete) return a.complete;\n    if (a.complete) return a.ops.size() < b.ops.size();\n    if (a.placed != b.placed) return a.placed > b.placed;\n    return a.ops.size() < b.ops.size();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // Precompute coordinates and graph.\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = id(x, y);\n            coord[u] = {x, y};\n            centerDist[u] = abs(2 * y - x);\n\n            if (x > 0) {\n                if (y > 0) parentsList[u].push_back(id(x - 1, y - 1));\n                if (y < x) parentsList[u].push_back(id(x - 1, y));\n            }\n            if (x + 1 < N) {\n                childrenList[u].push_back(id(x + 1, y));\n                childrenList[u].push_back(id(x + 1, y + 1));\n            }\n\n            if (y > 0) {\n                int v = id(x, y - 1);\n                adj[u].push_back(v);\n                adj[v].push_back(u);\n            }\n            if (x + 1 < N) {\n                int d1 = id(x + 1, y);\n                int d2 = id(x + 1, y + 1);\n                adj[u].push_back(d1);\n                adj[d1].push_back(u);\n                adj[u].push_back(d2);\n                adj[d2].push_back(u);\n            }\n        }\n    }\n\n    for (int i = 0; i < V; ++i) {\n        needParents[i] = (int)parentsList[i].size();\n        needChildren[i] = (int)childrenList[i].size();\n    }\n\n    // Precompute all-pairs graph distances.\n    for (int s = 0; s < V; ++s) {\n        array<int, V> dist;\n        dist.fill(-1);\n        vector<int> q;\n        q.reserve(V);\n        q.push_back(s);\n        dist[s] = 0;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int v : adj[u]) {\n                if (dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                q.push_back(v);\n            }\n        }\n\n        for (int i = 0; i < V; ++i) {\n            fullDist[s][i] = static_cast<unsigned char>(dist[i]);\n        }\n    }\n\n    array<int, V> initBoard{};\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            initBoard[id(x, y)] = v;\n        }\n    }\n\n    array<int, V> mirrored = mirror_board(initBoard);\n\n    vector<Variant> variants = {\n        {true,  1, 120, 35, 100, 25, 3, 1,  2, 2, 6, 8, 5},\n        {true,  2, 105, 25,  80, 20, 4, 2, -1, 2, 6, 8, 5},\n        {false, 3, 120, 35, 100, 25, 3, 1,  2, 2, 6, 8, 5},\n        {false, 4, 105, 25,  80, 20, 4, 2, -1, 2, 6, 8, 5},\n    };\n\n    Result best;\n    bool bestSet = false;\n\n    auto consider = [&](const Result& r) {\n        if (!bestSet || better_result(r, best)) {\n            best = r;\n            bestSet = true;\n        }\n    };\n\n    // Original board.\n    for (const auto& var : variants) {\n        consider(run_variant(initBoard, var, 3));\n    }\n    // Mirrored board.\n    for (const auto& var : variants) {\n        consider(mirror_result(run_variant(mirrored, var, 3)));\n    }\n\n    // Greedy fallback if needed.\n    if (!best.complete) {\n        for (const auto& var : variants) {\n            consider(run_variant(initBoard, var, 1));\n        }\n        for (const auto& var : variants) {\n            consider(mirror_result(run_variant(mirrored, var, 1)));\n        }\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (const auto& mv : best.ops) {\n        cout << mv.x1 << ' ' << mv.y1 << ' ' << mv.x2 << ' ' << mv.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int INF = 1e9;\n\nstruct TreeMeta {\n    vector<vector<int>> child;\n    vector<int> parent;\n    vector<int> depth;\n    vector<int> subtree;\n    vector<int> childCnt;\n    // rank[0] : depth-based order\n    // rank[1] : preorder-based order\n    // rank[2] : build/BFS-like order\n    vector<vector<int>> rank;\n};\n\nint D, N, M;\nvector<vector<int>> cellId;\nvector<int> cellR, cellC;\nvector<int> gridDist;\nvector<int> nextDeg;\nint er, ec;\n\nconst int dr[4] = {1, 0, 0, -1};\nconst int dc[4] = {0, -1, 1, 0};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nTreeMeta buildTreeA(const vector<vector<bool>>& obstacle) {\n    TreeMeta tr;\n    tr.child.assign(M + 1, {});\n    tr.parent.assign(M + 1, 0);\n    tr.depth.assign(M + 1, 0);\n    tr.subtree.assign(M + 1, 0);\n    tr.childCnt.assign(M + 1, 0);\n    tr.rank.assign(3, vector<int>(M + 1, -1));\n\n    vector<vector<bool>> vis(D, vector<bool>(D, false));\n    queue<int> q;\n\n    vis[er][ec] = true;\n    int bfsOrder = 0;\n\n    // Tree A: plain BFS from entrance, with fixed direction order.\n    for (int k = 0; k < 4; ++k) {\n        int nr = er + dr[k], nc = ec + dc[k];\n        if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n        int v = cellId[nr][nc];\n        if (v == -1) continue;\n        vis[nr][nc] = true;\n        tr.parent[v] = 0;\n        tr.depth[v] = 1;\n        tr.child[0].push_back(v);\n        tr.rank[2][v] = bfsOrder++;\n        q.push(v);\n    }\n\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n        int r = cellR[u], c = cellC[u];\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc] || vis[nr][nc]) continue;\n            int v = cellId[nr][nc];\n            if (v == -1) continue;\n            vis[nr][nc] = true;\n            tr.parent[v] = u;\n            tr.depth[v] = tr.depth[u] + 1;\n            tr.child[u].push_back(v);\n            tr.rank[2][v] = bfsOrder++;\n            q.push(v);\n        }\n    }\n\n    return tr;\n}\n\nTreeMeta buildTreeB(const vector<vector<bool>>& obstacle) {\n    TreeMeta tr;\n    tr.child.assign(M + 1, {});\n    tr.parent.assign(M + 1, 0);\n    tr.depth.assign(M + 1, 0);\n    tr.subtree.assign(M + 1, 0);\n    tr.childCnt.assign(M + 1, 0);\n    tr.rank.assign(3, vector<int>(M + 1, -1));\n\n    vector<int> ord;\n    ord.reserve(M);\n    for (int id = 1; id <= M; ++id) ord.push_back(id);\n\n    // Process shallow cells first, and among them prefer cells with many forward neighbors.\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (gridDist[a] != gridDist[b]) return gridDist[a] < gridDist[b];\n        if (nextDeg[a] != nextDeg[b]) return nextDeg[a] > nextDeg[b];\n        if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n        return cellC[a] < cellC[b];\n    });\n\n    int buildOrder = 0;\n    for (int v : ord) {\n        int d = gridDist[v];\n        if (d == 1) {\n            tr.parent[v] = 0;\n            tr.depth[v] = 1;\n            tr.child[0].push_back(v);\n            tr.rank[2][v] = buildOrder++;\n            continue;\n        }\n\n        int best = -1;\n        int bestScore = INF;\n        int r = cellR[v], c = cellC[v];\n\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n            if (gridDist[cellId[nr][nc]] != d - 1) continue;\n            int p = cellId[nr][nc];\n            if (p == -1) continue;\n\n            // Prefer parents that currently have fewer children, and among them\n            // those with larger future branching potential.\n            int score = tr.childCnt[p] * 100 - nextDeg[p];\n            if (score < bestScore ||\n                (score == bestScore &&\n                 (cellR[p] < cellR[best] ||\n                  (cellR[p] == cellR[best] && cellC[p] < cellC[best])))) {\n                bestScore = score;\n                best = p;\n            }\n        }\n\n        if (best == -1) {\n            // Fallback should never happen under valid input.\n            best = 0;\n        }\n\n        tr.parent[v] = best;\n        tr.depth[v] = tr.depth[best] + 1;\n        tr.child[best].push_back(v);\n        ++tr.childCnt[best];\n        tr.rank[2][v] = buildOrder++;\n    }\n\n    return tr;\n}\n\nvoid computeMeta(TreeMeta& tr) {\n    // subtree sizes\n    function<int(int)> dfsSub = [&](int u) -> int {\n        int s = 1;\n        for (int v : tr.child[u]) s += dfsSub(v);\n        tr.subtree[u] = s;\n        return s;\n    };\n    dfsSub(0);\n\n    // rank[0] : depth order\n    vector<int> nodes;\n    nodes.reserve(M);\n    for (int i = 1; i <= M; ++i) nodes.push_back(i);\n    sort(nodes.begin(), nodes.end(), [&](int a, int b) {\n        if (tr.depth[a] != tr.depth[b]) return tr.depth[a] < tr.depth[b];\n        if (tr.subtree[a] != tr.subtree[b]) return tr.subtree[a] > tr.subtree[b];\n        if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n        return cellC[a] < cellC[b];\n    });\n    for (int i = 0; i < M; ++i) tr.rank[0][nodes[i]] = i;\n\n    // rank[1] : preorder with larger subtrees first\n    int cnt = 0;\n    function<void(int)> dfsPre = [&](int u) {\n        if (u != 0) tr.rank[1][u] = cnt++;\n        vector<int> ch = tr.child[u];\n        sort(ch.begin(), ch.end(), [&](int a, int b) {\n            if (tr.subtree[a] != tr.subtree[b]) return tr.subtree[a] > tr.subtree[b];\n            if (cellR[a] != cellR[b]) return cellR[a] < cellR[b];\n            return cellC[a] < cellC[b];\n        });\n        for (int v : ch) dfsPre(v);\n    };\n    dfsPre(0);\n\n    // childCnt\n    for (int i = 0; i <= M; ++i) tr.childCnt[i] = (int)tr.child[i].size();\n}\n\nint chainLen(const TreeMeta& tr, const vector<int>& remChild, int u) {\n    int cnt = 0;\n    int x = u;\n    while (tr.parent[x] != 0 && remChild[tr.parent[x]] == 1) {\n        ++cnt;\n        x = tr.parent[x];\n    }\n    return cnt;\n}\n\nint pickLeaf(const TreeMeta& tr, const vector<int>& remChild, const vector<char>& used,\n             int t, int rankKind, int gamma) {\n    int best = -1;\n    long long bestScore = (1LL << 60);\n    long long bestEff = (1LL << 60);\n    int bestChain = -1;\n\n    for (int u = 1; u <= M; ++u) {\n        if (used[u] || remChild[u] != 0) continue;\n        int ch = chainLen(tr, remChild, u);\n        long long eff = tr.rank[rankKind][u] + 1LL * gamma * ch;\n        long long score = llabs(eff - t);\n\n        if (best == -1 ||\n            score < bestScore ||\n            (score == bestScore && eff < bestEff) ||\n            (score == bestScore && eff == bestEff && ch > bestChain) ||\n            (score == bestScore && eff == bestEff && ch == bestChain &&\n             (cellR[u] < cellR[best] || (cellR[u] == cellR[best] && cellC[u] < cellC[best])))) {\n            best = u;\n            bestScore = score;\n            bestEff = eff;\n            bestChain = ch;\n        }\n    }\n    return best;\n}\n\nlong long simulate(const TreeMeta& tr, const vector<int>& perm, int rankKind, int gamma) {\n    vector<int> remChild = tr.childCnt;\n    vector<char> used(M + 1, 0);\n    vector<int> assigned(M + 1, -1);\n\n    for (int t : perm) {\n        int u = pickLeaf(tr, remChild, used, t, rankKind, gamma);\n        used[u] = 1;\n        assigned[u] = t;\n        int p = tr.parent[u];\n        if (p != 0) --remChild[p];\n    }\n\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int v : tr.child[0]) pq.push({assigned[v], v});\n\n    vector<int> seq;\n    seq.reserve(M);\n    while (!pq.empty()) {\n        auto [lab, u] = pq.top();\n        pq.pop();\n        seq.push_back(lab);\n        for (int v : tr.child[u]) pq.push({assigned[v], v});\n    }\n\n    long long 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 Choice {\n    int treeId = 0;\n    int rankKind = 0;\n    int gamma = 0;\n    long long score = (1LL << 60);\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int i = 0; i < N; ++i) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    er = 0;\n    ec = (D - 1) / 2;\n\n    auto freeCell = [&](int r, int c) {\n        return inside(r, c) && !obstacle[r][c] && !(r == er && c == ec);\n    };\n\n    // Grid distances from entrance\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n    dist[er][ec] = 0;\n    q.push({er, ec});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc] || dist[nr][nc] != -1) continue;\n            dist[nr][nc] = dist[r][c] + 1;\n            q.push({nr, nc});\n        }\n    }\n\n    // Build cell compression\n    M = 0;\n    cellId.assign(D, vector<int>(D, -1));\n    cellR.assign(1, 0);\n    cellC.assign(1, 0);\n    gridDist.assign(1, 0);\n    nextDeg.assign(1, 0);\n\n    for (int r = 0; r < D; ++r) {\n        for (int c = 0; c < D; ++c) {\n            if (freeCell(r, c)) {\n                int id = ++M;\n                cellId[r][c] = id;\n                cellR.push_back(r);\n                cellC.push_back(c);\n                gridDist.push_back(dist[r][c]);\n            }\n        }\n    }\n\n    nextDeg.assign(M + 1, 0);\n    for (int id = 1; id <= M; ++id) {\n        int r = cellR[id], c = cellC[id];\n        int d = gridDist[id];\n        int cnt = 0;\n        for (int k = 0; k < 4; ++k) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc) || obstacle[nr][nc]) continue;\n            int nid = cellId[nr][nc];\n            if (nid != -1 && gridDist[nid] == d + 1) ++cnt;\n        }\n        nextDeg[id] = cnt;\n    }\n\n    // Build candidate trees\n    vector<TreeMeta> trees;\n    trees.push_back(buildTreeA(obstacle));\n    trees.push_back(buildTreeB(obstacle));\n\n    for (auto& tr : trees) computeMeta(tr);\n\n    // Monte Carlo selection of heuristic parameters\n    vector<vector<int>> samples;\n    {\n        uint64_t seed = 88172645463393265ULL;\n        seed ^= (uint64_t)D * 1000003ULL + (uint64_t)N * 9176ULL;\n        for (int i = 0; i < min(M, 12); ++i) seed ^= (uint64_t)(cellR[i % max(1, M)] + 1) * 1315423911ULL + (uint64_t)(cellC[i % max(1, M)] + 7);\n\n        mt19937_64 rng(seed);\n        int S = 24;\n        samples.reserve(S);\n        vector<int> base(M);\n        iota(base.begin(), base.end(), 0);\n        for (int s = 0; s < S; ++s) {\n            auto perm = base;\n            shuffle(perm.begin(), perm.end(), rng);\n            samples.push_back(move(perm));\n        }\n    }\n\n    vector<int> gammaCandidates = {-2, 0, 1, 2, 4};\n    Choice best;\n\n    for (int ti = 0; ti < (int)trees.size(); ++ti) {\n        for (int rk = 0; rk < 3; ++rk) {\n            for (int gamma : gammaCandidates) {\n                long long sum = 0;\n                for (auto& perm : samples) {\n                    sum += simulate(trees[ti], perm, rk, gamma);\n                }\n                if (sum < best.score ||\n                    (sum == best.score && ti < best.treeId) ||\n                    (sum == best.score && ti == best.treeId && rk < best.rankKind) ||\n                    (sum == best.score && ti == best.treeId && rk == best.rankKind && gamma < best.gamma)) {\n                    best.treeId = ti;\n                    best.rankKind = rk;\n                    best.gamma = gamma;\n                    best.score = sum;\n                }\n            }\n        }\n    }\n\n    TreeMeta& tr = trees[best.treeId];\n    int rankKind = best.rankKind;\n    int gamma = best.gamma;\n\n    // Online placement\n    vector<int> remChild = tr.childCnt;\n    vector<char> used(M + 1, 0);\n    vector<int> assigned(M + 1, -1);\n\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        int u = pickLeaf(tr, remChild, used, t, rankKind, gamma);\n        used[u] = 1;\n        assigned[u] = t;\n        int p = tr.parent[u];\n        if (p != 0) --remChild[p];\n\n        cout << cellR[u] << ' ' << cellC[u] << '\\n' << flush;\n    }\n\n    // Final removal order: smallest available label first on the rooted tree\n    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n    for (int v : tr.child[0]) pq.push({assigned[v], v});\n\n    vector<int> order;\n    order.reserve(M);\n\n    while (!pq.empty()) {\n        auto [lab, u] = pq.top();\n        pq.pop();\n        order.push_back(u);\n        for (int v : tr.child[u]) pq.push({assigned[v], v});\n    }\n\n    for (int u : order) {\n        cout << cellR[u] << ' ' << cellC[u] << '\\n';\n    }\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int MAXN = 50;\nstatic const int MAXM = 100;\nstatic const int MAXV = MAXN * MAXN;\n\nstruct Edge {\n    int u, v;\n};\n\nstruct RemInfo {\n    bool ok = false;\n    int same = 0;      // same-color neighbors\n    int loss0 = 0;     // sides that become 0/outside after removal\n    int diffTypes = 0; // distinct neighboring colors\n    int sumSlack = 0;  // remaining adjacency slack after removal\n};\n\nstruct GreedyWeight {\n    long long termW;     // distance to soft sources\n    long long leafBonus;  // bonus if same<=1\n    long long cntW;      // current color size\n    long long lossW;     // frontier exposure\n    long long slackW;    // remaining adjacency slack\n    long long sameW;     // penalty for many same-color neighbors\n    long long diffW;     // penalty for many distinct neighboring colors\n    long long distW;     // penalty by distance to original border\n};\n\nstruct TrialConfig {\n    int utilType;\n    int pairOrderType;\n    bool useWitness;\n    bool preferLeafFirst;\n    int refreshLimit;\n    array<GreedyWeight, 4> phaseW;\n    uint64_t seed;\n};\n\nint n, m, N;\nvector<int> initBoard, boardCur;\nint nb[MAXV][4];\nint distToBorder[MAXV];\nint sameDegOrig[MAXV];\nint diffDegOrig[MAXV];\nint borderAdjDeg[MAXV];\nbool borderTouchCell[MAXV];\nbool frozenCell[MAXV];\nbool origB[MAXM + 1];\nbool origAdj[MAXM + 1][MAXM + 1];\n\nvector<int> colorCells[MAXM + 1];\nvector<Edge> pairEdges[MAXM + 1][MAXM + 1];\nvector<int> pairA, pairB, pairCnt, pairDegSum;\nvector<int> pairOrderAsc, pairOrderDesc;\n\nint curCnt[MAXM + 1];\nint curTouch0[MAXM + 1];\nint curPairCnt[MAXM + 1][MAXM + 1];\n\nint artSeen[MAXV], artDisc[MAXV], artLow[MAXV];\nbool isArt[MAXV];\nint artToken = 1;\n\nvector<int> candidateCells;\n\ninline int id(int i, int j) { return i * n + j; }\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\nint countZeros(const vector<int>& b) {\n    int z = 0;\n    for (int x : b) if (x == 0) ++z;\n    return z;\n}\n\nint countTouchBad() {\n    int bad = 0;\n    for (int c = 1; c <= m; ++c) {\n        if (origB[c] && curTouch0[c] == 0) bad++;\n    }\n    return bad;\n}\n\nlong long vertexUtility(int idx, int type, uint64_t seed) {\n    long long s = 0;\n    if (type == 0) {\n        s += 2000LL * diffDegOrig[idx];\n        s += 200LL * sameDegOrig[idx];\n        s += 150LL * borderAdjDeg[idx];\n        s -= 5LL * distToBorder[idx];\n    } else if (type == 1) {\n        s += 1500LL * diffDegOrig[idx];\n        s += 300LL * sameDegOrig[idx];\n        s += 100LL * borderAdjDeg[idx];\n        s -= 3LL * distToBorder[idx];\n    } else {\n        s += 2500LL * diffDegOrig[idx];\n        s += 100LL * sameDegOrig[idx];\n        s += 200LL * borderAdjDeg[idx];\n        s -= 8LL * distToBorder[idx];\n    }\n    if (borderTouchCell[idx]) s += 50;\n    s += (long long)(splitmix64(seed + 1234567ULL * idx + 998244353ULL * (uint64_t)type) & 63ULL);\n    return s;\n}\n\nvoid recomputeArtColor(int c) {\n    for (int idx : colorCells[c]) isArt[idx] = false;\n    if (curCnt[c] <= 1) return;\n\n    int root = -1;\n    for (int idx : colorCells[c]) {\n        if (boardCur[idx] == c) {\n            root = idx;\n            break;\n        }\n    }\n    if (root == -1) return;\n\n    ++artToken;\n    int timer = 0;\n    function<void(int,int)> dfs = [&](int u, int p) {\n        artSeen[u] = artToken;\n        artDisc[u] = artLow[u] = ++timer;\n        int child = 0;\n\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[u][d];\n            if (v == -1 || v == p || boardCur[v] != c) continue;\n            if (artSeen[v] != artToken) {\n                ++child;\n                dfs(v, u);\n                artLow[u] = min(artLow[u], artLow[v]);\n                if (p != -1 && artLow[v] >= artDisc[u]) isArt[u] = true;\n            } else {\n                artLow[u] = min(artLow[u], artDisc[v]);\n            }\n        }\n\n        if (p == -1 && child > 1) isArt[u] = true;\n    };\n\n    dfs(root, -1);\n}\n\nvoid initState(const vector<int>& startBoard) {\n    boardCur = startBoard;\n    memset(curCnt, 0, sizeof(curCnt));\n    memset(curTouch0, 0, sizeof(curTouch0));\n    memset(curPairCnt, 0, sizeof(curPairCnt));\n    memset(isArt, 0, sizeof(isArt));\n    memset(artSeen, 0, sizeof(artSeen));\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c > 0) curCnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = boardCur[idx];\n        if (c == 0) continue;\n\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1 || boardCur[v] == 0) curTouch0[c]++;\n        }\n\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = boardCur[right];\n            if (d > 0 && d != c && origB[c] && origB[d]) {\n                curPairCnt[c][d]++;\n                curPairCnt[d][c]++;\n            }\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = boardCur[down];\n            if (d > 0 && d != c && origB[c] && origB[d]) {\n                curPairCnt[c][d]++;\n                curPairCnt[d][c]++;\n            }\n        }\n    }\n\n    for (int c = 1; c <= m; ++c) {\n        if (origB[c]) recomputeArtColor(c);\n    }\n}\n\nbool frontierToZero(int idx) {\n    if (borderTouchCell[idx]) return true;\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) return true;\n    }\n    return false;\n}\n\nbool analyzeCell(int idx, RemInfo& info) {\n    info = {};\n    int c = boardCur[idx];\n    if (c == 0) return false;\n    if (!origB[c]) return false;\n    if (frozenCell[idx]) return false;\n    if (isArt[idx]) return false;\n    if (curCnt[c] <= 1) return false;\n    if (!frontierToZero(idx)) return false;\n\n    int loss[MAXM + 1];\n    memset(loss, 0, sizeof(loss));\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            info.loss0++;\n        } else {\n            int t = boardCur[v];\n            if (t == c) {\n                info.same++;\n            } else {\n                if (!origB[t]) return false; // would expose a non-border-touching color to 0\n                if (loss[t] == 0) info.diffTypes++;\n                loss[t]++;\n            }\n        }\n    }\n\n    // Original adjacency pairs between border-touching colors must never disappear.\n    for (int t = 1; t <= m; ++t) {\n        if (loss[t] == 0) continue;\n        if (curPairCnt[c][t] <= loss[t]) return false;\n        info.sumSlack += curPairCnt[c][t] - loss[t];\n    }\n\n    if (info.same > 1) {\n        // Connectivity check for color c after removing idx.\n        int start = -1;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v != -1 && boardCur[v] == c) {\n                start = v;\n                break;\n            }\n        }\n        if (start == -1) return false;\n\n        ++artToken;\n        vector<int> q;\n        q.reserve(curCnt[c]);\n        q.push_back(start);\n        artSeen[start] = artToken;\n        int seen = 1;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v == -1 || v == idx) continue;\n                if (boardCur[v] == c && artSeen[v] != artToken) {\n                    artSeen[v] = artToken;\n                    q.push_back(v);\n                    ++seen;\n                }\n            }\n        }\n        if (seen != curCnt[c] - 1) return false;\n    }\n\n    info.ok = true;\n    return true;\n}\n\nstruct CandEval {\n    int nextTouchBad = INT_MAX;\n    long long score = -(1LL << 60);\n    RemInfo info;\n};\n\nint evalNextTouchBad(int idx, int currentTouchBad, const RemInfo& info) {\n    int c = boardCur[idx];\n    int delta[MAXM + 1];\n    memset(delta, 0, sizeof(delta));\n\n    delta[c] += -info.loss0 + info.same;\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) continue;\n        int t = boardCur[v];\n        if (t == c) continue;\n        if (!origB[t]) continue;\n        delta[t]++;\n    }\n\n    int nextBad = currentTouchBad;\n    bool seen[MAXM + 1] = {};\n    int affected[MAXM + 1];\n    int ac = 0;\n\n    auto addColor = [&](int col) {\n        if (!origB[col] || seen[col]) return;\n        seen[col] = true;\n        affected[ac++] = col;\n    };\n\n    addColor(c);\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) continue;\n        int t = boardCur[v];\n        if (t != c) addColor(t);\n    }\n\n    for (int i = 0; i < ac; ++i) {\n        int col = affected[i];\n        int oldBad = (curTouch0[col] == 0);\n        int newTouch = curTouch0[col] + delta[col];\n        int newBad = (newTouch == 0);\n        nextBad += newBad - oldBad;\n    }\n    return nextBad;\n}\n\nlong long scoreCell(int idx, const RemInfo& info, const GreedyWeight& w, const vector<int>& softDist, uint64_t seed, int phase) {\n    int c = boardCur[idx];\n    long long s = 0;\n    s += w.termW * softDist[idx];\n    s += w.leafBonus * (info.same <= 1 ? 1 : 0);\n    s += w.cntW * curCnt[c];\n    s += w.lossW * info.loss0;\n    s += w.slackW * info.sumSlack;\n    s -= w.sameW * info.same;\n    s -= w.diffW * info.diffTypes;\n    s -= w.distW * distToBorder[idx];\n\n    s += (long long)(splitmix64(seed + 1234567ULL * idx + 998244353ULL * (uint64_t)phase) & 1023ULL);\n    return s;\n}\n\nvoid applyRemoval(int idx) {\n    int c = boardCur[idx];\n    int same = 0, loss0 = 0;\n\n    for (int d = 0; d < 4; ++d) {\n        int v = nb[idx][d];\n        if (v == -1 || boardCur[v] == 0) {\n            loss0++;\n        } else if (boardCur[v] == c) {\n            same++;\n        } else {\n            int t = boardCur[v];\n            if (origB[t]) curTouch0[t]++;\n            if (origB[c] && origB[t]) {\n                curPairCnt[c][t]--;\n                curPairCnt[t][c]--;\n            }\n        }\n    }\n\n    boardCur[idx] = 0;\n    curCnt[c]--;\n    curTouch0[c] += same - loss0;\n\n    recomputeArtColor(c);\n}\n\nvoid buildSources(const TrialConfig& cfg, uint64_t seed, vector<char>& source) {\n    source.assign(N, false);\n\n    auto util = [&](int idx) { return vertexUtility(idx, cfg.utilType, seed); };\n\n    // Frozen cells are always soft sources.\n    for (int idx = 0; idx < N; ++idx) {\n        if (boardCur[idx] != 0 && frozenCell[idx]) source[idx] = true;\n    }\n\n    if (!cfg.useWitness) return;\n\n    // Add one witness edge per border-touching adjacency pair, trying to reuse terminals.\n    struct Task {\n        int a, b, cnt, degSum;\n    };\n    vector<Task> tasks;\n    tasks.reserve(pairA.size());\n    for (size_t i = 0; i < pairA.size(); ++i) {\n        tasks.push_back({pairA[i], pairB[i], pairCnt[i], pairDegSum[i]});\n    }\n\n    if (cfg.pairOrderType == 0) {\n        sort(tasks.begin(), tasks.end(), [](const Task& x, const Task& y) {\n            if (x.cnt != y.cnt) return x.cnt < y.cnt;\n            if (x.degSum != y.degSum) return x.degSum < y.degSum;\n            if (x.a != y.a) return x.a < y.a;\n            return x.b < y.b;\n        });\n    } else {\n        sort(tasks.begin(), tasks.end(), [](const Task& x, const Task& y) {\n            if (x.cnt != y.cnt) return x.cnt > y.cnt;\n            if (x.degSum != y.degSum) return x.degSum > y.degSum;\n            if (x.a != y.a) return x.a < y.a;\n            return x.b < y.b;\n        });\n    }\n\n    for (const auto& t : tasks) {\n        bool covered = false;\n        Edge bestE{-1, -1};\n        long long bestSc = -(1LL << 60);\n\n        for (const auto& e : pairEdges[t.a][t.b]) {\n            if (boardCur[e.u] != t.a || boardCur[e.v] != t.b) continue;\n            if (source[e.u] && source[e.v]) {\n                covered = true;\n                break;\n            }\n\n            int reuse = (source[e.u] ? 1 : 0) + (source[e.v] ? 1 : 0);\n            long long sc = 1000000LL * reuse + util(e.u) + util(e.v);\n            sc += 1000LL * (borderAdjDeg[e.u] + borderAdjDeg[e.v]);\n            sc += (long long)(splitmix64(seed + 911382323ULL * e.u + 972663749ULL * e.v + 1000003ULL * t.a + 10007ULL * t.b) & 255ULL);\n\n            if (sc > bestSc) {\n                bestSc = sc;\n                bestE = e;\n            }\n        }\n\n        if (!covered && bestE.u != -1) {\n            source[bestE.u] = true;\n            source[bestE.v] = true;\n        }\n    }\n}\n\nvoid computeSoftDist(const vector<char>& source, vector<int>& softDist) {\n    softDist.assign(N, 0);\n    vector<int> dist(N, -1);\n    vector<int> q;\n    q.reserve(N);\n\n    for (int c = 1; c <= m; ++c) {\n        if (!origB[c]) continue;\n\n        fill(dist.begin(), dist.end(), -1);\n        q.clear();\n\n        for (int idx : colorCells[c]) {\n            if (boardCur[idx] == c && source[idx]) {\n                dist[idx] = 0;\n                q.push_back(idx);\n            }\n        }\n\n        if (q.empty()) {\n            for (int idx : colorCells[c]) {\n                if (boardCur[idx] == c && frontierToZero(idx)) {\n                    dist[idx] = 0;\n                    q.push_back(idx);\n                }\n            }\n        }\n\n        if (q.empty()) {\n            for (int idx : colorCells[c]) {\n                if (boardCur[idx] == c) {\n                    dist[idx] = 0;\n                    q.push_back(idx);\n                    break;\n                }\n            }\n        }\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v == -1 || boardCur[v] != c || dist[v] != -1) continue;\n                dist[v] = dist[u] + 1;\n                q.push_back(v);\n            }\n        }\n\n        for (int idx : colorCells[c]) {\n            if (boardCur[idx] == c && dist[idx] != -1) softDist[idx] = dist[idx];\n        }\n    }\n}\n\nvector<int> runTrial(const vector<int>& startBoard, const TrialConfig& cfg) {\n    initState(startBoard);\n\n    int touchBadCount = countTouchBad();\n    vector<char> source;\n    vector<int> softDist;\n\n    vector<int> bestBoard = boardCur;\n    int bestZeros = (touchBadCount == 0 ? countZeros(boardCur) : -1);\n\n    for (int phase = 0; phase < 4; ++phase) {\n        buildSources(cfg, cfg.seed + 1000003ULL * phase, source);\n        computeSoftDist(source, softDist);\n\n        int sinceRefresh = 0;\n        while (true) {\n            int bestIdx = -1;\n            int bestNextBad = INT_MAX;\n            long long bestScore = -(1LL << 60);\n            RemInfo bestInfo;\n\n            for (int idx : candidateCells) {\n                if (boardCur[idx] == 0) continue;\n\n                RemInfo info;\n                if (!analyzeCell(idx, info)) continue;\n\n                int nextBad = evalNextTouchBad(idx, touchBadCount, info);\n                long long sc = scoreCell(idx, info, cfg.phaseW[phase], softDist, cfg.seed, phase);\n\n                if (nextBad < bestNextBad || (nextBad == bestNextBad && sc > bestScore)) {\n                    bestNextBad = nextBad;\n                    bestScore = sc;\n                    bestIdx = idx;\n                    bestInfo = info;\n                }\n            }\n\n            if (bestIdx == -1) break;\n\n            bool wasSource = source[bestIdx];\n            applyRemoval(bestIdx);\n            touchBadCount = countTouchBad();\n            ++sinceRefresh;\n\n            if (touchBadCount == 0) {\n                int z = countZeros(boardCur);\n                if (z > bestZeros) {\n                    bestZeros = z;\n                    bestBoard = boardCur;\n                }\n            }\n\n            if (wasSource || sinceRefresh >= cfg.refreshLimit) {\n                buildSources(cfg, cfg.seed + 1000003ULL * phase + 17ULL * sinceRefresh, source);\n                computeSoftDist(source, softDist);\n                sinceRefresh = 0;\n            }\n        }\n    }\n\n    if (bestZeros >= 0) return bestBoard;\n    return boardCur;\n}\n\nbool validate(const vector<int>& b) {\n    bool outAdj[MAXM + 1][MAXM + 1];\n    memset(outAdj, 0, sizeof(outAdj));\n    bool outTouch0[MAXM + 1];\n    memset(outTouch0, 0, sizeof(outTouch0));\n\n    vector<int> cnt(MAXM + 1, 0);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c > 0) cnt[c]++;\n    }\n\n    for (int idx = 0; idx < N; ++idx) {\n        int c = b[idx];\n        if (c == 0) continue;\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1 || b[v] == 0) {\n                outTouch0[c] = true;\n            } else if (b[v] != c) {\n                int t = b[v];\n                outAdj[c][t] = outAdj[t][c] = true;\n            }\n        }\n    }\n\n    for (int c = 1; c <= m; ++c) {\n        if (outTouch0[c] != origB[c]) return false;\n        for (int d = 1; d <= m; ++d) {\n            if (outAdj[c][d] != origAdj[c][d]) return false;\n        }\n    }\n\n    vector<int> seen(N, 0);\n    int stamp = 1;\n    vector<int> q;\n    q.reserve(N);\n\n    // Connectivity of each color.\n    for (int c = 1; c <= m; ++c) {\n        int start = -1;\n        for (int idx = 0; idx < N; ++idx) {\n            if (b[idx] == c) {\n                start = idx;\n                break;\n            }\n        }\n        if (start == -1) return false;\n\n        ++stamp;\n        q.clear();\n        q.push_back(start);\n        seen[start] = stamp;\n        int got = 1;\n\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == c && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                    ++got;\n                }\n            }\n        }\n        if (got != cnt[c]) return false;\n    }\n\n    // 0-color connectivity through outside.\n    int zeroCnt = 0;\n    for (int idx = 0; idx < N; ++idx) if (b[idx] == 0) zeroCnt++;\n    if (zeroCnt > 0) {\n        ++stamp;\n        q.clear();\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    int idx = id(i, j);\n                    if (b[idx] == 0 && seen[idx] != stamp) {\n                        seen[idx] = stamp;\n                        q.push_back(idx);\n                    }\n                }\n            }\n        }\n        if (q.empty()) return false;\n\n        int got = 0;\n        for (size_t head = 0; head < q.size(); ++head) {\n            int u = q[head];\n            ++got;\n            for (int d = 0; d < 4; ++d) {\n                int v = nb[u][d];\n                if (v != -1 && b[v] == 0 && seen[v] != stamp) {\n                    seen[v] = stamp;\n                    q.push_back(v);\n                }\n            }\n        }\n        if (got != zeroCnt) return false;\n    }\n\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n    N = n * n;\n    initBoard.assign(N, 0);\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c;\n            cin >> c;\n            initBoard[id(i, j)] = c;\n            colorCells[c].push_back(id(i, j));\n        }\n    }\n\n    // Geometry.\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int idx = id(i, j);\n            nb[idx][0] = (i == 0 ? -1 : id(i - 1, j));\n            nb[idx][1] = (i + 1 == n ? -1 : id(i + 1, j));\n            nb[idx][2] = (j == 0 ? -1 : id(i, j - 1));\n            nb[idx][3] = (j + 1 == n ? -1 : id(i, j + 1));\n            distToBorder[idx] = min(min(i, j), min(n - 1 - i, n - 1 - j));\n            borderTouchCell[idx] = (i == 0 || i == n - 1 || j == 0 || j == n - 1);\n        }\n    }\n\n    // Original border-touching colors.\n    memset(origB, 0, sizeof(origB));\n    for (int i = 0; i < n; ++i) {\n        origB[initBoard[id(i, 0)]] = true;\n        origB[initBoard[id(i, n - 1)]] = true;\n    }\n    for (int j = 0; j < n; ++j) {\n        origB[initBoard[id(0, j)]] = true;\n        origB[initBoard[id(n - 1, j)]] = true;\n    }\n\n    // Original adjacency graph.\n    memset(origAdj, 0, sizeof(origAdj));\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int right = nb[idx][3];\n        if (right != -1) {\n            int d = initBoard[right];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n        int down = nb[idx][1];\n        if (down != -1) {\n            int d = initBoard[down];\n            if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n        }\n    }\n\n    // Static per-cell features.\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        int same = 0;\n        bool seenDiff[MAXM + 1] = {};\n        bool seenBorderDiff[MAXM + 1] = {};\n        int diffCnt = 0;\n        int bdeg = 0;\n        bool frozen = false;\n\n        for (int d = 0; d < 4; ++d) {\n            int v = nb[idx][d];\n            if (v == -1) continue;\n            int t = initBoard[v];\n            if (t == c) {\n                same++;\n            } else {\n                if (!seenDiff[t]) {\n                    seenDiff[t] = true;\n                    diffCnt++;\n                }\n                if (origB[t] && !seenBorderDiff[t]) {\n                    seenBorderDiff[t] = true;\n                    bdeg++;\n                }\n                if (t > 0 && !origB[t]) frozen = true;\n            }\n        }\n\n        sameDegOrig[idx] = same;\n        diffDegOrig[idx] = diffCnt;\n        borderAdjDeg[idx] = bdeg;\n        frozenCell[idx] = (!origB[c] || frozen);\n    }\n\n    // Witness edges.\n    for (int idx = 0; idx < N; ++idx) {\n        for (int dir : {1, 3}) { // down, right\n            int v = nb[idx][dir];\n            if (v == -1) continue;\n            int a = initBoard[idx], b = initBoard[v];\n            if (a == b) continue;\n            if (!origB[a] || !origB[b]) continue;\n            if (a > b) swap(a, b), pairEdges[a][b].push_back({v, idx});\n            else pairEdges[a][b].push_back({idx, v});\n        }\n    }\n\n    // Pair task lists.\n    int borderDeg[MAXM + 1];\n    memset(borderDeg, 0, sizeof(borderDeg));\n    for (int c = 1; c <= m; ++c) {\n        for (int d = 1; d <= m; ++d) if (origAdj[c][d] && origB[d]) borderDeg[c]++;\n    }\n\n    for (int a = 1; a <= m; ++a) {\n        for (int b = a + 1; b <= m; ++b) {\n            if (!origB[a] || !origB[b] || !origAdj[a][b]) continue;\n            if (pairEdges[a][b].empty()) continue;\n            pairA.push_back(a);\n            pairB.push_back(b);\n            pairCnt.push_back((int)pairEdges[a][b].size());\n            pairDegSum.push_back(borderDeg[a] + borderDeg[b]);\n        }\n    }\n\n    pairOrderAsc.resize(pairA.size());\n    iota(pairOrderAsc.begin(), pairOrderAsc.end(), 0);\n    sort(pairOrderAsc.begin(), pairOrderAsc.end(), [&](int x, int y) {\n        if (pairCnt[x] != pairCnt[y]) return pairCnt[x] < pairCnt[y];\n        if (pairDegSum[x] != pairDegSum[y]) return pairDegSum[x] < pairDegSum[y];\n        if (pairA[x] != pairA[y]) return pairA[x] < pairA[y];\n        return pairB[x] < pairB[y];\n    });\n    pairOrderDesc = pairOrderAsc;\n    reverse(pairOrderDesc.begin(), pairOrderDesc.end());\n\n    // Candidate cells: only border-touching colors and not frozen.\n    candidateCells.reserve(N);\n    for (int idx = 0; idx < N; ++idx) {\n        int c = initBoard[idx];\n        if (c >= 1 && c <= m && origB[c] && !frozenCell[idx]) candidateCells.push_back(idx);\n    }\n\n    // Trial settings.\n    array<GreedyWeight, 4> basePhaseW = {\n        GreedyWeight{5000, 9000, 150, 300, 500, 200, 20, 5},\n        GreedyWeight{3000, 8000, 150, 250, 700, 220, 20, 4},\n        GreedyWeight{1500, 10000, 120, 250, 900, 240, 15, 3},\n        GreedyWeight{0, 12000, 0, 300, 1200, 300, 10, 2}\n    };\n\n    vector<TrialConfig> trials = {\n        {0, 0, true,  true,  8, basePhaseW, 123456789ULL},\n        {1, 1, true,  false, 8, basePhaseW, 987654321ULL},\n        {2, 0, false, true,  8, basePhaseW, 19260817ULL},\n        {1, 0, true,  false, 6, basePhaseW, 998244353ULL},\n    };\n\n    vector<int> bestBoard = initBoard;\n    int bestZeros = 0;\n    TrialConfig bestCfg = trials[0];\n\n    for (const auto& cfg : trials) {\n        vector<int> cand = runTrial(initBoard, cfg);\n        if (validate(cand)) {\n            int z = countZeros(cand);\n            if (z > bestZeros) {\n                bestZeros = z;\n                bestBoard = std::move(cand);\n                bestCfg = cfg;\n            }\n        }\n    }\n\n    // One extra polishing pass from the best board found so far.\n    {\n        TrialConfig cfg = bestCfg;\n        cfg.seed ^= 0x9e3779b97f4a7c15ULL;\n        cfg.preferLeafFirst = !cfg.preferLeafFirst;\n        vector<int> cand = runTrial(bestBoard, cfg);\n        if (validate(cand)) {\n            int z = countZeros(cand);\n            if (z > bestZeros) {\n                bestZeros = z;\n                bestBoard = std::move(cand);\n            }\n        }\n    }\n\n    if (!validate(bestBoard)) bestBoard = initBoard;\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << bestBoard[id(i, j)];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ld = long double;\n\nstruct Bucket {\n    vector<int> items;\n    int l = 0, r = -1;      // descending rank interval [l, r]\n    bool sameGroup = false; // all items in this bucket are known equal\n    bool exhausted = false;  // no more useful queries expected here\n    ld value = 0.0L;        // estimated total weight of this interval\n};\n\nstruct PartResult {\n    vector<int> ans;\n    ld score = numeric_limits<ld>::infinity();\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    const ld MU = 100000.0L;\n    const ld CAP = MU * (ld)N / (ld)D;\n\n    mt19937_64 rng(\n        0x9e3779b97f4a7c15ULL ^\n        (uint64_t)N * 1000003ULL ^\n        (uint64_t)D * 10007ULL ^\n        (uint64_t)Q * 10000019ULL\n    );\n\n    auto rand_int = [&](int l, int r) -> int {\n        uniform_int_distribution<int> dist(l, r);\n        return dist(rng);\n    };\n\n    // Rank-based expected weights for descending rank r = 0..N-1.\n    vector<ld> rankExp(N, 0.0L);\n    vector<ld> H(N + 1, 0.0L);\n    for (int i = 1; i <= N; ++i) H[i] = H[i - 1] + 1.0L / (ld)i;\n\n    ld capProb = 1.0L - expl(-CAP / MU);\n    for (int r = 0; r < N; ++r) {\n        ld p = ((ld)N - (ld)r - 0.5L) / (ld)N;\n        if (p < 1e-18L) p = 1e-18L;\n        if (p > 1.0L - 1e-18L) p = 1.0L - 1e-18L;\n\n        ld harm = MU * (H[N] - H[r]);\n        ld quant = -MU * log1pl(-capProb * p);\n\n        ld v = 0.65L * harm + 0.35L * quant;\n        if (v < 1.0L) v = 1.0L;\n        if (v > CAP) v = CAP;\n        rankExp[r] = v;\n    }\n\n    vector<ld> pref(N + 1, 0.0L);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + rankExp[i];\n\n    auto intervalValue = [&](int l, int r) -> ld {\n        if (l > r) return 0.0L;\n        return pref[r + 1] - pref[l];\n    };\n\n    vector<ld> win(N, 0.0L);\n    vector<int> deg(N, 0);\n\n    vector<vector<unsigned char>> seen(N, vector<unsigned char>(N, 0));\n    auto is_seen = [&](int a, int b) -> bool {\n        if (a > b) swap(a, b);\n        return seen[a][b] != 0;\n    };\n    auto mark_seen = [&](int a, int b) {\n        if (a > b) swap(a, b);\n        seen[a][b] = 1;\n    };\n\n    int queries_left = Q;\n\n    auto pct = [&](int i) -> ld {\n        return (win[i] + 0.5L) / (ld)(deg[i] + 1);\n    };\n\n    auto ask = [&](int a, int b) -> int {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n' << flush;\n        char c;\n        cin >> c;\n        --queries_left;\n        mark_seen(a, b);\n\n        int res = (c == '>' ? 1 : (c == '<' ? -1 : 0));\n        ++deg[a];\n        ++deg[b];\n        if (res > 0) {\n            win[a] += 1.0L;\n        } else if (res < 0) {\n            win[b] += 1.0L;\n        } else {\n            win[a] += 0.5L;\n            win[b] += 0.5L;\n        }\n        return res;\n    };\n\n    // Warm-up: a few random disjoint comparisons.\n    {\n        int warm = min({N / 2, max(4, Q / 12), 10});\n        vector<int> perm(N);\n        iota(perm.begin(), perm.end(), 0);\n        shuffle(perm.begin(), perm.end(), rng);\n        for (int i = 0; i < warm; ++i) {\n            ask(perm[2 * i], perm[2 * i + 1]);\n        }\n    }\n\n    vector<Bucket> buckets;\n    {\n        Bucket root;\n        root.items.resize(N);\n        iota(root.items.begin(), root.items.end(), 0);\n        root.l = 0;\n        root.r = N - 1;\n        root.sameGroup = false;\n        root.exhausted = false;\n        root.value = pref[N];\n        buckets.push_back(move(root));\n    }\n\n    auto sort_by_pct = [&](vector<int>& items) {\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n    };\n\n    auto sort_for_pivot = [&](vector<int> items) {\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] < deg[b]; // low-degree pivot preferred\n            return a < b;\n        });\n        return items;\n    };\n\n    auto pick_split_bucket = [&]() -> int {\n        int best = -1;\n        ld bestMetric = -1.0L;\n        ld bestValue = -1.0L;\n\n        for (int i = 0; i < (int)buckets.size(); ++i) {\n            const auto& bk = buckets[i];\n            int m = (int)bk.items.size();\n            if (m <= 1) continue;\n            if (bk.sameGroup || bk.exhausted) continue;\n            if (m - 1 > queries_left) continue;\n\n            ld metric = bk.value / (ld)(m - 1);\n            if (metric > bestMetric + 1e-18L ||\n                (fabsl(metric - bestMetric) <= 1e-18L && bk.value > bestValue)) {\n                bestMetric = metric;\n                bestValue = bk.value;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    auto split_bucket = [&](int idx) {\n        Bucket cur = buckets[idx];\n        buckets[idx] = buckets.back();\n        buckets.pop_back();\n\n        int m = (int)cur.items.size();\n        if (m <= 1) {\n            buckets.push_back(move(cur));\n            return;\n        }\n\n        vector<int> ord = sort_for_pivot(cur.items);\n        int mid = m / 2;\n        int lo = max(0, mid - 1);\n        int hi = min(m - 1, mid + 1);\n\n        int pivot = ord[lo];\n        for (int i = lo + 1; i <= hi; ++i) {\n            if (deg[ord[i]] < deg[pivot]) pivot = ord[i];\n        }\n\n        vector<int> greater, equal, less;\n        greater.reserve(m);\n        equal.reserve(m);\n        less.reserve(m);\n\n        for (int x : cur.items) {\n            if (x == pivot) continue;\n            int res = ask(pivot, x);\n            if (res > 0) {\n                // pivot heavier => x is lighter\n                less.push_back(x);\n            } else if (res < 0) {\n                greater.push_back(x);\n            } else {\n                equal.push_back(x);\n            }\n        }\n\n        int g = (int)greater.size();\n        int e = (int)equal.size();\n\n        if (!greater.empty()) {\n            Bucket bk;\n            bk.items = move(greater);\n            bk.l = cur.l;\n            bk.r = cur.l + g - 1;\n            bk.sameGroup = false;\n            bk.exhausted = (bk.items.size() <= 1);\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n\n        {\n            Bucket bk;\n            bk.items.reserve(1 + e);\n            bk.items.push_back(pivot);\n            for (int x : equal) bk.items.push_back(x);\n            bk.l = cur.l + g;\n            bk.r = cur.l + g + e;\n            bk.sameGroup = (e > 0);\n            bk.exhausted = (bk.items.size() <= 1) || bk.sameGroup;\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n\n        if (!less.empty()) {\n            Bucket bk;\n            bk.items = move(less);\n            bk.l = cur.l + g + e + 1;\n            bk.r = cur.r;\n            bk.sameGroup = false;\n            bk.exhausted = (bk.items.size() <= 1);\n            bk.value = intervalValue(bk.l, bk.r);\n            buckets.push_back(move(bk));\n        }\n    };\n\n    // Main splitting phase.\n    while (queries_left > 0) {\n        int idx = pick_split_bucket();\n        if (idx == -1) break;\n        split_bucket(idx);\n    }\n\n    const int SMALL_T = 8;\n    int pairPtr = 0;\n    vector<pair<int, int>> allPairs;\n    allPairs.reserve(N * (N - 1) / 2);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            allPairs.push_back({i, j});\n        }\n    }\n    shuffle(allPairs.begin(), allPairs.end(), rng);\n\n    auto global_adjacent_pair = [&]() -> pair<int, int> {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n        for (int i = 0; i + 1 < N; ++i) {\n            int a = ord[i], b = ord[i + 1];\n            if (!is_seen(a, b)) return {a, b};\n        }\n        return {-1, -1};\n    };\n\n    auto next_random_unseen_pair = [&]() -> pair<int, int> {\n        while (pairPtr < (int)allPairs.size()) {\n            auto [a, b] = allPairs[pairPtr++];\n            if (!is_seen(a, b)) return {a, b};\n        }\n        for (int t = 0; t < 200; ++t) {\n            int a = rand_int(0, N - 1);\n            int b = rand_int(0, N - 2);\n            if (b >= a) ++b;\n            if (!is_seen(a, b)) return {a, b};\n        }\n        return {-1, -1};\n    };\n\n    // Use remaining queries to refine ambiguous areas.\n    while (queries_left > 0) {\n        int bestIdx = -1;\n        ld bestValue = -1.0L;\n        for (int i = 0; i < (int)buckets.size(); ++i) {\n            const auto& bk = buckets[i];\n            if (bk.exhausted) continue;\n            if ((int)bk.items.size() <= 1) continue;\n            if (bk.value > bestValue) {\n                bestValue = bk.value;\n                bestIdx = i;\n            }\n        }\n\n        if (bestIdx != -1) {\n            auto& bk = buckets[bestIdx];\n            int m = (int)bk.items.size();\n\n            if (m <= SMALL_T) {\n                bool completed = true;\n                for (int i = 0; i < m && queries_left > 0; ++i) {\n                    for (int j = i + 1; j < m && queries_left > 0; ++j) {\n                        int a = bk.items[i], b = bk.items[j];\n                        if (is_seen(a, b)) continue;\n                        ask(a, b);\n                    }\n                }\n                // All pairs in this small bucket have been tried.\n                bk.exhausted = true;\n                continue;\n            } else {\n                vector<int> cand = bk.items;\n                sort(cand.begin(), cand.end(), [&](int a, int b) {\n                    ld pa = pct(a), pb = pct(b);\n                    if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n                    if (deg[a] != deg[b]) return deg[a] > deg[b];\n                    return a < b;\n                });\n                bool found = false;\n                for (int i = 0; i + 1 < m; ++i) {\n                    int a = cand[i], b = cand[i + 1];\n                    if (!is_seen(a, b)) {\n                        ask(a, b);\n                        found = true;\n                        break;\n                    }\n                }\n                if (found) continue;\n            }\n        }\n\n        auto p = global_adjacent_pair();\n        if (p.first != -1) {\n            ask(p.first, p.second);\n            continue;\n        }\n\n        p = next_random_unseen_pair();\n        if (p.first == -1) {\n            // Fallback: any valid distinct pair.\n            int a = rand_int(0, N - 1);\n            int b = rand_int(0, N - 2);\n            if (b >= a) ++b;\n            ask(a, b);\n        } else {\n            ask(p.first, p.second);\n        }\n    }\n\n    // Final estimation of item weights.\n    vector<ld> est(N, 0.0L);\n    for (const auto& bk : buckets) {\n        int m = (int)bk.items.size();\n        if (m == 0) continue;\n\n        ld intervalSum = intervalValue(bk.l, bk.r);\n        ld avg = intervalSum / (ld)m;\n\n        if (bk.sameGroup) {\n            for (int x : bk.items) est[x] = avg;\n            continue;\n        }\n\n        vector<int> ord = bk.items;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            ld pa = pct(a), pb = pct(b);\n            if (fabsl(pa - pb) > 1e-18L) return pa > pb;\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n\n        vector<ld> tmp(m);\n        ld sumTmp = 0.0L;\n        for (int j = 0; j < m; ++j) {\n            int x = ord[j];\n            ld target = rankExp[bk.l + j];\n\n            ld conf;\n            if (bk.exhausted) {\n                conf = 0.85L;\n            } else {\n                conf = 0.25L + 0.50L * (ld)deg[x] / ((ld)deg[x] + 10.0L);\n                if (conf > 0.85L) conf = 0.85L;\n            }\n\n            ld v = avg * (1.0L - conf) + target * conf;\n            tmp[j] = v;\n            sumTmp += v;\n        }\n\n        ld scale = (sumTmp > 1e-18L ? intervalSum / sumTmp : 1.0L);\n        for (int j = 0; j < m; ++j) {\n            est[ord[j]] = tmp[j] * scale;\n            if (est[ord[j]] < 1.0L) est[ord[j]] = 1.0L;\n            if (est[ord[j]] > CAP) est[ord[j]] = CAP;\n        }\n    }\n\n    auto local_search = [&](vector<vector<int>>& bins, vector<ld>& load, const vector<ld>& w) {\n        auto remove_from_bin = [&](int item, int b, vector<int>& posInBin, vector<int>& where) {\n            int idx = posInBin[item];\n            int last = bins[b].back();\n            bins[b][idx] = last;\n            posInBin[last] = idx;\n            bins[b].pop_back();\n            where[item] = -1;\n        };\n\n        auto add_to_bin = [&](int item, int b, vector<int>& posInBin, vector<int>& where) {\n            where[item] = b;\n            posInBin[item] = (int)bins[b].size();\n            bins[b].push_back(item);\n        };\n\n        vector<int> where(N, -1), posInBin(N, -1);\n        for (int b = 0; b < D; ++b) {\n            for (int x : bins[b]) {\n                where[x] = b;\n                posInBin[x] = (int)(&x - &bins[b][0]); // placeholder, not used\n            }\n        }\n        // Rebuild positions safely.\n        for (int b = 0; b < D; ++b) {\n            for (int i = 0; i < (int)bins[b].size(); ++i) {\n                int x = bins[b][i];\n                where[x] = b;\n                posInBin[x] = i;\n            }\n        }\n\n        auto apply_move = [&](int item, int from, int to) {\n            int idx = posInBin[item];\n            int last = bins[from].back();\n            bins[from][idx] = last;\n            posInBin[last] = idx;\n            bins[from].pop_back();\n\n            load[from] -= w[item];\n\n            where[item] = to;\n            posInBin[item] = (int)bins[to].size();\n            bins[to].push_back(item);\n            load[to] += w[item];\n        };\n\n        auto apply_swap = [&](int x, int bx, int y, int by) {\n            int ix = posInBin[x];\n            int iy = posInBin[y];\n            bins[bx][ix] = y;\n            bins[by][iy] = x;\n            posInBin[x] = iy;\n            posInBin[y] = ix;\n            where[x] = by;\n            where[y] = bx;\n            load[bx] += w[y] - w[x];\n            load[by] += w[x] - w[y];\n        };\n\n        for (int iter = 0; iter < 160; ++iter) {\n            ld bestDelta = 0.0L;\n            int bestType = 0; // 1: move, 2: swap\n            int ba = -1, bb = -1, bx = -1, by = -1;\n\n            for (int a = 0; a < D; ++a) {\n                for (int b = 0; b < D; ++b) {\n                    if (a == b) continue;\n                    if (load[a] <= load[b] + 1e-18L) continue;\n                    ld d = load[a] - load[b];\n\n                    if ((int)bins[a].size() > 1) {\n                        for (int x : bins[a]) {\n                            ld ww = w[x];\n                            ld delta = 2.0L * ww * (ww - d);\n                            if (delta < bestDelta) {\n                                bestDelta = delta;\n                                bestType = 1;\n                                ba = a; bb = b; bx = x;\n                            }\n                        }\n                    }\n\n                    for (int x : bins[a]) {\n                        for (int y : bins[b]) {\n                            ld diff = w[x] - w[y];\n                            ld delta = 2.0L * diff * (diff - d);\n                            if (delta < bestDelta) {\n                                bestDelta = delta;\n                                bestType = 2;\n                                ba = a; bb = b; bx = x; by = y;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestDelta >= -1e-12L) break;\n\n            if (bestType == 1) {\n                apply_move(bx, ba, bb);\n            } else if (bestType == 2) {\n                apply_swap(bx, ba, by, bb);\n            } else {\n                break;\n            }\n        }\n\n        vector<int> ans(N, 0);\n        for (int b = 0; b < D; ++b) {\n            for (int x : bins[b]) ans[x] = b;\n        }\n\n        ld sumsq = 0.0L;\n        for (int b = 0; b < D; ++b) sumsq += load[b] * load[b];\n        return PartResult{ans, sumsq};\n    };\n\n    auto build_partition = [&](int mode, ld noiseAmp, int offset) -> PartResult {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        vector<ld> key(N, 0.0L);\n        for (int i = 0; i < N; ++i) {\n            ld noise = 0.0L;\n            if (noiseAmp > 0.0L) {\n                ld u = (ld)rand_int(0, 1000000) / 1000000.0L;\n                noise = (2.0L * u - 1.0L) * noiseAmp;\n            }\n            key[i] = est[i] * (1.0L + noise);\n        }\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (fabsl(key[a] - key[b]) > 1e-18L) return key[a] > key[b];\n            return a < b;\n        });\n\n        vector<vector<int>> bins(D);\n        vector<ld> load(D, 0.0L);\n\n        if (mode == 0) {\n            // LPT greedy\n            for (int id : ord) {\n                int best = 0;\n                for (int d = 1; d < D; ++d) {\n                    if (load[d] < load[best] - 1e-18L ||\n                        (fabsl(load[d] - load[best]) <= 1e-18L && bins[d].size() < bins[best].size())) {\n                        best = d;\n                    }\n                }\n                bins[best].push_back(id);\n                load[best] += est[id];\n            }\n        } else {\n            // Cyclic assignment with offset.\n            if (D == 0) offset = 0;\n            offset %= D;\n            if (offset < 0) offset += D;\n            for (int i = 0; i < N; ++i) {\n                int b = (i + offset) % D;\n                bins[b].push_back(ord[i]);\n                load[b] += est[ord[i]];\n            }\n        }\n\n        PartResult res = local_search(bins, load, est);\n        return res;\n    };\n\n    // Try several restarts with different initial packings.\n    PartResult best;\n    int restarts = min(8, 4 + Q / 1000);\n    for (int r = 0; r < restarts; ++r) {\n        int mode = r % 2; // 0 = LPT, 1 = cyclic\n        ld noiseAmp = (r == 0 ? 0.0L : min(0.05L, 0.01L * (ld)r));\n        int offset = (D > 0 ? rand_int(0, D - 1) : 0);\n        PartResult cur = build_partition(mode, noiseAmp, offset);\n        if (cur.score < best.score) best = move(cur);\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << best.ans[i];\n    }\n    cout << '\\n' << flush;\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing i16 = int16_t;\n\nstatic constexpr int MAXN = 205;\nstatic constexpr int MAXM = 10;\nstatic constexpr int MAX_SEQ = 512;\nstatic constexpr ll INF = (1LL << 60);\n\nint n, m;\n\nstruct Board {\n    i16 st[MAXM][MAXN];\n    i16 len[MAXM];\n    i16 posStack[MAXN];\n    i16 posIdx[MAXN];\n    int cur;\n};\n\nstruct Node {\n    Board b;\n    ll spent = 0;\n    ll eval = 0;\n    uint8_t path[MAX_SEQ]{};\n    uint16_t plen = 0;\n};\n\nstruct Candidate {\n    bool ok = false;\n    ll energy = INF;\n    vector<int> path;\n};\n\nstruct Preset {\n    int lookK;\n    ll remW, badW, nearW, sqW, topW, emptyW;\n    ll emptyBonus, fitGood, fitBad;\n    int noise;\n    int beamWidth;\n    int completeTop;\n    int depthThresh;\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\nstatic inline bool timeUp(const chrono::steady_clock::time_point &start, double limitSec) {\n    return chrono::duration<double>(chrono::steady_clock::now() - start).count() > limitSec;\n}\n\nstatic inline void flush(Board &b, vector<pair<int,int>> *ops) {\n    while (b.cur <= n) {\n        int x = b.cur;\n        int s = b.posStack[x];\n        if (s < 0) break;\n        if (b.posIdx[x] != b.len[s] - 1) break;\n\n        if (ops) ops->push_back({x, 0});\n        b.posStack[x] = -1;\n        b.posIdx[x] = -1;\n        --b.len[s];\n        ++b.cur;\n    }\n}\n\n// Operation 1 + forced free removal of the current smallest.\n// dest is 0-indexed stack index.\nstatic inline bool applyForcedMove(Board &b, ll &spent, int dest, vector<pair<int,int>> *ops) {\n    int x = b.cur;\n    int s = b.posStack[x];\n    int idx = b.posIdx[x];\n    int from = idx + 1;              // first moved box\n    int k = b.len[s] - from;         // number of moved boxes\n    if (k <= 0) return false;\n\n    spent += k + 1;\n\n    if (ops) ops->push_back({(int)b.st[s][from], dest + 1});\n\n    int base = b.len[dest];\n    for (int t = 0; t < k; ++t) {\n        int v = b.st[s][from + t];\n        b.st[dest][base + t] = (i16)v;\n        b.posStack[v] = (i16)dest;\n        b.posIdx[v] = (i16)(base + t);\n    }\n    b.len[dest] += k;\n\n    if (ops) ops->push_back({x, 0});\n\n    b.posStack[x] = -1;\n    b.posIdx[x] = -1;\n    b.len[s] = idx;\n    ++b.cur;\n\n    flush(b, ops);\n    return true;\n}\n\nstatic inline ll fitPenalty(const Board &b, int dest, const Preset &P) {\n    int src = b.posStack[b.cur];\n    int idx = b.posIdx[b.cur];\n    int firstMoved = b.st[src][idx + 1];\n\n    if (b.len[dest] == 0) return -P.emptyBonus;\n\n    int top = b.st[dest][b.len[dest] - 1];\n    int diff = top - firstMoved;\n\n    if (diff >= 0) {\n        return -P.fitGood + min<ll>(4, diff / 4);\n    } else {\n        return P.fitBad + min<ll>(6, (-diff) / 4);\n    }\n}\n\nstatic inline ll heuristic(const Board &b, const Preset &P, uint64_t seed) {\n    if (b.cur > n) return 0;\n\n    int rem = n - b.cur + 1;\n    int L = min(rem, P.lookK);\n\n    ll near = 0;\n    for (int t = 0; t < L; ++t) {\n        int v = b.cur + t;\n        int s = b.posStack[v];\n        int depth = b.len[s] - 1 - b.posIdx[v];\n        near += 1LL * (L - t) * depth;\n    }\n\n    ll bad = 0;\n    ll sumSq = 0;\n    ll topSum = 0;\n    ll empty = 0;\n    ll maxH = 0;\n\n    for (int s = 0; s < m; ++s) {\n        int h = b.len[s];\n        sumSq += 1LL * h * h;\n        maxH = std::max(maxH, (ll)h);\n\n        if (h == 0) {\n            ++empty;\n            continue;\n        }\n\n        topSum += b.st[s][h - 1];\n        for (int i = 0; i + 1 < h; ++i) {\n            if (b.st[s][i] < b.st[s][i + 1]) bad += 2;\n            if (i + 2 < h && b.st[s][i] < b.st[s][i + 2]) bad += 1;\n        }\n    }\n\n    ll remW = P.remW, badW = P.badW, nearW = P.nearW, sqW = P.sqW, topW = P.topW, emptyW = P.emptyW;\n\n    if (rem > 120) emptyW *= 2;\n    if (rem < 50) {\n        badW += 2;\n        nearW += 3;\n    }\n\n    ll sc = 0;\n    sc += remW * rem;\n    sc += badW * bad;\n    sc += nearW * near / 16;\n    sc += sqW * sumSq / 20;\n    sc += topW * topSum / 20;\n    sc -= emptyW * empty;\n    sc += maxH;\n\n    if (P.noise > 0) {\n        uint64_t x = seed;\n        x ^= (uint64_t)b.cur * 0x9e3779b97f4a7c15ULL;\n        x ^= (uint64_t)bad * 0xbf58476d1ce4e5b9ULL;\n        x ^= (uint64_t)sumSq * 0x94d049bb133111ebULL;\n        sc += (ll)(splitmix64(x) % (uint64_t)P.noise);\n    }\n\n    return sc;\n}\n\nstatic inline Candidate candidateFromNode(const Node &node) {\n    Candidate c;\n    c.ok = true;\n    c.energy = node.spent;\n    c.path.resize(node.plen);\n    for (int i = 0; i < (int)node.plen; ++i) c.path[i] = (int)node.path[i];\n    return c;\n}\n\nstatic inline ll eval1(const Board &b, ll spent, int dest, const Preset &P, uint64_t seed) {\n    Board tb = b;\n    ll sp = spent;\n    if (!applyForcedMove(tb, sp, dest, nullptr)) return INF;\n    if (tb.cur > n) return sp + fitPenalty(b, dest, P);\n    return sp + heuristic(tb, P, seed) + fitPenalty(b, dest, P);\n}\n\nstatic inline ll eval2(const Board &b, ll spent, int dest, const Preset &P, uint64_t seed) {\n    Board t1 = b;\n    ll sp1 = spent;\n    if (!applyForcedMove(t1, sp1, dest, nullptr)) return INF;\n\n    ll base = fitPenalty(b, dest, P);\n    if (t1.cur > n) return sp1 + base;\n\n    int src2 = t1.posStack[t1.cur];\n    ll best = INF;\n\n    for (int d2 = 0; d2 < m; ++d2) {\n        if (d2 == src2) continue;\n        Board t2 = t1;\n        ll sp2 = sp1;\n        if (!applyForcedMove(t2, sp2, d2, nullptr)) continue;\n        ll sc = sp2 + heuristic(t2, P, seed) + fitPenalty(t1, d2, P);\n        best = min(best, sc);\n    }\n\n    return best + base;\n}\n\nstatic inline Candidate completeGreedy(Node node, const Preset &P, uint64_t seed,\n                                       const chrono::steady_clock::time_point &start,\n                                       double limitSec) {\n    Candidate res;\n    flush(node.b, nullptr);\n\n    vector<int> path;\n    path.reserve(128);\n    for (int i = 0; i < (int)node.plen; ++i) path.push_back((int)node.path[i]);\n\n    int steps = 0;\n    while (node.b.cur <= n) {\n        if ((steps & 7) == 0 && timeUp(start, limitSec)) return {};\n        ++steps;\n\n        int src = node.b.posStack[node.b.cur];\n        ll bestScore = INF;\n        int bestDest = -1;\n\n        bool use2 = (n - node.b.cur + 1 > P.depthThresh);\n        for (int d = 0; d < m; ++d) {\n            if (d == src) continue;\n            ll sc = use2 ? eval2(node.b, node.spent, d, P, seed)\n                         : eval1(node.b, node.spent, d, P, seed);\n            if (sc < bestScore || (sc == bestScore && (bestDest == -1 || d < bestDest))) {\n                bestScore = sc;\n                bestDest = d;\n            }\n        }\n\n        if (bestDest < 0) return {};\n        path.push_back(bestDest);\n        if ((int)path.size() > 5000) return {};\n\n        if (!applyForcedMove(node.b, node.spent, bestDest, nullptr)) return {};\n    }\n\n    res.ok = true;\n    res.energy = node.spent;\n    res.path = std::move(path);\n    return res;\n}\n\nstatic inline bool simulatePrefix(const Board &init, const vector<int> &path, int steps, Node &out) {\n    out = Node{};\n    out.b = init;\n    out.spent = 0;\n    out.plen = 0;\n    flush(out.b, nullptr);\n\n    if (steps > (int)path.size()) return false;\n    for (int i = 0; i < steps; ++i) {\n        if (out.b.cur > n) return false;\n        int d = path[i];\n        if (d < 0 || d >= m) return false;\n        if (d == out.b.posStack[out.b.cur]) return false;\n        if (!applyForcedMove(out.b, out.spent, d, nullptr)) return false;\n        out.path[out.plen++] = (uint8_t)d;\n    }\n    return true;\n}\n\nstatic inline Candidate refineMutations(const Board &init, Candidate best, const Preset &P, uint64_t seed,\n                                        const chrono::steady_clock::time_point &start, double limitSec) {\n    if (!best.ok || best.path.empty()) return best;\n\n    int cap = min<int>(12, (int)best.path.size());\n    if (cap == 0) return best;\n\n    uint64_t s = seed;\n    for (int iter = 0; iter < 8; ++iter) {\n        if (timeUp(start, limitSec)) break;\n        s = splitmix64(s + 0x9e3779b97f4a7c15ULL + (uint64_t)iter);\n\n        int p = (int)(s % cap);\n\n        Node pref;\n        if (!simulatePrefix(init, best.path, p, pref)) continue;\n        if (pref.b.cur > n) continue;\n\n        int src = pref.b.posStack[pref.b.cur];\n        int old = best.path[p];\n\n        vector<pair<ll,int>> choices;\n        choices.reserve(m - 1);\n        for (int d = 0; d < m; ++d) {\n            if (d == src || d == old) continue;\n            ll sc = eval1(pref.b, pref.spent, d, P, s);\n            choices.push_back({sc, d});\n        }\n\n        sort(choices.begin(), choices.end());\n        int lim = min<int>(3, (int)choices.size());\n\n        for (int i = 0; i < lim; ++i) {\n            int d = choices[i].second;\n            Node mutated = pref;\n            if (!applyForcedMove(mutated.b, mutated.spent, d, nullptr)) continue;\n            mutated.path[mutated.plen++] = (uint8_t)d;\n\n            Candidate cand = completeGreedy(mutated, P, s ^ 0x123456789abcdefULL, start, limitSec);\n            if (cand.ok && cand.energy < best.energy) best = std::move(cand);\n        }\n    }\n\n    return best;\n}\n\nstatic inline Candidate beamAttempt(const Board &init, const Preset &P, uint64_t seed,\n                                    const chrono::steady_clock::time_point &start,\n                                    double searchLimitSec, double fullLimitSec) {\n    Candidate best;\n    vector<Node> beam;\n\n    Node root{};\n    root.b = init;\n    root.spent = 0;\n    root.plen = 0;\n    flush(root.b, nullptr);\n    root.eval = heuristic(root.b, P, seed);\n    beam.push_back(root);\n\n    int layer = 0;\n    while (!beam.empty()) {\n        if ((layer & 3) == 0 && timeUp(start, searchLimitSec)) break;\n\n        vector<Node> cand;\n        cand.reserve(beam.size() * (m - 1));\n\n        for (const Node &node : beam) {\n            if ((layer & 7) == 0 && timeUp(start, searchLimitSec)) break;\n\n            if (node.b.cur > n) {\n                Candidate c = candidateFromNode(node);\n                if (!best.ok || c.energy < best.energy) best = std::move(c);\n                continue;\n            }\n\n            int src = node.b.posStack[node.b.cur];\n            for (int d = 0; d < m; ++d) {\n                if (d == src) continue;\n\n                Node child = node;\n                if (!applyForcedMove(child.b, child.spent, d, nullptr)) continue;\n                child.path[child.plen++] = (uint8_t)d;\n\n                if (child.b.cur > n) {\n                    Candidate c = candidateFromNode(child);\n                    if (!best.ok || c.energy < best.energy) best = std::move(c);\n                } else {\n                    child.eval = child.spent + heuristic(child.b, P, seed) + fitPenalty(node.b, d, P);\n                    cand.push_back(std::move(child));\n                }\n            }\n        }\n\n        if (cand.empty()) break;\n\n        vector<int> ord(cand.size());\n        iota(ord.begin(), ord.end(), 0);\n\n        auto cmp = [&](int a, int b) {\n            if (cand[a].eval != cand[b].eval) return cand[a].eval < cand[b].eval;\n            if (cand[a].spent != cand[b].spent) return cand[a].spent < cand[b].spent;\n            return cand[a].b.cur > cand[b].b.cur;\n        };\n\n        int keep = min<int>(P.beamWidth, (int)ord.size());\n        if ((int)ord.size() > keep) {\n            nth_element(ord.begin(), ord.begin() + keep, ord.end(), cmp);\n            ord.resize(keep);\n        }\n        sort(ord.begin(), ord.end(), cmp);\n\n        vector<Node> next;\n        next.reserve(ord.size());\n        for (int id : ord) next.push_back(std::move(cand[id]));\n        beam.swap(next);\n\n        ++layer;\n    }\n\n    if (!beam.empty()) {\n        vector<int> ord(beam.size());\n        iota(ord.begin(), ord.end(), 0);\n        auto cmp = [&](int a, int b) {\n            if (beam[a].eval != beam[b].eval) return beam[a].eval < beam[b].eval;\n            if (beam[a].spent != beam[b].spent) return beam[a].spent < beam[b].spent;\n            return beam[a].b.cur > beam[b].b.cur;\n        };\n        sort(ord.begin(), ord.end(), cmp);\n\n        int lim = min<int>(P.completeTop, (int)ord.size());\n        for (int i = 0; i < lim; ++i) {\n            Candidate c = completeGreedy(beam[ord[i]], P, seed, start, fullLimitSec);\n            if (c.ok && (!best.ok || c.energy < best.energy)) best = std::move(c);\n        }\n    }\n\n    return best;\n}\n\nstatic inline bool replayPath(const Board &init, const vector<int> &path,\n                              vector<pair<int,int>> &ops, ll &energy) {\n    Board b = init;\n    energy = 0;\n    ops.clear();\n    ops.reserve(1000);\n\n    flush(b, &ops);\n\n    for (int d : path) {\n        if (b.cur > n) return false;\n        if (d < 0 || d >= m) return false;\n        if (d == b.posStack[b.cur]) return false;\n        if (!applyForcedMove(b, energy, d, &ops)) return false;\n        if ((int)ops.size() > 5000) return false;\n    }\n\n    if (b.cur <= n) return false;\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> n >> m;\n\n    Board init{};\n    init.cur = 1;\n    memset(init.posStack, -1, sizeof(init.posStack));\n    memset(init.posIdx, -1, sizeof(init.posIdx));\n\n    uint64_t baseSeed = 0x123456789abcdefULL;\n\n    int h = n / m;\n    for (int s = 0; s < m; ++s) {\n        init.len[s] = h;\n        for (int i = 0; i < h; ++i) {\n            int v;\n            cin >> v;\n            init.st[s][i] = (i16)v;\n            init.posStack[v] = (i16)s;\n            init.posIdx[v] = (i16)i;\n            baseSeed = splitmix64(baseSeed ^ (uint64_t)v);\n        }\n    }\n\n    Node root{};\n    root.b = init;\n    root.spent = 0;\n    root.plen = 0;\n    flush(root.b, nullptr);\n\n    Preset basePreset{\n        16, 2, 3, 10, 2, 1, 18,\n        6, 4, 6,\n        0, 1, 1, 1000\n    };\n\n    vector<Preset> presets = {\n        {16, 2, 4, 10, 2, 1, 18, 6, 4, 6,  3,  60,  8, 80},\n        {18, 3, 4, 12, 3, 1, 22, 8, 5, 7,  7,  80, 10, 65},\n        {20, 3, 5, 14, 3, 2, 24, 9, 6, 8, 11, 100, 12, 60},\n        {22, 4, 5, 16, 4, 2, 28,10, 6, 9, 13, 120, 12, 55},\n    };\n\n    auto start = chrono::steady_clock::now();\n    const double SEARCH_LIMIT = 1.60;\n    const double FULL_LIMIT = 1.85;\n\n    Candidate best = completeGreedy(root, basePreset, splitmix64(baseSeed ^ 0x9e3779b97f4a7c15ULL), start, FULL_LIMIT);\n    int bestPresetIdx = -1;\n    uint64_t bestSeed = splitmix64(baseSeed ^ 0x9e3779b97f4a7c15ULL);\n\n    for (int t = 0; t < (int)presets.size(); ++t) {\n        if (timeUp(start, SEARCH_LIMIT)) break;\n        uint64_t seed = splitmix64(baseSeed + 0x9e3779b97f4a7c15ULL * (uint64_t)(t + 1));\n        Candidate cand = beamAttempt(init, presets[t], seed, start, SEARCH_LIMIT, FULL_LIMIT);\n        if (cand.ok && (!best.ok || cand.energy < best.energy)) {\n            best = std::move(cand);\n            bestPresetIdx = t;\n            bestSeed = seed;\n        }\n    }\n\n    if (best.ok && bestPresetIdx >= 0) {\n        best = refineMutations(init, best, presets[bestPresetIdx], bestSeed, start, FULL_LIMIT);\n    }\n\n    vector<pair<int,int>> ops;\n    ll verifiedEnergy = 0;\n\n    if (!best.ok || !replayPath(init, best.path, ops, verifiedEnergy)) {\n        Candidate fb = completeGreedy(root, basePreset, splitmix64(baseSeed ^ 0xabcdef123456789ULL), start, FULL_LIMIT);\n        if (!fb.ok || !replayPath(init, fb.path, ops, verifiedEnergy)) {\n            return 0;\n        }\n        best = std::move(fb);\n    } else {\n        best.energy = verifiedEnergy;\n    }\n\n    for (auto [v, i] : ops) {\n        cout << v << ' ' << i << '\\n';\n    }\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing i128 = __int128_t;\n\nstatic const int DR[4] = {-1, 1, 0, 0};\nstatic const int DC[4] = {0, 0, -1, 1};\nstatic const int REV[4] = {1, 0, 3, 2};\nstatic const char CH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Edge {\n    int to, dir;\n};\n\nstruct TreeInfo {\n    int root;\n    vector<int> parent;\n    vector<int> order;\n    vector<vector<pair<int,int>>> children;\n    vector<long long> subW;\n    vector<int> subCnt;\n};\n\nint N, TOT;\nvector<int> D;\nvector<vector<Edge>> adj, highAdj, lowAdj;\nvector<array<int,4>> nxt;\nvector<long long> localScore, nodeHeu;\n\n// BFS from origin: shortest paths, but neighbor order prefers low-weight cells\nvector<int> parent0, pdir0, dist0;\n\nstatic void emitTour(int u, const vector<vector<pair<int,int>>>& ch, vector<int>& out) {\n    for (auto [v, dir] : ch[u]) {\n        out.push_back(dir);\n        emitTour(v, ch, out);\n        out.push_back(REV[dir]);\n    }\n}\n\nstatic vector<int> reverseRoute(const vector<int>& dirs) {\n    vector<int> rev;\n    rev.reserve(dirs.size());\n    for (auto it = dirs.rbegin(); it != dirs.rend(); ++it) {\n        rev.push_back(REV[*it]);\n    }\n    return rev;\n}\n\nstatic pair<i128,int> evaluateRoute(const vector<int>& dirs) {\n    vector<int> first(TOT, -1), last(TOT, -1);\n    vector<long long> acc(TOT, 0);\n\n    int cur = 0;\n    int t = 0;\n    for (int dir : dirs) {\n        cur = nxt[cur][dir];\n        ++t;\n        if (first[cur] == -1) {\n            first[cur] = last[cur] = t;\n        } else {\n            int gap = t - last[cur];\n            acc[cur] += 1LL * gap * (gap - 1) / 2;\n            last[cur] = t;\n        }\n    }\n\n    i128 total = 0;\n    for (int u = 0; u < TOT; ++u) {\n        // All cells must be visited in a valid route.\n        int gap = first[u] + t - last[u];\n        acc[u] += 1LL * gap * (gap - 1) / 2;\n        total += (i128)acc[u] * (i128)D[u];\n    }\n    return {total, t};\n}\n\nstatic bool better(i128 num1, int den1, i128 num2, int den2) {\n    // compare num1/den1 < num2/den2\n    return num1 * (i128)den2 < num2 * (i128)den1;\n}\n\nstatic TreeInfo buildTree(int root, const vector<vector<Edge>>& orderAdj, bool bfsMode) {\n    TreeInfo tr;\n    tr.root = root;\n    tr.parent.assign(TOT, -1);\n    tr.order.reserve(TOT);\n    tr.children.assign(TOT, {});\n\n    if (bfsMode) {\n        vector<int> q;\n        q.reserve(TOT);\n        int head = 0;\n        tr.parent[root] = root;\n        q.push_back(root);\n        tr.order.push_back(root);\n\n        while (head < (int)q.size()) {\n            int u = q[head++];\n            for (const auto& e : orderAdj[u]) {\n                int v = e.to;\n                if (tr.parent[v] == -1) {\n                    tr.parent[v] = u;\n                    tr.children[u].push_back({v, e.dir});\n                    tr.order.push_back(v);\n                    q.push_back(v);\n                }\n            }\n        }\n    } else {\n        vector<int> st;\n        vector<int> it(TOT, 0);\n        st.reserve(TOT);\n        tr.parent[root] = root;\n        st.push_back(root);\n        tr.order.push_back(root);\n\n        while (!st.empty()) {\n            int u = st.back();\n            if (it[u] == (int)orderAdj[u].size()) {\n                st.pop_back();\n                continue;\n            }\n            auto e = orderAdj[u][it[u]++];\n            int v = e.to;\n            if (tr.parent[v] == -1) {\n                tr.parent[v] = u;\n                tr.children[u].push_back({v, e.dir});\n                tr.order.push_back(v);\n                st.push_back(v);\n            }\n        }\n    }\n\n    tr.subW.assign(TOT, 0);\n    tr.subCnt.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        tr.subW[u] = D[u];\n        tr.subCnt[u] = 1;\n    }\n    for (int i = TOT - 1; i >= 0; --i) {\n        int u = tr.order[i];\n        if (u == root) continue;\n        int p = tr.parent[u];\n        tr.subW[p] += tr.subW[u];\n        tr.subCnt[p] += tr.subCnt[u];\n    }\n\n    return tr;\n}\n\nstatic vector<int> pathToRoot(int root) {\n    vector<int> dirs;\n    int x = root;\n    while (x != 0) {\n        dirs.push_back(pdir0[x]);\n        x = parent0[x];\n    }\n    reverse(dirs.begin(), dirs.end());\n    return dirs;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    TOT = N * 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    D.assign(TOT, 0);\n    auto id = [&](int r, int c) { return r * N + c; };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> D[id(i, j)];\n        }\n    }\n\n    adj.assign(TOT, {});\n    nxt.assign(TOT, {});\n    for (int i = 0; i < TOT; ++i) nxt[i].fill(-1);\n\n    auto addEdge = [&](int u, int vtx, int dirUV, int dirVU) {\n        adj[u].push_back({vtx, dirUV});\n        adj[vtx].push_back({u, dirVU});\n        nxt[u][dirUV] = vtx;\n        nxt[vtx][dirVU] = u;\n    };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int u = id(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                addEdge(u, id(i + 1, j), 1, 0); // D / U\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                addEdge(u, id(i, j + 1), 3, 2); // R / L\n            }\n        }\n    }\n\n    localScore.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        long long s = D[u];\n        for (auto e : adj[u]) s += D[e.to];\n        localScore[u] = s;\n    }\n\n    // Heuristic importance used for adjacency ordering.\n    nodeHeu.assign(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        nodeHeu[u] = localScore[u] * 1000LL + 100LL * D[u] + (long long)adj[u].size();\n    }\n\n    highAdj = adj;\n    lowAdj = adj;\n    for (int u = 0; u < TOT; ++u) {\n        sort(highAdj[u].begin(), highAdj[u].end(), [&](const Edge& a, const Edge& b) {\n            if (nodeHeu[a.to] != nodeHeu[b.to]) return nodeHeu[a.to] > nodeHeu[b.to];\n            return a.to < b.to;\n        });\n        sort(lowAdj[u].begin(), lowAdj[u].end(), [&](const Edge& a, const Edge& b) {\n            if (nodeHeu[a.to] != nodeHeu[b.to]) return nodeHeu[a.to] < nodeHeu[b.to];\n            return a.to < b.to;\n        });\n    }\n\n    // Shortest paths from origin, preferring low-score cells among shortest options.\n    parent0.assign(TOT, -1);\n    pdir0.assign(TOT, -1);\n    dist0.assign(TOT, -1);\n    {\n        vector<int> q;\n        q.reserve(TOT);\n        int head = 0;\n        q.push_back(0);\n        parent0[0] = 0;\n        dist0[0] = 0;\n\n        while (head < (int)q.size()) {\n            int u = q[head++];\n            for (const auto& e : lowAdj[u]) {\n                int vtx = e.to;\n                if (dist0[vtx] == -1) {\n                    dist0[vtx] = dist0[u] + 1;\n                    parent0[vtx] = u;\n                    pdir0[vtx] = e.dir;\n                    q.push_back(vtx);\n                }\n            }\n        }\n    }\n\n    // Candidate roots from several heuristics.\n    vector<int> roots;\n    vector<char> used(TOT, 0);\n    auto addRoot = [&](int x) {\n        if (!used[x]) {\n            used[x] = 1;\n            roots.push_back(x);\n        }\n    };\n\n    addRoot(0);\n\n    auto addTop = [&](auto scorer, int K) {\n        vector<pair<long double,int>> vec;\n        vec.reserve(TOT);\n        for (int u = 0; u < TOT; ++u) vec.push_back({scorer(u), u});\n        sort(vec.begin(), vec.end(), [&](const auto& a, const auto& b) {\n            if (fabsl(a.first - b.first) > 1e-18L) return a.first > b.first;\n            return a.second < b.second;\n        });\n        for (int i = 0; i < K && i < (int)vec.size(); ++i) addRoot(vec[i].second);\n    };\n\n    addTop([&](int u) -> long double { return (long double)localScore[u]; }, 8);\n    addTop([&](int u) -> long double { return (long double)D[u]; }, 8);\n    addTop([&](int u) -> long double { return (long double)(localScore[u] + 10LL * D[u]) / (dist0[u] + 1.0L); }, 8);\n    addTop([&](int u) -> long double { return (long double)(nodeHeu[u]) / (dist0[u] + 1.0L); }, 8);\n\n    vector<long double> rootRank(TOT, 0);\n    for (int u = 0; u < TOT; ++u) {\n        rootRank[u] = (long double)(localScore[u] + 10LL * D[u]) / (dist0[u] + 1.0L);\n    }\n\n    vector<int> others;\n    others.reserve(roots.size());\n    for (int x : roots) if (x != 0) others.push_back(x);\n    sort(others.begin(), others.end(), [&](int a, int b) {\n        if (fabsl(rootRank[a] - rootRank[b]) > 1e-18L) return rootRank[a] > rootRank[b];\n        if (dist0[a] != dist0[b]) return dist0[a] < dist0[b];\n        return a < b;\n    });\n\n    roots.clear();\n    roots.push_back(0);\n    for (int x : others) roots.push_back(x);\n    if ((int)roots.size() > 12) roots.resize(12);\n\n    // Tree modes: BFS/DFS x high/low adjacency.\n    struct Mode {\n        const vector<vector<Edge>>* ordAdj;\n        bool bfsMode;\n    };\n    vector<Mode> modes = {\n        {&highAdj, true},\n        {&lowAdj,  true},\n        {&highAdj, false},\n        {&lowAdj,  false},\n    };\n\n    string bestRoute;\n    i128 bestNum = 0;\n    int bestDen = 1;\n    bool hasBest = false;\n\n    auto saveCandidate = [&](const vector<int>& dirs) {\n        auto [num, den] = evaluateRoute(dirs);\n        if (!hasBest || better(num, den, bestNum, bestDen) || (!better(bestNum, bestDen, num, den) && den < bestDen)) {\n            hasBest = true;\n            bestNum = num;\n            bestDen = den;\n            bestRoute.clear();\n            bestRoute.reserve(dirs.size());\n            for (int d : dirs) bestRoute.push_back(CH[d]);\n        }\n    };\n\n    auto timeStart = chrono::steady_clock::now();\n    auto timeOver = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - timeStart).count() > 1850;\n    };\n\n    for (int root : roots) {\n        if (timeOver()) break;\n\n        vector<int> path = pathToRoot(root);\n\n        for (const auto& mode : modes) {\n            if (timeOver()) break;\n\n            TreeInfo tr = buildTree(root, *mode.ordAdj, mode.bfsMode);\n\n            vector<long double> keyDensity(TOT), keyWeight(TOT);\n            for (int u = 0; u < TOT; ++u) {\n                keyDensity[u] = (long double)tr.subW[u] / (long double)tr.subCnt[u];\n                keyWeight[u] = (long double)tr.subW[u];\n            }\n\n            for (int variant = 0; variant < 4; ++variant) {\n                if (timeOver()) break;\n\n                vector<vector<pair<int,int>>> ch = tr.children;\n                for (int u = 0; u < TOT; ++u) {\n                    auto cmpAsc = [&](const pair<int,int>& a, const pair<int,int>& b) {\n                        long double ka = (variant < 2 ? keyDensity[a.first] : keyWeight[a.first]);\n                        long double kb = (variant < 2 ? keyDensity[b.first] : keyWeight[b.first]);\n                        if (fabsl(ka - kb) > 1e-18L) {\n                            if (variant % 2 == 0) return ka < kb;\n                            else return ka > kb;\n                        }\n                        return a.first < b.first;\n                    };\n                    if ((int)ch[u].size() >= 2) sort(ch[u].begin(), ch[u].end(), cmpAsc);\n                }\n\n                vector<int> tour;\n                tour.reserve(2 * (TOT - 1));\n                emitTour(root, ch, tour);\n\n                vector<int> dirs;\n                dirs.reserve(path.size() * 2 + tour.size());\n                for (int d : path) dirs.push_back(d);\n                for (int d : tour) dirs.push_back(d);\n                for (auto it = path.rbegin(); it != path.rend(); ++it) dirs.push_back(REV[*it]);\n\n                saveCandidate(dirs);\n\n                vector<int> revDirs = reverseRoute(dirs);\n                saveCandidate(revDirs);\n            }\n        }\n    }\n\n    if (!hasBest) {\n        // Fallback: just output a trivial DFS-like route from origin tree.\n        // In practice this should never happen.\n        TreeInfo tr = buildTree(0, highAdj, true);\n        vector<long double> keyDensity(TOT), keyWeight(TOT);\n        for (int u = 0; u < TOT; ++u) {\n            keyDensity[u] = (long double)tr.subW[u] / (long double)tr.subCnt[u];\n            keyWeight[u] = (long double)tr.subW[u];\n        }\n        vector<vector<pair<int,int>>> ch = tr.children;\n        for (int u = 0; u < TOT; ++u) {\n            sort(ch[u].begin(), ch[u].end(), [&](const pair<int,int>& a, const pair<int,int>& b) {\n                if (fabsl(keyDensity[a.first] - keyDensity[b.first]) > 1e-18L) return keyDensity[a.first] < keyDensity[b.first];\n                return a.first < b.first;\n            });\n        }\n        vector<int> tour;\n        emitTour(0, ch, tour);\n        bestRoute.clear();\n        for (int d : tour) bestRoute.push_back(CH[d]);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 15;\nstatic constexpr int CELLS = H * H;\nstatic constexpr int MAXM = 205;\nstatic constexpr int INF = 100000000;\nstatic constexpr int FUTK = 10;\n\nint N, M, si, sj;\nvector<string> words;\n\nint boardLetter[CELLS];\nint distCell[CELLS][CELLS];\nint letterDist[26][26];\nvector<int> cellsByLetter[26];\n\nstring suffixes[MAXM][5];\nint suffixLB[MAXM][5];\n\nstruct FastRng {\n    uint64_t x;\n    explicit FastRng(uint64_t seed = 88172645463393265ULL) : x(seed) {}\n    uint64_t next() {\n        uint64_t z = (x += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int nextInt(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n};\n\ninline int safeAdd1(int x) {\n    return (x >= INF - 1 ? INF : x + 1);\n}\n\ninline bool usedBit(const array<uint64_t, 4>& u, int i) {\n    return (u[i >> 6] >> (i & 63)) & 1ULL;\n}\ninline void setBit(array<uint64_t, 4>& u, int i) {\n    u[i >> 6] |= (1ULL << (i & 63));\n}\n\ninline int minCost(const array<int, CELLS>& dp) {\n    return *min_element(dp.begin(), dp.end());\n}\n\n// 2D Manhattan distance transform:\n// out[q] = min_p src[p] + manhattan(p, q)\nvoid manhattanTransform(const array<int, CELLS>& src, array<int, CELLS>& out) {\n    int horiz[CELLS];\n\n    for (int r = 0; r < H; ++r) {\n        int base = r * H;\n        int left[H], right[H];\n\n        left[0] = src[base];\n        for (int c = 1; c < H; ++c) {\n            left[c] = min(src[base + c], safeAdd1(left[c - 1]));\n        }\n\n        right[H - 1] = src[base + H - 1];\n        for (int c = H - 2; c >= 0; --c) {\n            right[c] = min(src[base + c], safeAdd1(right[c + 1]));\n        }\n\n        for (int c = 0; c < H; ++c) {\n            horiz[base + c] = min(left[c], right[c]);\n        }\n    }\n\n    for (int c = 0; c < H; ++c) {\n        int up[H], down[H];\n\n        up[0] = horiz[c];\n        for (int r = 1; r < H; ++r) {\n            up[r] = min(horiz[r * H + c], safeAdd1(up[r - 1]));\n        }\n\n        down[H - 1] = horiz[(H - 1) * H + c];\n        for (int r = H - 2; r >= 0; --r) {\n            down[r] = min(horiz[r * H + c], safeAdd1(down[r + 1]));\n        }\n\n        for (int r = 0; r < H; ++r) {\n            out[r * H + c] = min(up[r], down[r]);\n        }\n    }\n}\n\nvoid applyChar(array<int, CELLS>& dp, char ch) {\n    array<int, CELLS> mv;\n    manhattanTransform(dp, mv);\n    int need = ch - 'A';\n    for (int i = 0; i < CELLS; ++i) {\n        dp[i] = (boardLetter[i] == need ? safeAdd1(mv[i]) : INF);\n    }\n}\n\nvoid applyString(array<int, CELLS>& dp, const string& s) {\n    for (char ch : s) applyChar(dp, ch);\n}\n\nvoid buildMoveAndBestStart(const array<int, CELLS>& dp,\n                           array<int, CELLS>& move,\n                           array<int, 26>& bestStart) {\n    manhattanTransform(dp, move);\n    bestStart.fill(INF);\n    for (int i = 0; i < CELLS; ++i) {\n        bestStart[boardLetter[i]] = min(bestStart[boardLetter[i]], move[i]);\n    }\n}\n\nbool overlapValid(const string& tail, const string& w, int k) {\n    if (k > (int)tail.size()) return false;\n    for (int i = 0; i < k; ++i) {\n        if (tail[(int)tail.size() - k + i] != w[i]) return false;\n    }\n    return true;\n}\n\nint wordApproxScore(const string& tail, int idx, const array<int, 26>& bestStart) {\n    int best = INF;\n    int lim = min(4, (int)tail.size());\n    const string& w = words[idx];\n    for (int k = 0; k <= lim; ++k) {\n        if (!overlapValid(tail, w, k)) continue;\n        int c = w[k] - 'A';\n        best = min(best, bestStart[c] + suffixLB[idx][k]);\n    }\n    return best;\n}\n\nint estimateFutureFromBestStart(const string& tail,\n                                const array<uint64_t, 4>& used,\n                                const array<int, 26>& bestStart) {\n    int best[FUTK];\n    for (int i = 0; i < FUTK; ++i) best[i] = INF;\n    int cnt = 0, rem = 0;\n\n    for (int idx = 0; idx < M; ++idx) {\n        if (usedBit(used, idx)) continue;\n        ++rem;\n        int sc = wordApproxScore(tail, idx, bestStart);\n        if (cnt < FUTK) {\n            int pos = cnt++;\n            while (pos > 0 && best[pos - 1] > sc) {\n                best[pos] = best[pos - 1];\n                --pos;\n            }\n            best[pos] = sc;\n        } else if (sc < best[FUTK - 1]) {\n            int pos = FUTK - 1;\n            while (pos > 0 && best[pos - 1] > sc) {\n                best[pos] = best[pos - 1];\n                --pos;\n            }\n            best[pos] = sc;\n        }\n    }\n\n    int k = min(FUTK, rem);\n    int sum = 0;\n    for (int i = 0; i < k; ++i) sum += best[i];\n    return sum;\n}\n\nstruct Node {\n    array<int, CELLS> dp{};\n    array<uint64_t, 4> used{};\n    string tail;\n    int lastWord = -1;\n    int ov = 0;\n    int parent = -1;\n    int depth = 0;\n    int cost = INF;\n    int future = INF;\n};\n\nNode makeRoot(int idx) {\n    Node st;\n    st.dp.fill(INF);\n    st.dp[si * H + sj] = 0;\n    applyString(st.dp, words[idx]);\n\n    st.used.fill(0);\n    setBit(st.used, idx);\n    st.tail = words[idx].substr(max(0, (int)words[idx].size() - 4));\n    st.lastWord = idx;\n    st.ov = 0;\n    st.parent = -1;\n    st.depth = 1;\n    st.cost = minCost(st.dp);\n\n    array<int, CELLS> move;\n    array<int, 26> bestStart;\n    buildMoveAndBestStart(st.dp, move, bestStart);\n    st.future = estimateFutureFromBestStart(st.tail, st.used, bestStart);\n    return st;\n}\n\nNode bestChildForCandidate(const Node& st, int parentId, int idx) {\n    Node best;\n    int bestPr = INF * 4;\n    array<uint64_t, 4> used2 = st.used;\n    setBit(used2, idx);\n\n    int lim = min(4, (int)st.tail.size());\n    for (int k = 0; k <= lim; ++k) {\n        if (!overlapValid(st.tail, words[idx], k)) continue;\n\n        array<int, CELLS> dp2 = st.dp;\n        applyString(dp2, suffixes[idx][k]);\n\n        int cost2 = minCost(dp2);\n\n        array<int, CELLS> move2;\n        array<int, 26> bestStart2;\n        buildMoveAndBestStart(dp2, move2, bestStart2);\n\n        string tail2 = st.tail + suffixes[idx][k];\n        if ((int)tail2.size() > 4) tail2.erase(0, (int)tail2.size() - 4);\n\n        int future2 = estimateFutureFromBestStart(tail2, used2, bestStart2);\n        int pr = cost2 + future2;\n\n        if (pr < bestPr ||\n            (pr == bestPr && cost2 < best.cost) ||\n            (pr == bestPr && cost2 == best.cost && k > best.ov)) {\n            bestPr = pr;\n            best.dp = dp2;\n            best.used = used2;\n            best.tail = tail2;\n            best.lastWord = idx;\n            best.ov = k;\n            best.parent = parentId;\n            best.depth = st.depth + 1;\n            best.cost = cost2;\n            best.future = future2;\n        }\n    }\n\n    return best;\n}\n\nstring reconstructString(const vector<Node>& pool, int id) {\n    vector<pair<int, int>> seq;\n    while (id != -1) {\n        seq.push_back({pool[id].lastWord, pool[id].ov});\n        id = pool[id].parent;\n    }\n    reverse(seq.begin(), seq.end());\n\n    string s = words[seq[0].first];\n    for (int i = 1; i < (int)seq.size(); ++i) {\n        s += suffixes[seq[i].first][seq[i].second];\n    }\n    return s;\n}\n\nstruct RunResult {\n    int cost = INF;\n    string s;\n};\n\nRunResult beamSearch(const vector<int>& seedIndices, int beamSize, int candK, uint64_t runSeed) {\n    FastRng rng(runSeed);\n\n    vector<Node> pool;\n    pool.reserve(60000);\n\n    vector<int> beam;\n    beam.reserve(seedIndices.size());\n\n    for (int idx : seedIndices) {\n        Node root = makeRoot(idx);\n        pool.push_back(std::move(root));\n        beam.push_back((int)pool.size() - 1);\n    }\n\n    auto cmp = [&](int a, int b) {\n        int pa = pool[a].cost + pool[a].future;\n        int pb = pool[b].cost + pool[b].future;\n        if (pa != pb) return pa < pb;\n        if (pool[a].cost != pool[b].cost) return pool[a].cost < pool[b].cost;\n        if (pool[a].future != pool[b].future) return pool[a].future < pool[b].future;\n        return a < b;\n    };\n\n    sort(beam.begin(), beam.end(), cmp);\n    if ((int)beam.size() > beamSize) beam.resize(beamSize);\n\n    for (int depth = 1; depth < M; ++depth) {\n        vector<int> nxt;\n        nxt.reserve((int)beam.size() * candK);\n\n        for (int id : beam) {\n            array<int, CELLS> move;\n            array<int, 26> bestStart;\n            buildMoveAndBestStart(pool[id].dp, move, bestStart);\n\n            vector<pair<int, int>> cand;\n            cand.reserve(M);\n            for (int idx = 0; idx < M; ++idx) {\n                if (usedBit(pool[id].used, idx)) continue;\n                int sc = wordApproxScore(pool[id].tail, idx, bestStart);\n                sc += (int)(rng.next() % 3); // tiny noise for diversity\n                cand.push_back({sc, idx});\n            }\n\n            sort(cand.begin(), cand.end());\n            if ((int)cand.size() > candK) cand.resize(candK);\n\n            for (auto [sc, idx] : cand) {\n                (void)sc;\n                Node child = bestChildForCandidate(pool[id], id, idx);\n                pool.push_back(std::move(child));\n                nxt.push_back((int)pool.size() - 1);\n            }\n        }\n\n        sort(nxt.begin(), nxt.end(), cmp);\n        if ((int)nxt.size() > beamSize) nxt.resize(beamSize);\n        beam.swap(nxt);\n    }\n\n    int bestId = beam[0];\n    for (int id : beam) {\n        if (cmp(id, bestId)) bestId = id;\n    }\n\n    RunResult res;\n    res.cost = pool[bestId].cost;\n    res.s = reconstructString(pool, bestId);\n    return res;\n}\n\npair<long long, vector<int>> solveTypingPath(const string& s) {\n    int L = (int)s.size();\n    vector<array<int16_t, CELLS>> par(L);\n\n    array<int, CELLS> dp, ndp;\n    dp.fill(INF);\n    dp[si * H + sj] = 0;\n\n    for (int i = 0; i < L; ++i) {\n        int c = s[i] - 'A';\n        ndp.fill(INF);\n        par[i].fill(-1);\n\n        for (int q : cellsByLetter[c]) {\n            int best = INF, bestp = -1;\n            for (int p = 0; p < CELLS; ++p) {\n                if (dp[p] >= INF) continue;\n                int v = dp[p] + distCell[p][q] + 1;\n                if (v < best) {\n                    best = v;\n                    bestp = p;\n                }\n            }\n            ndp[q] = best;\n            par[i][q] = (int16_t)bestp;\n        }\n        dp = ndp;\n    }\n\n    int end = -1, best = INF;\n    for (int q : cellsByLetter[s.back() - 'A']) {\n        if (dp[q] < best) {\n            best = dp[q];\n            end = q;\n        }\n    }\n\n    vector<int> path(L);\n    int cur = end;\n    for (int i = L - 1; i >= 0; --i) {\n        path[i] = cur;\n        cur = par[i][cur];\n    }\n    return {best, path};\n}\n\nvector<int> sampleSeeds(const vector<pair<int, int>>& ranked, int poolSize, int fixedTop, int take, FastRng& rng) {\n    vector<int> res;\n    int n = (int)ranked.size();\n    fixedTop = min(fixedTop, min(take, n));\n    for (int i = 0; i < fixedTop; ++i) res.push_back(ranked[i].second);\n\n    vector<int> pool;\n    int lim = min(poolSize, n);\n    for (int i = fixedTop; i < lim; ++i) pool.push_back(ranked[i].second);\n\n    for (int i = (int)pool.size() - 1; i > 0; --i) {\n        int j = rng.nextInt(0, i);\n        swap(pool[i], pool[j]);\n    }\n\n    for (int i = 0; i < take - fixedTop && i < (int)pool.size(); ++i) {\n        res.push_back(pool[i]);\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    cin >> si >> sj;\n    words.resize(M);\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n    for (int i = 0; i < M; ++i) cin >> words[i];\n\n    for (int c = 0; c < 26; ++c) cellsByLetter[c].clear();\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * H + j;\n            int c = grid[i][j] - 'A';\n            boardLetter[id] = c;\n            cellsByLetter[c].push_back(id);\n        }\n    }\n\n    for (int a = 0; a < CELLS; ++a) {\n        int x1 = a / H, y1 = a % H;\n        for (int b = 0; b < CELLS; ++b) {\n            int x2 = b / H, y2 = b % H;\n            distCell[a][b] = abs(x1 - x2) + abs(y1 - y2);\n        }\n    }\n\n    for (int a = 0; a < 26; ++a) {\n        for (int b = 0; b < 26; ++b) letterDist[a][b] = INF;\n    }\n    for (int a = 0; a < CELLS; ++a) {\n        int ca = boardLetter[a];\n        for (int b = 0; b < CELLS; ++b) {\n            int cb = boardLetter[b];\n            letterDist[ca][cb] = min(letterDist[ca][cb], distCell[a][b]);\n        }\n    }\n\n    for (int i = 0; i < M; ++i) {\n        for (int k = 0; k <= 4; ++k) {\n            suffixes[i][k] = words[i].substr(k);\n            const string& t = suffixes[i][k];\n            int lb = (int)t.size();\n            for (int j = 1; j < (int)t.size(); ++j) {\n                lb += letterDist[t[j - 1] - 'A'][t[j] - 'A'];\n            }\n            suffixLB[i][k] = lb;\n        }\n    }\n\n    // Rank seed words by exact one-word cost + future estimate.\n    vector<pair<int, int>> seedRank; // (priority, idx)\n    seedRank.reserve(M);\n\n    for (int i = 0; i < M; ++i) {\n        Node root = makeRoot(i);\n        seedRank.push_back({root.cost + root.future, i});\n    }\n    sort(seedRank.begin(), seedRank.end());\n\n    uint64_t baseSeed = chrono::steady_clock::now().time_since_epoch().count();\n\n    vector<RunResult> results;\n\n    // Run 1: strong deterministic top seeds\n    {\n        FastRng rng(baseSeed ^ 0x123456789abcdefULL);\n        vector<int> seeds = sampleSeeds(seedRank, 10, 10, 10, rng);\n        results.push_back(beamSearch(seeds, 10, 14, rng.next()));\n    }\n\n    // Run 2: diversified random subset from top 20\n    {\n        FastRng rng(baseSeed ^ 0xfedcba987654321ULL);\n        vector<int> seeds = sampleSeeds(seedRank, 20, 4, 12, rng);\n        results.push_back(beamSearch(seeds, 8, 18, rng.next()));\n    }\n\n    // Run 3: another diversified random subset from top 30\n    {\n        FastRng rng(baseSeed ^ 0x314159265358979ULL);\n        vector<int> seeds = sampleSeeds(seedRank, 30, 4, 12, rng);\n        results.push_back(beamSearch(seeds, 8, 20, rng.next()));\n    }\n\n    int bestIdx = 0;\n    for (int i = 1; i < (int)results.size(); ++i) {\n        if (results[i].cost < results[bestIdx].cost ||\n            (results[i].cost == results[bestIdx].cost &&\n             results[i].s.size() < results[bestIdx].s.size())) {\n            bestIdx = i;\n        }\n    }\n\n    auto [finalCost, path] = solveTypingPath(results[bestIdx].s);\n\n    for (int idx : path) {\n        cout << idx / H << ' ' << idx % H << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, M;\n    double eps;\n    double invcoef;\n\n    vector<vector<pair<int,int>>> shapes;\n    vector<vector<int>> known; // -1 unknown, 0 empty, 1 positive\n    vector<double> priorCnt;    // expected v(i,j) from prior\n    vector<double> support;     // from queries\n    vector<double> score;       // prior + support\n\n    int ops = 0;\n    const int op_limit = 0;\n\n    inline int id(int i, int j) const { return i * N + j; }\n    inline bool inb(int i, int j) const { return 0 <= i && i < N && 0 <= j && j < N; }\n\n    double est_from_raw(int raw, int k) const {\n        return (raw - k * eps) * invcoef;\n    }\n\n    double ask_set(const vector<pair<int,int>>& cells) {\n        int k = (int)cells.size();\n        cout << \"q \" << k;\n        for (auto [i, j] : cells) cout << ' ' << i << ' ' << j;\n        cout << '\\n' << flush;\n\n        int resp;\n        cin >> resp;\n        ++ops;\n        return est_from_raw(resp, k);\n    }\n\n    void drill(int i, int j) {\n        if (known[i][j] != -1) return;\n        cout << \"q 1 \" << i << ' ' << j << '\\n' << flush;\n        int v;\n        cin >> v;\n        ++ops;\n        known[i][j] = (v > 0 ? 1 : 0);\n    }\n\n    void bfs_expand(int si, int sj) {\n        queue<pair<int,int>> q;\n        q.push({si, sj});\n\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n\n        while (!q.empty() && ops < 2 * N * N - 10) {\n            auto [i, j] = q.front();\n            q.pop();\n\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inb(ni, nj) || known[ni][nj] != -1) continue;\n                drill(ni, nj);\n                if (known[ni][nj] == 1) q.push({ni, nj});\n            }\n        }\n    }\n\n    void add_support_set(const vector<pair<int,int>>& cells, double est, double weight) {\n        int k = (int)cells.size();\n        if (k == 0) return;\n        double density = est / k;\n        // Keep it moderately bounded; noisy outliers should not dominate.\n        density = max(-0.25, min(3.0, density));\n        double add = weight * density;\n        for (auto [i, j] : cells) support[id(i, j)] += add;\n    }\n\n    void compute_prior() {\n        priorCnt.assign(N * N, 0.0);\n\n        for (const auto& shp : shapes) {\n            int mx = 0, my = 0;\n            for (auto [x, y] : shp) {\n                mx = max(mx, x);\n                my = max(my, y);\n            }\n            int Ti = N - mx;\n            int Tj = N - my;\n            double inv = 1.0 / (Ti * Tj);\n\n            vector<double> p(N * N, 0.0);\n\n            for (auto [x, y] : shp) {\n                for (int i = x; i < x + Ti; ++i) {\n                    for (int j = y; j < y + Tj; ++j) {\n                        p[id(i, j)] += inv;\n                    }\n                }\n            }\n\n            for (int i = 0; i < N * N; ++i) priorCnt[i] += p[i];\n        }\n    }\n\n    void build_support() {\n        support.assign(N * N, 0.0);\n\n        auto add_line = [&](const vector<pair<int,int>>& cells, double weight) {\n            double est = ask_set(cells);\n            add_support_set(cells, est, weight);\n        };\n\n        // Rows\n        for (int i = 0; i < N; ++i) {\n            vector<pair<int,int>> cells;\n            cells.reserve(N);\n            for (int j = 0; j < N; ++j) cells.push_back({i, j});\n            add_line(cells, 0.30);\n        }\n\n        // Columns\n        for (int j = 0; j < N; ++j) {\n            vector<pair<int,int>> cells;\n            cells.reserve(N);\n            for (int i = 0; i < N; ++i) cells.push_back({i, j});\n            add_line(cells, 0.30);\n        }\n\n        // Overlapping 4x4 blocks with two offsets.\n        for (int oi : {0, 2}) {\n            for (int oj : {0, 2}) {\n                for (int r = oi; r + 3 < N; r += 4) {\n                    for (int c = oj; c + 3 < N; c += 4) {\n                        vector<pair<int,int>> cells;\n                        cells.reserve(16);\n                        for (int i = r; i < r + 4; ++i) {\n                            for (int j = c; j < c + 4; ++j) cells.push_back({i, j});\n                        }\n                        add_line(cells, 1.00);\n                    }\n                }\n            }\n        }\n\n        // A small smoothing pass to make local peaks more stable.\n        vector<double> sm = support;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                double sum = support[id(i, j)];\n                int cnt = 1;\n                for (int d = 0; d < 4; ++d) {\n                    int ni = i + di[d], nj = j + dj[d];\n                    if (!inb(ni, nj)) continue;\n                    sum += support[id(ni, nj)];\n                    ++cnt;\n                }\n                sm[id(i, j)] = 0.7 * support[id(i, j)] + 0.3 * (sum / cnt);\n            }\n        }\n        support.swap(sm);\n\n        score.assign(N * N, 0.0);\n        for (int i = 0; i < N * N; ++i) {\n            score[i] = priorCnt[i] + support[i];\n        }\n    }\n\n    vector<int> sorted_cells_by_score() const {\n        vector<int> ord(N * N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (fabs(score[a] - score[b]) > 1e-12) return score[a] > score[b];\n            return a < b;\n        });\n        return ord;\n    }\n\n    vector<pair<int,int>> current_answer() const {\n        vector<pair<int,int>> ans;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (known[i][j] == 1) ans.push_back({i, j});\n            }\n        }\n        return ans;\n    }\n\n    int output_answer() {\n        auto ans = current_answer();\n        cout << \"a \" << ans.size();\n        for (auto [i, j] : ans) cout << ' ' << i << ' ' << j;\n        cout << '\\n' << flush;\n\n        int ok;\n        cin >> ok;\n        ++ops;\n        return ok;\n    }\n\n    void exact_fallback() {\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (known[i][j] == -1) drill(i, j);\n            }\n        }\n    }\n\n    void run() {\n        cin >> N >> M >> eps;\n        invcoef = 1.0 / (1.0 - 2.0 * eps);\n\n        shapes.resize(M);\n        for (int k = 0; k < M; ++k) {\n            int d;\n            cin >> d;\n            shapes[k].resize(d);\n            for (int t = 0; t < d; ++t) {\n                cin >> shapes[k][t].first >> shapes[k][t].second;\n            }\n        }\n\n        known.assign(N, vector<int>(N, -1));\n\n        compute_prior();\n        build_support();\n\n        auto ord = sorted_cells_by_score();\n        double mx = 0.0;\n        for (double x : score) mx = max(mx, x);\n\n        const int seed_limit = min(35, N * N);\n        const int repair1_limit = min(25, N * N);\n        const int repair2_limit = min(15, N * N);\n\n        auto try_seed_pass = [&](int limit) {\n            for (int t = 0; t < (int)ord.size() && t < limit; ++t) {\n                int p = ord[t];\n                int i = p / N, j = p % N;\n                if (known[i][j] != -1) continue;\n                drill(i, j);\n                if (known[i][j] == 1) bfs_expand(i, j);\n                if (ops >= 2 * N * N - 20) return;\n            }\n        };\n\n        auto try_repair_pass = [&](double thr, int limit) {\n            int used = 0;\n            for (int p : ord) {\n                if (used >= limit) break;\n                if (score[p] < thr) break;\n                int i = p / N, j = p % N;\n                if (known[i][j] != -1) continue;\n                drill(i, j);\n                ++used;\n                if (known[i][j] == 1) bfs_expand(i, j);\n                if (ops >= 2 * N * N - 20) return;\n            }\n        };\n\n        // Phase 1: strong seeds.\n        try_seed_pass(seed_limit);\n\n        // Phase 2: local repair based on score.\n        double thr1 = max(0.10, mx * 0.18);\n        double thr2 = max(0.05, mx * 0.10);\n        try_repair_pass(thr1, repair1_limit);\n        try_repair_pass(thr2, repair2_limit);\n\n        // First guess.\n        int ok = output_answer();\n        if (ok == 1) return;\n\n        // Exact fallback for correctness.\n        exact_fallback();\n        output_answer();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.run();\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const ll INF = (1LL << 60);\n\nstatic int W, D, N;\n\nenum class RowMode {\n    UNIFORM,\n    GREEDY_LOW,\n    GREEDY_HIGH,\n    PROP\n};\n\nstruct Candidate {\n    vector<int> layerH;          // heights of layers, sum = W\n    vector<vector<int>> cuts;    // vertical cut positions for each layer\n    vector<int> ycuts;           // horizontal cut positions\n    ll cost = 0;                 // shortage cost only\n};\n\nstatic inline int clampi(int x, int lo, int hi) {\n    return max(lo, min(hi, x));\n}\n\nstatic inline vector<int> make_prefix(const vector<int>& v) {\n    vector<int> p;\n    p.reserve(v.empty() ? 0 : (int)v.size() - 1);\n    int s = 0;\n    for (int i = 0; i + 1 < (int)v.size(); ++i) {\n        s += v[i];\n        p.push_back(s);\n    }\n    return p;\n}\n\nstatic inline int symdiff_len(const vector<int>& A, const vector<int>& B) {\n    int i = 0, j = 0, c = 0;\n    while (i < (int)A.size() || j < (int)B.size()) {\n        int x = (i < (int)A.size() ? A[i] : INT_MAX);\n        int y = (j < (int)B.size() ? B[j] : INT_MAX);\n        if (x < y) {\n            ++c;\n            ++i;\n        } else if (y < x) {\n            ++c;\n            ++j;\n        } else {\n            ++i;\n            ++j;\n        }\n    }\n    return c;\n}\n\nstatic vector<int> build_uniform_parts(int g) {\n    vector<int> p(g, 1);\n    int extra = W - g;\n    int q = extra / g, r = extra % g;\n    for (int i = 0; i < g; ++i) p[i] += q;\n    for (int i = g - r; i < g; ++i) if (r > 0) p[i] += 1;\n    sort(p.begin(), p.end());\n    return p;\n}\n\nstatic ll gain_one_step(int demand, int rowH, int curPart) {\n    ll rem = 1LL * demand - 1LL * rowH * curPart;\n    if (rem <= 0) return 0;\n    return 100LL * min<ll>(rowH, rem);\n}\n\nstatic vector<int> build_parts_mode(const vector<int>& dem, int rowH, RowMode mode) {\n    int g = (int)dem.size();\n    if (mode == RowMode::UNIFORM) return build_uniform_parts(g);\n\n    vector<int> part(g, 1);\n    int extra = W - g;\n\n    if (mode == RowMode::PROP) {\n        ll sumD = 0;\n        for (int x : dem) sumD += x;\n\n        vector<pair<ll, int>> frac;\n        frac.reserve(g);\n\n        ll used = 0;\n        for (int i = 0; i < g; ++i) {\n            ll num = 1LL * extra * dem[i];\n            int add = (int)(num / sumD);\n            ll rem = num % sumD;\n            part[i] += add;\n            used += add;\n            frac.push_back({rem, i});\n        }\n\n        int left = extra - (int)used;\n        sort(frac.begin(), frac.end(), [&](const auto& a, const auto& b) {\n            if (a.first != b.first) return a.first > b.first;\n            return a.second < b.second;\n        });\n        for (int i = 0; i < left; ++i) part[frac[i].second] += 1;\n\n        sort(part.begin(), part.end());\n        return part;\n    }\n\n    struct Node {\n        ll gain;\n        int idx;\n    };\n    struct Cmp {\n        bool preferHigh = false;\n        bool operator()(const Node& a, const Node& b) const {\n            if (a.gain != b.gain) return a.gain < b.gain;\n            if (preferHigh) return a.idx < b.idx;\n            return a.idx > b.idx;\n        }\n    };\n\n    Cmp cmp;\n    cmp.preferHigh = (mode == RowMode::GREEDY_HIGH);\n    priority_queue<Node, vector<Node>, Cmp> pq(cmp);\n\n    for (int i = 0; i < g; ++i) {\n        pq.push({gain_one_step(dem[i], rowH, 1), i});\n    }\n\n    while (extra > 0) {\n        auto cur = pq.top();\n        pq.pop();\n\n        if (cur.gain == 0) {\n            part.back() += extra;\n            break;\n        }\n\n        int i = cur.idx;\n        ++part[i];\n        --extra;\n        pq.push({gain_one_step(dem[i], rowH, part[i]), i});\n    }\n\n    sort(part.begin(), part.end());\n    return part;\n}\n\nstatic vector<int> candidate_split2(const vector<int>& dem) {\n    vector<ll> pref(N + 1, 0);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + dem[i];\n    ll total = pref[N];\n\n    set<int> s;\n\n    int bDemand = (int)(lower_bound(pref.begin() + 1, pref.begin() + N, total / 2) - pref.begin());\n    int bCount = N / 2;\n\n    for (int base : {bDemand, bCount}) {\n        for (int d = -1; d <= 1; ++d) {\n            int x = clampi(base + d, 1, N - 1);\n            s.insert(x);\n        }\n    }\n\n    return vector<int>(s.begin(), s.end());\n}\n\nstatic vector<pair<int, int>> candidate_split3(const vector<int>& dem) {\n    vector<ll> pref(N + 1, 0);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + dem[i];\n    ll total = pref[N];\n\n    int d1 = (int)(lower_bound(pref.begin() + 1, pref.begin() + N, total / 3) - pref.begin());\n    int d2 = (int)(lower_bound(pref.begin() + 1, pref.begin() + N, (total * 2) / 3) - pref.begin());\n    int c1 = N / 3;\n    int c2 = (2 * N) / 3;\n\n    set<pair<int, int>> s;\n    vector<pair<int, int>> bases = {\n        {d1, d2},\n        {c1, c2}\n    };\n\n    for (auto [b1, b2] : bases) {\n        for (int x = -1; x <= 1; ++x) {\n            for (int y = -1; y <= 1; ++y) {\n                int p1 = clampi(b1 + x, 1, N - 1);\n                int p2 = clampi(b2 + y, 1, N - 1);\n                if (p1 < p2) s.insert({p1, p2});\n            }\n        }\n    }\n\n    return vector<pair<int, int>>(s.begin(), s.end());\n}\n\nstatic vector<int> allocate_heights(const vector<ll>& sums) {\n    int L = (int)sums.size();\n    vector<int> h(L, 1);\n    int extra = W - L;\n    if (L == 1) {\n        h[0] = W;\n        return h;\n    }\n\n    ll total = 0;\n    for (ll x : sums) total += x;\n\n    if (total == 0) {\n        int q = extra / L, r = extra % L;\n        for (int i = 0; i < L; ++i) h[i] += q;\n        for (int i = L - r; i < L; ++i) if (r > 0) h[i] += 1;\n        return h;\n    }\n\n    vector<pair<ll, int>> frac;\n    frac.reserve(L);\n\n    ll used = 0;\n    for (int i = 0; i < L; ++i) {\n        ll num = 1LL * extra * sums[i];\n        int add = (int)(num / total);\n        ll rem = num % total;\n        h[i] += add;\n        used += add;\n        frac.push_back({rem, i});\n    }\n\n    int left = extra - (int)used;\n    sort(frac.begin(), frac.end(), [&](const auto& a, const auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n    for (int i = 0; i < left; ++i) h[frac[i].second] += 1;\n\n    return h;\n}\n\nstatic ll shortage_cost_sorted_areas(const vector<int>& dem, const vector<ll>& areas_sorted) {\n    ll c = 0;\n    for (int i = 0; i < (int)dem.size(); ++i) {\n        if ((ll)dem[i] > areas_sorted[i]) c += 100LL * ((ll)dem[i] - areas_sorted[i]);\n    }\n    return c;\n}\n\nstatic vector<ll> collect_areas(const Candidate& c) {\n    vector<ll> areas;\n    areas.reserve(N);\n\n    for (int i = 0; i < (int)c.layerH.size(); ++i) {\n        int h = c.layerH[i];\n        int prev = 0;\n        for (int x : c.cuts[i]) {\n            areas.push_back(1LL * h * (x - prev));\n            prev = x;\n        }\n        areas.push_back(1LL * h * (W - prev));\n    }\n\n    sort(areas.begin(), areas.end());\n    return areas;\n}\n\nstatic ll calc_cost(const vector<int>& dem, const Candidate& c) {\n    return shortage_cost_sorted_areas(dem, collect_areas(c));\n}\n\nstatic Candidate build_layout_candidate(const vector<int>& dem, const vector<int>& splitPos, const vector<RowMode>& modes) {\n    int L = (int)modes.size();\n    vector<ll> pref(N + 1, 0);\n    for (int i = 0; i < N; ++i) pref[i + 1] = pref[i] + dem[i];\n\n    vector<ll> sums(L);\n    int l = 0;\n    for (int i = 0; i < L; ++i) {\n        int r = (i < L - 1 ? splitPos[i] : N);\n        sums[i] = pref[r] - pref[l];\n        l = r;\n    }\n\n    vector<int> layerH = allocate_heights(sums);\n\n    Candidate c;\n    c.layerH = move(layerH);\n    c.ycuts = make_prefix(c.layerH);\n    c.cuts.resize(L);\n\n    vector<ll> areas;\n    areas.reserve(N);\n\n    l = 0;\n    for (int i = 0; i < L; ++i) {\n        int r = (i < L - 1 ? splitPos[i] : N);\n        vector<int> sub(dem.begin() + l, dem.begin() + r);\n        vector<int> widths = build_parts_mode(sub, c.layerH[i], modes[i]);\n        c.cuts[i] = make_prefix(widths);\n        for (int w : widths) areas.push_back(1LL * c.layerH[i] * w);\n        l = r;\n    }\n\n    sort(areas.begin(), areas.end());\n    c.cost = shortage_cost_sorted_areas(dem, areas);\n    return c;\n}\n\nstatic Candidate build_concentrated_stack_candidate(const vector<int>& dem, int m) {\n    m = max(1, min(m, N));\n    vector<int> w(N, 1);\n    int extra = W - N;\n    int q = extra / m, r = extra % m;\n\n    for (int i = N - m; i < N; ++i) w[i] += q;\n    for (int i = N - r; i < N; ++i) if (r > 0) w[i] += 1;\n\n    sort(w.begin(), w.end());\n\n    Candidate c;\n    c.layerH = {W};\n    c.ycuts.clear();\n    c.cuts = {make_prefix(w)};\n    c.cost = calc_cost(dem, c);\n    return c;\n}\n\nstatic inline bool same_geometry(const Candidate& a, const Candidate& b) {\n    return a.layerH == b.layerH && a.cuts == b.cuts;\n}\n\nstatic inline void add_unique(vector<Candidate>& vec, const Candidate& cand) {\n    for (const auto& x : vec) {\n        if (same_geometry(x, cand)) return;\n    }\n    vec.push_back(cand);\n}\n\nstatic int complexity(const Candidate& c) {\n    int x = (int)c.ycuts.size();\n    for (const auto& v : c.cuts) x += (int)v.size();\n    return x;\n}\n\nstatic vector<Candidate> build_stack_family(const vector<int>& dem) {\n    vector<Candidate> cand;\n\n    add_unique(cand, build_layout_candidate(dem, {}, {RowMode::UNIFORM}));\n    add_unique(cand, build_layout_candidate(dem, {}, {RowMode::PROP}));\n    add_unique(cand, build_layout_candidate(dem, {}, {RowMode::GREEDY_LOW}));\n    add_unique(cand, build_layout_candidate(dem, {}, {RowMode::GREEDY_HIGH}));\n\n    add_unique(cand, build_concentrated_stack_candidate(dem, 1));\n    add_unique(cand, build_concentrated_stack_candidate(dem, max(1, N / 2)));\n    add_unique(cand, build_concentrated_stack_candidate(dem, N - 1));\n\n    stable_sort(cand.begin(), cand.end(), [](const Candidate& a, const Candidate& b) {\n        if (a.cost != b.cost) return a.cost < b.cost;\n        return complexity(a) < complexity(b);\n    });\n\n    if ((int)cand.size() > 5) cand.resize(5);\n    return cand;\n}\n\nstatic vector<Candidate> build_two_family(const vector<int>& dem) {\n    vector<Candidate> cand;\n    vector<int> splits = candidate_split2(dem);\n\n    vector<array<RowMode, 2>> patterns = {\n        {RowMode::GREEDY_LOW, RowMode::GREEDY_LOW},\n        {RowMode::PROP,       RowMode::PROP},\n        {RowMode::GREEDY_LOW, RowMode::PROP},\n        {RowMode::PROP,       RowMode::GREEDY_LOW}\n    };\n\n    for (int m : splits) {\n        for (auto pat : patterns) {\n            add_unique(cand, build_layout_candidate(dem, {m}, {pat[0], pat[1]}));\n        }\n    }\n\n    stable_sort(cand.begin(), cand.end(), [](const Candidate& a, const Candidate& b) {\n        if (a.cost != b.cost) return a.cost < b.cost;\n        return complexity(a) < complexity(b);\n    });\n\n    if ((int)cand.size() > 3) cand.resize(3);\n    return cand;\n}\n\nstatic vector<Candidate> build_three_family(const vector<int>& dem) {\n    vector<Candidate> cand;\n    vector<pair<int, int>> splits = candidate_split3(dem);\n\n    vector<array<RowMode, 3>> patterns = {\n        {RowMode::GREEDY_LOW, RowMode::GREEDY_LOW, RowMode::GREEDY_LOW},\n        {RowMode::PROP,       RowMode::PROP,       RowMode::PROP},\n        {RowMode::GREEDY_LOW, RowMode::PROP,       RowMode::GREEDY_LOW},\n        {RowMode::PROP,       RowMode::GREEDY_LOW, RowMode::PROP}\n    };\n\n    for (auto [m1, m2] : splits) {\n        for (auto pat : patterns) {\n            add_unique(cand, build_layout_candidate(dem, {m1, m2}, {pat[0], pat[1], pat[2]}));\n        }\n    }\n\n    stable_sort(cand.begin(), cand.end(), [](const Candidate& a, const Candidate& b) {\n        if (a.cost != b.cost) return a.cost < b.cost;\n        return complexity(a) < complexity(b);\n    });\n\n    if ((int)cand.size() > 4) cand.resize(4);\n    return cand;\n}\n\nstatic vector<int> build_average_demands(const vector<vector<int>>& a) {\n    vector<int> avg(N, 0);\n    for (int i = 0; i < N; ++i) {\n        ll s = 0;\n        for (int d = 0; d < D; ++d) s += a[d][i];\n        avg[i] = (int)((s + D / 2) / D);\n    }\n    sort(avg.begin(), avg.end());\n    return avg;\n}\n\nstatic vector<Candidate> build_shared_pool(const vector<vector<int>>& a) {\n    vector<Candidate> pool;\n    vector<int> avg = build_average_demands(a);\n\n    add_unique(pool, build_layout_candidate(avg, {}, {RowMode::PROP}));\n\n    auto two = build_two_family(avg);\n    if (!two.empty()) add_unique(pool, two[0]);\n\n    auto three = build_three_family(avg);\n    if (!three.empty()) add_unique(pool, three[0]);\n\n    return pool;\n}\n\nstatic Candidate recalc_candidate(Candidate c, const vector<int>& dem) {\n    c.cost = calc_cost(dem, c);\n    return c;\n}\n\nstatic vector<vector<Candidate>> build_base_sets(const vector<vector<int>>& a, const vector<Candidate>& sharedPool) {\n    vector<vector<Candidate>> sets(D);\n    for (int d = 0; d < D; ++d) {\n        vector<Candidate> cand = build_stack_family(a[d]);\n\n        auto two = build_two_family(a[d]);\n        for (const auto& x : two) add_unique(cand, x);\n\n        auto three = build_three_family(a[d]);\n        for (const auto& x : three) add_unique(cand, x);\n\n        for (const auto& s : sharedPool) add_unique(cand, recalc_candidate(s, a[d]));\n\n        sets[d] = move(cand);\n    }\n    return sets;\n}\n\nstatic ll transition_cost(const Candidate& A, const Candidate& B) {\n    ll c = 1LL * W * symdiff_len(A.ycuts, B.ycuts);\n\n    vector<int> bp = {0, W};\n    bp.insert(bp.end(), A.ycuts.begin(), A.ycuts.end());\n    bp.insert(bp.end(), B.ycuts.begin(), B.ycuts.end());\n    sort(bp.begin(), bp.end());\n    bp.erase(unique(bp.begin(), bp.end()), bp.end());\n\n    for (int i = 0; i + 1 < (int)bp.size(); ++i) {\n        int l = bp[i], r = bp[i + 1];\n        if (l == r) continue;\n\n        int ia = (int)(upper_bound(A.ycuts.begin(), A.ycuts.end(), l) - A.ycuts.begin());\n        int ib = (int)(upper_bound(B.ycuts.begin(), B.ycuts.end(), l) - B.ycuts.begin());\n\n        c += 1LL * (r - l) * symdiff_len(A.cuts[ia], B.cuts[ib]);\n    }\n\n    return c;\n}\n\nstruct SolveResult {\n    ll cost = INF;\n    vector<Candidate> chosen;\n};\n\nstatic SolveResult solve_dp(const vector<vector<Candidate>>& sets) {\n    int dnum = (int)sets.size();\n    vector<vector<int>> parent(dnum);\n\n    vector<ll> prev(sets[0].size(), INF), cur;\n    for (int i = 0; i < (int)sets[0].size(); ++i) prev[i] = sets[0][i].cost;\n\n    for (int d = 1; d < dnum; ++d) {\n        int pc = (int)sets[d - 1].size();\n        int cc = (int)sets[d].size();\n        cur.assign(cc, INF);\n        parent[d].assign(cc, -1);\n\n        for (int c = 0; c < cc; ++c) {\n            const Candidate& B = sets[d][c];\n            for (int p = 0; p < pc; ++p) {\n                if (prev[p] >= INF / 2) continue;\n                const Candidate& A = sets[d - 1][p];\n                ll val = prev[p] + transition_cost(A, B) + B.cost;\n                if (val < cur[c]) {\n                    cur[c] = val;\n                    parent[d][c] = p;\n                }\n            }\n        }\n        prev.swap(cur);\n    }\n\n    int bestLast = 0;\n    for (int i = 1; i < (int)prev.size(); ++i) {\n        if (prev[i] < prev[bestLast]) bestLast = i;\n    }\n\n    SolveResult res;\n    res.cost = prev[bestLast];\n    res.chosen.resize(dnum);\n\n    int curIdx = bestLast;\n    for (int d = dnum - 1; d >= 0; --d) {\n        res.chosen[d] = sets[d][curIdx];\n        if (d > 0) curIdx = parent[d][curIdx];\n    }\n\n    return res;\n}\n\nstatic Candidate shift_boundary(const Candidate& base, int idx, int delta) {\n    Candidate c = base;\n    if (idx < 0 || idx + 1 >= (int)c.layerH.size()) return c;\n    if (c.layerH[idx] + delta <= 0 || c.layerH[idx + 1] - delta <= 0) return c;\n\n    c.layerH[idx] += delta;\n    c.layerH[idx + 1] -= delta;\n    c.ycuts = make_prefix(c.layerH);\n    return c;\n}\n\nstatic vector<vector<Candidate>> augment_sets(\n    vector<vector<Candidate>> sets,\n    const vector<Candidate>& seq,\n    const vector<vector<int>>& a\n) {\n    for (int d = 0; d < D; ++d) {\n        auto add = [&](Candidate c) {\n            c = recalc_candidate(move(c), a[d]);\n            add_unique(sets[d], c);\n        };\n\n        add(seq[d]);\n\n        if (d > 0) add(seq[d - 1]);\n        if (d + 1 < D) add(seq[d + 1]);\n\n        const Candidate& c = seq[d];\n        int L = (int)c.layerH.size();\n        for (int idx = 0; idx + 1 < L; ++idx) {\n            add(shift_boundary(c, idx, +1));\n            add(shift_boundary(c, idx, -1));\n        }\n    }\n    return sets;\n}\n\nstatic vector<array<int, 4>> build_rectangles(const Candidate& c) {\n    vector<pair<ll, array<int, 4>>> tmp;\n    tmp.reserve(N);\n\n    int y = 0;\n    for (int i = 0; i < (int)c.layerH.size(); ++i) {\n        int h = c.layerH[i];\n        int x = 0;\n        const auto& cuts = c.cuts[i];\n        if (cuts.empty()) {\n            tmp.push_back({1LL * h * W, {0, y, W, y + h}});\n        } else {\n            for (int cut : cuts) {\n                tmp.push_back({1LL * h * (cut - x), {x, y, cut, y + h}});\n                x = cut;\n            }\n            tmp.push_back({1LL * h * (W - x), {x, y, W, y + h}});\n        }\n        y += h;\n    }\n\n    sort(tmp.begin(), tmp.end(), [](const auto& A, const auto& B) {\n        if (A.first != B.first) return A.first < B.first;\n        return A.second < B.second;\n    });\n\n    vector<array<int, 4>> rects;\n    rects.reserve(tmp.size());\n    for (auto& p : tmp) rects.push_back(p.second);\n    return rects;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> W >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; ++d) {\n        for (int i = 0; i < N; ++i) cin >> a[d][i];\n    }\n\n    vector<Candidate> sharedPool = build_shared_pool(a);\n    vector<vector<Candidate>> baseSets = build_base_sets(a, sharedPool);\n\n    SolveResult res1 = solve_dp(baseSets);\n\n    vector<vector<Candidate>> sets2 = augment_sets(baseSets, res1.chosen, a);\n    SolveResult res2 = solve_dp(sets2);\n\n    for (int d = 0; d < D; ++d) {\n        auto rects = build_rectangles(res2.chosen[d]);\n        for (const auto& r : rects) {\n            cout << r[0] << ' ' << r[1] << ' ' << r[2] << ' ' << r[3] << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr ll MOD = 998244353LL;\nstatic constexpr int H = 9;\nstatic constexpr int W = 9;\nstatic constexpr int CELLS = 81;\nstatic constexpr int STAMPS = 20;\nstatic constexpr int POS = 7;\nstatic constexpr int ACTIONS = STAMPS * POS * POS; // 980\nstatic constexpr int NOOP = ACTIONS;\nstatic constexpr int KMAX = 81;\n\nstatic constexpr int TOP_SCAN = 8;\nstatic constexpr int POOL_SCAN = 24;\nstatic constexpr int BEAM_W = 12;\n\nstatic constexpr int POOL_GAIN = 24;\nstatic constexpr int POOL_SUM = 8;\nstatic constexpr int POOL_RANDOM = 4;\n\nint N, M, K;\n\nstruct Action {\n    int m = -1, p = -1, q = -1;\n    int len = 0;\n    array<int, 9> cells{};\n    array<int, 9> vals{};\n};\n\nstruct Cand {\n    ll score = LLONG_MIN;\n    int id = -1;\n};\n\nstruct Result {\n    array<int, CELLS> board{};\n    array<int, KMAX> seq{};\n    ll score = 0;\n};\n\nstruct BeamState {\n    array<int, CELLS> board{};\n    array<int, KMAX> seq{};\n    ll score = 0;\n    ll key = 0;\n};\n\narray<array<array<int, 3>, 3>, STAMPS> stamps;\narray<Action, ACTIONS + 1> acts; // last one is NOOP\narray<ll, ACTIONS> actionSum{};\narray<int, ACTIONS> sumOrder{};\narray<int, CELLS> initBoard{};\n\ninline ll calc_score(const array<int, CELLS>& b) {\n    ll s = 0;\n    for (int x : b) s += x;\n    return s;\n}\n\ninline void apply_action(array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    for (int t = 0; t < ac.len; ++t) {\n        int c = ac.cells[t];\n        int x = board[c] + ac.vals[t];\n        if (x >= MOD) x -= MOD;\n        board[c] = x;\n    }\n}\n\ninline void remove_action(array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    for (int t = 0; t < ac.len; ++t) {\n        int c = ac.cells[t];\n        int x = board[c] - ac.vals[t];\n        if (x < 0) x += MOD;\n        board[c] = x;\n    }\n}\n\ninline ll gain_of_action(const array<int, CELLS>& board, int id) {\n    const auto& ac = acts[id];\n    ll g = 0;\n    for (int t = 0; t < ac.len; ++t) {\n        int c = ac.cells[t];\n        int w = ac.vals[t];\n        int x = board[c];\n        if ((ll)x >= MOD - w) g += (ll)w - MOD;\n        else g += w;\n    }\n    return g;\n}\n\ninline ll delta_replace(const array<int, CELLS>& board, int oldId, int newId) {\n    struct Touch {\n        int c;\n        int before;\n        int after;\n    };\n    Touch tmp[18];\n    int cnt = 0;\n\n    auto touch = [&](int c) -> int {\n        for (int i = 0; i < cnt; ++i) {\n            if (tmp[i].c == c) return i;\n        }\n        tmp[cnt] = {c, board[c], board[c]};\n        return cnt++;\n    };\n\n    const auto& oldA = acts[oldId];\n    const auto& newA = acts[newId];\n\n    for (int t = 0; t < oldA.len; ++t) {\n        int idx = touch(oldA.cells[t]);\n        int x = tmp[idx].after - oldA.vals[t];\n        if (x < 0) x += MOD;\n        tmp[idx].after = x;\n    }\n    for (int t = 0; t < newA.len; ++t) {\n        int idx = touch(newA.cells[t]);\n        int x = tmp[idx].after + newA.vals[t];\n        if (x >= MOD) x -= MOD;\n        tmp[idx].after = x;\n    }\n\n    ll delta = 0;\n    for (int i = 0; i < cnt; ++i) delta += (ll)tmp[i].after - tmp[i].before;\n    return delta;\n}\n\ntemplate <size_t T>\ninline void push_top(array<Cand, T>& top, int& n, ll score, int id) {\n    if (n < (int)T) {\n        int pos = n++;\n        while (pos > 0 &&\n               (top[pos - 1].score < score ||\n                (top[pos - 1].score == score && top[pos - 1].id > id))) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {score, id};\n    } else if (score > top[T - 1].score ||\n               (score == top[T - 1].score && id < top[T - 1].id)) {\n        int pos = (int)T - 1;\n        while (pos > 0 &&\n               (top[pos - 1].score < score ||\n                (top[pos - 1].score == score && top[pos - 1].id > id))) {\n            top[pos] = top[pos - 1];\n            --pos;\n        }\n        top[pos] = {score, id};\n    }\n}\n\ntemplate <size_t T>\ninline int build_top(const array<int, CELLS>& board, array<Cand, T>& top) {\n    int n = 0;\n    for (int id = 0; id < ACTIONS; ++id) {\n        ll g = gain_of_action(board, id);\n        push_top(top, n, g, id);\n    }\n    return n;\n}\n\ninline Result make_empty() {\n    Result r;\n    r.board = initBoard;\n    r.seq.fill(NOOP);\n    r.score = calc_score(r.board);\n    return r;\n}\n\ninline void add_unique(vector<int>& v, int x) {\n    for (int y : v) if (y == x) return;\n    v.push_back(x);\n}\n\nResult construct_greedy(bool stop_positive, bool randomized, mt19937_64& rng) {\n    Result r = make_empty();\n\n    for (int step = 0; step < KMAX; ++step) {\n        array<Cand, TOP_SCAN> top{};\n        int n = build_top(r.board, top);\n        if (n == 0) break;\n        if (stop_positive && top[0].score <= 0) break;\n\n        int chosen = top[0].id;\n        if (randomized && n > 1) {\n            int lim = min(n, 4);\n            chosen = top[(int)(rng() % (unsigned long long)lim)].id;\n        }\n\n        ll g = gain_of_action(r.board, chosen);\n        apply_action(r.board, chosen);\n        r.seq[step] = chosen;\n        r.score += g;\n    }\n\n    r.score = calc_score(r.board);\n    return r;\n}\n\nResult construct_beam(bool randomized, mt19937_64& rng) {\n    vector<BeamState> beam(1);\n    beam[0].board = initBoard;\n    beam[0].seq.fill(NOOP);\n    beam[0].score = calc_score(initBoard);\n    beam[0].key = beam[0].score;\n\n    for (int step = 0; step < KMAX; ++step) {\n        vector<BeamState> nxt;\n        nxt.reserve((int)beam.size() * 8);\n\n        for (const auto& st : beam) {\n            array<Cand, TOP_SCAN> top{};\n            int n = build_top(st.board, top);\n\n            vector<int> ids;\n            ids.reserve(8);\n            for (int i = 0; i < min(n, 5); ++i) add_unique(ids, top[i].id);\n            for (int i = 0; i < min(n, 2); ++i) add_unique(ids, sumOrder[i]);\n            if (randomized && n > 0) add_unique(ids, (int)(rng() % (unsigned long long)n));\n            add_unique(ids, NOOP);\n\n            for (int id : ids) {\n                BeamState ch = st;\n                ch.seq[step] = id;\n                if (id != NOOP) {\n                    ll g = gain_of_action(st.board, id);\n                    apply_action(ch.board, id);\n                    ch.score += g;\n                }\n                ll h1 = (n >= 1 ? max(0LL, top[0].score) : 0);\n                ll h2 = (n >= 2 ? max(0LL, top[1].score) / 2 : 0);\n                ch.key = ch.score + h1 + h2;\n                nxt.push_back(std::move(ch));\n            }\n        }\n\n        sort(nxt.begin(), nxt.end(), [](const BeamState& a, const BeamState& b) {\n            if (a.key != b.key) return a.key > b.key;\n            if (a.score != b.score) return a.score > b.score;\n            return a.seq < b.seq;\n        });\n\n        if ((int)nxt.size() > BEAM_W) nxt.resize(BEAM_W);\n        beam.swap(nxt);\n    }\n\n    const auto& best = *max_element(beam.begin(), beam.end(), [](const BeamState& a, const BeamState& b) {\n        if (a.score != b.score) return a.score < b.score;\n        return a.key < b.key;\n    });\n\n    Result r;\n    r.board = best.board;\n    r.seq = best.seq;\n    r.score = calc_score(r.board);\n    return r;\n}\n\nvector<int> build_pool(const array<int, CELLS>& board, mt19937_64& rng) {\n    array<Cand, POOL_SCAN> top{};\n    int n = build_top(board, top);\n\n    vector<int> pool;\n    pool.reserve(POOL_GAIN + POOL_SUM + POOL_RANDOM + 1);\n\n    add_unique(pool, NOOP);\n    for (int i = 0; i < min(n, POOL_GAIN); ++i) add_unique(pool, top[i].id);\n    for (int i = 0; i < min((int)ACTIONS, POOL_SUM); ++i) add_unique(pool, sumOrder[i]);\n    for (int i = 0; i < POOL_RANDOM; ++i) add_unique(pool, (int)(rng() % (unsigned long long)ACTIONS));\n\n    return pool;\n}\n\nvoid pool_improve(Result& r, int passes, mt19937_64& rng) {\n    for (int pass = 0; pass < passes; ++pass) {\n        vector<int> pool = build_pool(r.board, rng);\n\n        vector<pair<ll, int>> slots;\n        slots.reserve(KMAX);\n        for (int pos = 0; pos < KMAX; ++pos) {\n            int old = r.seq[pos];\n            ll loss = delta_replace(r.board, old, NOOP);\n            slots.push_back({loss, pos});\n        }\n\n        sort(slots.begin(), slots.end(), [](const auto& a, const auto& b) {\n            if (a.first != b.first) return a.first < b.first;\n            return a.second < b.second;\n        });\n\n        int limit = min((int)slots.size(), 40);\n        bool any = false;\n\n        for (int i = 0; i < limit; ++i) {\n            int pos = slots[i].second;\n            int old = r.seq[pos];\n            ll bestDelta = 0;\n            int bestId = old;\n\n            for (int id : pool) {\n                if (id == old) continue;\n                ll d = delta_replace(r.board, old, id);\n                if (d > bestDelta || (d == bestDelta && id < bestId)) {\n                    bestDelta = d;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != old && bestDelta > 0) {\n                remove_action(r.board, old);\n                apply_action(r.board, bestId);\n                r.seq[pos] = bestId;\n                r.score += bestDelta;\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    r.score = calc_score(r.board);\n}\n\nvoid exact_improve(Result& r, int passes, mt19937_64& rng) {\n    vector<int> ord(KMAX);\n    iota(ord.begin(), ord.end(), 0);\n\n    for (int pass = 0; pass < passes; ++pass) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool any = false;\n\n        for (int pos : ord) {\n            int old = r.seq[pos];\n            ll bestDelta = 0;\n            int bestId = old;\n\n            for (int id = 0; id <= ACTIONS; ++id) {\n                if (id == old) continue;\n                ll d = delta_replace(r.board, old, id);\n                if (d > bestDelta || (d == bestDelta && id < bestId)) {\n                    bestDelta = d;\n                    bestId = id;\n                }\n            }\n\n            if (bestId != old && bestDelta > 0) {\n                remove_action(r.board, old);\n                apply_action(r.board, bestId);\n                r.seq[pos] = bestId;\n                r.score += bestDelta;\n                any = true;\n            }\n        }\n\n        if (!any) break;\n    }\n\n    r.score = calc_score(r.board);\n}\n\nResult beam_fill(const Result& base, vector<int> holes, bool randomized, mt19937_64& rng) {\n    if (holes.empty()) return base;\n\n    vector<BeamState> beam(1);\n    beam[0].board = base.board;\n    beam[0].seq = base.seq;\n    beam[0].score = base.score;\n    beam[0].key = base.score;\n\n    for (int step = 0; step < (int)holes.size(); ++step) {\n        vector<BeamState> nxt;\n        nxt.reserve((int)beam.size() * 8);\n\n        for (const auto& st : beam) {\n            array<Cand, TOP_SCAN> top{};\n            int n = build_top(st.board, top);\n\n            vector<int> ids;\n            ids.reserve(8);\n            for (int i = 0; i < min(n, 5); ++i) add_unique(ids, top[i].id);\n            for (int i = 0; i < min(n, 2); ++i) add_unique(ids, sumOrder[i]);\n            if (randomized && n > 0) add_unique(ids, (int)(rng() % (unsigned long long)n));\n            add_unique(ids, NOOP);\n\n            for (int id : ids) {\n                BeamState ch = st;\n                ch.seq[holes[step]] = id;\n                if (id != NOOP) {\n                    ll g = gain_of_action(st.board, id);\n                    apply_action(ch.board, id);\n                    ch.score += g;\n                }\n                ll h1 = (n >= 1 ? max(0LL, top[0].score) : 0);\n                ll h2 = (n >= 2 ? max(0LL, top[1].score) / 2 : 0);\n                ch.key = ch.score + h1 + h2;\n                nxt.push_back(std::move(ch));\n            }\n        }\n\n        sort(nxt.begin(), nxt.end(), [](const BeamState& a, const BeamState& b) {\n            if (a.key != b.key) return a.key > b.key;\n            if (a.score != b.score) return a.score > b.score;\n            return a.seq < b.seq;\n        });\n\n        if ((int)nxt.size() > BEAM_W) nxt.resize(BEAM_W);\n        beam.swap(nxt);\n    }\n\n    const auto& best = *max_element(beam.begin(), beam.end(), [](const BeamState& a, const BeamState& b) {\n        if (a.score != b.score) return a.score < b.score;\n        return a.key < b.key;\n    });\n\n    Result r;\n    r.board = best.board;\n    r.seq = best.seq;\n    r.score = calc_score(r.board);\n    return r;\n}\n\nResult ruin_and_fill(const Result& base, bool randomized, mt19937_64& rng) {\n    Result cur = base;\n\n    vector<pair<ll, int>> slots;\n    slots.reserve(KMAX);\n    for (int pos = 0; pos < KMAX; ++pos) {\n        int old = cur.seq[pos];\n        ll loss = delta_replace(cur.board, old, NOOP);\n        slots.push_back({loss, pos});\n    }\n\n    sort(slots.begin(), slots.end(), [](const auto& a, const auto& b) {\n        if (a.first != b.first) return a.first < b.first;\n        return a.second < b.second;\n    });\n\n    if ((int)slots.size() < 2) return cur;\n\n    int target = min((int)slots.size(), 12 + (int)(rng() % 9)); // 12..20\n    int lim = min((int)slots.size(), target * 3);\n\n    vector<pair<ll, int>> picked;\n    picked.reserve(target);\n    for (int i = 0; i < lim; ++i) picked.push_back(slots[i]);\n    shuffle(picked.begin(), picked.end(), rng);\n    picked.resize(target);\n\n    sort(picked.begin(), picked.end(), [](const auto& a, const auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    vector<int> holes;\n    holes.reserve(target);\n    for (auto [loss, pos] : picked) {\n        (void)loss;\n        remove_action(cur.board, cur.seq[pos]);\n        cur.seq[pos] = NOOP;\n        holes.push_back(pos);\n    }\n\n    cur.score = calc_score(cur.board);\n    cur = beam_fill(cur, holes, randomized, rng);\n    pool_improve(cur, 1, rng);\n    return cur;\n}\n\ninline void insert_elite(vector<Result>& elite, const Result& r, int keep = 4) {\n    elite.push_back(r);\n    sort(elite.begin(), elite.end(), [](const Result& a, const Result& b) {\n        if (a.score != b.score) return a.score > b.score;\n        return a.seq < b.seq;\n    });\n    if ((int)elite.size() > keep) elite.resize(keep);\n}\n\nint choose_elite(const vector<Result>& elite, mt19937_64& rng) {\n    if ((int)elite.size() == 1) return 0;\n    int x = (int)(rng() % 100);\n    if (x < 55) return 0;\n    if (x < 80) return min<int>(1, (int)elite.size() - 1);\n    if (x < 92) return min<int>(2, (int)elite.size() - 1);\n    return (int)(rng() % (unsigned long long)elite.size());\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> K;\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    for (int m = 0; m < STAMPS; ++m) {\n        for (int i = 0; i < 3; ++i) {\n            for (int j = 0; j < 3; ++j) cin >> stamps[m][i][j];\n        }\n    }\n\n    // Precompute all actions.\n    int id = 0;\n    for (int m = 0; m < STAMPS; ++m) {\n        for (int p = 0; p < POS; ++p) {\n            for (int q = 0; q < POS; ++q) {\n                Action ac{};\n                ac.m = m;\n                ac.p = p;\n                ac.q = q;\n                ac.len = 9;\n\n                ll s = 0;\n                int t = 0;\n                for (int di = 0; di < 3; ++di) {\n                    for (int dj = 0; dj < 3; ++dj) {\n                        ac.cells[t] = (p + di) * W + (q + dj);\n                        ac.vals[t] = stamps[m][di][dj];\n                        s += ac.vals[t];\n                        ++t;\n                    }\n                }\n                acts[id] = ac;\n                actionSum[id] = s;\n                ++id;\n            }\n        }\n    }\n    acts[ACTIONS] = Action{}; // NOOP\n\n    for (int i = 0; i < ACTIONS; ++i) sumOrder[i] = i;\n    sort(sumOrder.begin(), sumOrder.end(), [&](int x, int y) {\n        if (actionSum[x] != actionSum[y]) return actionSum[x] > actionSum[y];\n        return x < y;\n    });\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            initBoard[i * W + j] = a[i][j];\n        }\n    }\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::steady_clock::now();\n    auto deadline = start + chrono::milliseconds(1700);\n\n    vector<Result> elite;\n    elite.reserve(4);\n\n    // Initial diverse candidates.\n    vector<Result> init;\n    init.reserve(5);\n    init.push_back(make_empty());\n    init.push_back(construct_greedy(false, false, rng)); // always fill greedily\n    init.push_back(construct_greedy(true, false, rng));  // stop when non-positive\n    init.push_back(construct_beam(false, rng));\n    init.push_back(construct_beam(true, rng));\n\n    for (auto& r : init) {\n        pool_improve(r, 1, rng);\n    }\n    sort(init.begin(), init.end(), [](const Result& a, const Result& b) {\n        if (a.score != b.score) return a.score > b.score;\n        return a.seq < b.seq;\n    });\n    for (int i = 0; i < min<int>(4, init.size()); ++i) elite.push_back(init[i]);\n\n    if (!elite.empty()) {\n        exact_improve(elite[0], 1, rng);\n        pool_improve(elite[0], 1, rng);\n    }\n\n    Result best = elite[0];\n    for (auto& r : elite) if (r.score > best.score) best = r;\n\n    // Main search loop: ruin-and-fill + local polishing.\n    while (chrono::steady_clock::now() < deadline) {\n        int src = choose_elite(elite, rng);\n        bool randomized = (rng() & 1ULL);\n\n        Result cand = ruin_and_fill(elite[src], randomized, rng);\n\n        if (cand.score > best.score) {\n            best = cand;\n            exact_improve(best, 1, rng);\n            pool_improve(best, 1, rng);\n            insert_elite(elite, best, 4);\n        } else {\n            insert_elite(elite, cand, 4);\n        }\n\n        if ((rng() & 7ULL) == 0 && !elite.empty()) {\n            Result tmp = construct_beam(true, rng);\n            pool_improve(tmp, 1, rng);\n            insert_elite(elite, tmp, 4);\n            if (tmp.score > best.score) best = tmp;\n        }\n    }\n\n    // Final polish on the best solution.\n    exact_improve(best, 1, rng);\n    pool_improve(best, 1, rng);\n    exact_improve(best, 1, rng);\n\n    vector<tuple<int, int, int>> ans;\n    ans.reserve(KMAX);\n    for (int i = 0; i < KMAX; ++i) {\n        int aid = best.seq[i];\n        if (aid == NOOP) continue;\n        ans.emplace_back(acts[aid].m, acts[aid].p, acts[aid].q);\n    }\n\n    cout << ans.size() << '\\n';\n    for (auto [m, p, q] : ans) {\n        cout << m << ' ' << p << ' ' << q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int FULL_MASK = (1 << N) - 1;\nstatic constexpr int BEAM = 8000; // enough for strong search, still fast\n\nstruct Node {\n    array<uint8_t, N> p{};      // next unread index in each source row\n    array<uint8_t, N> mask{};   // dispatched ranks for each gate (bitmask of ranks 0..4)\n    uint8_t curRow = 0;         // current crane row (if start==false, crane is at (curRow, 4))\n    bool start = true;          // true only at the beginning\n    int turns = 0;             // M0 so far\n    int inv = 0;               // M1 so far\n    int lb = 0;                // optimistic lower bound of remaining inversions\n    int parent = -1;           // parent node index in global pool\n    int choice = -1;           // chosen source row at this step\n    int eval = 0;              // turns + 100*(inv + lb)\n};\n\nstatic inline uint64_t packKey(const Node& s) {\n    // bits:\n    // 0..2   : curRow\n    // 3..27  : mask[0..4] (5 bits each)\n    // 28..42 : p[0..4] (3 bits each)\n    // 43     : start\n    uint64_t k = 0;\n    k |= uint64_t(s.curRow);\n    for (int i = 0; i < N; ++i) {\n        k |= uint64_t(s.mask[i]) << (3 + 5 * i);\n        k |= uint64_t(s.p[i]) << (28 + 3 * i);\n    }\n    if (s.start) k |= 1ULL << 43;\n    return k;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inN;\n    cin >> inN; // fixed to 5\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> A[i][j];\n    }\n\n    // rankOf[v] = local rank 0..4 inside its destination gate\n    array<int, 25> rankOf{};\n    array<vector<int>, N> gateVals;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            gateVals[A[i][j] / N].push_back(A[i][j]);\n        }\n    }\n    for (int g = 0; g < N; ++g) {\n        sort(gateVals[g].begin(), gateVals[g].end());\n        for (int r = 0; r < N; ++r) rankOf[gateVals[g][r]] = r;\n    }\n\n    // addInv[mask][r] = number of already-dispatched ranks in mask that are > r\n    int addInv[32][N]{};\n    // forcedLB[mask] = lower bound of future inversions caused by already-dispatched\n    // higher ranks and still-undispatched lower ranks.\n    int forcedLB[32]{};\n\n    for (int mask = 0; mask < 32; ++mask) {\n        for (int r = 0; r < N; ++r) {\n            addInv[mask][r] = __builtin_popcount((unsigned)(mask >> (r + 1)));\n        }\n        int lb = 0;\n        for (int hi = 0; hi < N; ++hi) if (mask & (1 << hi)) {\n            lb += __builtin_popcount((unsigned)((FULL_MASK ^ mask) & ((1 << hi) - 1)));\n        }\n        forcedLB[mask] = lb;\n    }\n\n    // Exact move cost for one chosen container:\n    // start == true  : current crane is at (0,0)\n    // start == false : current crane is at (curRow, 4)\n    int costStart[N][N];\n    int costMid[N][N][N];\n    for (int r = 0; r < N; ++r) {\n        for (int g = 0; g < N; ++g) {\n            // from (0,0) to (r,0), pick, to (g,4), release\n            costStart[r][g] = r + abs(r - g) + 6; // moves + P + Q\n        }\n    }\n    for (int c = 0; c < N; ++c) {\n        for (int r = 0; r < N; ++r) {\n            for (int g = 0; g < N; ++g) {\n                // from (c,4) to (r,0), pick, to (g,4), release\n                costMid[c][r][g] = abs(c - r) + abs(r - g) + 10;\n            }\n        }\n    }\n\n    vector<Node> pool;\n    pool.reserve(200000);\n\n    Node root;\n    root.start = true;\n    root.curRow = 0;\n    root.turns = 0;\n    root.inv = 0;\n    root.lb = 0;\n    root.eval = 0;\n    pool.push_back(root);\n\n    vector<int> layer = {0};\n\n    for (int step = 0; step < N * N; ++step) {\n        unordered_map<uint64_t, int> pos;\n        pos.reserve(layer.size() * N * 2);\n        pos.max_load_factor(0.7f);\n\n        vector<Node> nxt;\n        nxt.reserve(layer.size() * N);\n\n        for (int gid : layer) {\n            const Node& s = pool[gid];\n            for (int r = 0; r < N; ++r) {\n                if (s.p[r] >= N) continue;\n\n                int v = A[r][s.p[r]];\n                int g = v / N;\n                int rk = rankOf[v];\n\n                Node t = s;\n                t.p[r]++;\n\n                int oldMask = t.mask[g];\n                int newMask = oldMask | (1 << rk);\n\n                t.mask[g] = (uint8_t)newMask;\n                t.inv += addInv[oldMask][rk];\n                t.lb += forcedLB[newMask] - forcedLB[oldMask];\n\n                if (s.start) t.turns += costStart[r][g];\n                else t.turns += costMid[s.curRow][r][g];\n\n                t.curRow = (uint8_t)g;\n                t.start = false;\n                t.parent = gid;\n                t.choice = r;\n                t.eval = t.turns + 100 * (t.inv + t.lb);\n\n                uint64_t key = packKey(t);\n                auto it = pos.find(key);\n                int exact = t.turns + 100 * t.inv;\n\n                if (it == pos.end()) {\n                    pos[key] = (int)nxt.size();\n                    nxt.push_back(t);\n                } else {\n                    Node& u = nxt[it->second];\n                    int exactU = u.turns + 100 * u.inv;\n                    if (exact < exactU) {\n                        u = t;\n                    }\n                }\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        vector<int> ord(nxt.size());\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (nxt[a].eval != nxt[b].eval) return nxt[a].eval < nxt[b].eval;\n            int ea = nxt[a].turns + 100 * nxt[a].inv;\n            int eb = nxt[b].turns + 100 * nxt[b].inv;\n            if (ea != eb) return ea < eb;\n            if (nxt[a].turns != nxt[b].turns) return nxt[a].turns < nxt[b].turns;\n            if (nxt[a].inv != nxt[b].inv) return nxt[a].inv < nxt[b].inv;\n            return nxt[a].lb < nxt[b].lb;\n        });\n\n        if ((int)ord.size() > BEAM) ord.resize(BEAM);\n\n        vector<int> newLayer;\n        newLayer.reserve(ord.size());\n        for (int idx : ord) {\n            pool.push_back(nxt[idx]);\n            newLayer.push_back((int)pool.size() - 1);\n        }\n        layer.swap(newLayer);\n    }\n\n    // Pick the best final node.\n    int bestId = layer[0];\n    int bestScore = pool[bestId].turns + 100 * pool[bestId].inv;\n    for (int id : layer) {\n        int sc = pool[id].turns + 100 * pool[id].inv;\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestId = id;\n        }\n    }\n\n    // Reconstruct chosen source-row sequence.\n    vector<int> order;\n    for (int id = bestId; pool[id].parent != -1; id = pool[id].parent) {\n        order.push_back(pool[id].choice);\n    }\n    reverse(order.begin(), order.end());\n\n    // Emit the operations for the large crane.\n    string big;\n    big.reserve(10000);\n\n    int x = 0, y = 0; // large crane position; starts at (0,0)\n    array<int, N> ptr{};\n    ptr.fill(0);\n\n    auto move_to = [&](int nx, int ny) {\n        while (x < nx) { big.push_back('D'); ++x; }\n        while (x > nx) { big.push_back('U'); --x; }\n        while (y < ny) { big.push_back('R'); ++y; }\n        while (y > ny) { big.push_back('L'); --y; }\n    };\n\n    for (int r : order) {\n        int v = A[r][ptr[r]++];\n        int g = v / N;\n\n        // go to source gate (r,0)\n        move_to(r, 0);\n        big.push_back('P');\n\n        // go to destination gate (g,4)\n        move_to(g, N - 1);\n        big.push_back('Q');\n    }\n\n    int T = (int)big.size();\n    vector<string> ans(N, string(T, '.'));\n\n    // Large crane\n    ans[0] = big;\n\n    // Bomb the 4 small cranes on turn 1, then they do nothing.\n    for (int i = 1; i < N; ++i) ans[i][0] = 'B';\n\n    for (int i = 0; i < N; ++i) {\n        cout << ans[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct P {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> H(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> H[i][j];\n    }\n\n    auto gen_base_cycle = [&](int N) {\n        vector<P> seq;\n        seq.reserve(N * N);\n        seq.push_back({0, 0});\n        for (int y = 1; y < N; ++y) seq.push_back({0, y});\n\n        for (int x = 1; x <= N - 2; ++x) {\n            if (x % 2 == 1) {\n                for (int y = N - 1; y >= 1; --y) seq.push_back({x, y});\n            } else {\n                for (int y = 1; y <= N - 1; ++y) seq.push_back({x, y});\n            }\n        }\n\n        for (int y = N - 1; y >= 0; --y) seq.push_back({N - 1, y});\n        for (int x = N - 2; x >= 1; --x) seq.push_back({x, 0});\n        return seq;\n    };\n\n    auto transform = [&](const P& p, int t) -> P {\n        int x = p.x, y = p.y;\n        switch (t) {\n            case 0: return {x, y};\n            case 1: return {x, N - 1 - y};\n            case 2: return {N - 1 - x, y};\n            case 3: return {N - 1 - x, N - 1 - y};\n            case 4: return {y, x};\n            case 5: return {y, N - 1 - x};\n            case 6: return {N - 1 - y, x};\n            case 7: return {N - 1 - y, N - 1 - x};\n        }\n        return {x, y};\n    };\n\n    vector<P> base = gen_base_cycle(N);\n\n    ll bestCost = (1LL << 60);\n    vector<P> bestSeq;\n    int bestStart = 0;\n\n    auto eval_candidate = [&](vector<P> seq) {\n        int L = (int)seq.size();\n        vector<ll> pref(L + 1, 0);\n        for (int i = 0; i < L; ++i) {\n            pref[i + 1] = pref[i] + H[seq[i].x][seq[i].y];\n        }\n\n        ll mn = pref[0];\n        for (int i = 1; i < L; ++i) mn = min(mn, pref[i]);\n\n        for (int s = 0; s < L; ++s) {\n            if (pref[s] != mn) continue; // valid rotation start\n\n            ll cost = 100LL * (seq[s].x + seq[s].y); // empty move to the start cell\n            ll cur = 0;\n            for (int k = 0; k < L; ++k) {\n                const P& p = seq[(s + k) % L];\n                cur += H[p.x][p.y];\n                if (k + 1 < L) cost += 100 + cur; // move to next cell\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSeq = seq;\n                bestStart = s;\n            }\n        }\n    };\n\n    for (int t = 0; t < 8; ++t) {\n        vector<P> seq;\n        seq.reserve(base.size());\n        for (const auto& p : base) seq.push_back(transform(p, t));\n\n        eval_candidate(seq);\n        reverse(seq.begin(), seq.end());\n        eval_candidate(seq);\n    }\n\n    // Output operations\n    vector<string> ops;\n    ops.reserve(1000);\n\n    auto add_op = [&](const string& s) {\n        ops.push_back(s);\n    };\n\n    // Move empty from (0,0) to the chosen start cell\n    int cx = 0, cy = 0;\n    P startP = bestSeq[bestStart];\n    while (cx < startP.x) {\n        add_op(\"D\");\n        ++cx;\n    }\n    while (cx > startP.x) {\n        add_op(\"U\");\n        --cx;\n    }\n    while (cy < startP.y) {\n        add_op(\"R\");\n        ++cy;\n    }\n    while (cy > startP.y) {\n        add_op(\"L\");\n        --cy;\n    }\n\n    int L = (int)bestSeq.size();\n    for (int step = 0; step < L; ++step) {\n        int idx = (bestStart + step) % L;\n        P p = bestSeq[idx];\n        int h = H[p.x][p.y];\n        if (h > 0) {\n            add_op(\"+\" + to_string(h));\n        } else if (h < 0) {\n            add_op(\"-\" + to_string(-h));\n        }\n\n        if (step + 1 < L) {\n            P q = bestSeq[(bestStart + step + 1) % L];\n            if (q.x == p.x + 1 && q.y == p.y) add_op(\"D\");\n            else if (q.x == p.x - 1 && q.y == p.y) add_op(\"U\");\n            else if (q.x == p.x && q.y == p.y + 1) add_op(\"R\");\n            else if (q.x == p.x && q.y == p.y - 1) add_op(\"L\");\n            else {\n                // Should never happen for our Hamiltonian cycle.\n                // If it does, the output would be invalid, so keep a safe fallback.\n                // But in practice, this branch is unreachable.\n            }\n        }\n    }\n\n    for (const auto& s : ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXM = 15;\nstatic constexpr int MAXS = 60;\nstatic constexpr int MAXP = 36;\nstatic constexpr int MAXV = 100;\n\nstruct Seed {\n    array<int, MAXM> x{};\n    int sum = 0;\n};\n\nstruct SelState {\n    vector<int> sel;\n    array<array<int, MAXV + 1>, MAXM> cnt{};\n    array<int, MAXM> mx{};\n    array<int, MAXM> sec{};\n    array<int, MAXM> cntMx{};\n    array<long long, MAXS> rowSum{};\n    long long pairSum = 0;\n    long long cov = 0;        // sum of best values\n    long long traitScore = 0; // 2*best + second, summed over traits\n    long long sumSel = 0;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int S = 2 * N * (N - 1); // 60\n    const int P = N * N;           // 36\n\n    vector<Seed> seeds(S);\n\n    auto read_pool = [&]() {\n        for (int i = 0; i < S; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    };\n\n    read_pool();\n\n    vector<pair<int, int>> edges;\n    vector<vector<int>> cellNbs(P);\n    vector<int> cellDeg(P), cellDist(P);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            int deg = 0;\n            if (i > 0) deg++;\n            if (i + 1 < N) deg++;\n            if (j > 0) deg++;\n            if (j + 1 < N) deg++;\n            cellDeg[id] = deg;\n            cellDist[id] = abs(2 * i - (N - 1)) + abs(2 * j - (N - 1));\n\n            if (i + 1 < N) {\n                int to = (i + 1) * N + j;\n                edges.push_back({id, to});\n                cellNbs[id].push_back(to);\n                cellNbs[to].push_back(id);\n            }\n            if (j + 1 < N) {\n                int to = i * N + (j + 1);\n                edges.push_back({id, to});\n                cellNbs[id].push_back(to);\n                cellNbs[to].push_back(id);\n            }\n        }\n    }\n\n    vector<int> posDeg, posCenter, posSnake;\n    {\n        vector<tuple<int, int, int>> a, b;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int id = i * N + j;\n                a.emplace_back(-cellDeg[id], cellDist[id], id);\n                b.emplace_back(cellDist[id], -cellDeg[id], id);\n            }\n        }\n        sort(a.begin(), a.end());\n        sort(b.begin(), b.end());\n        for (auto &t : a) posDeg.push_back(get<2>(t));\n        for (auto &t : b) posCenter.push_back(get<2>(t));\n\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; j++) posSnake.push_back(i * N + j);\n            } else {\n                for (int j = N - 1; j >= 0; j--) posSnake.push_back(i * N + j);\n            }\n        }\n    }\n\n    mt19937 rng(712367821);\n\n    auto traitScoreNow = [&](const SelState& st) -> long long {\n        long long res = 0;\n        for (int l = 0; l < M; l++) {\n            int best = 0, second = 0;\n            bool gotFirst = false;\n            for (int v = MAXV; v >= 0; v--) {\n                int c = st.cnt[l][v];\n                if (!c) continue;\n                if (!gotFirst) {\n                    best = v;\n                    gotFirst = true;\n                    if (c >= 2) {\n                        second = v;\n                        break;\n                    }\n                } else {\n                    second = v;\n                    break;\n                }\n            }\n            res += 2LL * best + second;\n        }\n        return res;\n    };\n\n    auto traitScoreAfter = [&](const SelState& st, int oldId, int newId) -> long long {\n        long long res = 0;\n        for (int l = 0; l < M; l++) {\n            int best = 0, second = 0;\n            bool gotFirst = false;\n            for (int v = MAXV; v >= 0; v--) {\n                int c = st.cnt[l][v];\n                if (v == seeds[oldId].x[l]) c--;\n                if (v == seeds[newId].x[l]) c++;\n                if (c <= 0) continue;\n                if (!gotFirst) {\n                    best = v;\n                    gotFirst = true;\n                    if (c >= 2) {\n                        second = v;\n                        break;\n                    }\n                } else {\n                    second = v;\n                    break;\n                }\n            }\n            res += 2LL * best + second;\n        }\n        return res;\n    };\n\n    auto recalc_traits = [&](SelState& st) {\n        st.cov = 0;\n        st.traitScore = 0;\n        for (int l = 0; l < M; l++) {\n            int best = 0, second = 0;\n            bool gotFirst = false;\n            int bestCnt = 0;\n            for (int v = MAXV; v >= 0; v--) {\n                int c = st.cnt[l][v];\n                if (c == 0) continue;\n                if (!gotFirst) {\n                    best = v;\n                    bestCnt = c;\n                    gotFirst = true;\n                    if (c >= 2) {\n                        second = v;\n                        break;\n                    }\n                } else {\n                    second = v;\n                    break;\n                }\n            }\n            st.mx[l] = best;\n            st.sec[l] = second;\n            st.cntMx[l] = bestCnt;\n            st.cov += best;\n            st.traitScore += 2LL * best + second;\n        }\n    };\n\n    auto build_state = [&](const vector<int>& sel,\n                           const array<array<long long, MAXS>, MAXS>& U) {\n        SelState st;\n        st.sel = sel;\n        st.rowSum.fill(0);\n        st.pairSum = 0;\n        st.sumSel = 0;\n\n        for (int l = 0; l < M; l++) {\n            for (int v = 0; v <= MAXV; v++) st.cnt[l][v] = 0;\n        }\n\n        for (int id : sel) {\n            st.sumSel += seeds[id].sum;\n            for (int l = 0; l < M; l++) st.cnt[l][seeds[id].x[l]]++;\n        }\n\n        for (int x = 0; x < S; x++) {\n            long long s = 0;\n            for (int id : sel) s += U[x][id];\n            st.rowSum[x] = s;\n        }\n\n        for (int i = 0; i < P; i++) {\n            for (int j = i + 1; j < P; j++) {\n                st.pairSum += U[sel[i]][sel[j]];\n            }\n        }\n\n        recalc_traits(st);\n        return st;\n    };\n\n    auto refine_selection = [&](SelState st,\n                                const array<array<long long, MAXS>, MAXS>& U,\n                                long long betaCov) {\n        for (int pass = 0; pass < 2; pass++) {\n            vector<char> inSel(S, 0);\n            for (int id : st.sel) inSel[id] = 1;\n\n            vector<pair<long long, int>> candScore;\n            candScore.reserve(S);\n\n            for (int x = 0; x < S; x++) if (!inSel[x]) {\n                long long gain = 0;\n                for (int l = 0; l < M; l++) {\n                    gain += max(0, seeds[x].x[l] - st.mx[l]);\n                }\n                long long approx = st.rowSum[x] + 25LL * gain + seeds[x].sum;\n                candScore.push_back({approx, x});\n            }\n\n            sort(candScore.begin(), candScore.end(), [&](const auto& a, const auto& b) {\n                if (a.first != b.first) return a.first > b.first;\n                return a.second < b.second;\n            });\n\n            vector<int> shortlist;\n            vector<char> used(S, 0);\n            for (int i = 0; i < (int)candScore.size() && i < 10; i++) {\n                shortlist.push_back(candScore[i].second);\n                used[candScore[i].second] = 1;\n            }\n\n            // Add a few globally strong seeds to stabilize the search.\n            vector<int> globalOrd(S);\n            iota(globalOrd.begin(), globalOrd.end(), 0);\n            sort(globalOrd.begin(), globalOrd.end(), [&](int a, int b) {\n                if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n                return a < b;\n            });\n            for (int i = 0; i < S && (int)shortlist.size() < 14; i++) {\n                int id = globalOrd[i];\n                if (!inSel[id] && !used[id]) {\n                    used[id] = 1;\n                    shortlist.push_back(id);\n                }\n            }\n\n            long long bestDelta = 0;\n            long long bestPairDelta = 0;\n            int bestPos = -1, bestCand = -1;\n            long long bestTraitNew = st.traitScore;\n\n            for (int pos = 0; pos < P; pos++) {\n                int old = st.sel[pos];\n                for (int cand : shortlist) {\n                    if (cand == old) continue;\n\n                    long long dPair = st.rowSum[cand] - U[cand][old] - st.rowSum[old];\n                    long long newTrait = traitScoreAfter(st, old, cand);\n                    long long dTrait = newTrait - st.traitScore;\n                    long long dSum = (seeds[cand].sum - seeds[old].sum) / 5;\n                    long long d = dPair + betaCov * dTrait + dSum;\n\n                    if (d > bestDelta) {\n                        bestDelta = d;\n                        bestPairDelta = dPair;\n                        bestPos = pos;\n                        bestCand = cand;\n                        bestTraitNew = newTrait;\n                    }\n                }\n            }\n\n            if (bestDelta <= 0) break;\n\n            int old = st.sel[bestPos];\n            st.sel[bestPos] = bestCand;\n\n            st.pairSum += bestPairDelta;\n            st.sumSel += seeds[bestCand].sum - seeds[old].sum;\n\n            for (int x = 0; x < S; x++) {\n                st.rowSum[x] += U[x][bestCand] - U[x][old];\n            }\n\n            for (int l = 0; l < M; l++) {\n                st.cnt[l][seeds[old].x[l]]--;\n                st.cnt[l][seeds[bestCand].x[l]]++;\n            }\n\n            st.traitScore = bestTraitNew;\n            recalc_traits(st);\n        }\n\n        return st;\n    };\n\n    auto score_arr = [&](const vector<int>& perm,\n                         const auto& Usel) -> long long {\n        long long sc = 0;\n        for (auto [u, v] : edges) {\n            sc += Usel[perm[u]][perm[v]];\n        }\n        return sc;\n    };\n\n    auto delta_swap = [&](const vector<int>& perm, int a, int b,\n                          const auto& Usel) -> long long {\n        int sa = perm[a];\n        int sb = perm[b];\n        long long d = 0;\n\n        for (int na : cellNbs[a]) {\n            if (na == b) continue;\n            d += Usel[sb][perm[na]] - Usel[sa][perm[na]];\n        }\n        for (int nb : cellNbs[b]) {\n            if (nb == a) continue;\n            d += Usel[sa][perm[nb]] - Usel[sb][perm[nb]];\n        }\n        return d;\n    };\n\n    auto refine_arrangement = [&](vector<int> perm, const auto& Usel) {\n        long long cur = score_arr(perm, Usel);\n        for (int pass = 0; pass < 2; pass++) {\n            long long bestDelta = 0;\n            int bi = -1, bj = -1;\n            for (int a = 0; a < P; a++) {\n                for (int b = a + 1; b < P; b++) {\n                    long long d = delta_swap(perm, a, b, Usel);\n                    if (d > bestDelta) {\n                        bestDelta = d;\n                        bi = a;\n                        bj = b;\n                    }\n                }\n            }\n            if (bestDelta <= 0) break;\n            swap(perm[bi], perm[bj]);\n            cur += bestDelta;\n        }\n        return pair<long long, vector<int>>(cur, perm);\n    };\n\n    auto make_perm = [&](const vector<int>& order, const vector<int>& cellOrder) {\n        vector<int> perm(P, -1);\n        for (int i = 0; i < P; i++) perm[cellOrder[i]] = order[i];\n        return perm;\n    };\n\n    auto build_conn_order = [&](const vector<long long>& localConn,\n                                const vector<int>& localSum) {\n        vector<int> ord(P);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (localConn[a] != localConn[b]) return localConn[a] > localConn[b];\n            if (localSum[a] != localSum[b]) return localSum[a] > localSum[b];\n            return a < b;\n        });\n        return ord;\n    };\n\n    auto build_snake_order = [&](const auto& Usel,\n                                 const vector<long long>& localConn,\n                                 const vector<int>& localSum) {\n        vector<int> ord;\n        vector<char> used(P, 0);\n\n        int start = 0;\n        for (int i = 1; i < P; i++) {\n            if (localConn[i] > localConn[start] ||\n                (localConn[i] == localConn[start] && localSum[i] > localSum[start])) {\n                start = i;\n            }\n        }\n\n        ord.push_back(start);\n        used[start] = 1;\n\n        while ((int)ord.size() < P) {\n            int last = ord.back();\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < P; i++) if (!used[i]) {\n                long long sc = Usel[last][i] + localConn[i] + localSum[i];\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            used[best] = 1;\n            ord.push_back(best);\n        }\n        return ord;\n    };\n\n    auto build_star_order = [&](const auto& Usel,\n                                const vector<long long>& localConn,\n                                const vector<int>& localSum) {\n        vector<int> ord;\n        vector<char> used(P, 0);\n\n        int root = 0;\n        for (int i = 1; i < P; i++) {\n            if (localConn[i] > localConn[root] ||\n                (localConn[i] == localConn[root] && localSum[i] > localSum[root])) {\n                root = i;\n            }\n        }\n\n        ord.push_back(root);\n        used[root] = 1;\n\n        for (int t = 0; t < 4; t++) {\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < P; i++) if (!used[i]) {\n                long long sc = 3LL * Usel[root][i] + localConn[i] + localSum[i];\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            used[best] = 1;\n            ord.push_back(best);\n        }\n\n        while ((int)ord.size() < P) {\n            int last = ord.back();\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < P; i++) if (!used[i]) {\n                long long sc = Usel[last][i] + localConn[i];\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            used[best] = 1;\n            ord.push_back(best);\n        }\n\n        return ord;\n    };\n\n    auto build_grow_perm = [&](const auto& Usel,\n                               const vector<long long>& localConn,\n                               const vector<int>& localSum) {\n        vector<int> perm(P, -1);\n        vector<char> filled(P, 0), usedSeed(P, 0);\n\n        vector<pair<int, int>> centerPairs = {\n            {14, 15}, {20, 21}, {14, 20}, {15, 21}\n        };\n\n        int bestA = 0, bestB = 1;\n        int bestPos1 = 14, bestPos2 = 15;\n        long long bestSc = -(1LL << 60);\n\n        for (auto [c1, c2] : centerPairs) {\n            for (int i = 0; i < P; i++) {\n                for (int j = i + 1; j < P; j++) {\n                    long long sc = Usel[i][j] + localConn[i] + localConn[j];\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        bestA = i;\n                        bestB = j;\n                        bestPos1 = c1;\n                        bestPos2 = c2;\n                    }\n                }\n            }\n        }\n\n        perm[bestPos1] = bestA;\n        perm[bestPos2] = bestB;\n        filled[bestPos1] = filled[bestPos2] = 1;\n        usedSeed[bestA] = usedSeed[bestB] = 1;\n\n        int placed = 2;\n        while (placed < P) {\n            int bestCell = -1, bestAdj = -1;\n            for (int c = 0; c < P; c++) if (!filled[c]) {\n                int adj = 0;\n                for (int nb : cellNbs[c]) if (filled[nb]) adj++;\n                if (bestCell == -1 ||\n                    adj > bestAdj ||\n                    (adj == bestAdj && cellDeg[c] > cellDeg[bestCell]) ||\n                    (adj == bestAdj && cellDeg[c] == cellDeg[bestCell] && cellDist[c] < cellDist[bestCell])) {\n                    bestCell = c;\n                    bestAdj = adj;\n                }\n            }\n\n            int bestSeed = -1;\n            long long bestVal = -(1LL << 60);\n            for (int s = 0; s < P; s++) if (!usedSeed[s]) {\n                long long adjScore = 0;\n                for (int nb : cellNbs[bestCell]) if (filled[nb]) {\n                    adjScore += Usel[s][perm[nb]];\n                }\n                long long sc = 20LL * adjScore + localConn[s] + localSum[s];\n                if (sc > bestVal) {\n                    bestVal = sc;\n                    bestSeed = s;\n                }\n            }\n\n            perm[bestCell] = bestSeed;\n            filled[bestCell] = 1;\n            usedSeed[bestSeed] = 1;\n            placed++;\n        }\n\n        return perm;\n    };\n\n    auto build_star_candidate = [&](int root,\n                                    const array<array<long long, MAXS>, MAXS>& U) {\n        vector<int> cand;\n        vector<char> used(S, 0);\n        cand.push_back(root);\n        used[root] = 1;\n\n        array<int, MAXM> curMx{};\n        curMx.fill(0);\n        for (int l = 0; l < M; l++) curMx[l] = seeds[root].x[l];\n\n        // Add a few seeds that complement the root well.\n        for (int step = 0; step < 4; step++) {\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < S; i++) if (!used[i]) {\n                long long gain = 0;\n                for (int l = 0; l < M; l++) gain += max(0, seeds[i].x[l] - curMx[l]);\n                long long sc = 3LL * U[root][i] + 20LL * gain + seeds[i].sum;\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            used[best] = 1;\n            cand.push_back(best);\n            for (int l = 0; l < M; l++) curMx[l] = max(curMx[l], seeds[best].x[l]);\n        }\n\n        while ((int)cand.size() < P) {\n            int best = -1;\n            long long bestSc = -(1LL << 60);\n            for (int i = 0; i < S; i++) if (!used[i]) {\n                long long pairSum = 0;\n                for (int j : cand) pairSum += U[i][j];\n                long long gain = 0;\n                for (int l = 0; l < M; l++) gain += max(0, seeds[i].x[l] - curMx[l]);\n                long long sc = pairSum / (long long)cand.size() + 20LL * gain + seeds[i].sum / 4;\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n            used[best] = 1;\n            cand.push_back(best);\n            for (int l = 0; l < M; l++) curMx[l] = max(curMx[l], seeds[best].x[l]);\n        }\n\n        return cand;\n    };\n\n    auto best_pair_value = [&](const vector<int>& sel, const array<array<long long, MAXS>, MAXS>& U) {\n        long long best = 0;\n        for (int i = 0; i < P; i++) {\n            for (int j = i + 1; j < P; j++) {\n                best = max(best, U[sel[i]][sel[j]]);\n            }\n        }\n        return best;\n    };\n\n    for (int turn = 0; turn < T; turn++) {\n        if (turn > 0) read_pool();\n\n        // Pairwise union table for the current pool.\n        array<array<long long, MAXS>, MAXS> U{};\n        vector<long long> conn(S, 0), bestPairSeed(S, 0), baseScore(S, 0), peakScore(S, 0);\n\n        for (int i = 0; i < S; i++) {\n            for (int j = i + 1; j < S; j++) {\n                long long w = 0;\n                for (int l = 0; l < M; l++) {\n                    w += max(seeds[i].x[l], seeds[j].x[l]);\n                }\n                U[i][j] = U[j][i] = w;\n                conn[i] += w;\n                conn[j] += w;\n                bestPairSeed[i] = max(bestPairSeed[i], w);\n                bestPairSeed[j] = max(bestPairSeed[j], w);\n            }\n        }\n\n        for (int i = 0; i < S; i++) {\n            baseScore[i] = conn[i] + 10LL * seeds[i].sum;\n            peakScore[i] = baseScore[i] + bestPairSeed[i];\n        }\n\n        vector<int> ordBase(S), ordPeak(S);\n        iota(ordBase.begin(), ordBase.end(), 0);\n        iota(ordPeak.begin(), ordPeak.end(), 0);\n\n        sort(ordBase.begin(), ordBase.end(), [&](int a, int b) {\n            if (baseScore[a] != baseScore[b]) return baseScore[a] > baseScore[b];\n            return a < b;\n        });\n        sort(ordPeak.begin(), ordPeak.end(), [&](int a, int b) {\n            if (peakScore[a] != peakScore[b]) return peakScore[a] > peakScore[b];\n            return a < b;\n        });\n\n        vector<vector<int>> candidates;\n\n        // 1) Strong overall connectivity\n        candidates.push_back(vector<int>(ordBase.begin(), ordBase.begin() + P));\n\n        // 2) Coverage greedy\n        {\n            vector<int> cand;\n            vector<char> used(S, 0);\n            array<int, MAXM> curMx{};\n            curMx.fill(0);\n            array<long long, MAXS> attach{};\n            attach.fill(0);\n\n            for (int step = 0; step < P; step++) {\n                int best = -1;\n                long long bestSc = -(1LL << 60);\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    long long gain = 0;\n                    for (int l = 0; l < M; l++) gain += max(0, seeds[i].x[l] - curMx[l]);\n                    long long sc = 25LL * gain + attach[i] / 3 + seeds[i].sum;\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n                used[best] = 1;\n                cand.push_back(best);\n                for (int x = 0; x < S; x++) attach[x] += U[x][best];\n                for (int l = 0; l < M; l++) curMx[l] = max(curMx[l], seeds[best].x[l]);\n            }\n            candidates.push_back(cand);\n        }\n\n        // 3) Pair-greedy\n        {\n            int bi = 0, bj = 1;\n            long long best = -(1LL << 60);\n            for (int i = 0; i < S; i++) {\n                for (int j = i + 1; j < S; j++) {\n                    long long sc = U[i][j] + seeds[i].sum + seeds[j].sum;\n                    if (sc > best) {\n                        best = sc;\n                        bi = i;\n                        bj = j;\n                    }\n                }\n            }\n\n            vector<int> cand;\n            cand.push_back(bi);\n            cand.push_back(bj);\n            vector<char> used(S, 0);\n            used[bi] = used[bj] = 1;\n\n            array<int, MAXM> curMx{};\n            curMx.fill(0);\n            for (int l = 0; l < M; l++) curMx[l] = max(seeds[bi].x[l], seeds[bj].x[l]);\n\n            array<long long, MAXS> attach{};\n            for (int x = 0; x < S; x++) attach[x] = U[x][bi] + U[x][bj];\n\n            while ((int)cand.size() < P) {\n                int bestId = -1;\n                long long bestSc = -(1LL << 60);\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    long long gain = 0;\n                    for (int l = 0; l < M; l++) gain += max(0, seeds[i].x[l] - curMx[l]);\n                    long long sc = 25LL * gain + attach[i] / 3 + seeds[i].sum;\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        bestId = i;\n                    }\n                }\n                used[bestId] = 1;\n                cand.push_back(bestId);\n                for (int x = 0; x < S; x++) attach[x] += U[x][bestId];\n                for (int l = 0; l < M; l++) curMx[l] = max(curMx[l], seeds[bestId].x[l]);\n            }\n            candidates.push_back(cand);\n        }\n\n        // 4) Star around strong root\n        candidates.push_back(build_star_candidate(ordBase[0], U));\n\n        // 5) Trait-specialist mix\n        {\n            vector<int> bonus(S, 0);\n            for (int l = 0; l < M; l++) {\n                vector<int> ord(S);\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (seeds[a].x[l] != seeds[b].x[l]) return seeds[a].x[l] > seeds[b].x[l];\n                    if (peakScore[a] != peakScore[b]) return peakScore[a] > peakScore[b];\n                    return a < b;\n                });\n                for (int r = 0; r < 3; r++) bonus[ord[r]] += 3 - r;\n            }\n\n            vector<int> ord(S);\n            iota(ord.begin(), ord.end(), 0);\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                long long sa = 2000LL * bonus[a] + peakScore[a];\n                long long sb = 2000LL * bonus[b] + peakScore[b];\n                if (sa != sb) return sa > sb;\n                return a < b;\n            });\n\n            candidates.push_back(vector<int>(ord.begin(), ord.begin() + P));\n        }\n\n        // 6) Randomized subset from strong seeds\n        {\n            int K = min(50, S);\n            vector<int> tmp(ordPeak.begin(), ordPeak.begin() + K);\n            shuffle(tmp.begin(), tmp.end(), rng);\n            candidates.push_back(vector<int>(tmp.begin(), tmp.begin() + P));\n        }\n\n        double rem = (T <= 1 ? 0.0 : double(T - 1 - turn) / double(T - 1));\n        long long betaCov = 50 + (long long)llround(30.0 * rem); // early turns: more coverage\n\n        vector<int> bestSel, bestPerm;\n        long long bestFit = -(1LL << 60);\n\n        for (auto cand : candidates) {\n            SelState st = build_state(cand, U);\n            st = refine_selection(st, U, betaCov);\n\n            // Local matrix for selected seeds.\n            array<array<long long, MAXP>, MAXP> Usel{};\n            vector<long long> localConn(P, 0);\n            vector<int> localSum(P, 0);\n\n            for (int i = 0; i < P; i++) {\n                localSum[i] = seeds[st.sel[i]].sum;\n                for (int j = 0; j < P; j++) {\n                    Usel[i][j] = U[st.sel[i]][st.sel[j]];\n                    localConn[i] += Usel[i][j];\n                }\n            }\n\n            vector<int> orderConn = build_conn_order(localConn, localSum);\n            vector<int> orderSnake = build_snake_order(Usel, localConn, localSum);\n            vector<int> orderStar = build_star_order(Usel, localConn, localSum);\n            vector<int> orderRand = orderConn;\n            shuffle(orderRand.begin(), orderRand.end(), rng);\n\n            vector<vector<int>> starts;\n            starts.push_back(make_perm(orderConn, posDeg));\n            starts.push_back(make_perm(orderConn, posCenter));\n            starts.push_back(make_perm(orderSnake, posSnake));\n            starts.push_back(make_perm(orderStar, posCenter));\n            starts.push_back(build_grow_perm(Usel, localConn, localSum));\n\n            long long bestArrScore = -(1LL << 60);\n            vector<int> bestLocalPerm;\n\n            auto eval_arr = [&](const vector<int>& perm) {\n                long long sumEW = 0;\n                long long bestEdge = 0;\n                array<long long, 5> top{};\n                top.fill(0);\n\n                auto pushTop = [&](long long v) {\n                    if (v <= top[0]) return;\n                    top[0] = v;\n                    for (int i = 0; i < 4; i++) {\n                        if (top[i] > top[i + 1]) swap(top[i], top[i + 1]);\n                        else break;\n                    }\n                };\n\n                for (auto [u, v] : edges) {\n                    long long w = Usel[perm[u]][perm[v]];\n                    sumEW += w;\n                    bestEdge = max(bestEdge, w);\n                    pushTop(w);\n                }\n                long long top5 = 0;\n                for (long long x : top) top5 += x;\n                return tuple<long long, long long, long long>(sumEW, bestEdge, top5);\n            };\n\n            // Also try a random arrangement start.\n            {\n                vector<int> perm(P, -1);\n                for (int i = 0; i < P; i++) perm[posDeg[i]] = orderRand[i];\n                starts.push_back(perm);\n            }\n\n            for (auto perm : starts) {\n                auto [dummy, refined] = refine_arrangement(perm, Usel);\n                auto [sumEW, bestEdge, top5] = eval_arr(refined);\n\n                long long fit = sumEW\n                              + 8LL * bestEdge\n                              + 10LL * st.traitScore\n                              + st.pairSum / 10\n                              + 5LL * best_pair_value(st.sel, U)\n                              + st.sumSel / 20;\n\n                if (fit > bestArrScore) {\n                    bestArrScore = fit;\n                    bestLocalPerm = move(refined);\n                }\n            }\n\n            if (bestArrScore > bestFit) {\n                bestFit = bestArrScore;\n                bestSel = move(st.sel);\n                bestPerm = move(bestLocalPerm);\n            }\n        }\n\n        // Output the chosen grid.\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int pos = i * N + j;\n                int localIdx = bestPerm[pos];\n                int seedId = bestSel[localIdx];\n                cout << seedId << (j + 1 == N ? '\\n' : ' ');\n            }\n        }\n        cout.flush();\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Point {\n    int x, y;\n};\n\nstruct State {\n    int x, y, d; // 0=R, 1=D, 2=L, 3=U\n};\n\nstruct Job {\n    Point s, t;\n    vector<State> pickStates;\n    vector<State> dropStates;\n    int pairDist;\n    int srcRow, srcSnake, srcMorton;\n    int tgtRow, tgtSnake, tgtMorton;\n    int midSnake, midMorton;\n};\n\nstruct Plan {\n    ll cost = (1LL << 60);\n    Point startRoot{0, 0};\n    vector<int> ord, pickSel, dropSel;\n    int jobsId = -1;\n};\n\nstatic const int DX4[4] = {0, 1, 0, -1};\nstatic const int DY4[4] = {1, 0, -1, 0};\n\nint N, M, V;\nvector<string> S, T;\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\ninline int manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\ninline int manhattan(const Point& a, const Point& b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\ninline int orientDist(int a, int b) {\n    int cw = (b - a + 4) % 4;\n    int ccw = (a - b + 4) % 4;\n    return min(cw, ccw);\n}\ninline char orientChar(int a, int b) {\n    int cw = (b - a + 4) % 4;\n    int ccw = (a - b + 4) % 4;\n    return (cw <= ccw ? 'R' : 'L');\n}\ninline int turnCost(const State& a, const State& b) {\n    return max(1, max(manhattan(a.x, a.y, b.x, b.y), orientDist(a.d, b.d)));\n}\n\ninline int rowKey(const Point& p) {\n    return p.x * N + p.y;\n}\ninline int snakeKey(const Point& p) {\n    return p.x * N + ((p.x & 1) ? (N - 1 - p.y) : p.y);\n}\ninline int mortonKey(const Point& p) {\n    int r = 0;\n    for (int b = 0; b < 5; b++) {\n        r |= ((p.x >> b) & 1) << (2 * b);\n        r |= ((p.y >> b) & 1) << (2 * b + 1);\n    }\n    return r;\n}\ninline int diagKey(const Point& p) {\n    return (p.x + p.y) * N + p.x;\n}\ninline Point midPoint(const Job& j) {\n    return {(j.s.x + j.t.x) / 2, (j.s.y + j.t.y) / 2};\n}\n\nvector<State> makeStatesAtCell(const Point& c) {\n    vector<State> res;\n    for (int d = 0; d < 4; d++) {\n        int rx = c.x - DX4[d];\n        int ry = c.y - DY4[d];\n        if (inside(rx, ry)) res.push_back({rx, ry, d});\n    }\n    return res;\n}\n\nvoid fillJob(Job& j, const Point& s, const Point& t) {\n    j.s = s;\n    j.t = t;\n    j.pickStates = makeStatesAtCell(s);\n    j.dropStates = makeStatesAtCell(t);\n    j.pairDist = manhattan(s, t);\n\n    j.srcRow = rowKey(s);\n    j.srcSnake = snakeKey(s);\n    j.srcMorton = mortonKey(s);\n\n    j.tgtRow = rowKey(t);\n    j.tgtSnake = snakeKey(t);\n    j.tgtMorton = mortonKey(t);\n\n    Point m = midPoint(j);\n    j.midSnake = snakeKey(m);\n    j.midMorton = mortonKey(m);\n}\n\nvector<int> sortedIdxByKey(const vector<Point>& pts, int mode) {\n    vector<int> ord((int)pts.size());\n    iota(ord.begin(), ord.end(), 0);\n\n    auto key = [&](const Point& p) -> int {\n        if (mode == 0) return rowKey(p);\n        if (mode == 1) return snakeKey(p);\n        if (mode == 2) return mortonKey(p);\n        return diagKey(p);\n    };\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        int ka = key(pts[a]), kb = key(pts[b]);\n        if (ka != kb) return ka < kb;\n        if (pts[a].x != pts[b].x) return pts[a].x < pts[b].x;\n        return pts[a].y < pts[b].y;\n    });\n    return ord;\n}\n\nvector<int> hungarianAssign(const vector<vector<int>>& cost) {\n    int n = (int)cost.size();\n    if (n == 0) return {};\n    const int INF = 1e9;\n\n    vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n    for (int i = 1; i <= n; i++) {\n        p[0] = i;\n        int j0 = 0;\n        vector<int> minv(n + 1, INF);\n        vector<char> used(n + 1, 0);\n        do {\n            used[j0] = 1;\n            int i0 = p[j0], j1 = 0;\n            int delta = INF;\n            for (int j = 1; j <= n; j++) if (!used[j]) {\n                int cur = cost[i0 - 1][j - 1] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= n; j++) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n\n    vector<int> ans(n);\n    for (int j = 1; j <= n; j++) if (p[j] != 0) ans[p[j] - 1] = j - 1;\n    return ans;\n}\n\nvector<Job> buildJobsHungarian(const vector<Point>& src, const vector<Point>& tgt) {\n    int K = (int)src.size();\n    vector<vector<int>> cost(K, vector<int>(K));\n    for (int i = 0; i < K; i++) {\n        for (int j = 0; j < K; j++) cost[i][j] = manhattan(src[i], tgt[j]);\n    }\n    vector<int> assign = hungarianAssign(cost);\n\n    vector<Job> jobs(K);\n    for (int i = 0; i < K; i++) fillJob(jobs[i], src[i], tgt[assign[i]]);\n    return jobs;\n}\n\nvector<Job> buildJobsShifted(const vector<Point>& src, const vector<Point>& tgt, int mode, int shift, bool reverseTgt) {\n    int K = (int)src.size();\n    vector<int> is = sortedIdxByKey(src, mode);\n    vector<int> it = sortedIdxByKey(tgt, mode);\n    if (reverseTgt) reverse(it.begin(), it.end());\n    if (K > 0) {\n        shift %= K;\n        if (shift < 0) shift += K;\n    }\n\n    vector<Job> jobs(K);\n    for (int i = 0; i < K; i++) {\n        int tj = it[(i + shift) % K];\n        fillJob(jobs[i], src[is[i]], tgt[tj]);\n    }\n    return jobs;\n}\n\nint jobKey(const Job& j, int mode) {\n    switch (mode) {\n        case 0: return j.srcRow;\n        case 1: return j.srcSnake;\n        case 2: return j.srcMorton;\n        case 3: return j.tgtRow;\n        case 4: return j.tgtSnake;\n        case 5: return j.tgtMorton;\n        case 6: return j.midMorton;\n        case 7: return j.midSnake;\n        default: return j.pairDist;\n    }\n}\n\nvector<int> orderByKey(const vector<Job>& jobs, int mode) {\n    vector<int> ord((int)jobs.size());\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        int ka = jobKey(jobs[a], mode), kb = jobKey(jobs[b], mode);\n        if (ka != kb) return ka < kb;\n        if (jobs[a].s.x != jobs[b].s.x) return jobs[a].s.x < jobs[b].s.x;\n        if (jobs[a].s.y != jobs[b].s.y) return jobs[a].s.y < jobs[b].s.y;\n        if (jobs[a].t.x != jobs[b].t.x) return jobs[a].t.x < jobs[b].t.x;\n        return jobs[a].t.y < jobs[b].t.y;\n    });\n    return ord;\n}\n\nll transitionProxyCost(const Job& a, const Job& b) {\n    ll best = (1LL << 60);\n    for (const auto& q : a.dropStates) {\n        for (const auto& p : b.pickStates) {\n            best = min(best, (ll)turnCost(q, p));\n        }\n    }\n    return best;\n}\n\nll startProxyCost(const Job& j) {\n    ll best = (1LL << 60);\n    for (const auto& p : j.pickStates) {\n        best = min(best, (ll)max(1, orientDist(0, p.d)));\n    }\n    return best;\n}\n\nll proxyOrderCost(const vector<int>& ord, const vector<Job>& jobs) {\n    if (ord.empty()) return 0;\n    ll res = startProxyCost(jobs[ord[0]]);\n    for (int i = 0; i + 1 < (int)ord.size(); i++) {\n        res += transitionProxyCost(jobs[ord[i]], jobs[ord[i + 1]]);\n    }\n    return res;\n}\n\nvoid improveOrderProxy(vector<int>& ord, const vector<Job>& jobs) {\n    int n = (int)ord.size();\n    if (n <= 2) return;\n\n    ll cur = proxyOrderCost(ord, jobs);\n    for (int pass = 0; pass < 2; pass++) {\n        bool changed = false;\n        for (int i = 0; i + 1 < n; i++) {\n            swap(ord[i], ord[i + 1]);\n            ll cand = proxyOrderCost(ord, jobs);\n            if (cand < cur) {\n                cur = cand;\n                changed = true;\n            } else {\n                swap(ord[i], ord[i + 1]);\n            }\n        }\n        if (!changed) break;\n    }\n}\n\nvector<int> greedyOrder(const vector<Job>& jobs, int seed) {\n    int n = (int)jobs.size();\n    vector<int> ord;\n    ord.reserve(n);\n    vector<char> used(n, 0);\n    ord.push_back(seed);\n    used[seed] = 1;\n    int cur = seed;\n\n    while ((int)ord.size() < n) {\n        int best = -1;\n        ll bestScore = (1LL << 60);\n        int bestTie = INT_MAX;\n        for (int j = 0; j < n; j++) if (!used[j]) {\n            ll sc = transitionProxyCost(jobs[cur], jobs[j]);\n            int tie = jobs[j].pairDist;\n            if (sc < bestScore || (sc == bestScore && tie < bestTie)) {\n                bestScore = sc;\n                bestTie = tie;\n                best = j;\n            }\n        }\n        used[best] = 1;\n        ord.push_back(best);\n        cur = best;\n    }\n    return ord;\n}\n\nint bestShiftByPairDistance(const vector<Point>& src, const vector<Point>& tgt, int mode, bool reverseTgt) {\n    int K = (int)src.size();\n    if (K == 0) return 0;\n    vector<int> is = sortedIdxByKey(src, mode);\n    vector<int> it = sortedIdxByKey(tgt, mode);\n    if (reverseTgt) reverse(it.begin(), it.end());\n\n    ll best = (1LL << 60);\n    int bestSh = 0;\n    for (int sh = 0; sh < K; sh++) {\n        ll sum = 0;\n        for (int i = 0; i < K; i++) {\n            sum += manhattan(src[is[i]], tgt[it[(i + sh) % K]]);\n        }\n        if (sum < best) {\n            best = sum;\n            bestSh = sh;\n        }\n    }\n    return bestSh;\n}\n\nvector<int> makeShiftSet(int K, int a, int b) {\n    set<int> ss;\n    auto add = [&](int x) {\n        if (K == 0) return;\n        x %= K;\n        if (x < 0) x += K;\n        ss.insert(x);\n    };\n    add(0);\n    add(K / 2);\n    add(a);\n    add(a - 1);\n    add(a + 1);\n    add(b);\n    return vector<int>(ss.begin(), ss.end());\n}\n\nvector<vector<int>> makeOrderCandidates(const vector<Job>& jobs) {\n    vector<vector<int>> cand;\n    auto add = [&](vector<int> ord) {\n        if (ord.empty()) return;\n        improveOrderProxy(ord, jobs);\n        cand.push_back(ord);\n        vector<int> rev = ord;\n        reverse(rev.begin(), rev.end());\n        improveOrderProxy(rev, jobs);\n        cand.push_back(rev);\n    };\n\n    add(orderByKey(jobs, 0));\n    add(orderByKey(jobs, 1));\n    add(orderByKey(jobs, 2));\n    add(orderByKey(jobs, 3));\n    add(orderByKey(jobs, 4));\n    add(orderByKey(jobs, 5));\n    add(orderByKey(jobs, 6));\n    add(orderByKey(jobs, 7));\n    add(orderByKey(jobs, 8));\n\n    if (!jobs.empty()) {\n        vector<int> base = orderByKey(jobs, 6);\n        add(greedyOrder(jobs, base[0]));\n        base = orderByKey(jobs, 1);\n        add(greedyOrder(jobs, base[0]));\n    }\n\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n    return cand;\n}\n\nPlan solveOrder(const vector<Job>& jobs, int jobsId, const vector<int>& ord) {\n    Plan res;\n    res.jobsId = jobsId;\n    res.ord = ord;\n\n    int n = (int)ord.size();\n    if (n == 0) {\n        res.cost = 0;\n        res.startRoot = {0, 0};\n        return res;\n    }\n\n    vector<vector<State>> P(n), D(n);\n    for (int i = 0; i < n; i++) {\n        P[i] = jobs[ord[i]].pickStates;\n        D[i] = jobs[ord[i]].dropStates;\n    }\n\n    const ll INF = (1LL << 60);\n    vector<vector<ll>> dp(n);\n    vector<vector<int>> parPick(n), parPrev(n);\n\n    dp[0].assign(D[0].size(), INF);\n    parPick[0].assign(D[0].size(), -1);\n    parPrev[0].assign(D[0].size(), -1);\n\n    for (int q = 0; q < (int)D[0].size(); q++) {\n        ll best = INF;\n        int bp = -1;\n        for (int p = 0; p < (int)P[0].size(); p++) {\n            ll c = max(1, orientDist(0, P[0][p].d)) + turnCost(P[0][p], D[0][q]);\n            if (c < best) {\n                best = c;\n                bp = p;\n            }\n        }\n        dp[0][q] = best;\n        parPick[0][q] = bp;\n    }\n\n    for (int i = 1; i < n; i++) {\n        dp[i].assign(D[i].size(), INF);\n        parPick[i].assign(D[i].size(), -1);\n        parPrev[i].assign(D[i].size(), -1);\n\n        for (int prevQ = 0; prevQ < (int)D[i - 1].size(); prevQ++) {\n            if (dp[i - 1][prevQ] >= INF) continue;\n            const State& curDrop = D[i - 1][prevQ];\n\n            for (int p = 0; p < (int)P[i].size(); p++) {\n                ll mid = dp[i - 1][prevQ] + turnCost(curDrop, P[i][p]);\n                for (int q = 0; q < (int)D[i].size(); q++) {\n                    ll c = mid + turnCost(P[i][p], D[i][q]);\n                    if (c < dp[i][q]) {\n                        dp[i][q] = c;\n                        parPrev[i][q] = prevQ;\n                        parPick[i][q] = p;\n                    }\n                }\n            }\n        }\n    }\n\n    int bestQ = 0;\n    for (int q = 1; q < (int)D[n - 1].size(); q++) {\n        if (dp[n - 1][q] < dp[n - 1][bestQ]) bestQ = q;\n    }\n\n    res.cost = dp[n - 1][bestQ];\n    res.pickSel.assign(n, -1);\n    res.dropSel.assign(n, -1);\n\n    int curQ = bestQ;\n    for (int i = n - 1; i >= 0; i--) {\n        res.dropSel[i] = curQ;\n        res.pickSel[i] = parPick[i][curQ];\n        curQ = parPrev[i][curQ];\n    }\n\n    const State& firstPick = P[0][res.pickSel[0]];\n    res.startRoot = {firstPick.x, firstPick.y};\n    return res;\n}\n\ntemplate <class TimeCheck>\nPlan exactImprovePlan(Plan cur, const vector<Job>& jobs, TimeCheck timeOver) {\n    int n = (int)cur.ord.size();\n    if (n <= 1) return cur;\n\n    Plan best = cur;\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count() ^ (uint64_t)n);\n    uniform_real_distribution<double> ur(0.0, 1.0);\n\n    auto eval = [&](const vector<int>& ord) -> Plan {\n        return solveOrder(jobs, cur.jobsId, ord);\n    };\n\n    // Deterministic adjacent-swap hill climbing.\n    for (int pass = 0; pass < 3 && !timeOver(); pass++) {\n        bool improved = false;\n        for (int i = 0; i + 1 < n && !timeOver(); i++) {\n            vector<int> o = cur.ord;\n            swap(o[i], o[i + 1]);\n            Plan cand = eval(o);\n            if (cand.cost < cur.cost) {\n                cur = move(cand);\n                improved = true;\n            }\n            if (cur.cost < best.cost) best = cur;\n        }\n        if (!improved) break;\n    }\n\n    // Exact simulated annealing-like local search.\n    int limit = min(5000, max(1800, n * 15));\n    for (int it = 0; it < limit && !timeOver(); it++) {\n        vector<int> o = cur.ord;\n        int op = (int)(rng() % 4);\n\n        if (op == 0) {\n            int i = (int)(rng() % n);\n            int j = (int)(rng() % n);\n            if (i == j) continue;\n            swap(o[i], o[j]);\n        } else if (op == 1) {\n            int i = (int)(rng() % n);\n            int j = (int)(rng() % n);\n            if (i == j) continue;\n            int x = o[i];\n            o.erase(o.begin() + i);\n            if (j > i) j--;\n            o.insert(o.begin() + j, x);\n        } else if (op == 2) {\n            int l = (int)(rng() % n);\n            int r = (int)(rng() % n);\n            if (l > r) swap(l, r);\n            if (l == r) continue;\n            reverse(o.begin() + l, o.begin() + r + 1);\n        } else {\n            int l = (int)(rng() % n);\n            int r = (int)(rng() % n);\n            if (l > r) swap(l, r);\n            if (r - l < 2) continue;\n            rotate(o.begin() + l, o.begin() + l + 1, o.begin() + r + 1);\n        }\n\n        Plan cand = eval(o);\n        ll delta = cand.cost - cur.cost;\n\n        double ratio = (double)it / max(1, limit - 1);\n        double temp = 4.0 * (1.0 - ratio) + 0.15;\n        bool accept = false;\n        if (delta <= 0) accept = true;\n        else {\n            double prob = exp(-(double)delta / temp);\n            accept = (ur(rng) < prob);\n        }\n\n        if (accept) cur = move(cand);\n        if (cur.cost < best.cost) best = cur;\n    }\n\n    // Final local cleanup.\n    for (int pass = 0; pass < 2 && !timeOver(); pass++) {\n        bool improved = false;\n        for (int i = 0; i + 1 < n && !timeOver(); i++) {\n            vector<int> o = best.ord;\n            swap(o[i], o[i + 1]);\n            Plan cand = eval(o);\n            if (cand.cost < best.cost) {\n                best = move(cand);\n                improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n\n    return best;\n}\n\nvector<char> buildMovePath(const State& a, const State& b) {\n    vector<char> path;\n    int dx = b.x - a.x;\n    int dy = b.y - a.y;\n    while (dx > 0) { path.push_back('D'); dx--; }\n    while (dx < 0) { path.push_back('U'); dx++; }\n    while (dy > 0) { path.push_back('R'); dy--; }\n    while (dy < 0) { path.push_back('L'); dy++; }\n    return path;\n}\n\nvoid emitTurn(char mv, char rot, char act) {\n    char buf[4] = {mv, rot, '.', act};\n    cout.write(buf, 4);\n    cout.put('\\n');\n}\n\nvoid emitSegment(const State& a, const State& b, char finalAct) {\n    vector<char> path = buildMovePath(a, b);\n    int m = (int)path.size();\n    int r = orientDist(a.d, b.d);\n    char rc = (r ? orientChar(a.d, b.d) : '.');\n    int L = max(1, max(m, r));\n\n    for (int i = 0; i < L; i++) {\n        char mv = (i < m ? path[i] : '.');\n        char rot = (i < r ? rc : '.');\n        char act = (i + 1 == L ? finalAct : '.');\n        emitTurn(mv, rot, act);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M >> V;\n    S.resize(N);\n    T.resize(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<Point> src, tgt;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            bool a = (S[i][j] == '1');\n            bool b = (T[i][j] == '1');\n            if (a && !b) src.push_back({i, j});\n            if (b && !a) tgt.push_back({i, j});\n        }\n    }\n\n    int K = (int)src.size();\n    if ((int)tgt.size() != K) {\n        int mn = min((int)src.size(), (int)tgt.size());\n        src.resize(mn);\n        tgt.resize(mn);\n        K = mn;\n    }\n\n    if (K == 0) {\n        cout << 2 << '\\n';\n        cout << 0 << ' ' << 1 << '\\n';\n        cout << 0 << ' ' << 0 << '\\n';\n        return 0;\n    }\n\n    using Clock = chrono::steady_clock;\n    auto t0 = Clock::now();\n    auto timeOver = [&]() -> bool {\n        return chrono::duration<double>(Clock::now() - t0).count() > 2.85;\n    };\n\n    vector<vector<Job>> jobLists;\n    jobLists.reserve(16);\n\n    // Exact Hungarian pairing.\n    jobLists.push_back(buildJobsHungarian(src, tgt));\n\n    // Compact set of shifted pairings.\n    for (int mode = 0; mode < 4; mode++) {\n        int sh0 = bestShiftByPairDistance(src, tgt, mode, false);\n        int sh1 = bestShiftByPairDistance(src, tgt, mode, true);\n        vector<int> shifts = makeShiftSet(K, sh0, sh1);\n\n        for (int rev = 0; rev < 2; rev++) {\n            bool reverseTgt = (rev != 0);\n            for (int sh : shifts) {\n                jobLists.push_back(buildJobsShifted(src, tgt, mode, sh, reverseTgt));\n                if (timeOver()) break;\n            }\n            if (timeOver()) break;\n        }\n        if (timeOver()) break;\n    }\n\n    vector<Plan> plans;\n    for (int id = 0; id < (int)jobLists.size() && !timeOver(); id++) {\n        const auto& jobs = jobLists[id];\n        auto orders = makeOrderCandidates(jobs);\n\n        vector<pair<ll, vector<int>>> scored;\n        scored.reserve(orders.size());\n        for (auto& ord : orders) {\n            scored.push_back({proxyOrderCost(ord, jobs), ord});\n        }\n        sort(scored.begin(), scored.end(), [](const auto& a, const auto& b) {\n            if (a.first != b.first) return a.first < b.first;\n            return a.second < b.second;\n        });\n\n        int keep = min<int>(5, scored.size());\n        for (int k = 0; k < keep && !timeOver(); k++) {\n            plans.push_back(solveOrder(jobs, id, scored[k].second));\n        }\n    }\n\n    if (plans.empty()) {\n        const auto& jobs = jobLists[0];\n        vector<int> ord(jobs.size());\n        iota(ord.begin(), ord.end(), 0);\n        plans.push_back(solveOrder(jobs, 0, ord));\n    }\n\n    sort(plans.begin(), plans.end(), [](const Plan& a, const Plan& b) {\n        return a.cost < b.cost;\n    });\n    if ((int)plans.size() > 3) plans.resize(3);\n\n    // Spend remaining time on exact local improvement for the strongest few plans.\n    for (auto& p : plans) {\n        if (timeOver()) break;\n        const auto& jobs = jobLists[p.jobsId];\n        p = exactImprovePlan(move(p), jobs, timeOver);\n    }\n\n    sort(plans.begin(), plans.end(), [](const Plan& a, const Plan& b) {\n        return a.cost < b.cost;\n    });\n    Plan best = plans[0];\n    const auto& jobs = jobLists[best.jobsId];\n\n    cout << 2 << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n    cout << best.startRoot.x << ' ' << best.startRoot.y << '\\n';\n\n    State cur{best.startRoot.x, best.startRoot.y, 0}; // initial direction: right\n    for (int i = 0; i < (int)best.ord.size(); i++) {\n        const Job& j = jobs[best.ord[i]];\n        const State& p = j.pickStates[best.pickSel[i]];\n        const State& q = j.dropStates[best.dropSel[i]];\n        emitSegment(cur, p, 'P'); // pick\n        emitSegment(p, q, 'P');    // drop\n        cur = q;\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int MAXC = 100000;\nstatic constexpr int VERT_LIMIT = 1000;\nstatic constexpr ll PER_LIMIT = 400000;\nstatic constexpr int SHIFT = 17; // 2^17 > 100000\n\nstruct Pt {\n    int x, y, w;\n};\n\nstruct P {\n    int x, y;\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nstruct Answer {\n    int score = INT_MIN;\n    ll area = (1LL << 60);\n    vector<P> poly;\n};\n\nstatic inline bool operator==(const P& a, const P& b) {\n    return a.x == b.x && a.y == b.y;\n}\n\nstatic inline bool valid_rect(const Rect& r) {\n    return r.x1 < r.x2 && r.y1 < r.y2;\n}\n\nstatic inline ll rect_area(const Rect& r) {\n    return 1LL * (r.x2 - r.x1) * (r.y2 - r.y1);\n}\n\nstatic inline ll encode_point(int x, int y) {\n    return ((ll)x << SHIFT) | (ll)y;\n}\n\nstatic inline P decode_point(ll code) {\n    return P{(int)(code >> SHIFT), (int)(code & ((1LL << SHIFT) - 1))};\n}\n\nstatic vector<int> uniq_sorted(vector<int> v) {\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nstatic inline bool on_segment(int px, int py, const P& a, const P& b) {\n    if (a.x == b.x) {\n        if (px != a.x) return false;\n        return min(a.y, b.y) <= py && py <= max(a.y, b.y);\n    } else {\n        if (py != a.y) return false;\n        return min(a.x, b.x) <= px && px <= max(a.x, b.x);\n    }\n}\n\nstatic bool inside_or_on(const vector<P>& poly, int px, int py) {\n    bool inside = false;\n    int n = (int)poly.size();\n    for (int i = 0; i < n; ++i) {\n        const P& a = poly[i];\n        const P& b = poly[(i + 1) % n];\n        if (on_segment(px, py, a, b)) return true;\n\n        // Ray cast toward +x.\n        if (a.x == b.x) {\n            int y1 = min(a.y, b.y), y2 = max(a.y, b.y);\n            if (y1 <= py && py < y2 && a.x > px) inside = !inside;\n        }\n    }\n    return inside;\n}\n\nstatic ll polygon_area2(const vector<P>& poly) {\n    ll s = 0;\n    int n = (int)poly.size();\n    for (int i = 0; i < n; ++i) {\n        const P& a = poly[i];\n        const P& b = poly[(i + 1) % n];\n        s += 1LL * a.x * b.y - 1LL * b.x * a.y;\n    }\n    return llabs(s);\n}\n\nstatic ll polygon_area(const vector<P>& poly) {\n    return polygon_area2(poly) / 2;\n}\n\nstatic ll polygon_perimeter(const vector<P>& poly) {\n    ll per = 0;\n    int n = (int)poly.size();\n    for (int i = 0; i < n; ++i) {\n        const P& a = poly[i];\n        const P& b = poly[(i + 1) % n];\n        per += llabs(a.x - b.x) + llabs(a.y - b.y);\n    }\n    return per;\n}\n\nstatic int exact_polygon_score(const vector<P>& poly, const vector<Pt>& pts) {\n    if (poly.empty()) return INT_MIN;\n\n    int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN;\n    for (const auto& p : poly) {\n        minx = min(minx, p.x);\n        miny = min(miny, p.y);\n        maxx = max(maxx, p.x);\n        maxy = max(maxy, p.y);\n    }\n\n    int s = 0;\n    for (const auto& pt : pts) {\n        if (pt.x < minx || pt.x > maxx || pt.y < miny || pt.y > maxy) continue;\n        if (inside_or_on(poly, pt.x, pt.y)) s += pt.w;\n    }\n    return s;\n}\n\nstatic int exact_rect_score(const Rect& r, const vector<Pt>& pts) {\n    int s = 0;\n    for (const auto& p : pts) {\n        if (r.x1 <= p.x && p.x <= r.x2 && r.y1 <= p.y && p.y <= r.y2) s += p.w;\n    }\n    return s;\n}\n\nstatic inline bool better_answer(const Answer& a, const Answer& b) {\n    if (a.score != b.score) return a.score > b.score;\n    if (a.area != b.area) return a.area < b.area;\n    return a.poly.size() < b.poly.size();\n}\n\nstatic void consider_poly(Answer& best, const vector<P>& poly, const vector<Pt>& pts) {\n    if ((int)poly.size() < 4 || (int)poly.size() > VERT_LIMIT) return;\n    if (polygon_perimeter(poly) > PER_LIMIT) return;\n\n    int sc = exact_polygon_score(poly, pts);\n    ll ar = polygon_area(poly);\n    if (sc > best.score || (sc == best.score && ar < best.area)) {\n        best.score = sc;\n        best.area = ar;\n        best.poly = poly;\n    }\n}\n\nstatic void consider_rect(Answer& best, const Rect& r, const vector<Pt>& pts) {\n    if (!valid_rect(r)) return;\n    vector<P> poly = {{r.x1, r.y1}, {r.x2, r.y1}, {r.x2, r.y2}, {r.x1, r.y2}};\n    int sc = exact_rect_score(r, pts);\n    ll ar = rect_area(r);\n    if (sc > best.score || (sc == best.score && ar < best.area)) {\n        best.score = sc;\n        best.area = ar;\n        best.poly = poly;\n    }\n}\n\nstatic vector<P> make_rect_poly(int x1, int y1, int x2, int y2) {\n    return {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}};\n}\n\nstruct GridData {\n    vector<int> bx, by;\n    int nx = 0, ny = 0;\n    vector<int> raw;\n    vector<int> sm3, sm5, sm7;\n    vector<int> pri;\n};\n\nstatic vector<int> build_boundaries_region(int L, int R, int S, int off) {\n    vector<int> b;\n    b.push_back(L);\n    if (S <= 0) S = 1;\n    int shift = off % S;\n    if (shift < 0) shift += S;\n    int start = L + shift;\n    if (start > R) start = L;\n    if (start > L && start < R) b.push_back(start);\n\n    for (int l = start; l < R; l += S) {\n        int rr = min(R, l + S);\n        if (b.back() != rr) b.push_back(rr);\n        if (rr == R) break;\n    }\n    if (b.back() != R) b.push_back(R);\n    return uniq_sorted(b);\n}\n\nstatic inline int cell_idx(int v, const vector<int>& b) {\n    int id = (int)(upper_bound(b.begin(), b.end(), v) - b.begin()) - 1;\n    return max(0, min(id, (int)b.size() - 2));\n}\n\nstatic GridData build_grid_region(const vector<Pt>& pts,\n                                  int xL, int xR, int yL, int yR,\n                                  int S, int ox, int oy) {\n    GridData g;\n    g.bx = build_boundaries_region(xL, xR, S, ox);\n    g.by = build_boundaries_region(yL, yR, S, oy);\n    g.nx = (int)g.bx.size() - 1;\n    g.ny = (int)g.by.size() - 1;\n    g.raw.assign(g.nx * g.ny, 0);\n\n    for (const auto& p : pts) {\n        if (p.x < xL || p.x > xR || p.y < yL || p.y > yR) continue;\n        int ix = cell_idx(p.x, g.bx);\n        int iy = cell_idx(p.y, g.by);\n        g.raw[ix * g.ny + iy] += p.w;\n    }\n\n    vector<int> ps((g.nx + 1) * (g.ny + 1), 0);\n    auto pid = [&](int i, int j) { return i * (g.ny + 1) + j; };\n    for (int i = 0; i < g.nx; ++i) {\n        for (int j = 0; j < g.ny; ++j) {\n            ps[pid(i + 1, j + 1)] = g.raw[i * g.ny + j]\n                                   + ps[pid(i, j + 1)]\n                                   + ps[pid(i + 1, j)]\n                                   - ps[pid(i, j)];\n        }\n    }\n\n    auto sum_rect = [&](int x1, int y1, int x2, int y2) -> int {\n        x1 = max(x1, 0);\n        y1 = max(y1, 0);\n        x2 = min(x2, g.nx - 1);\n        y2 = min(y2, g.ny - 1);\n        if (x1 > x2 || y1 > y2) return 0;\n        return ps[pid(x2 + 1, y2 + 1)]\n             - ps[pid(x1, y2 + 1)]\n             - ps[pid(x2 + 1, y1)]\n             + ps[pid(x1, y1)];\n    };\n\n    g.sm3.assign(g.nx * g.ny, 0);\n    g.sm5.assign(g.nx * g.ny, 0);\n    g.sm7.assign(g.nx * g.ny, 0);\n    g.pri.assign(g.nx * g.ny, 0);\n\n    for (int i = 0; i < g.nx; ++i) {\n        for (int j = 0; j < g.ny; ++j) {\n            int s3 = sum_rect(i - 1, j - 1, i + 1, j + 1);\n            int s5 = sum_rect(i - 2, j - 2, i + 2, j + 2);\n            int s7 = sum_rect(i - 3, j - 3, i + 3, j + 3);\n            g.sm3[i * g.ny + j] = s3;\n            g.sm5[i * g.ny + j] = s5;\n            g.sm7[i * g.ny + j] = s7;\n            g.pri[i * g.ny + j] = max({g.raw[i * g.ny + j], s3 / 9, s5 / 25, s7 / 49});\n        }\n    }\n\n    return g;\n}\n\nstatic Rect grid_best_rect(const GridData& g) {\n    Rect best{g.bx[0], g.by[0], g.bx[1], g.by[1]};\n    int bestScore = INT_MIN;\n    ll bestArea = (1LL << 60);\n\n    vector<int> col(g.ny, 0);\n    for (int top = 0; top < g.nx; ++top) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < g.nx; ++bot) {\n            const int* row = &g.raw[bot * g.ny];\n            for (int c = 0; c < g.ny; ++c) col[c] += row[c];\n\n            int cur = 0, left = 0;\n            for (int c = 0; c < g.ny; ++c) {\n                if (cur < 0) {\n                    cur = col[c];\n                    left = c;\n                } else {\n                    cur += col[c];\n                }\n\n                ll ar = 1LL * (g.bx[bot + 1] - g.bx[top]) * (g.by[c + 1] - g.by[left]);\n                if (cur > bestScore || (cur == bestScore && ar < bestArea)) {\n                    bestScore = cur;\n                    bestArea = ar;\n                    best = {g.bx[top], g.by[left], g.bx[bot + 1], g.by[c + 1]};\n                }\n            }\n        }\n    }\n    return best;\n}\n\nstruct Component {\n    int sum = 0;\n    int minI = 0, maxI = 0, minJ = 0, maxJ = 0;\n    vector<int> cells;\n};\n\nstatic vector<Component> find_components(const GridData& g, const vector<char>& mask) {\n    vector<Component> comps;\n    int n = g.nx * g.ny;\n    vector<char> vis(n, 0);\n    queue<int> q;\n    const int di[4] = {1, -1, 0, 0};\n    const int dj[4] = {0, 0, 1, -1};\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < g.nx && 0 <= j && j < g.ny;\n    };\n\n    for (int s = 0; s < n; ++s) {\n        if (!mask[s] || vis[s]) continue;\n\n        Component c;\n        int si = s / g.ny;\n        int sj = s % g.ny;\n        c.minI = c.maxI = si;\n        c.minJ = c.maxJ = sj;\n\n        vis[s] = 1;\n        q.push(s);\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            int i = v / g.ny;\n            int j = v % g.ny;\n            c.cells.push_back(v);\n            c.sum += g.raw[v];\n            c.minI = min(c.minI, i);\n            c.maxI = max(c.maxI, i);\n            c.minJ = min(c.minJ, j);\n            c.maxJ = max(c.maxJ, j);\n\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj)) continue;\n                int nv = ni * g.ny + nj;\n                if (!mask[nv] || vis[nv]) continue;\n                vis[nv] = 1;\n                q.push(nv);\n            }\n        }\n        comps.push_back(move(c));\n    }\n\n    return comps;\n}\n\nstatic vector<char> fill_holes_local(const vector<char>& sel, int w, int h) {\n    vector<char> outside(w * h, 0);\n    queue<pair<int, int>> q;\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < w && 0 <= j && j < h;\n    };\n    auto push = [&](int i, int j) {\n        if (!inside(i, j)) return;\n        int id = i * h + j;\n        if (!sel[id] && !outside[id]) {\n            outside[id] = 1;\n            q.push({i, j});\n        }\n    };\n\n    for (int i = 0; i < w; ++i) {\n        push(i, 0);\n        push(i, h - 1);\n    }\n    for (int j = 0; j < h; ++j) {\n        push(0, j);\n        push(w - 1, j);\n    }\n\n    const int di[4] = {1, -1, 0, 0};\n    const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (!inside(ni, nj)) continue;\n            int nid = ni * h + nj;\n            if (sel[nid] || outside[nid]) continue;\n            outside[nid] = 1;\n            q.push({ni, nj});\n        }\n    }\n\n    vector<char> res = sel;\n    for (int i = 0; i < w; ++i) {\n        for (int j = 0; j < h; ++j) {\n            int id = i * h + j;\n            if (!res[id] && !outside[id]) res[id] = 1;\n        }\n    }\n    return res;\n}\n\nstatic int local_mask_score(const GridData& g, int bi, int bj, int w, int h, const vector<char>& sel) {\n    int s = 0;\n    for (int i = 0; i < w; ++i) {\n        int gi = bi + i;\n        for (int j = 0; j < h; ++j) {\n            if (sel[i * h + j]) s += g.raw[gi * g.ny + (bj + j)];\n        }\n    }\n    return s;\n}\n\nstatic vector<char> articulation_points(const vector<char>& sel, int w, int h) {\n    int n = w * h;\n    vector<int> disc(n, -1), low(n, 0), parent(n, -1);\n    vector<char> art(n, 0);\n    int timer = 0;\n\n    const int di[4] = {1, -1, 0, 0};\n    const int dj[4] = {0, 0, 1, -1};\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < w && 0 <= j && j < h;\n    };\n\n    auto dfs = [&](auto&& self, int v) -> void {\n        disc[v] = low[v] = ++timer;\n        int vi = v / h;\n        int vj = v % h;\n        int child = 0;\n\n        for (int d = 0; d < 4; ++d) {\n            int ni = vi + di[d], nj = vj + dj[d];\n            if (!inside(ni, nj)) continue;\n            int u = ni * h + nj;\n            if (!sel[u]) continue;\n\n            if (disc[u] == -1) {\n                parent[u] = v;\n                ++child;\n                self(self, u);\n                low[v] = min(low[v], low[u]);\n                if (parent[v] != -1 && low[u] >= disc[v]) art[v] = 1;\n            } else if (u != parent[v]) {\n                low[v] = min(low[v], disc[u]);\n            }\n        }\n\n        if (parent[v] == -1 && child > 1) art[v] = 1;\n    };\n\n    for (int s = 0; s < n; ++s) {\n        if (!sel[s] || disc[s] != -1) continue;\n        parent[s] = -1;\n        dfs(dfs, s);\n    }\n\n    return art;\n}\n\nstatic vector<char> optimize_mask(const GridData& g, int bi, int bj, int w, int h, vector<char> sel) {\n    sel = fill_holes_local(sel, w, h);\n    int cur = local_mask_score(g, bi, bj, w, h, sel);\n\n    const int di[4] = {1, -1, 0, 0};\n    const int dj[4] = {0, 0, 1, -1};\n\n    auto has_selected_neighbor = [&](int i, int j) {\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < w && 0 <= nj && nj < h && sel[ni * h + nj]) return true;\n        }\n        return false;\n    };\n    auto has_empty_neighbor = [&](int i, int j) {\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < w && 0 <= nj && nj < h && !sel[ni * h + nj]) return true;\n        }\n        return false;\n    };\n\n    for (int iter = 0; iter < 8; ++iter) {\n        vector<char> art = articulation_points(sel, w, h);\n\n        vector<pair<int, int>> addCand;\n        vector<pair<int, int>> remCand;\n        addCand.reserve(w * h);\n        remCand.reserve(w * h);\n\n        for (int i = 0; i < w; ++i) {\n            int gi = bi + i;\n            for (int j = 0; j < h; ++j) {\n                int id = i * h + j;\n                int idx = gi * g.ny + (bj + j);\n\n                if (sel[id]) {\n                    if (has_empty_neighbor(i, j) && !art[id] && g.raw[idx] <= 0) {\n                        remCand.push_back({g.raw[idx], id}); // smaller is better for removal\n                    }\n                } else {\n                    if (has_selected_neighbor(i, j) && g.pri[idx] > 0) {\n                        addCand.push_back({g.pri[idx], id});\n                    }\n                }\n            }\n        }\n\n        sort(addCand.begin(), addCand.end(), greater<>());\n        sort(remCand.begin(), remCand.end()); // raw ascending: most negative first\n\n        if ((int)addCand.size() > 24) addCand.resize(24);\n        if ((int)remCand.size() > 24) remCand.resize(24);\n\n        int best = cur;\n        vector<char> bestSel = sel;\n\n        // Try removals.\n        for (auto [v, id] : remCand) {\n            (void)v;\n            vector<char> t = sel;\n            t[id] = 0;\n            t = fill_holes_local(t, w, h);\n            int sc = local_mask_score(g, bi, bj, w, h, t);\n            if (sc > best) {\n                best = sc;\n                bestSel = move(t);\n            }\n        }\n\n        // Try additions.\n        for (auto [v, id] : addCand) {\n            (void)v;\n            vector<char> t = sel;\n            t[id] = 1;\n            t = fill_holes_local(t, w, h);\n            int sc = local_mask_score(g, bi, bj, w, h, t);\n            if (sc > best) {\n                best = sc;\n                bestSel = move(t);\n            }\n        }\n\n        if (best > cur) {\n            sel = move(bestSel);\n            cur = best;\n        } else {\n            break;\n        }\n    }\n\n    return sel;\n}\n\nstatic vector<char> grow_mask(const GridData& g, int bi, int bj, int w, int h, vector<char> sel) {\n    sel = fill_holes_local(sel, w, h);\n    int cur = local_mask_score(g, bi, bj, w, h, sel);\n\n    const int di[4] = {1, -1, 0, 0};\n    const int dj[4] = {0, 0, 1, -1};\n\n    auto has_selected_neighbor = [&](int i, int j) {\n        for (int d = 0; d < 4; ++d) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (0 <= ni && ni < w && 0 <= nj && nj < h && sel[ni * h + nj]) return true;\n        }\n        return false;\n    };\n\n    for (int iter = 0; iter < 4; ++iter) {\n        vector<pair<int, int>> cand;\n        cand.reserve(w * h);\n\n        for (int i = 0; i < w; ++i) {\n            int gi = bi + i;\n            for (int j = 0; j < h; ++j) {\n                int id = i * h + j;\n                if (sel[id]) continue;\n                if (!has_selected_neighbor(i, j)) continue;\n\n                int idx = gi * g.ny + (bj + j);\n                if (g.pri[idx] > 0) cand.push_back({g.pri[idx], id});\n            }\n        }\n\n        sort(cand.begin(), cand.end(), greater<>());\n        if ((int)cand.size() > 20) cand.resize(20);\n\n        int best = cur;\n        vector<char> bestSel = sel;\n\n        for (auto [v, id] : cand) {\n            (void)v;\n            vector<char> t = sel;\n            t[id] = 1;\n            t = fill_holes_local(t, w, h);\n            int sc = local_mask_score(g, bi, bj, w, h, t);\n            if (sc > best) {\n                best = sc;\n                bestSel = move(t);\n            }\n        }\n\n        if (best > cur) {\n            sel = move(bestSel);\n            cur = best;\n        } else {\n            break;\n        }\n    }\n\n    return sel;\n}\n\nstruct DEdge {\n    ll u, v;\n    bool operator==(const DEdge& other) const {\n        return u == other.u && v == other.v;\n    }\n};\n\nstruct DEdgeHash {\n    size_t operator()(const DEdge& e) const noexcept {\n        uint64_t x = (uint64_t)e.u + 0x9e3779b97f4a7c15ULL;\n        x ^= x >> 30;\n        x *= 0xbf58476d1ce4e5b9ULL;\n        x ^= x >> 27;\n        x *= 0x94d049bb133111ebULL;\n        x ^= x >> 31;\n\n        uint64_t y = (uint64_t)e.v + 0x94d049bb133111ebULL;\n        y ^= y >> 30;\n        y *= 0xbf58476d1ce4e5b9ULL;\n        y ^= y >> 27;\n        y *= 0x94d049bb133111ebULL;\n        y ^= y >> 31;\n\n        return (size_t)(x ^ (y << 1));\n    }\n};\n\nstatic vector<P> simplify_collinear(const vector<P>& poly) {\n    int n = (int)poly.size();\n    if (n < 4) return {};\n    vector<P> res;\n    res.reserve(n);\n    for (int i = 0; i < n; ++i) {\n        const P& a = poly[(i - 1 + n) % n];\n        const P& b = poly[i];\n        const P& c = poly[(i + 1) % n];\n        if ((a.x == b.x && b.x == c.x) || (a.y == b.y && b.y == c.y)) continue;\n        res.push_back(b);\n    }\n    if ((int)res.size() < 4) return {};\n    return res;\n}\n\nstatic vector<P> trace_local_mask(const GridData& g,\n                                  int bi, int bj, int w, int h,\n                                  const vector<char>& sel) {\n    int cnt = 0;\n    for (char c : sel) if (c) ++cnt;\n    if (cnt == 0) return {};\n\n    unordered_set<DEdge, DEdgeHash> edges;\n    edges.reserve((size_t)cnt * 4 + 8);\n\n    auto toggle = [&](int x1, int y1, int x2, int y2) {\n        ll u = encode_point(x1, y1);\n        ll v = encode_point(x2, y2);\n        DEdge e{u, v}, rev{v, u};\n        auto it = edges.find(rev);\n        if (it != edges.end()) edges.erase(it);\n        else edges.insert(e);\n    };\n\n    for (int i = 0; i < w; ++i) {\n        for (int j = 0; j < h; ++j) {\n            if (!sel[i * h + j]) continue;\n            int gi = bi + i;\n            int gj = bj + j;\n            int x0 = g.bx[gi];\n            int x1 = g.bx[gi + 1];\n            int y0 = g.by[gj];\n            int y1 = g.by[gj + 1];\n\n            toggle(x0, y0, x1, y0);\n            toggle(x1, y0, x1, y1);\n            toggle(x1, y1, x0, y1);\n            toggle(x0, y1, x0, y0);\n        }\n    }\n\n    if (edges.empty() || (int)edges.size() > 1200) return {};\n\n    unordered_map<ll, ll> nxt;\n    nxt.reserve(edges.size() * 2 + 8);\n\n    ll start = LLONG_MAX;\n    for (const auto& e : edges) {\n        if (nxt.count(e.u)) return {};\n        nxt[e.u] = e.v;\n        start = min(start, e.u);\n    }\n\n    vector<P> poly;\n    poly.reserve(nxt.size());\n    unordered_set<ll> seen;\n    seen.reserve(nxt.size() * 2 + 8);\n\n    ll cur = start;\n    for (size_t step = 0; step <= nxt.size() + 3; ++step) {\n        if (seen.count(cur)) return {};\n        seen.insert(cur);\n        poly.push_back(decode_point(cur));\n\n        auto it = nxt.find(cur);\n        if (it == nxt.end()) return {};\n        cur = it->second;\n        if (cur == start) break;\n    }\n\n    if (cur != start) return {};\n    poly = simplify_collinear(poly);\n    if ((int)poly.size() < 4 || (int)poly.size() > VERT_LIMIT) return {};\n    if (polygon_perimeter(poly) > PER_LIMIT) return {};\n    return poly;\n}\n\nstatic bool rect_to_cell_box(const GridData& g, const Rect& r,\n                             int& bi, int& bj, int& w, int& h) {\n    auto itx1 = lower_bound(g.bx.begin(), g.bx.end(), r.x1);\n    auto itx2 = lower_bound(g.bx.begin(), g.bx.end(), r.x2);\n    auto ity1 = lower_bound(g.by.begin(), g.by.end(), r.y1);\n    auto ity2 = lower_bound(g.by.begin(), g.by.end(), r.y2);\n    if (itx1 == g.bx.end() || itx2 == g.bx.end() || ity1 == g.by.end() || ity2 == g.by.end()) return false;\n    if (*itx1 != r.x1 || *itx2 != r.x2 || *ity1 != r.y1 || *ity2 != r.y2) return false;\n    bi = (int)(itx1 - g.bx.begin());\n    bj = (int)(ity1 - g.by.begin());\n    int ei = (int)(itx2 - g.bx.begin()) - 1;\n    int ej = (int)(ity2 - g.by.begin()) - 1;\n    w = ei - bi + 1;\n    h = ej - bj + 1;\n    return w > 0 && h > 0;\n}\n\nstatic void process_component_candidate(const GridData& g, const vector<Pt>& pts,\n                                        const Component& comp, Answer& best) {\n    int pad = 3;\n    int bi = max(0, comp.minI - pad);\n    int bj = max(0, comp.minJ - pad);\n    int ei = min(g.nx - 1, comp.maxI + pad);\n    int ej = min(g.ny - 1, comp.maxJ + pad);\n    int w = ei - bi + 1;\n    int h = ej - bj + 1;\n\n    vector<char> sel(w * h, 0);\n    for (int v : comp.cells) {\n        int i = v / g.ny;\n        int j = v % g.ny;\n        if (bi <= i && i <= ei && bj <= j && j <= ej) {\n            sel[(i - bi) * h + (j - bj)] = 1;\n        }\n    }\n\n    sel = fill_holes_local(sel, w, h);\n    sel = grow_mask(g, bi, bj, w, h, sel);\n    sel = optimize_mask(g, bi, bj, w, h, sel);\n\n    vector<P> poly = trace_local_mask(g, bi, bj, w, h, sel);\n    if (!poly.empty()) consider_poly(best, poly, pts);\n\n    // Rectangle fallbacks around this component.\n    Rect bbox{g.bx[comp.minI], g.by[comp.minJ], g.bx[comp.maxI + 1], g.by[comp.maxJ + 1]};\n    consider_rect(best, bbox, pts);\n\n    Rect padded{g.bx[bi], g.by[bj], g.bx[ei + 1], g.by[ej + 1]};\n    consider_rect(best, padded, pts);\n}\n\nstatic Rect expand_rect(const Rect& r, int pad) {\n    Rect t{\n        max(0, r.x1 - pad),\n        max(0, r.y1 - pad),\n        min(MAXC, r.x2 + pad),\n        min(MAXC, r.y2 + pad)\n    };\n    if (t.x1 == t.x2) {\n        if (t.x2 < MAXC) ++t.x2;\n        else --t.x1;\n    }\n    if (t.y1 == t.y2) {\n        if (t.y2 < MAXC) ++t.y2;\n        else --t.y1;\n    }\n    return t;\n}\n\nstatic vector<pair<int,int>> phase_list_global(int S) {\n    vector<pair<int,int>> res = {\n        {0, 0},\n        {S / 3, (2 * S) / 3},\n        {(2 * S) / 3, S / 3}\n    };\n    for (auto& p : res) {\n        p.first %= max(1, S);\n        p.second %= max(1, S);\n    }\n    sort(res.begin(), res.end());\n    res.erase(unique(res.begin(), res.end()), res.end());\n    return res;\n}\n\nstatic vector<pair<int,int>> phase_list_local(int S, const Rect& seed, const Rect& region) {\n    int cx = (seed.x1 + seed.x2) / 2;\n    int cy = (seed.y1 + seed.y2) / 2;\n    int ox = (cx - region.x1) % max(1, S);\n    int oy = (cy - region.y1) % max(1, S);\n    if (ox < 0) ox += S;\n    if (oy < 0) oy += S;\n\n    vector<pair<int,int>> res = {\n        {0, 0},\n        {S / 3, (2 * S) / 3},\n        {(2 * S) / 3, S / 3},\n        {ox, oy}\n    };\n    for (auto& p : res) {\n        p.first %= max(1, S);\n        p.second %= max(1, S);\n    }\n    sort(res.begin(), res.end());\n    res.erase(unique(res.begin(), res.end()), res.end());\n    return res;\n}\n\nstatic void process_grid(const GridData& g, const vector<Pt>& pts, Answer& best, vector<Rect>* seeds = nullptr) {\n    // Best rectangle on this grid.\n    Rect bestRect = grid_best_rect(g);\n    consider_rect(best, bestRect, pts);\n    if (seeds) seeds->push_back(bestRect);\n\n    // Try to improve the rectangle by treating it as a cell mask.\n    {\n        int bi, bj, w, h;\n        if (rect_to_cell_box(g, bestRect, bi, bj, w, h) && w * h <= 3600) {\n            vector<char> sel(w * h, 1);\n            sel = grow_mask(g, bi, bj, w, h, sel);\n            sel = optimize_mask(g, bi, bj, w, h, sel);\n            vector<P> poly = trace_local_mask(g, bi, bj, w, h, sel);\n            if (!poly.empty()) consider_poly(best, poly, pts);\n        }\n    }\n\n    // Masks built from different smoothing thresholds.\n    vector<vector<char>> masks;\n    masks.emplace_back(g.nx * g.ny, 0); // raw > 0\n    masks.emplace_back(g.nx * g.ny, 0); // raw >= 2\n    masks.emplace_back(g.nx * g.ny, 0); // sm3 > 0\n    masks.emplace_back(g.nx * g.ny, 0); // sm5 > 0\n    masks.emplace_back(g.nx * g.ny, 0); // sm7 > 0\n\n    for (int i = 0; i < g.nx * g.ny; ++i) {\n        if (g.raw[i] > 0) masks[0][i] = 1;\n        if (g.raw[i] >= 2) masks[1][i] = 1;\n        if (g.sm3[i] > 0) masks[2][i] = 1;\n        if (g.sm5[i] > 0) masks[3][i] = 1;\n        if (g.sm7[i] > 0) masks[4][i] = 1;\n    }\n\n    for (const auto& mask : masks) {\n        auto comps = find_components(g, mask);\n        if (comps.empty()) continue;\n\n        vector<int> ord(comps.size());\n        iota(ord.begin(), ord.end(), 0);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (comps[a].sum != comps[b].sum) return comps[a].sum > comps[b].sum;\n            double da = (double)comps[a].sum / max(1, (int)comps[a].cells.size());\n            double db = (double)comps[b].sum / max(1, (int)comps[b].cells.size());\n            if (da != db) return da > db;\n            return comps[a].cells.size() < comps[b].cells.size();\n        });\n\n        vector<int> chosen;\n        auto push_unique = [&](int id) {\n            for (int x : chosen) if (x == id) return;\n            chosen.push_back(id);\n        };\n\n        for (int k = 0; k < (int)ord.size() && k < 3; ++k) {\n            if (comps[ord[k]].sum > 0) push_unique(ord[k]);\n        }\n\n        // Also add the densest positive component if different.\n        int bestD = -1;\n        double bestDense = -1e100;\n        for (int i = 0; i < (int)comps.size(); ++i) {\n            if (comps[i].sum <= 0) continue;\n            double d = (double)comps[i].sum / max(1, (int)comps[i].cells.size());\n            if (d > bestDense) {\n                bestDense = d;\n                bestD = i;\n            }\n        }\n        if (bestD != -1) push_unique(bestD);\n\n        for (int id : chosen) {\n            const Component& c = comps[id];\n            if (c.sum <= 0) continue;\n            process_component_candidate(g, pts, c, best);\n\n            if (seeds) {\n                Rect bbox{g.bx[c.minI], g.by[c.minJ], g.bx[c.maxI + 1], g.by[c.maxJ + 1]};\n                seeds->push_back(bbox);\n                int bi = max(0, c.minI - 1);\n                int bj = max(0, c.minJ - 1);\n                int ei = min(g.nx - 1, c.maxI + 1);\n                int ej = min(g.ny - 1, c.maxJ + 1);\n                Rect padded{g.bx[bi], g.by[bj], g.bx[ei + 1], g.by[ej + 1]};\n                seeds->push_back(padded);\n            }\n        }\n    }\n}\n\nstatic Rect bbox_of_mackerels(const vector<Pt>& mackerels) {\n    int mnx = MAXC, mxx = 0, mny = MAXC, mxy = 0;\n    for (const auto& p : mackerels) {\n        mnx = min(mnx, p.x);\n        mxx = max(mxx, p.x);\n        mny = min(mny, p.y);\n        mxy = max(mxy, p.y);\n    }\n    if (mnx == mxx) {\n        if (mxx < MAXC) ++mxx;\n        else --mnx;\n    }\n    if (mny == mxy) {\n        if (mxy < MAXC) ++mxy;\n        else --mny;\n    }\n    return {mnx, mny, mxx, mxy};\n}\n\nstatic void refine_seed(const Rect& seed, const vector<Pt>& pts, Answer& best, bool fine) {\n    if (!valid_rect(seed)) return;\n\n    int w = seed.x2 - seed.x1;\n    int h = seed.y2 - seed.y1;\n    int pad = fine ? clamp(max(w, h) + 1000, 800, 4000)\n                   : clamp(max(w, h) * 2 + 1500, 1500, 7000);\n    Rect region = expand_rect(seed, pad);\n    if (!valid_rect(region)) return;\n\n    int d = max(region.x2 - region.x1, region.y2 - region.y1);\n    vector<int> scales = fine\n        ? vector<int>{max(40, d / 28), max(60, d / 16), max(90, d / 10)}\n        : vector<int>{max(70, d / 20), max(120, d / 12), max(180, d / 8)};\n\n    scales = uniq_sorted(scales);\n    sort(scales.rbegin(), scales.rend());\n\n    for (int S : scales) {\n        auto phases = phase_list_local(S, seed, region);\n        for (auto [ox, oy] : phases) {\n            GridData g = build_grid_region(pts, region.x1, region.x2, region.y1, region.y2, S, ox, oy);\n            process_grid(g, pts, best, nullptr);\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<Pt> mackerels(N), sardines(N), pts;\n    pts.reserve(2 * N);\n\n    for (int i = 0; i < N; ++i) {\n        cin >> mackerels[i].x >> mackerels[i].y;\n        mackerels[i].w = +1;\n        pts.push_back(mackerels[i]);\n    }\n    for (int i = 0; i < N; ++i) {\n        cin >> sardines[i].x >> sardines[i].y;\n        sardines[i].w = -1;\n        pts.push_back(sardines[i]);\n    }\n\n    Answer best;\n    best.score = INT_MIN;\n    best.area = (1LL << 60);\n\n    vector<Rect> seeds;\n\n    // Tiny safe rectangles around sampled mackerels.\n    int step = max(1, N / 20);\n    for (int i = 0; i < N; i += step) {\n        int x1 = max(0, mackerels[i].x - 1);\n        int y1 = max(0, mackerels[i].y - 1);\n        int x2 = min(MAXC, mackerels[i].x + 1);\n        int y2 = min(MAXC, mackerels[i].y + 1);\n        if (x1 == x2) {\n            if (x2 < MAXC) ++x2;\n            else --x1;\n        }\n        if (y1 == y2) {\n            if (y2 < MAXC) ++y2;\n            else --y1;\n        }\n        Rect r{x1, y1, x2, y2};\n        seeds.push_back(r);\n        consider_rect(best, r, pts);\n    }\n\n    // Mackerel bounding box.\n    Rect mb = bbox_of_mackerels(mackerels);\n    seeds.push_back(mb);\n    consider_rect(best, mb, pts);\n\n    // Global multi-scale search.\n    vector<int> scales = {700, 1200, 2000, 3200, 5000};\n    for (int S : scales) {\n        for (auto [ox, oy] : phase_list_global(S)) {\n            GridData g = build_grid_region(pts, 0, MAXC, 0, MAXC, S, ox, oy);\n            process_grid(g, pts, best, &seeds);\n        }\n    }\n\n    // Deduplicate seeds.\n    sort(seeds.begin(), seeds.end(), [](const Rect& a, const Rect& b) {\n        if (a.x1 != b.x1) return a.x1 < b.x1;\n        if (a.y1 != b.y1) return a.y1 < b.y1;\n        if (a.x2 != b.x2) return a.x2 < b.x2;\n        return a.y2 < b.y2;\n    });\n    seeds.erase(unique(seeds.begin(), seeds.end(), [](const Rect& a, const Rect& b) {\n        return a.x1 == b.x1 && a.y1 == b.y1 && a.x2 == b.x2 && a.y2 == b.y2;\n    }), seeds.end());\n\n    // Rank seeds by exact rectangle score and keep the best few.\n    vector<pair<int, Rect>> ranked;\n    ranked.reserve(seeds.size());\n    for (const auto& r : seeds) {\n        ranked.push_back({exact_rect_score(r, pts), r});\n    }\n    sort(ranked.begin(), ranked.end(), [](const auto& a, const auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return rect_area(a.second) < rect_area(b.second);\n    });\n    if ((int)ranked.size() > 6) ranked.resize(6);\n\n    // Local refinement around strong seeds.\n    for (const auto& [sc, r] : ranked) {\n        (void)sc;\n        refine_seed(r, pts, best, false);\n    }\n\n    // One extra pass around the current best polygon.\n    if (!best.poly.empty()) {\n        Rect br{MAXC, MAXC, 0, 0};\n        for (const auto& p : best.poly) {\n            br.x1 = min(br.x1, p.x);\n            br.y1 = min(br.y1, p.y);\n            br.x2 = max(br.x2, p.x);\n            br.y2 = max(br.y2, p.y);\n        }\n        if (valid_rect(br)) {\n            refine_seed(br, pts, best, true);\n        }\n    }\n\n    if (best.poly.empty()) {\n        best.poly = make_rect_poly(0, 0, 1, 1);\n    }\n\n    cout << best.poly.size() << '\\n';\n    for (const auto& p : best.poly) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing i128 = __int128_t;\n\nstruct Rect {\n    ll w, h;\n};\n\nstruct Op {\n    int p, r, b;\n    char d;\n};\n\nstruct SegPlan {\n    ll W = 0, H = 0;\n    int anchor = 0;          // relative index in the segment\n    vector<int> rot;         // 0/1 for each rectangle in the segment\n};\n\nstruct State {\n    ll W, H;\n    int prev_i = -1, prev_idx = -1, plan_idx = -1;\n};\n\nstruct Dataset {\n    vector<Rect> rects;  // local order\n    vector<int> orig;    // local -> original index\n    ll penalty = 0;      // omitted rectangles penalty\n};\n\nstruct Cand {\n    vector<Op> ops;\n    ll score = 0;\n    string sig;\n};\n\nstatic string serialize_ops(const vector<Op>& ops) {\n    string s;\n    s.reserve(ops.size() * 16);\n    for (const auto& op : ops) {\n        s += to_string(op.p);\n        s.push_back(',');\n        s += to_string(op.r);\n        s.push_back(',');\n        s.push_back(op.d);\n        s.push_back(',');\n        s += to_string(op.b);\n        s.push_back(';');\n    }\n    return s;\n}\n\nstatic uint64_t hash_plan(const SegPlan& p) {\n    uint64_t h = 1469598103934665603ULL;\n    for (int x : p.rot) {\n        h ^= (uint64_t)(x + 1);\n        h *= 1099511628211ULL;\n    }\n    h ^= (uint64_t)p.anchor + 0x9e3779b97f4a7c15ULL;\n    h *= 1099511628211ULL;\n    return h;\n}\n\nstatic pair<ll,ll> pack_dims(const Rect& x, bool rowMode, int rot) {\n    // rowMode:\n    //   rot=0 -> (w, h)\n    //   rot=1 -> (h, w)\n    // colMode:\n    //   rot=0 -> (h, w)\n    //   rot=1 -> (w, h)\n    if (rowMode) {\n        return rot ? make_pair(x.h, x.w) : make_pair(x.w, x.h);\n    } else {\n        return rot ? make_pair(x.w, x.h) : make_pair(x.h, x.w);\n    }\n}\n\nstatic int choose_rot_policy(const Rect& x, bool rowMode, int policy, int idx) {\n    auto [w0, h0] = pack_dims(x, rowMode, 0);\n    auto [w1, h1] = pack_dims(x, rowMode, 1);\n\n    auto choose_by = [&](ll a, ll b) {\n        i128 v0 = (i128)a * w0 + (i128)b * h0;\n        i128 v1 = (i128)a * w1 + (i128)b * h1;\n        if (v1 < v0) return 1;\n        if (v0 < v1) return 0;\n        ll s0 = w0 + h0, s1 = w1 + h1;\n        if (s1 < s0) return 1;\n        if (s0 < s1) return 0;\n        return (w1 < w0) ? 1 : 0;\n    };\n\n    switch (policy) {\n        case 0: // min width / height\n            return rowMode ? ((w1 < w0) ? 1 : 0) : ((h1 < h0) ? 1 : 0);\n        case 1: // min other dimension\n            return rowMode ? ((h1 < h0) ? 1 : 0) : ((w1 < w0) ? 1 : 0);\n        case 2: // min max-side\n        {\n            ll s0 = max(w0, h0), s1 = max(w1, h1);\n            if (s1 < s0) return 1;\n            if (s0 < s1) return 0;\n            return rowMode ? ((w1 < w0) ? 1 : 0) : ((h1 < h0) ? 1 : 0);\n        }\n        case 3: // threshold 1.0\n            return rowMode ? ((w0 > h0) ? 1 : 0) : ((h0 > w0) ? 1 : 0);\n        case 4: // threshold 1.2\n            return rowMode ? (((i128)w0 * 5 > (i128)h0 * 6) ? 1 : 0)\n                           : (((i128)h0 * 5 > (i128)w0 * 6) ? 1 : 0);\n        case 5: // threshold 1.5\n            return rowMode ? (((i128)w0 * 2 > (i128)h0 * 3) ? 1 : 0)\n                           : (((i128)h0 * 2 > (i128)w0 * 3) ? 1 : 0);\n        case 6: // parity mix\n            return (idx & 1) ? choose_by(1, 2) : choose_by(2, 1);\n        case 7: // hash mix\n        {\n            uint64_t z = (uint64_t)idx * 1000003ULL\n                       ^ (uint64_t)x.w * 911382323ULL\n                       ^ (uint64_t)x.h * 972663749ULL;\n            return (z & 1ULL) ? choose_by(1, 1) : choose_by(2, 1);\n        }\n        default:\n            return choose_by(1, 1);\n    }\n}\n\nstatic vector<int> select_cap_indices(const vector<ll>& vals, int pattern) {\n    int m = (int)vals.size();\n    set<int> st;\n    auto add = [&](int idx) {\n        if (0 <= idx && idx < m) st.insert(idx);\n    };\n\n    if (pattern == 0) {\n        add(0);\n        add(m / 4);\n        add(m / 2);\n        add((3 * m) / 4);\n        add(m - 1);\n    } else if (pattern == 1) {\n        add(0);\n        add(m / 6);\n        add(m / 3);\n        add(m / 2);\n        add((2 * m) / 3);\n        add((5 * m) / 6);\n        add(m - 1);\n    } else {\n        add(0);\n        add(m / 8);\n        add(m / 4);\n        add((3 * m) / 8);\n        add(m / 2);\n        add((5 * m) / 8);\n        add((3 * m) / 4);\n        add((7 * m) / 8);\n        add(m - 1);\n    }\n\n    return vector<int>(st.begin(), st.end());\n}\n\nstatic bool build_segment_plan(\n    const vector<Rect>& a, int l, int r, ll cap, bool rowMode, int variant, SegPlan& out\n) {\n    int m = r - l;\n    out.rot.assign(m, 0);\n\n    ll W = 0, H = 0;\n    int anchor = 0;\n\n    for (int k = 0; k < m; ++k) {\n        const Rect& x = a[l + k];\n        auto [w0, h0] = pack_dims(x, rowMode, 0);\n        auto [w1, h1] = pack_dims(x, rowMode, 1);\n\n        bool f0 = rowMode ? (h0 <= cap) : (w0 <= cap);\n        bool f1 = rowMode ? (h1 <= cap) : (w1 <= cap);\n        if (!f0 && !f1) return false;\n\n        int rot = 0;\n        if (f0 && f1) {\n            bool choose1 = false;\n            if (variant == 0) {\n                // minimize width (row) / height (col)\n                if (rowMode) {\n                    if (w1 < w0 || (w1 == w0 && h1 < h0)) choose1 = true;\n                } else {\n                    if (h1 < h0 || (h1 == h0 && w1 < w0)) choose1 = true;\n                }\n            } else if (variant == 1) {\n                // minimize max-side\n                ll s0 = max(w0, h0), s1 = max(w1, h1);\n                if (s1 < s0 || (s1 == s0 && ((rowMode ? w1 : h1) < (rowMode ? w0 : h0)))) choose1 = true;\n            } else {\n                // minimize abs difference\n                ll d0 = llabs(w0 - h0), d1 = llabs(w1 - h1);\n                if (d1 < d0 || (d1 == d0 && ((rowMode ? w1 : h1) < (rowMode ? w0 : h0)))) choose1 = true;\n            }\n            rot = choose1 ? 1 : 0;\n        } else {\n            rot = f1 ? 1 : 0;\n        }\n\n        ll w = rot ? w1 : w0;\n        ll h = rot ? h1 : h0;\n        out.rot[k] = rot;\n\n        if (rowMode) {\n            W += w;\n            if (h > H) {\n                H = h;\n                anchor = k;\n            }\n        } else {\n            W = max(W, w);\n            H += h;\n            if (w > W) {\n                W = w;\n                anchor = k;\n            }\n        }\n    }\n\n    out.W = W;\n    out.H = H;\n    out.anchor = anchor;\n    return true;\n}\n\nstatic vector<State> prune_frontier(vector<State> cand, int limit) {\n    if (cand.empty()) return cand;\n\n    sort(cand.begin(), cand.end(), [](const State& a, const State& b) {\n        if (a.W != b.W) return a.W < b.W;\n        if (a.H != b.H) return a.H < b.H;\n        if (a.prev_i != b.prev_i) return a.prev_i < b.prev_i;\n        if (a.prev_idx != b.prev_idx) return a.prev_idx < b.prev_idx;\n        return a.plan_idx < b.plan_idx;\n    });\n\n    // keep the best H for each W\n    vector<State> uniqW;\n    uniqW.reserve(cand.size());\n    for (size_t i = 0; i < cand.size();) {\n        size_t j = i + 1;\n        State best = cand[i];\n        while (j < cand.size() && cand[j].W == cand[i].W) {\n            if (cand[j].H < best.H) best = cand[j];\n            ++j;\n        }\n        uniqW.push_back(best);\n        i = j;\n    }\n\n    // Pareto frontier\n    vector<State> front;\n    front.reserve(uniqW.size());\n    ll bestH = (1LL << 62);\n    for (auto &s : uniqW) {\n        if (s.H < bestH) {\n            front.push_back(s);\n            bestH = s.H;\n        }\n    }\n\n    if ((int)front.size() <= limit) return front;\n\n    set<int> idxs;\n    auto add = [&](int idx) {\n        if (0 <= idx && idx < (int)front.size()) idxs.insert(idx);\n    };\n\n    add(0);\n    add((int)front.size() - 1);\n    add((int)front.size() / 2);\n    add((int)front.size() / 3);\n    add((2 * (int)front.size()) / 3);\n\n    vector<pair<ll,ll>> forms = {\n        {1,1}, {2,1}, {1,2}, {3,1}, {1,3},\n        {5,2}, {2,5}, {8,3}, {3,8}, {13,5}, {5,13}\n    };\n    auto best_by_linear = [&](ll a, ll b) {\n        int best = 0;\n        i128 bv = (i128)a * front[0].W + (i128)b * front[0].H;\n        for (int i = 1; i < (int)front.size(); ++i) {\n            i128 v = (i128)a * front[i].W + (i128)b * front[i].H;\n            if (v < bv || (v == bv && (front[i].W + front[i].H < front[best].W + front[best].H))) {\n                bv = v;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    for (auto [a, b] : forms) {\n        int p = best_by_linear(a, b);\n        add(p);\n        add(p - 1);\n        add(p + 1);\n    }\n\n    int K = min(limit, (int)front.size());\n    if (K >= 2) {\n        for (int k = 0; k < K; ++k) {\n            int idx = (int)((1LL * k * ((int)front.size() - 1)) / (K - 1));\n            add(idx);\n        }\n    } else {\n        add(0);\n    }\n\n    vector<State> sel;\n    sel.reserve(idxs.size());\n    for (int idx : idxs) sel.push_back(front[idx]);\n\n    if ((int)sel.size() > limit) sel.resize(limit);\n    return sel;\n}\n\nstatic vector<int> select_final_indices(const vector<State>& front) {\n    vector<int> ids;\n    if (front.empty()) return ids;\n\n    set<int> idxs;\n    auto add = [&](int idx) {\n        if (0 <= idx && idx < (int)front.size()) idxs.insert(idx);\n    };\n\n    int m = (int)front.size();\n    add(0);\n    add(m - 1);\n    add(m / 2);\n    add(m / 3);\n    add((2 * m) / 3);\n\n    vector<pair<ll,ll>> forms = {\n        {1,1}, {2,1}, {1,2}, {3,1}, {1,3},\n        {4,1}, {1,4}, {5,2}, {2,5}, {7,3}, {3,7},\n        {11,4}, {4,11}\n    };\n\n    auto best_by_linear = [&](ll a, ll b) {\n        int best = 0;\n        i128 bv = (i128)a * front[0].W + (i128)b * front[0].H;\n        for (int i = 1; i < m; ++i) {\n            i128 v = (i128)a * front[i].W + (i128)b * front[i].H;\n            if (v < bv || (v == bv && front[i].W + front[i].H < front[best].W + front[best].H)) {\n                bv = v;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    for (auto [a, b] : forms) {\n        int p = best_by_linear(a, b);\n        add(p);\n        add(p - 1);\n        add(p + 1);\n    }\n\n    int K = min(m, 16);\n    if (K >= 2) {\n        for (int k = 0; k < K; ++k) {\n            int idx = (int)((1LL * k * (m - 1)) / (K - 1));\n            add(idx);\n        }\n    } else {\n        add(0);\n    }\n\n    for (int idx : idxs) ids.push_back(idx);\n    return ids;\n}\n\nstatic vector<Op> reconstruct_ops(\n    const vector<Rect>& rects,\n    const vector<int>& orig,\n    const vector<vector<vector<SegPlan>>>& plans,\n    const vector<vector<State>>& dp,\n    bool rowMode,\n    int idx\n) {\n    int N = (int)rects.size();\n    vector<tuple<int,int,int>> steps; // (l, r, stateIdxAtR)\n    int cur_i = N, cur_idx = idx;\n\n    while (cur_i > 0) {\n        const State& s = dp[cur_i][cur_idx];\n        steps.push_back({s.prev_i, cur_i, cur_idx});\n        cur_idx = s.prev_idx;\n        cur_i = s.prev_i;\n    }\n    reverse(steps.begin(), steps.end());\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int prev_anchor = -1;\n    bool firstSeg = true;\n\n    for (auto [l, r, sidx] : steps) {\n        const State& s = dp[r][sidx];\n        const SegPlan& p = plans[l][r][s.plan_idx];\n\n        if (firstSeg) {\n            ops.push_back({orig[l], p.rot[0], -1, 'U'});\n        } else {\n            ops.push_back({orig[l], p.rot[0], prev_anchor, rowMode ? 'L' : 'U'});\n        }\n\n        for (int k = 1; k < (int)p.rot.size(); ++k) {\n            ops.push_back({orig[l + k], p.rot[k], orig[l + k - 1], rowMode ? 'U' : 'L'});\n        }\n\n        prev_anchor = orig[l + p.anchor];\n        firstSeg = false;\n    }\n\n    return ops;\n}\n\nstatic vector<Cand> build_family_candidates(const Dataset& ds, bool rowMode, int pattern) {\n    int N = (int)ds.rects.size();\n\n    vector<vector<vector<SegPlan>>> plans(N + 1, vector<vector<SegPlan>>(N + 1));\n\n    // Precompute interval plans\n    for (int l = 0; l < N; ++l) {\n        vector<ll> vals;\n        vals.reserve(2 * (N - l));\n        for (int r = l + 1; r <= N; ++r) {\n            const Rect& x = ds.rects[r - 1];\n            vals.push_back(x.w);\n            vals.push_back(x.h);\n\n            vector<ll> u = vals;\n            sort(u.begin(), u.end());\n            u.erase(unique(u.begin(), u.end()), u.end());\n\n            vector<int> idxs = select_cap_indices(u, pattern);\n            unordered_set<uint64_t> seen;\n            seen.reserve(idxs.size() * 4 + 8);\n\n            for (int id : idxs) {\n                ll cap = u[id];\n                for (int variant = 0; variant < 3; ++variant) {\n                    SegPlan p;\n                    if (build_segment_plan(ds.rects, l, r, cap, rowMode, variant, p)) {\n                        uint64_t h = hash_plan(p);\n                        if (seen.insert(h).second) plans[l][r].push_back(std::move(p));\n                    }\n                }\n            }\n\n            if (plans[l][r].empty()) {\n                // Extremely defensive fallback\n                SegPlan p;\n                build_segment_plan(ds.rects, l, r, u.back(), rowMode, 0, p);\n                plans[l][r].push_back(std::move(p));\n            }\n        }\n    }\n\n    // Prefix DP\n    vector<vector<State>> dp(N + 1);\n    dp[0].push_back({0, 0, -1, -1, -1});\n\n    const int LIMIT = 100;\n\n    for (int i = 1; i <= N; ++i) {\n        vector<State> cand;\n        for (int j = 0; j < i; ++j) {\n            const auto& vecPlans = plans[j][i];\n            const auto& prev = dp[j];\n            if (vecPlans.empty() || prev.empty()) continue;\n\n            cand.reserve(cand.size() + prev.size() * vecPlans.size());\n            for (int pid = 0; pid < (int)vecPlans.size(); ++pid) {\n                const SegPlan& p = vecPlans[pid];\n                for (int s = 0; s < (int)prev.size(); ++s) {\n                    const State& st = prev[s];\n                    cand.push_back({\n                        max(st.W, p.W),\n                        st.H + p.H,\n                        j, s, pid\n                    });\n                }\n            }\n        }\n        dp[i] = prune_frontier(std::move(cand), LIMIT);\n    }\n\n    // Extract representative final states\n    vector<Cand> res;\n    const auto& front = dp[N];\n    vector<int> ids = select_final_indices(front);\n\n    unordered_set<string> seen;\n    seen.reserve(ids.size() * 2 + 8);\n\n    for (int idx : ids) {\n        if (idx < 0 || idx >= (int)front.size()) continue;\n        vector<Op> ops = reconstruct_ops(ds.rects, ds.orig, plans, dp, rowMode, idx);\n\n        Cand c;\n        c.ops = std::move(ops);\n        c.score = front[idx].W + front[idx].H + ds.penalty;\n        c.sig = serialize_ops(c.ops);\n\n        if (seen.insert(c.sig).second) res.push_back(std::move(c));\n    }\n\n    return res;\n}\n\nstatic Cand build_chain_candidate(const Dataset& ds, bool rowMode, int policy) {\n    int N = (int)ds.rects.size();\n    Cand c;\n    vector<Op> ops;\n    ops.reserve(N);\n\n    ll W = 0, H = 0;\n    for (int i = 0; i < N; ++i) {\n        int r = choose_rot_policy(ds.rects[i], rowMode, policy, i);\n        auto [w, h] = pack_dims(ds.rects[i], rowMode, r);\n        if (rowMode) {\n            W += w;\n            H = max(H, h);\n        } else {\n            W = max(W, w);\n            H += h;\n        }\n\n        if (i == 0) {\n            ops.push_back({ds.orig[i], r, -1, 'U'});\n        } else {\n            ops.push_back({ds.orig[i], r, ds.orig[i - 1], rowMode ? 'U' : 'L'});\n        }\n    }\n\n    c.ops = std::move(ops);\n    c.score = W + H + ds.penalty;\n    c.sig = serialize_ops(c.ops);\n    return c;\n}\n\nstatic Dataset make_full_dataset(const vector<Rect>& base) {\n    Dataset ds;\n    ds.rects = base;\n    ds.orig.resize(base.size());\n    iota(ds.orig.begin(), ds.orig.end(), 0);\n    ds.penalty = 0;\n    return ds;\n}\n\nstatic Dataset make_drop_dataset(const vector<Rect>& base, int omit) {\n    Dataset ds;\n    ds.penalty = base[omit].w + base[omit].h;\n    ds.rects.reserve(base.size() - 1);\n    ds.orig.reserve(base.size() - 1);\n    for (int i = 0; i < (int)base.size(); ++i) {\n        if (i == omit) continue;\n        ds.rects.push_back(base[i]);\n        ds.orig.push_back(i);\n    }\n    return ds;\n}\n\nstatic int argmax_perimeter(const vector<Rect>& base) {\n    int id = 0;\n    for (int i = 1; i < (int)base.size(); ++i) {\n        ll a = base[i].w + base[i].h;\n        ll b = base[id].w + base[id].h;\n        if (a > b) id = i;\n    }\n    return id;\n}\n\nstatic int argmax_maxside(const vector<Rect>& base) {\n    int id = 0;\n    for (int i = 1; i < (int)base.size(); ++i) {\n        ll a = max(base[i].w, base[i].h);\n        ll b = max(base[id].w, base[id].h);\n        if (a > b) id = i;\n    }\n    return id;\n}\n\nstatic int argmax_area(const vector<Rect>& base) {\n    int id = 0;\n    for (int i = 1; i < (int)base.size(); ++i) {\n        i128 a = (i128)base[i].w * base[i].h;\n        i128 b = (i128)base[id].w * base[id].h;\n        if (a > b) id = i;\n    }\n    return id;\n}\n\nstatic int argmax_aspect(const vector<Rect>& base) {\n    int id = 0;\n    for (int i = 1; i < (int)base.size(); ++i) {\n        ll a1 = max(base[i].w, base[i].h), a2 = min(base[i].w, base[i].h);\n        ll b1 = max(base[id].w, base[id].h), b2 = min(base[id].w, base[id].h);\n        if ((i128)a1 * b2 > (i128)b1 * a2) id = i;\n    }\n    return id;\n}\n\nstatic void add_candidate(\n    vector<Cand>& pool,\n    unordered_map<string, int>& pos,\n    Cand c\n) {\n    auto it = pos.find(c.sig);\n    if (it == pos.end()) {\n        pos.emplace(c.sig, (int)pool.size());\n        pool.push_back(std::move(c));\n    } else {\n        int idx = it->second;\n        if (c.score < pool[idx].score) pool[idx] = std::move(c);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    ll sigma;\n    cin >> N >> T >> sigma;\n\n    vector<Rect> base(N);\n    for (int i = 0; i < N; ++i) cin >> base[i].w >> base[i].h;\n\n    vector<Cand> pool;\n    unordered_map<string, int> pos;\n    pos.reserve(2048);\n\n    Dataset full = make_full_dataset(base);\n\n    // Cheap baselines on the full set\n    for (int mode = 0; mode < 2; ++mode) {\n        bool rowMode = (mode == 0);\n        for (int policy = 0; policy <= 7; ++policy) {\n            add_candidate(pool, pos, build_chain_candidate(full, rowMode, policy));\n        }\n    }\n\n    // Cheap omission baselines\n    vector<int> drops = {\n        argmax_perimeter(base),\n        argmax_maxside(base),\n        argmax_area(base),\n        argmax_aspect(base)\n    };\n    sort(drops.begin(), drops.end());\n    drops.erase(unique(drops.begin(), drops.end()), drops.end());\n\n    for (int omit : drops) {\n        Dataset ds = make_drop_dataset(base, omit);\n        for (int mode = 0; mode < 2; ++mode) {\n            bool rowMode = (mode == 0);\n            for (int policy = 0; policy <= 2; ++policy) {\n                add_candidate(pool, pos, build_chain_candidate(ds, rowMode, policy));\n            }\n        }\n    }\n\n    // Stronger families: cap-based interval DP\n    for (int pattern = 0; pattern < 3; ++pattern) {\n        for (int mode = 0; mode < 2; ++mode) {\n            bool rowMode = (mode == 0);\n            vector<Cand> cands = build_family_candidates(full, rowMode, pattern);\n            for (auto& c : cands) add_candidate(pool, pos, std::move(c));\n        }\n    }\n\n    if (pool.empty()) {\n        Cand c;\n        vector<Op> ops;\n        for (int i = 0; i < N; ++i) {\n            if (i == 0) ops.push_back({i, 0, -1, 'U'});\n            else ops.push_back({i, 0, i - 1, 'U'});\n        }\n        c.ops = std::move(ops);\n        c.score = 0;\n        c.sig = serialize_ops(c.ops);\n        pool.push_back(std::move(c));\n    }\n\n    sort(pool.begin(), pool.end(), [](const Cand& a, const Cand& b) {\n        if (a.score != b.score) return a.score < b.score;\n        return a.sig < b.sig;\n    });\n\n    int use = min(T, (int)pool.size());\n    for (int t = 0; t < use; ++t) {\n        const Cand& c = pool[t];\n        cout << c.ops.size() << '\\n';\n        for (const auto& op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm; // Feedback is noisy; the candidate set is fixed in advance.\n    }\n\n    for (int t = use; t < T; ++t) {\n        const Cand& c = pool[0];\n        cout << c.ops.size() << '\\n';\n        for (const auto& op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        ll Wm, Hm;\n        cin >> Wm >> Hm;\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing Key = array<long long, 6>;\n\nstruct Move {\n    long long gain = 0;\n    int v = -1, u = -1;\n};\n\nstruct Info {\n    vector<vector<int>> children;\n    vector<int> parent, roots, comp, depth, tin, tout, maxDown;\n    vector<long long> subW;\n    vector<vector<int>> compNodes;\n    long long score = 0;\n};\n\nstatic int N, M, H;\nstatic vector<int> A, X, Y, degv, r2v, mort, bucket8, neighSum;\nstatic vector<vector<int>> adj;\nstatic chrono::steady_clock::time_point start_time;\n\nstatic inline bool time_up() {\n    return chrono::duration_cast<chrono::milliseconds>(\n        chrono::steady_clock::now() - start_time\n    ).count() > 1850;\n}\n\nstatic int morton_code(int x, int y) {\n    int z = 0;\n    for (int i = 0; i < 10; ++i) {\n        z |= ((x >> i) & 1) << (2 * i);\n        z |= ((y >> i) & 1) << (2 * i + 1);\n    }\n    return z;\n}\n\nstatic inline long long sqdist(int i, int j) {\n    long long dx = X[i] - X[j];\n    long long dy = Y[i] - Y[j];\n    return dx * dx + dy * dy;\n}\n\nstatic Key rootKeyLowDeg(int v)   { return {A[v], degv[v], -r2v[v], neighSum[v], mort[v], v}; }\nstatic Key rootKeyHighDeg(int v)  { return {A[v], -degv[v], -r2v[v], neighSum[v], mort[v], v}; }\nstatic Key rootKeyNeigh(int v)    { return {A[v], neighSum[v], -degv[v], -r2v[v], mort[v], v}; }\nstatic Key rootKeySpread(int v)   { return {A[v], bucket8[v], r2v[v], -degv[v], mort[v], v}; }\n\nstatic Key prefLowDeg(int v)      { return {A[v], degv[v], -r2v[v], neighSum[v], mort[v], v}; }\nstatic Key prefHighDeg(int v)     { return {A[v], -degv[v], -r2v[v], neighSum[v], mort[v], v}; }\nstatic Key prefNeigh(int v)       { return {A[v], neighSum[v], degv[v], -r2v[v], mort[v], v}; }\n\nstatic Key childLowA(int v)       { return {A[v], degv[v], r2v[v], neighSum[v], mort[v], v}; }\nstatic Key childHighA(int v)      { return {-A[v], -degv[v], -r2v[v], -neighSum[v], mort[v], v}; }\n\nstatic Info compute_info(const vector<int>& parent) {\n    Info info;\n    info.parent = parent;\n    info.children.assign(N, {});\n    info.roots.clear();\n\n    for (int v = 0; v < N; ++v) {\n        if (parent[v] == -1) info.roots.push_back(v);\n        else info.children[parent[v]].push_back(v);\n    }\n\n    info.comp.assign(N, -1);\n    info.depth.assign(N, -1);\n    info.tin.assign(N, -1);\n    info.tout.assign(N, -1);\n    info.subW.assign(N, 0);\n    info.maxDown.assign(N, 0);\n    info.compNodes.clear();\n    info.score = 0;\n\n    int timer = 0, cid = 0;\n    for (int r : info.roots) {\n        info.compNodes.push_back({});\n        auto dfs = [&](auto&& self, int v, int d) -> void {\n            info.comp[v] = cid;\n            info.depth[v] = d;\n            info.tin[v] = timer++;\n            info.subW[v] = A[v];\n            info.maxDown[v] = 0;\n            info.score += 1LL * (d + 1) * A[v];\n            info.compNodes.back().push_back(v);\n            for (int ch : info.children[v]) {\n                self(self, ch, d + 1);\n                info.subW[v] += info.subW[ch];\n                info.maxDown[v] = max(info.maxDown[v], info.maxDown[ch] + 1);\n            }\n            info.tout[v] = timer;\n        };\n        dfs(dfs, r, 0);\n        ++cid;\n    }\n\n    return info;\n}\n\ntemplate <class PrefFunc>\nstatic vector<int> build_greedy(const vector<int>& order, PrefFunc pref) {\n    vector<int> parent(N, -2), depth(N, -1);\n\n    for (int v : order) {\n        int best = -1;\n        for (int u : adj[v]) {\n            if (depth[u] == -1 || depth[u] >= H) continue;\n            if (best == -1 ||\n                depth[u] > depth[best] ||\n                (depth[u] == depth[best] && pref(u) < pref(best))) {\n                best = u;\n            }\n        }\n        if (best == -1) {\n            parent[v] = -1;\n            depth[v] = 0;\n        } else {\n            parent[v] = best;\n            depth[v] = depth[best] + 1;\n        }\n    }\n\n    for (int i = 0; i < N; ++i) if (parent[i] == -2) parent[i] = -1;\n    return parent;\n}\n\nstatic vector<int> choose_seeds(const vector<int>& order, int K) {\n    vector<int> pool;\n    int lim = min(N, 250);\n    for (int i = 0; i < lim; ++i) pool.push_back(order[i]);\n\n    vector<int> seeds;\n    vector<char> used(N, 0);\n    if (pool.empty()) return seeds;\n\n    seeds.push_back(pool[0]);\n    used[pool[0]] = 1;\n\n    while ((int)seeds.size() < K) {\n        int best = -1;\n        long long bestScore = LLONG_MIN;\n        for (int v : pool) {\n            if (used[v]) continue;\n            long long md = (1LL << 60);\n            for (int s : seeds) md = min(md, sqdist(v, s));\n            long long score = md * 1000LL + 2000LL * degv[v] - 10000LL * A[v] - 20LL * r2v[v];\n            if (score > bestScore) {\n                bestScore = score;\n                best = v;\n            }\n        }\n        if (best == -1) break;\n        used[best] = 1;\n        seeds.push_back(best);\n    }\n    return seeds;\n}\n\ntemplate <class KeyFunc>\nstatic vector<int> build_connected_order(const vector<int>& seeds, KeyFunc key) {\n    vector<int> ord;\n    ord.reserve(N);\n\n    using P = pair<Key, int>;\n    priority_queue<P, vector<P>, greater<P>> pq;\n    vector<char> inq(N, 0), vis(N, 0);\n\n    if (seeds.empty()) {\n        pq.push({key(0), 0});\n        inq[0] = 1;\n    } else {\n        for (int s : seeds) {\n            if (!inq[s]) {\n                inq[s] = 1;\n                pq.push({key(s), s});\n            }\n        }\n    }\n\n    while (!pq.empty()) {\n        auto [k, v] = pq.top();\n        pq.pop();\n        if (vis[v]) continue;\n        vis[v] = 1;\n        ord.push_back(v);\n        for (int to : adj[v]) {\n            if (!inq[to]) {\n                inq[to] = 1;\n                pq.push({key(to), to});\n            }\n        }\n    }\n    return ord;\n}\n\ntemplate <class ChildKeyFunc>\nstatic vector<int> build_dfs_forest(const vector<int>& rootOrder, ChildKeyFunc childKey) {\n    vector<vector<int>> ordAdj = adj;\n    for (int v = 0; v < N; ++v) {\n        sort(ordAdj[v].begin(), ordAdj[v].end(), [&](int x, int y) {\n            return childKey(x) < childKey(y);\n        });\n    }\n\n    vector<int> parent(N, -2);\n    vector<char> vis(N, 0);\n\n    auto dfs = [&](auto&& self, int v, int d) -> void {\n        vis[v] = 1;\n        if (d == H) return;\n        for (int to : ordAdj[v]) {\n            if (!vis[to]) {\n                parent[to] = v;\n                self(self, to, d + 1);\n            }\n        }\n    };\n\n    for (int r : rootOrder) {\n        if (!vis[r]) {\n            parent[r] = -1;\n            dfs(dfs, r, 0);\n        }\n    }\n\n    for (int v = 0; v < N; ++v) if (parent[v] == -2) parent[v] = -1;\n    return parent;\n}\n\nstatic vector<int> exact_root_optimize(const vector<int>& parentIn) {\n    Info info = compute_info(parentIn);\n    vector<int> ans = parentIn;\n    vector<long long> f(N, 0);\n\n    auto bfs = [&](int s) {\n        vector<int> dist(N, -1);\n        queue<int> q;\n        q.push(s);\n        dist[s] = 0;\n        int far = s;\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n            if (dist[v] > dist[far]) far = v;\n            int p = info.parent[v];\n            if (p != -1 && dist[p] == -1) {\n                dist[p] = dist[v] + 1;\n                q.push(p);\n            }\n            for (int ch : info.children[v]) {\n                if (dist[ch] == -1) {\n                    dist[ch] = dist[v] + 1;\n                    q.push(ch);\n                }\n            }\n        }\n        return pair<int, vector<int>>(far, move(dist));\n    };\n\n    for (int cid = 0; cid < (int)info.roots.size(); ++cid) {\n        int root = info.roots[cid];\n        const auto& nodes = info.compNodes[cid];\n        if ((int)nodes.size() == 1) continue;\n\n        long long W = info.subW[root];\n        long long base = 0;\n        for (int v : nodes) base += 1LL * info.depth[v] * A[v];\n\n        f[root] = base;\n        auto dfs = [&](auto&& self, int v) -> void {\n            for (int ch : info.children[v]) {\n                f[ch] = f[v] + W - 2LL * info.subW[ch];\n                self(self, ch);\n            }\n        };\n        dfs(dfs, root);\n\n        auto [x, dx0] = bfs(root);\n        auto [y, dx] = bfs(x);\n        auto [z, dy] = bfs(y);\n        (void)dx0;\n        (void)z;\n\n        int best = root;\n        long long bestVal = f[root];\n        int bestEcc = max(dx[root], dy[root]);\n\n        for (int v : nodes) {\n            int ecc = max(dx[v], dy[v]);\n            if (ecc > H) continue;\n            if (f[v] > bestVal ||\n                (f[v] == bestVal &&\n                 (ecc < bestEcc ||\n                  (ecc == bestEcc &&\n                   (degv[v] > degv[best] ||\n                    (degv[v] == degv[best] &&\n                     (A[v] < A[best] || (A[v] == A[best] && v < best)))))))) {\n                best = v;\n                bestVal = f[v];\n                bestEcc = ecc;\n            }\n        }\n\n        if (best == root) continue;\n\n        vector<char> vis(N, 0);\n        queue<int> q;\n        q.push(best);\n        vis[best] = 1;\n        ans[best] = -1;\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            auto tryPush = [&](int to) {\n                if (!vis[to]) {\n                    vis[to] = 1;\n                    ans[to] = v;\n                    q.push(to);\n                }\n            };\n\n            int p = info.parent[v];\n            if (p != -1) tryPush(p);\n            for (int ch : info.children[v]) tryPush(ch);\n        }\n    }\n\n    return ans;\n}\n\nstatic vector<int> merge_roots(vector<int> parent, int maxIter = 80) {\n    for (int iter = 0; iter < maxIter && !time_up(); ++iter) {\n        Info info = compute_info(parent);\n\n        long long bestGain = 0;\n        int bestV = -1, bestU = -1;\n\n        for (int v = 0; v < N; ++v) {\n            if (parent[v] != -1) continue; // only current roots\n            if (info.maxDown[v] == H) continue;\n            long long W = info.subW[v];\n\n            for (int u : adj[v]) {\n                if (info.comp[u] == info.comp[v]) continue;\n                int shift = info.depth[u] + 1;\n                if (shift + info.maxDown[v] > H) continue;\n\n                long long gain = 1LL * shift * W;\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestV = v;\n                    bestU = u;\n                }\n            }\n        }\n\n        if (bestGain <= 0) break;\n        parent[bestV] = bestU;\n    }\n    return parent;\n}\n\nstatic Move find_best_move(const Info& info, const vector<int>& parent) {\n    long long bestGain = 0;\n    vector<pair<int, int>> cand;\n\n    for (int v = 0; v < N; ++v) {\n        if (info.maxDown[v] == H) continue;\n        for (int u : adj[v]) {\n            if (u == parent[v]) continue;\n            if (info.comp[u] == info.comp[v] &&\n                info.tin[v] <= info.tin[u] && info.tin[u] < info.tout[v]) {\n                continue;\n            }\n\n            int nd = info.depth[u] + 1;\n            if (nd + info.maxDown[v] > H) continue;\n\n            long long gain = 1LL * (nd - info.depth[v]) * info.subW[v];\n            if (gain <= 0) continue;\n\n            if (gain > bestGain) {\n                bestGain = gain;\n                cand.clear();\n                cand.push_back({v, u});\n            } else if (gain == bestGain) {\n                cand.push_back({v, u});\n            }\n        }\n    }\n\n    if (cand.empty()) return {};\n    static mt19937_64 local_rng(123456789);\n    auto [v, u] = cand[local_rng() % cand.size()];\n    return {bestGain, v, u};\n}\n\nstatic vector<int> hill_climb(vector<int> parent, int maxSteps) {\n    for (int step = 0; step < maxSteps && !time_up(); ++step) {\n        Info info = compute_info(parent);\n        Move mv = find_best_move(info, parent);\n        if (mv.v == -1) break;\n        parent[mv.v] = mv.u;\n        if (step % 20 == 19) parent = exact_root_optimize(parent);\n    }\n    return parent;\n}\n\nstatic vector<int> shake(vector<int> parent, mt19937_64& rng, int steps) {\n    Info info = compute_info(parent);\n\n    for (int it = 0; it < steps && !time_up(); ++it) {\n        int v = (int)(rng() % N);\n        if (info.maxDown[v] == H) continue;\n\n        vector<int> cand;\n        for (int u : adj[v]) {\n            if (u == parent[v]) continue;\n            if (info.comp[u] == info.comp[v] &&\n                info.tin[v] <= info.tin[u] && info.tin[u] < info.tout[v]) {\n                continue;\n            }\n            int nd = info.depth[u] + 1;\n            if (nd + info.maxDown[v] > H) continue;\n            cand.push_back(u);\n        }\n        if (cand.empty()) continue;\n\n        int u = cand[rng() % cand.size()];\n        long long gain = 1LL * ((info.depth[u] + 1) - info.depth[v]) * info.subW[v];\n        bool accept = false;\n        if (gain >= 0) accept = true;\n        else if (gain >= -20 && (rng() % 100) < 5) accept = true;\n\n        if (accept) {\n            parent[v] = u;\n            info = compute_info(parent);\n        }\n    }\n\n    return parent;\n}\n\nstatic vector<int> refine(vector<int> parent, mt19937_64& rng) {\n    parent = exact_root_optimize(parent);\n    parent = merge_roots(parent, 60);\n    parent = exact_root_optimize(parent);\n    parent = hill_climb(parent, 40);\n    parent = exact_root_optimize(parent);\n    parent = merge_roots(parent, 40);\n    parent = shake(parent, rng, 50);\n    parent = exact_root_optimize(parent);\n    parent = hill_climb(parent, 20);\n    parent = exact_root_optimize(parent);\n    return parent;\n}\n\nstatic long long evaluate_score(const vector<int>& parent) {\n    return compute_info(parent).score;\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 >> M >> H;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n\n    adj.assign(N, {});\n    vector<pair<int, int>> edges(M);\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n\n    X.resize(N);\n    Y.resize(N);\n    for (int i = 0; i < N; ++i) cin >> X[i] >> Y[i];\n\n    degv.resize(N);\n    r2v.resize(N);\n    mort.resize(N);\n    bucket8.resize(N);\n    neighSum.resize(N);\n\n    const double PI = acos(-1.0);\n    for (int i = 0; i < N; ++i) {\n        degv[i] = (int)adj[i].size();\n        r2v[i] = (X[i] - 500) * (X[i] - 500) + (Y[i] - 500) * (Y[i] - 500);\n        mort[i] = morton_code(X[i], Y[i]);\n\n        long long s = 0;\n        for (int to : adj[i]) s += A[to];\n        neighSum[i] = (int)s;\n\n        double ang = atan2((double)Y[i] - 500.0, (double)X[i] - 500.0);\n        if (ang < 0) ang += 2.0 * PI;\n        int b = (int)(ang / (2.0 * PI) * 8.0);\n        bucket8[i] = max(0, min(7, b));\n    }\n\n    vector<int> ordLowDeg(N), ordHighDeg(N), ordNeigh(N), ordSpread(N);\n    iota(ordLowDeg.begin(), ordLowDeg.end(), 0);\n    iota(ordHighDeg.begin(), ordHighDeg.end(), 0);\n    iota(ordNeigh.begin(), ordNeigh.end(), 0);\n    iota(ordSpread.begin(), ordSpread.end(), 0);\n\n    sort(ordLowDeg.begin(), ordLowDeg.end(), [&](int x, int y) { return rootKeyLowDeg(x) < rootKeyLowDeg(y); });\n    sort(ordHighDeg.begin(), ordHighDeg.end(), [&](int x, int y) { return rootKeyHighDeg(x) < rootKeyHighDeg(y); });\n    sort(ordNeigh.begin(), ordNeigh.end(), [&](int x, int y) { return rootKeyNeigh(x) < rootKeyNeigh(y); });\n    sort(ordSpread.begin(), ordSpread.end(), [&](int x, int y) { return rootKeySpread(x) < rootKeySpread(y); });\n\n    vector<int> seeds1 = choose_seeds(ordLowDeg, 1);\n    vector<int> seeds3 = choose_seeds(ordLowDeg, 3);\n    vector<int> seeds6 = choose_seeds(ordLowDeg, 6);\n    vector<int> seedsH3 = choose_seeds(ordHighDeg, 3);\n    vector<int> seedsN3 = choose_seeds(ordNeigh, 3);\n    vector<int> seedsS6 = choose_seeds(ordSpread, 6);\n\n    vector<int> rootOrderLow = seeds6, rootOrderHigh = seedsH3, rootOrderNeigh = seedsN3, rootOrderSpread = seedsS6;\n    {\n        vector<char> used(N, 0);\n        for (int s : seeds6) used[s] = 1;\n        for (int v : ordLowDeg) if (!used[v]) rootOrderLow.push_back(v);\n\n        fill(used.begin(), used.end(), 0);\n        for (int s : seedsH3) used[s] = 1;\n        for (int v : ordHighDeg) if (!used[v]) rootOrderHigh.push_back(v);\n\n        fill(used.begin(), used.end(), 0);\n        for (int s : seedsN3) used[s] = 1;\n        for (int v : ordNeigh) if (!used[v]) rootOrderNeigh.push_back(v);\n\n        fill(used.begin(), used.end(), 0);\n        for (int s : seedsS6) used[s] = 1;\n        for (int v : ordSpread) if (!used[v]) rootOrderSpread.push_back(v);\n    }\n\n    vector<int> connLow = build_connected_order(seeds6, rootKeyLowDeg);\n    vector<int> connHigh = build_connected_order(seedsH3, rootKeyHighDeg);\n    vector<int> connNeigh = build_connected_order(seedsN3, rootKeyNeigh);\n\n    vector<int> cand1 = build_greedy(ordLowDeg, prefLowDeg);\n    vector<int> cand2 = build_greedy(ordHighDeg, prefHighDeg);\n    vector<int> cand3 = build_greedy(ordNeigh, prefNeigh);\n    vector<int> cand4 = build_greedy(ordSpread, prefLowDeg);\n    vector<int> cand5 = build_greedy(connLow, prefLowDeg);\n    vector<int> cand6 = build_greedy(connHigh, prefHighDeg);\n    vector<int> cand7 = build_greedy(connNeigh, prefNeigh);\n    vector<int> cand8 = build_dfs_forest(rootOrderLow, childLowA);\n    vector<int> cand9 = build_dfs_forest(rootOrderHigh, childHighA);\n    vector<int> cand10 = build_dfs_forest(rootOrderNeigh, childLowA);\n    vector<int> cand11 = build_dfs_forest(rootOrderSpread, childHighA);\n\n    uint64_t seed = 88172645463393265ULL;\n    auto mix = [&](uint64_t x) {\n        seed ^= x + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2);\n    };\n    mix(N); mix(M); mix(H);\n    for (int i = 0; i < N; ++i) {\n        mix((uint64_t)A[i] << 32 ^ (uint64_t)X[i]);\n        mix((uint64_t)Y[i] << 16 ^ (uint64_t)degv[i]);\n    }\n    for (auto [u, v] : edges) mix(((uint64_t)u << 32) ^ (uint64_t)v);\n    mt19937_64 rng(seed);\n\n    struct Sol {\n        long long score = -1;\n        vector<int> parent;\n    };\n\n    vector<vector<int>> bases = {cand1, cand2, cand3, cand4, cand5, cand6, cand7, cand8, cand9, cand10, cand11};\n\n    Sol best;\n    for (auto& b : bases) {\n        if (time_up()) break;\n        vector<int> cur = refine(b, rng);\n        long long sc = evaluate_score(cur);\n        if (sc > best.score) {\n            best.score = sc;\n            best.parent = move(cur);\n        }\n    }\n\n    if (!time_up() && !best.parent.empty()) {\n        for (int rep = 0; rep < 2 && !time_up(); ++rep) {\n            vector<int> cur = best.parent;\n            cur = shake(cur, rng, 70 + 30 * rep);\n            cur = exact_root_optimize(cur);\n            cur = merge_roots(cur, 40);\n            cur = refine(cur, rng);\n            long long sc = evaluate_score(cur);\n            if (sc > best.score) {\n                best.score = sc;\n                best.parent = move(cur);\n            }\n        }\n    }\n\n    if (best.parent.empty()) best.parent.assign(N, -1);\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << best.parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cand {\n    uint64_t mask;   // coverage over Oni bits (reduced universe later)\n    int cost;        // 2 * len\n    int len;         // strip length\n    int idx;         // row/col index\n    char dir;        // L/R/U/D\n    int orig;        // original candidate id\n};\n\nstruct U64Hash {\n    size_t operator()(uint64_t x) const noexcept {\n        x ^= x >> 33;\n        x *= 0xff51afd7ed558ccdULL;\n        x ^= x >> 33;\n        x *= 0xc4ceb9fe1a85ec53ULL;\n        x ^= x >> 33;\n        return (size_t)x;\n    }\n};\n\nstatic inline int pop64(uint64_t x) {\n    return __builtin_popcountll(x);\n}\n\nstatic inline char revDir(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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<string> C(N);\n    for (int i = 0; i < N; ++i) cin >> C[i];\n\n    vector<vector<int>> oniId(N, vector<int>(N, -1));\n    vector<pair<int,int>> oniPos;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'x') {\n                oniId[i][j] = (int)oniPos.size();\n                oniPos.push_back({i, j});\n            }\n        }\n    }\n\n    int M = (int)oniPos.size(); // 40\n    vector<Cand> cands;\n    cands.reserve(200);\n\n    auto addCand = [&](char dir, int idx, int len, uint64_t mask) {\n        if (mask == 0) return;\n        cands.push_back({mask, 2 * len, len, idx, dir, (int)cands.size()});\n    };\n\n    // Generate all useful candidates:\n    // only lengths where the newly removed border cell contains an Oni.\n    for (int i = 0; i < N; ++i) {\n        int firstF = N, lastF = -1;\n        for (int j = 0; j < N; ++j) {\n            if (C[i][j] == 'o') {\n                firstF = min(firstF, j);\n                lastF = max(lastF, j);\n            }\n        }\n\n        uint64_t mask = 0;\n        for (int j = 0; j < firstF; ++j) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('L', i, j + 1, mask);\n            }\n        }\n\n        mask = 0;\n        for (int j = N - 1; j > lastF; --j) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('R', i, N - j, mask);\n            }\n        }\n    }\n\n    for (int j = 0; j < N; ++j) {\n        int firstF = N, lastF = -1;\n        for (int i = 0; i < N; ++i) {\n            if (C[i][j] == 'o') {\n                firstF = min(firstF, i);\n                lastF = max(lastF, i);\n            }\n        }\n\n        uint64_t mask = 0;\n        for (int i = 0; i < firstF; ++i) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('U', j, i + 1, mask);\n            }\n        }\n\n        mask = 0;\n        for (int i = N - 1; i > lastF; --i) {\n            int id = oniId[i][j];\n            if (id != -1) {\n                mask |= 1ULL << id;\n                addCand('D', j, N - i, mask);\n            }\n        }\n    }\n\n    // Deduplicate identical masks, keep the cheapest one.\n    sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.idx < b.idx;\n    });\n\n    vector<Cand> uniq;\n    for (auto &c : cands) {\n        if (uniq.empty() || uniq.back().mask != c.mask) uniq.push_back(c);\n    }\n    cands.swap(uniq);\n\n    // Remove dominated candidates:\n    // if mask_i \u2286 mask_j and cost_j <= cost_i, i is useless.\n    {\n        int Cn = (int)cands.size();\n        vector<char> bad(Cn, false);\n        for (int i = 0; i < Cn; ++i) {\n            if (bad[i]) continue;\n            for (int j = 0; j < Cn; ++j) {\n                if (i == j || bad[i]) continue;\n                if ((cands[i].mask & ~cands[j].mask) == 0 && cands[j].cost <= cands[i].cost) {\n                    bad[i] = true;\n                    break;\n                }\n            }\n        }\n        vector<Cand> tmp;\n        for (int i = 0; i < Cn; ++i) if (!bad[i]) tmp.push_back(cands[i]);\n        cands.swap(tmp);\n    }\n\n    int Cn = (int)cands.size();\n    uint64_t fullMask = (M == 64 ? ~0ULL : ((1ULL << M) - 1ULL));\n\n    // Build original coverers and force unique-cover candidates.\n    vector<vector<int>> cover0(M);\n    for (int i = 0; i < Cn; ++i) {\n        uint64_t m = cands[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            cover0[b].push_back(i);\n            m &= (m - 1);\n        }\n    }\n\n    vector<char> forcedChosen(Cn, false);\n    vector<int> forcedSel;\n    for (int b = 0; b < M; ++b) {\n        if ((int)cover0[b].size() == 1) {\n            int id = cover0[b][0];\n            if (!forcedChosen[id]) {\n                forcedChosen[id] = true;\n                forcedSel.push_back(id);\n            }\n        }\n    }\n\n    uint64_t residualMask = fullMask;\n    long long forcedCost = 0;\n    for (int id : forcedSel) {\n        residualMask &= ~cands[id].mask;\n        forcedCost += cands[id].cost;\n    }\n\n    // Compress remaining bits.\n    vector<int> bitMap(64, -1);\n    vector<int> bits;\n    for (int b = 0; b < M; ++b) {\n        if ((residualMask >> b) & 1ULL) {\n            bitMap[b] = (int)bits.size();\n            bits.push_back(b);\n        }\n    }\n    int R = (int)bits.size();\n\n    // If forced candidates already cover everything.\n    if (R == 0) {\n        vector<pair<char,int>> ops;\n        for (int id : forcedSel) {\n            auto &c = cands[id];\n            for (int t = 0; t < c.len; ++t) ops.push_back({c.dir, c.idx});\n            for (int t = 0; t < c.len; ++t) ops.push_back({revDir(c.dir), c.idx});\n        }\n        for (auto [d, p] : ops) cout << d << ' ' << p << '\\n';\n        return 0;\n    }\n\n    vector<Cand> red;\n    red.reserve(Cn);\n    for (int i = 0; i < Cn; ++i) {\n        if (forcedChosen[i]) continue;\n        uint64_t m = cands[i].mask & residualMask;\n        if (m == 0) continue;\n        uint64_t nm = 0;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            m &= (m - 1);\n            nm |= 1ULL << bitMap[b];\n        }\n        red.push_back({nm, cands[i].cost, cands[i].len, cands[i].idx, cands[i].dir, cands[i].orig});\n    }\n\n    // Deduplicate and prune again on the reduced instance.\n    sort(red.begin(), red.end(), [&](const Cand& a, const Cand& b) {\n        if (a.mask != b.mask) return a.mask < b.mask;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.idx < b.idx;\n    });\n    {\n        vector<Cand> tmp;\n        for (auto &c : red) {\n            if (tmp.empty() || tmp.back().mask != c.mask) tmp.push_back(c);\n        }\n        red.swap(tmp);\n    }\n    {\n        int n = (int)red.size();\n        vector<char> bad(n, false);\n        for (int i = 0; i < n; ++i) {\n            if (bad[i]) continue;\n            for (int j = 0; j < n; ++j) {\n                if (i == j || bad[i]) continue;\n                if ((red[i].mask & ~red[j].mask) == 0 && red[j].cost <= red[i].cost) {\n                    bad[i] = true;\n                    break;\n                }\n            }\n        }\n        vector<Cand> tmp;\n        for (int i = 0; i < n; ++i) if (!bad[i]) tmp.push_back(red[i]);\n        red.swap(tmp);\n    }\n\n    Cn = (int)red.size();\n    vector<vector<int>> coverers(R);\n    vector<int> deg(R, 0), minCostBit(R, INT_MAX), maxCostBit(R, 0);\n\n    for (int i = 0; i < Cn; ++i) {\n        uint64_t m = red[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            coverers[b].push_back(i);\n            m &= (m - 1);\n        }\n    }\n    for (int b = 0; b < R; ++b) {\n        deg[b] = (int)coverers[b].size();\n        for (int id : coverers[b]) {\n            minCostBit[b] = min(minCostBit[b], red[id].cost);\n            maxCostBit[b] = max(maxCostBit[b], red[id].cost);\n        }\n    }\n\n    // Orders for dual lower bound.\n    vector<vector<int>> dualOrders(5, vector<int>(R));\n    for (int t = 0; t < 5; ++t) {\n        iota(dualOrders[t].begin(), dualOrders[t].end(), 0);\n    }\n    sort(dualOrders[0].begin(), dualOrders[0].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        return a < b;\n    });\n    sort(dualOrders[1].begin(), dualOrders[1].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        if (maxCostBit[a] != maxCostBit[b]) return maxCostBit[a] > maxCostBit[b];\n        return a < b;\n    });\n    sort(dualOrders[2].begin(), dualOrders[2].end(), [&](int a, int b) {\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        return a < b;\n    });\n    sort(dualOrders[3].begin(), dualOrders[3].end(), [&](int a, int b) {\n        long long lhs = 1LL * minCostBit[a] * max(1, deg[b]);\n        long long rhs = 1LL * minCostBit[b] * max(1, deg[a]);\n        if (lhs != rhs) return lhs < rhs;\n        if (deg[a] != deg[b]) return deg[a] < deg[b];\n        return a < b;\n    });\n    sort(dualOrders[4].begin(), dualOrders[4].end(), [&](int a, int b) {\n        if (deg[a] != deg[b]) return deg[a] > deg[b];\n        if (minCostBit[a] != minCostBit[b]) return minCostBit[a] < minCostBit[b];\n        return a < b;\n    });\n\n    auto cleanup = [&](vector<int> sel) -> vector<int> {\n        if (sel.empty()) return sel;\n        vector<int> cnt(R, 0);\n        for (int id : sel) {\n            uint64_t m = red[id].mask;\n            while (m) {\n                int b = __builtin_ctzll(m);\n                cnt[b]++;\n                m &= (m - 1);\n            }\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            sort(sel.begin(), sel.end(), [&](int a, int b) {\n                if (red[a].cost != red[b].cost) return red[a].cost > red[b].cost;\n                return a < b;\n            });\n\n            vector<int> nxt;\n            nxt.reserve(sel.size());\n            for (int id : sel) {\n                bool removable = true;\n                uint64_t m = red[id].mask;\n                while (m) {\n                    int b = __builtin_ctzll(m);\n                    if (cnt[b] <= 1) {\n                        removable = false;\n                        break;\n                    }\n                    m &= (m - 1);\n                }\n\n                if (removable) {\n                    uint64_t m2 = red[id].mask;\n                    while (m2) {\n                        int b = __builtin_ctzll(m2);\n                        cnt[b]--;\n                        m2 &= (m2 - 1);\n                    }\n                    changed = true;\n                } else {\n                    nxt.push_back(id);\n                }\n            }\n            sel.swap(nxt);\n        }\n        return sel;\n    };\n\n    auto greedySolve = [&](int K, bool ratioMode) -> pair<vector<int>, int> {\n        uint64_t U = (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL));\n        vector<int> sel;\n\n        while (U) {\n            // choose a forced candidate if some bit has only one coverer\n            vector<int> forced;\n            vector<char> seen(Cn, false);\n            uint64_t x = U;\n            while (x) {\n                int b = __builtin_ctzll(x);\n                x &= (x - 1);\n                if ((int)coverers[b].size() == 1) {\n                    int id = coverers[b][0];\n                    if (!seen[id]) {\n                        seen[id] = true;\n                        forced.push_back(id);\n                    }\n                }\n            }\n\n            if (!forced.empty()) {\n                for (int id : forced) {\n                    sel.push_back(id);\n                    U &= ~red[id].mask;\n                }\n                continue;\n            }\n\n            int best = -1;\n            int bestNew = -1;\n            int bestCost = INT_MAX;\n            long long bestScore = LLONG_MIN;\n\n            for (int id = 0; id < Cn; ++id) {\n                uint64_t nm = red[id].mask & U;\n                if (nm == 0) continue;\n                int newCnt = pop64(nm);\n\n                if (!ratioMode) {\n                    long long score = 1LL * K * newCnt - red[id].cost;\n                    if (best == -1 ||\n                        score > bestScore ||\n                        (score == bestScore && (newCnt > bestNew ||\n                                                (newCnt == bestNew && red[id].cost < bestCost)))) {\n                        best = id;\n                        bestScore = score;\n                        bestNew = newCnt;\n                        bestCost = red[id].cost;\n                    }\n                } else {\n                    if (best == -1) {\n                        best = id;\n                        bestNew = newCnt;\n                        bestCost = red[id].cost;\n                    } else {\n                        long long lhs = 1LL * newCnt * bestCost;\n                        long long rhs = 1LL * bestNew * red[id].cost;\n                        if (lhs > rhs ||\n                            (lhs == rhs && (newCnt > bestNew ||\n                                            (newCnt == bestNew && red[id].cost < bestCost)))) {\n                            best = id;\n                            bestNew = newCnt;\n                            bestCost = red[id].cost;\n                        }\n                    }\n                }\n            }\n\n            if (best == -1) break; // should not happen\n            sel.push_back(best);\n            U &= ~red[best].mask;\n        }\n\n        sel = cleanup(sel);\n\n        int cost = 0;\n        uint64_t cover = 0;\n        for (int id : sel) {\n            cost += red[id].cost;\n            cover |= red[id].mask;\n        }\n\n        // Safety fallback: if anything remains uncovered, add cheapest candidates.\n        if (cover != (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL))) {\n            uint64_t rem = ((R == 64 ? ~0ULL : ((1ULL << R) - 1ULL)) & ~cover);\n            while (rem) {\n                int b = __builtin_ctzll(rem);\n                int choose = -1;\n                int chooseCost = INT_MAX;\n                for (int id = 0; id < Cn; ++id) {\n                    if ((red[id].mask >> b) & 1ULL) {\n                        if (red[id].cost < chooseCost) {\n                            choose = id;\n                            chooseCost = red[id].cost;\n                        }\n                    }\n                }\n                if (choose == -1) break;\n                sel.push_back(choose);\n                cover |= red[choose].mask;\n                rem = ((R == 64 ? ~0ULL : ((1ULL << R) - 1ULL)) & ~cover);\n            }\n            sel = cleanup(sel);\n            cost = 0;\n            for (int id : sel) cost += red[id].cost;\n        }\n\n        return {sel, cost};\n    };\n\n    vector<int> bestSel;\n    int bestResCost = INT_MAX;\n\n    // Several greedy seeds.\n    vector<int> Ks = {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 50};\n    for (int K : Ks) {\n        auto [sel, cost] = greedySolve(K, false);\n        if (cost < bestResCost) {\n            bestResCost = cost;\n            bestSel = sel;\n        }\n    }\n    {\n        auto [sel, cost] = greedySolve(0, true);\n        if (cost < bestResCost) {\n            bestResCost = cost;\n            bestSel = sel;\n        }\n    }\n\n    bestSel = cleanup(bestSel);\n    bestResCost = 0;\n    {\n        uint64_t cover = 0;\n        for (int id : bestSel) {\n            bestResCost += red[id].cost;\n            cover |= red[id].mask;\n        }\n        (void)cover;\n    }\n\n    // Branch and bound search on the reduced problem.\n    chrono::steady_clock::time_point deadline = chrono::steady_clock::now() + chrono::milliseconds(1800);\n    bool timedOut = false;\n    uint64_t nodeCounter = 0;\n\n    unordered_map<uint64_t, int, U64Hash> memo;\n    memo.reserve(1 << 16);\n    memo.max_load_factor(0.7f);\n\n    vector<int> cur;\n\n    auto simpleLB = [&](uint64_t U) -> long long {\n        long long sumMin = 0;\n        int maxCover = 0;\n\n        uint64_t x = U;\n        while (x) {\n            int b = __builtin_ctzll(x);\n            x &= (x - 1);\n            sumMin += minCostBit[b];\n        }\n        for (int id = 0; id < Cn; ++id) {\n            int cov = pop64(red[id].mask & U);\n            if (cov > maxCover) maxCover = cov;\n        }\n        if (maxCover == 0) return (long long)1e9;\n        return (sumMin + maxCover - 1) / maxCover;\n    };\n\n    auto dualLB = [&](uint64_t U) -> long long {\n        long long best = 0;\n        for (int t = 0; t < 5; ++t) {\n            vector<int> slack(Cn);\n            for (int i = 0; i < Cn; ++i) slack[i] = red[i].cost;\n\n            long long val = 0;\n            for (int b : dualOrders[t]) {\n                if (((U >> b) & 1ULL) == 0) continue;\n                int delta = INT_MAX;\n                for (int id : coverers[b]) {\n                    delta = min(delta, slack[id]);\n                }\n                if (delta == INT_MAX || delta <= 0) continue;\n                val += delta;\n                for (int id : coverers[b]) slack[id] -= delta;\n            }\n            best = max(best, val);\n        }\n        return best;\n    };\n\n    auto choosePivot = [&](uint64_t U) -> int {\n        int pivot = -1;\n        int bestDeg = INT_MAX;\n        int bestMinCost = -1;\n        uint64_t x = U;\n        while (x) {\n            int b = __builtin_ctzll(x);\n            x &= (x - 1);\n            if (deg[b] < bestDeg || (deg[b] == bestDeg && minCostBit[b] > bestMinCost)) {\n                bestDeg = deg[b];\n                bestMinCost = minCostBit[b];\n                pivot = b;\n            }\n        }\n        return pivot;\n    };\n\n    function<void(uint64_t,int)> dfs = [&](uint64_t U, int cost) {\n        if (timedOut) return;\n        if ((++nodeCounter & 255ULL) == 0) {\n            if (chrono::steady_clock::now() > deadline) {\n                timedOut = true;\n                return;\n            }\n        }\n\n        if (cost >= bestResCost) return;\n        if (U == 0) {\n            bestResCost = cost;\n            bestSel = cur;\n            return;\n        }\n\n        auto it = memo.find(U);\n        if (it != memo.end() && it->second <= cost) return;\n        memo[U] = cost;\n\n        long long lb1 = simpleLB(U);\n        if (cost + lb1 >= bestResCost) return;\n        long long lb2 = dualLB(U);\n        if (cost + lb2 >= bestResCost) return;\n\n        int pivot = choosePivot(U);\n        if (pivot < 0) return;\n\n        vector<int> opts = coverers[pivot];\n        sort(opts.begin(), opts.end(), [&](int a, int b) {\n            int ca = pop64(red[a].mask & U);\n            int cb = pop64(red[b].mask & U);\n            long long lhs = 1LL * red[a].cost * cb;\n            long long rhs = 1LL * red[b].cost * ca;\n            if (lhs != rhs) return lhs < rhs;\n            if (ca != cb) return ca > cb;\n            if (red[a].cost != red[b].cost) return red[a].cost < red[b].cost;\n            return a < b;\n        });\n\n        for (int id : opts) {\n            uint64_t nU = U & ~red[id].mask;\n            if (nU == U) continue;\n            cur.push_back(id);\n            dfs(nU, cost + red[id].cost);\n            cur.pop_back();\n            if (timedOut) return;\n        }\n    };\n\n    uint64_t startU = (R == 64 ? ~0ULL : ((1ULL << R) - 1ULL));\n    dfs(startU, 0);\n\n    // Final cleanup of the reduced selected set.\n    bestSel = cleanup(bestSel);\n    bestResCost = 0;\n    for (int id : bestSel) bestResCost += red[id].cost;\n\n    // Build output operations.\n    vector<pair<char,int>> outOps;\n    outOps.reserve((size_t)(forcedSel.size() + bestSel.size()) * 40);\n\n    auto emitCandidate = [&](const Cand& c) {\n        for (int t = 0; t < c.len; ++t) outOps.push_back({c.dir, c.idx});\n        for (int t = 0; t < c.len; ++t) outOps.push_back({revDir(c.dir), c.idx});\n    };\n\n    for (int id : forcedSel) emitCandidate(cands[id]);\n    for (int id : bestSel) emitCandidate(red[id]);\n\n    for (auto [d, p] : outOps) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\n\nint N, L;\narray<int, MAXN> T{};\nint avgT = 0;\nint bestTargetNode = 0;\n\nstruct XorShift64 {\n    uint64_t x;\n    explicit XorShift64(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        return (int)(next() % (uint64_t)mod);\n    }\n};\n\nstruct Plan {\n    array<array<int, 2>, MAXN> to;\n};\n\nstruct Eval {\n    Plan plan;\n    array<int, MAXN> cnt{};\n    array<array<int, 2>, MAXN> use{};\n    long long err = (1LL << 60);\n    int last = 0;\n};\n\nstatic inline long long llabsll(long long x) { return x < 0 ? -x : x; }\n\nvoid finalizePlan(Plan &p) {\n    for (int i = 0; i < N; ++i) {\n        if (p.to[i][0] == -1 && p.to[i][1] == -1) {\n            int d = (T[i] >= avgT ? i : bestTargetNode);\n            p.to[i][0] = p.to[i][1] = d;\n        } else if (p.to[i][0] == -1) {\n            p.to[i][0] = p.to[i][1];\n        } else if (p.to[i][1] == -1) {\n            p.to[i][1] = p.to[i][0];\n        }\n    }\n}\n\nint chooseDest(\n    int src,\n    const array<long long, MAXN> &rem,\n    int exclude,\n    long long selfBias,\n    long long samePenalty,\n    XorShift64 &rng\n) {\n    int best = 0;\n    long long bestSc = -(1LL << 60);\n\n    for (int j = 0; j < N; ++j) {\n        long long sc = 0;\n        sc += rem[j] * 200LL;\n        sc += 3LL * T[j];\n        sc -= 4LL * llabsll((long long)T[src] - (long long)T[j]);\n\n        if (j == src) {\n            long long selfAdj = ((long long)T[src] - (long long)avgT) * selfBias / max(1, avgT);\n            sc += selfAdj;\n        }\n\n        if (j == exclude) sc -= samePenalty;\n\n        sc += (long long)(rng.next() & 31ULL) - 15LL;\n\n        if (sc > bestSc) {\n            bestSc = sc;\n            best = j;\n        }\n    }\n    return best;\n}\n\nEval simulate(const Plan &p) {\n    Eval e;\n    e.plan = p;\n    e.cnt.fill(0);\n    for (int i = 0; i < N; ++i) e.use[i][0] = e.use[i][1] = 0;\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        e.cnt[x]++;\n        if (step == L - 1) {\n            e.last = x;\n            break;\n        }\n        int par = e.cnt[x] & 1; // 1 = odd visit -> a_i, 0 = even visit -> b_i\n        e.use[x][par]++;\n        x = p.to[x][par];\n    }\n\n    e.last = x;\n    long long err = 0;\n    for (int i = 0; i < N; ++i) err += llabsll((long long)e.cnt[i] - (long long)T[i]);\n    e.err = err;\n    return e;\n}\n\nPlan buildOnline(uint64_t seed, long long selfBias, long long samePenalty) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    XorShift64 rng(seed);\n    array<int, MAXN> cnt{};\n    cnt.fill(0);\n\n    int x = 0;\n    for (int step = 0; step < L; ++step) {\n        cnt[x]++;\n        if (step == L - 1) break;\n\n        int par = cnt[x] & 1;\n        if (p.to[x][0] == -1 && p.to[x][1] == -1) {\n            array<long long, MAXN> rem{};\n            for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (long long)cnt[i];\n\n            int oddDest = chooseDest(x, rem, -1, selfBias, samePenalty, rng);\n            rem[oddDest] -= 1; // tiny bias for the second choice\n            int evenDest = chooseDest(x, rem, oddDest, selfBias, samePenalty, rng);\n\n            p.to[x][1] = oddDest;\n            p.to[x][0] = evenDest;\n        } else if (p.to[x][par] == -1) {\n            array<long long, MAXN> rem{};\n            for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (long long)cnt[i];\n            int other = p.to[x][1 - par];\n            p.to[x][par] = chooseDest(x, rem, other, selfBias, samePenalty, rng);\n        }\n\n        x = p.to[x][par];\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nPlan buildTransportFromSupply(const array<int, MAXN> &supply, int orderType, uint64_t seed, long long selfBias, long long samePenalty) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    XorShift64 rng(seed);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n\n    auto cmpDescSupply = [&](int a, int b) {\n        if (supply[a] != supply[b]) return supply[a] > supply[b];\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    };\n    auto cmpAscSupply = [&](int a, int b) {\n        if (supply[a] != supply[b]) return supply[a] < supply[b];\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    };\n    auto cmpDescT = [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        if (supply[a] != supply[b]) return supply[a] > supply[b];\n        return a < b;\n    };\n\n    if (orderType == 0) {\n        sort(ord.begin(), ord.end(), cmpDescSupply);\n    } else if (orderType == 1) {\n        sort(ord.begin(), ord.end(), cmpAscSupply);\n    } else {\n        // random order\n        for (int i = N - 1; i > 0; --i) {\n            int j = rng.nextInt(i + 1);\n            swap(ord[i], ord[j]);\n        }\n    }\n\n    array<long long, MAXN> rem{};\n    for (int i = 0; i < N; ++i) rem[i] = (long long)T[i] - (i == 0 ? 1LL : 0LL);\n\n    for (int idx = 0; idx < N; ++idx) {\n        int i = ord[idx];\n        long long wOdd = (supply[i] + 1LL) / 2LL;\n        long long wEven = supply[i] / 2LL;\n\n        int dOdd = chooseDest(i, rem, -1, selfBias, samePenalty, rng);\n        rem[dOdd] -= wOdd;\n\n        int dEven = chooseDest(i, rem, dOdd, selfBias, samePenalty, rng);\n        rem[dEven] -= wEven;\n\n        p.to[i][1] = dOdd;\n        p.to[i][0] = dEven;\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nPlan buildTemplate(int type) {\n    Plan p;\n    for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = -1;\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    });\n\n    int h1 = ord[0];\n    int h2 = ord[1];\n\n    for (int pos = 0; pos < N; ++pos) {\n        int i = ord[pos];\n        int nxt = ord[(pos + 1) % N];\n        int prv = ord[(pos + N - 1) % N];\n        int nxt2 = ord[(pos + 2) % N];\n\n        if (type == 0) {\n            if (T[i] >= avgT) {\n                p.to[i][1] = i;\n                p.to[i][0] = nxt;\n            } else {\n                p.to[i][1] = nxt;\n                p.to[i][0] = i;\n            }\n        } else if (type == 1) {\n            if (pos < 15) {\n                p.to[i][1] = i;\n                p.to[i][0] = i;\n            } else if (pos < 45) {\n                p.to[i][1] = i;\n                p.to[i][0] = nxt;\n            } else if (pos < 75) {\n                p.to[i][1] = nxt;\n                p.to[i][0] = i;\n            } else {\n                p.to[i][1] = nxt;\n                p.to[i][0] = nxt2;\n            }\n        } else if (type == 2) {\n            if (i == h1) {\n                p.to[i][1] = h1;\n                p.to[i][0] = h2;\n            } else if (T[i] >= avgT) {\n                p.to[i][1] = i;\n                p.to[i][0] = h1;\n            } else {\n                p.to[i][1] = h1;\n                p.to[i][0] = i;\n            }\n        } else {\n            p.to[i][1] = nxt;\n            p.to[i][0] = prv;\n        }\n    }\n\n    finalizePlan(p);\n    return p;\n}\n\nvoid buildCandidates(vector<Eval> &pool, uint64_t baseSeed) {\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (T[a] != T[b]) return T[a] > T[b];\n        return a < b;\n    });\n\n    vector<int> ends;\n    for (int i = 0; i < N && (int)ends.size() < 4; ++i) {\n        if (T[ord[i]] > 0) ends.push_back(ord[i]);\n    }\n    if (T[0] > 0 && find(ends.begin(), ends.end(), 0) == ends.end()) ends.push_back(0);\n\n    int randomPositive = -1;\n    {\n        vector<int> pos;\n        for (int i = 0; i < N; ++i) if (T[i] > 0) pos.push_back(i);\n        if (!pos.empty()) {\n            XorShift64 rng(baseSeed ^ 0x123456789abcdefULL);\n            randomPositive = pos[rng.nextInt((int)pos.size())];\n            if (find(ends.begin(), ends.end(), randomPositive) == ends.end()) ends.push_back(randomPositive);\n        }\n    }\n    if ((int)ends.size() > 5) ends.resize(5);\n\n    long long onlineBiases[4] = {700, 1600, 3000, -800};\n    long long transportBiases[2] = {800, 2000};\n\n    int cid = 0;\n    for (int k = 0; k < 4; ++k) {\n        uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(cid + 1));\n        Plan p = buildOnline(seed, onlineBiases[k], 600);\n        pool.push_back(simulate(p));\n        ++cid;\n    }\n\n    for (int e : ends) {\n        array<int, MAXN> supply{};\n        for (int i = 0; i < N; ++i) supply[i] = T[i];\n        if (supply[e] <= 0) continue;\n        supply[e]--;\n\n        for (int ordType = 0; ordType < 3; ++ordType) {\n            for (int b = 0; b < 2; ++b) {\n                uint64_t seed = baseSeed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(cid + 1)) ^ (uint64_t)(e + 1000 * ordType + 17 * b);\n                Plan p = buildTransportFromSupply(supply, ordType, seed, transportBiases[b], 500);\n                pool.push_back(simulate(p));\n                ++cid;\n            }\n        }\n    }\n\n    for (int tp = 0; tp < 4; ++tp) {\n        Plan p = buildTemplate(tp);\n        pool.push_back(simulate(p));\n    }\n}\n\nEval refineByTransport(Eval cur, uint64_t seed) {\n    for (int iter = 0; iter < 2; ++iter) {\n        array<int, MAXN> supply = cur.cnt;\n        supply[cur.last]--;\n        if (supply[cur.last] < 0) supply[cur.last] = 0;\n\n        Plan p = buildTransportFromSupply(supply, 0, seed ^ (0x9e3779b97f4a7c15ULL * (uint64_t)(iter + 1)), 1600, 500);\n        Eval e = simulate(p);\n        if (e.err < cur.err) cur = std::move(e);\n        else break;\n    }\n    return cur;\n}\n\nEval localSearch(Eval cur, uint64_t seed, chrono::steady_clock::time_point start) {\n    XorShift64 rng(seed);\n\n    auto nowSeconds = [&]() -> double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    for (int round = 0; round < 2; ++round) {\n        if (nowSeconds() > 1.93) break;\n        if (cur.err == 0) break;\n\n        vector<int> over, under;\n        over.reserve(N);\n        under.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            int d = cur.cnt[i] - T[i];\n            if (d > 0) over.push_back(i);\n            else if (d < 0) under.push_back(i);\n        }\n        if (over.empty() || under.empty()) break;\n\n        sort(over.begin(), over.end(), [&](int a, int b) {\n            return (cur.cnt[a] - T[a]) > (cur.cnt[b] - T[b]);\n        });\n        sort(under.begin(), under.end(), [&](int a, int b) {\n            return (T[a] - cur.cnt[a]) > (T[b] - cur.cnt[b]);\n        });\n\n        vector<int> overTop, underTop;\n        for (int i = 0; i < (int)min<size_t>(4, over.size()); ++i) overTop.push_back(over[i]);\n        for (int i = 0; i < (int)min<size_t>(3, under.size()); ++i) underTop.push_back(under[i]);\n\n        struct Slot {\n            int src, p, dest, use;\n        };\n\n        vector<Slot> slots;\n        for (int o : overTop) {\n            for (int i = 0; i < N; ++i) {\n                for (int p = 0; p < 2; ++p) {\n                    if (cur.plan.to[i][p] == o && cur.use[i][p] > 0) {\n                        slots.push_back({i, p, o, cur.use[i][p]});\n                    }\n                }\n            }\n        }\n\n        sort(slots.begin(), slots.end(), [&](const Slot &a, const Slot &b) {\n            return a.use > b.use;\n        });\n\n        long long bestErr = cur.err;\n        Eval bestCand = cur;\n        bool improved = false;\n\n        auto testPlan = [&](const Plan &pp) {\n            if (nowSeconds() > 1.93) return;\n            Eval e = simulate(pp);\n            if (e.err < bestErr) {\n                bestErr = e.err;\n                bestCand = std::move(e);\n                improved = true;\n            }\n        };\n\n        // 1) Change heavily used slots that currently point to overcounted nodes.\n        int slotLimit = min<int>(12, slots.size());\n        for (int i = 0; i < slotLimit; ++i) {\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[slots[i].src][slots[i].p] == u) continue;\n                Plan np = cur.plan;\n                np.to[slots[i].src][slots[i].p] = u;\n                testPlan(np);\n            }\n        }\n\n        // 2) Change one parity edge of overcounted source nodes.\n        for (int s = 0; s < (int)overTop.size(); ++s) {\n            int src = overTop[s];\n            int p = (cur.use[src][0] >= cur.use[src][1] ? 0 : 1);\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[src][p] == u) continue;\n                Plan np = cur.plan;\n                np.to[src][p] = u;\n                testPlan(np);\n            }\n        }\n\n        // 3) Change both edges of a strongly overcounted source to a better undercounted target.\n        for (int s = 0; s < (int)min<size_t>(3, overTop.size()); ++s) {\n            int src = overTop[s];\n            for (int u : underTop) {\n                if (nowSeconds() > 1.93) break;\n                if (cur.plan.to[src][0] == u && cur.plan.to[src][1] == u) continue;\n                Plan np = cur.plan;\n                np.to[src][0] = np.to[src][1] = u;\n                testPlan(np);\n            }\n        }\n\n        if (improved) cur = std::move(bestCand);\n        else break;\n    }\n\n    return cur;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    avgT = L / N;\n    bestTargetNode = 0;\n    for (int i = 1; i < N; ++i) {\n        if (T[i] > T[bestTargetNode]) bestTargetNode = i;\n    }\n\n    uint64_t baseSeed = 1469598103934665603ULL;\n    for (int i = 0; i < N; ++i) {\n        baseSeed ^= (uint64_t)(T[i] + 1);\n        baseSeed *= 1099511628211ULL;\n    }\n\n    auto start = chrono::steady_clock::now();\n\n    vector<Eval> pool;\n    pool.reserve(64);\n\n    buildCandidates(pool, baseSeed);\n\n    if (pool.empty()) {\n        Plan p;\n        for (int i = 0; i < N; ++i) p.to[i][0] = p.to[i][1] = bestTargetNode;\n        auto e = simulate(p);\n        pool.push_back(std::move(e));\n    }\n\n    sort(pool.begin(), pool.end(), [&](const Eval &a, const Eval &b) {\n        return a.err < b.err;\n    });\n\n    int topK = min<int>(3, pool.size());\n    Eval best = pool[0];\n\n    for (int i = 0; i < topK; ++i) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > 1.90) break;\n\n        Eval cur = pool[i];\n        cur = refineByTransport(cur, baseSeed ^ (0xabcdef0123456789ULL + (uint64_t)i * 1337ULL));\n        cur = localSearch(cur, baseSeed ^ (0x123456789abcdef0ULL + (uint64_t)i * 10007ULL), start);\n\n        if (cur.err < best.err) best = std::move(cur);\n    }\n\n    // Final safety fill.\n    finalizePlan(best.plan);\n\n    for (int i = 0; i < N; ++i) {\n        cout << best.plan.to[i][1] << ' ' << best.plan.to[i][0] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ull = unsigned long long;\n\nstatic const ll INFLL = (1LL << 62);\nstatic const int MAXN = 800;\n\nint N, M, Q, L, W;\nvector<int> G;\nvector<int> lx, rx, ly, ry;\nvector<int> exs, eys;\nvector<vector<ll>> dist2Mat;\nvector<double> densityScore;\nvector<int> densityOrder;\n\nint queries_used = 0;\n\nstruct BuiltGroup {\n    vector<int> cities;\n    vector<pair<int,int>> edges;\n};\n\null hilbertOrder(int x, int y) {\n    ull d = 0;\n    for (int s = 1 << 14; s > 0; s >>= 1) {\n        int rx = (x & s) ? 1 : 0;\n        int ry = (y & s) ? 1 : 0;\n        d += (ull)s * (ull)s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = s * 2 - 1 - x;\n                y = s * 2 - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\ninline ll d2(int a, int b) {\n    return dist2Mat[a][b];\n}\n\nstruct PrimRes {\n    vector<int> parent;\n    vector<ll> best;\n};\n\nPrimRes primParents(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    PrimRes res;\n    res.parent.assign(k, -1);\n    res.best.assign(k, INFLL);\n    if (k == 0) return res;\n    vector<char> used(k, 0);\n    res.best[0] = 0;\n\n    for (int it = 0; it < k; ++it) {\n        int v = -1;\n        for (int i = 0; i < k; ++i) {\n            if (!used[i] && (v == -1 || res.best[i] < res.best[v])) v = i;\n        }\n        used[v] = 1;\n        int a = nodes[v];\n        for (int to = 0; to < k; ++to) if (!used[to]) {\n            ll w = d2(a, nodes[to]);\n            if (w < res.best[to]) {\n                res.best[to] = w;\n                res.parent[to] = v;\n            }\n        }\n    }\n    return res;\n}\n\ndouble mstCostVec(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    if (k <= 1) return 0.0;\n    auto res = primParents(nodes);\n    double cost = 0.0;\n    for (int i = 1; i < k; ++i) cost += sqrt((double)res.best[i]);\n    return cost;\n}\n\nvector<pair<int,int>> primTree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    vector<pair<int,int>> edges;\n    if (k <= 1) return edges;\n    auto res = primParents(nodes);\n    edges.reserve(k - 1);\n    for (int i = 1; i < k; ++i) {\n        int a = nodes[i], b = nodes[res.parent[i]];\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nvector<pair<int,int>> queryTree(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    cout << \"? \" << k;\n    for (int v : nodes) cout << ' ' << v;\n    cout << '\\n' << flush;\n\n    ++queries_used;\n    vector<pair<int,int>> edges;\n    edges.reserve(k - 1);\n    for (int i = 0; i < k - 1; ++i) {\n        int a, b;\n        cin >> a >> b;\n        if (a > b) swap(a, b);\n        edges.push_back({a, b});\n    }\n    return edges;\n}\n\nvector<int> buildMSTPreorder(const vector<int>& nodes) {\n    int k = (int)nodes.size();\n    if (k <= 2) return nodes;\n\n    auto res = primParents(nodes);\n    vector<vector<pair<ll,int>>> adj(k);\n    for (int i = 1; i < k; ++i) {\n        int p = res.parent[i];\n        ll w = res.best[i];\n        adj[i].push_back({w, p});\n        adj[p].push_back({w, i});\n    }\n\n    int root = 0;\n    ll bestSum = INFLL;\n    for (int i = 0; i < k; ++i) {\n        ll sum = 0;\n        for (int j = 0; j < k; ++j) if (i != j) sum += d2(nodes[i], nodes[j]);\n        if (sum < bestSum || (sum == bestSum && nodes[i] < nodes[root])) {\n            bestSum = sum;\n            root = i;\n        }\n    }\n\n    for (int i = 0; i < k; ++i) {\n        sort(adj[i].begin(), adj[i].end());\n    }\n\n    vector<int> order;\n    order.reserve(k);\n    vector<int> par(k, -1);\n    vector<int> st;\n    st.push_back(root);\n    par[root] = root;\n\n    while (!st.empty()) {\n        int v = st.back();\n        st.pop_back();\n        order.push_back(nodes[v]);\n        for (int i = (int)adj[v].size() - 1; i >= 0; --i) {\n            int to = adj[v][i].second;\n            if (to == par[v]) continue;\n            par[to] = v;\n            st.push_back(to);\n        }\n    }\n    return order;\n}\n\nvector<vector<int>> splitChunks(const vector<int>& ord) {\n    int n = (int)ord.size();\n    vector<vector<int>> chunks;\n    if (n <= L) {\n        chunks.push_back(ord);\n        return chunks;\n    }\n\n    int p = 0, rem = n;\n    while (rem > 0) {\n        int take = min(L, rem);\n        if (rem > L && rem - take == 1) take--;\n        chunks.emplace_back(ord.begin() + p, ord.begin() + p + take);\n        p += take;\n        rem -= take;\n    }\n    return chunks;\n}\n\nvector<vector<ll>> computeChunkWeights(\n    const vector<vector<int>>& chunks,\n    vector<vector<pair<int,int>>>* bestPair = nullptr\n) {\n    int c = (int)chunks.size();\n    vector<vector<ll>> w(c, vector<ll>(c, INFLL));\n    if (bestPair) bestPair->assign(c, vector<pair<int,int>>(c, {INT_MAX, INT_MAX}));\n\n    for (int i = 0; i < c; ++i) {\n        for (int j = i + 1; j < c; ++j) {\n            ll bestW = INFLL;\n            pair<int,int> bestP = {INT_MAX, INT_MAX};\n            for (int a : chunks[i]) {\n                for (int b : chunks[j]) {\n                    ll d = d2(a, b);\n                    pair<int,int> p = (a < b ? make_pair(a, b) : make_pair(b, a));\n                    if (d < bestW || (d == bestW && p < bestP)) {\n                        bestW = d;\n                        bestP = p;\n                    }\n                }\n            }\n            w[i][j] = w[j][i] = bestW;\n            if (bestPair) {\n                (*bestPair)[i][j] = (*bestPair)[j][i] = bestP;\n            }\n        }\n    }\n    return w;\n}\n\ndouble estimateOrderCost(const vector<int>& ord) {\n    int n = (int)ord.size();\n    if (n <= 1) return 0.0;\n    if (n <= L) return mstCostVec(ord);\n\n    auto chunks = splitChunks(ord);\n    double cost = 0.0;\n    for (auto& ch : chunks) cost += mstCostVec(ch);\n\n    auto w = computeChunkWeights(chunks, nullptr);\n    int c = (int)chunks.size();\n    vector<ll> best(c, INFLL);\n    vector<char> used(c, 0);\n    best[0] = 0;\n\n    for (int it = 0; it < c; ++it) {\n        int v = -1;\n        for (int i = 0; i < c; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (best[v] != 0) cost += sqrt((double)best[v]);\n        for (int to = 0; to < c; ++to) if (!used[to]) {\n            if (w[v][to] < best[to]) best[to] = w[v][to];\n        }\n    }\n    return cost;\n}\n\nvector<pair<int,int>> buildChunkMSTEdges(const vector<vector<int>>& chunks) {\n    vector<pair<int,int>> edges;\n    int c = (int)chunks.size();\n    if (c <= 1) return edges;\n\n    vector<vector<pair<int,int>>> bestPair;\n    auto w = computeChunkWeights(chunks, &bestPair);\n\n    vector<ll> best(c, INFLL);\n    vector<int> parent(c, -1);\n    vector<char> used(c, 0);\n    best[0] = 0;\n\n    for (int it = 0; it < c; ++it) {\n        int v = -1;\n        for (int i = 0; i < c; ++i) {\n            if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n        }\n        used[v] = 1;\n        if (parent[v] != -1) edges.push_back(bestPair[v][parent[v]]);\n        for (int to = 0; to < c; ++to) if (!used[to]) {\n            if (w[v][to] < best[to]) {\n                best[to] = w[v][to];\n                parent[to] = v;\n            }\n        }\n    }\n    return edges;\n}\n\nvector<int> growCluster(int seed, int targetSize, const vector<char>& used) {\n    vector<int> cluster;\n    cluster.reserve(targetSize);\n    vector<char> inCluster(N, 0);\n    vector<ll> mind(N, INFLL);\n\n    cluster.push_back(seed);\n    inCluster[seed] = 1;\n    for (int i = 0; i < N; ++i) {\n        if (!used[i] && !inCluster[i]) mind[i] = d2(seed, i);\n    }\n\n    while ((int)cluster.size() < targetSize) {\n        int best = -1;\n        for (int i = 0; i < N; ++i) {\n            if (used[i] || inCluster[i]) continue;\n            if (best == -1 ||\n                mind[i] < mind[best] ||\n                (mind[i] == mind[best] && densityScore[i] < densityScore[best]) ||\n                (mind[i] == mind[best] && densityScore[i] == densityScore[best] && i < best)) {\n                best = i;\n            }\n        }\n        if (best == -1) break;\n        cluster.push_back(best);\n        inCluster[best] = 1;\n        for (int i = 0; i < N; ++i) {\n            if (used[i] || inCluster[i]) continue;\n            ll w = d2(best, i);\n            if (w < mind[i]) mind[i] = w;\n        }\n    }\n    return cluster;\n}\n\nvector<vector<int>> buildDensityGreedyPartition() {\n    vector<vector<int>> groups(M);\n    vector<char> used(N, 0);\n\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n\n    for (int gi : order) {\n        int s = G[gi];\n\n        if (s == 1) {\n            int seed = -1;\n            for (int v : densityOrder) if (!used[v]) { seed = v; break; }\n            if (seed == -1) seed = 0;\n            used[seed] = 1;\n            groups[gi] = {seed};\n            continue;\n        }\n\n        vector<int> seeds;\n        int seedLimit = min(5, s);\n        for (int v : densityOrder) {\n            if (!used[v]) {\n                seeds.push_back(v);\n                if ((int)seeds.size() >= seedLimit) break;\n            }\n        }\n        if (seeds.empty()) {\n            for (int i = 0; i < N; ++i) if (!used[i]) { seeds.push_back(i); break; }\n        }\n\n        double bestScore = 1e100;\n        vector<int> bestCluster;\n        for (int seed : seeds) {\n            auto cluster = growCluster(seed, s, used);\n            if ((int)cluster.size() != s) continue;\n            double score = mstCostVec(cluster);\n            if (score < bestScore) {\n                bestScore = score;\n                bestCluster = move(cluster);\n            }\n        }\n\n        if ((int)bestCluster.size() != s) {\n            // Fallback: just take the first s unused cities.\n            bestCluster.clear();\n            for (int v : densityOrder) {\n                if (!used[v]) {\n                    bestCluster.push_back(v);\n                    if ((int)bestCluster.size() == s) break;\n                }\n            }\n        }\n\n        for (int v : bestCluster) used[v] = 1;\n        groups[gi] = move(bestCluster);\n    }\n\n    return groups;\n}\n\nvector<vector<int>> buildContiguousPartition(const vector<int>& cityOrder, const vector<int>& groupOrder) {\n    vector<vector<int>> groups(M);\n    int p = 0;\n    for (int gi : groupOrder) {\n        groups[gi].assign(cityOrder.begin() + p, cityOrder.begin() + p + G[gi]);\n        p += G[gi];\n    }\n    return groups;\n}\n\nbool validatePartition(const vector<vector<int>>& groups) {\n    if ((int)groups.size() != M) return false;\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < M; ++i) {\n        if ((int)groups[i].size() != G[i]) return false;\n        for (int v : groups[i]) {\n            if (v < 0 || v >= N) return false;\n            if (++cnt[v] != 1) return false;\n        }\n    }\n    for (int v = 0; v < N; ++v) if (cnt[v] != 1) return false;\n    return true;\n}\n\ndouble evalPartition(const vector<vector<int>>& groups) {\n    double cost = 0.0;\n    for (const auto& g : groups) cost += mstCostVec(g);\n    return cost;\n}\n\nvector<int> chooseBestLocalOrder(const vector<int>& group) {\n    int k = (int)group.size();\n    if (k <= 1) return group;\n    if (k <= L) return group;\n\n    vector<vector<int>> cands;\n\n    auto add = [&](vector<int> v) {\n        cands.push_back(move(v));\n    };\n\n    add(group);\n    {\n        vector<int> v = group;\n        reverse(v.begin(), v.end());\n        add(move(v));\n    }\n\n    auto addSort = [&](auto cmp) {\n        vector<int> v = group;\n        sort(v.begin(), v.end(), cmp);\n        add(move(v));\n    };\n\n    addSort([&](int a, int b) {\n        if (exs[a] != exs[b]) return exs[a] < exs[b];\n        if (eys[a] != eys[b]) return eys[a] < eys[b];\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        if (eys[a] != eys[b]) return eys[a] < eys[b];\n        if (exs[a] != exs[b]) return exs[a] < exs[b];\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        ll sa = (ll)exs[a] + eys[a];\n        ll sb = (ll)exs[b] + eys[b];\n        if (sa != sb) return sa < sb;\n        return a < b;\n    });\n    addSort([&](int a, int b) {\n        ll da = (ll)exs[a] - eys[a];\n        ll db = (ll)exs[b] - eys[b];\n        if (da != db) return da < db;\n        return a < b;\n    });\n\n    for (int o = 0; o < 8; ++o) {\n        addSort([&](int a, int b) {\n            ull ka, kb;\n            {\n                int x = exs[a], y = eys[a];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                ka = hilbertOrder(x, y);\n            }\n            {\n                int x = exs[b], y = eys[b];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                kb = hilbertOrder(x, y);\n            }\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n    }\n\n    {\n        vector<int> v = buildMSTPreorder(group);\n        add(move(v));\n        vector<int> w = cands.back();\n        reverse(w.begin(), w.end());\n        add(move(w));\n    }\n\n    double best = 1e100;\n    vector<int> bestOrd = group;\n    for (auto& cand : cands) {\n        double sc = estimateOrderCost(cand);\n        if (sc < best) {\n            best = sc;\n            bestOrd = cand;\n        }\n    }\n    return bestOrd;\n}\n\nBuiltGroup buildGroupTree(const vector<int>& group) {\n    BuiltGroup res;\n    int k = (int)group.size();\n    if (k == 0) return res;\n\n    res.cities = chooseBestLocalOrder(group);\n\n    if (k == 1) return res;\n\n    if (k == 2) {\n        int a = res.cities[0], b = res.cities[1];\n        if (a > b) swap(a, b);\n        res.edges.push_back({a, b});\n        return res;\n    }\n\n    if (k <= L) {\n        if (queries_used < Q) res.edges = queryTree(res.cities);\n        else res.edges = primTree(res.cities);\n        if ((int)res.edges.size() != k - 1) res.edges = primTree(res.cities);\n        return res;\n    }\n\n    auto chunks = splitChunks(res.cities);\n\n    for (auto& ch : chunks) {\n        int s = (int)ch.size();\n        if (s == 1) continue;\n        if (s == 2) {\n            int a = ch[0], b = ch[1];\n            if (a > b) swap(a, b);\n            res.edges.push_back({a, b});\n        } else {\n            vector<pair<int,int>> got;\n            if (queries_used < Q) got = queryTree(ch);\n            else got = primTree(ch);\n            if ((int)got.size() != s - 1) got = primTree(ch);\n            res.edges.insert(res.edges.end(), got.begin(), got.end());\n        }\n    }\n\n    if (chunks.size() > 1) {\n        auto cross = buildChunkMSTEdges(chunks);\n        res.edges.insert(res.edges.end(), cross.begin(), cross.end());\n    }\n\n    if ((int)res.edges.size() != k - 1) {\n        res.edges = primTree(res.cities);\n    }\n\n    return res;\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    lx.resize(N); rx.resize(N); ly.resize(N); ry.resize(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    exs.resize(N);\n    eys.resize(N);\n    for (int i = 0; i < N; ++i) {\n        exs[i] = lx[i] + rx[i];\n        eys[i] = ly[i] + ry[i];\n    }\n\n    dist2Mat.assign(N, vector<ll>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = i; j < N; ++j) {\n            ll dx = (ll)exs[i] - exs[j];\n            ll dy = (ll)eys[i] - eys[j];\n            ll d = dx * dx + dy * dy;\n            dist2Mat[i][j] = dist2Mat[j][i] = d;\n        }\n    }\n\n    // Density score: sum of the nearest few estimated distances.\n    int K = min(12, N - 1);\n    densityScore.assign(N, 0.0);\n    for (int i = 0; i < N; ++i) {\n        vector<ll> ds;\n        ds.reserve(N - 1);\n        for (int j = 0; j < N; ++j) if (i != j) ds.push_back(dist2Mat[i][j]);\n        nth_element(ds.begin(), ds.begin() + K, ds.end());\n        double s = 0.0;\n        for (int t = 0; t < K; ++t) s += sqrt((double)ds[t]);\n        densityScore[i] = s;\n    }\n\n    densityOrder.resize(N);\n    iota(densityOrder.begin(), densityOrder.end(), 0);\n    sort(densityOrder.begin(), densityOrder.end(), [&](int a, int b) {\n        if (densityScore[a] != densityScore[b]) return densityScore[a] < densityScore[b];\n        return a < b;\n    });\n\n    // Build candidate city orders.\n    vector<vector<int>> cityOrders;\n\n    auto addOrder = [&](vector<int> ord) {\n        cityOrders.push_back(move(ord));\n    };\n\n    auto makeSorted = [&](auto cmp) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), cmp);\n        return ord;\n    };\n\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            if (eys[a] != eys[b]) return eys[a] < eys[b];\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            if (eys[a] != eys[b]) return eys[a] < eys[b];\n            if (exs[a] != exs[b]) return exs[a] < exs[b];\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            ll sa = (ll)exs[a] + eys[a];\n            ll sb = (ll)exs[b] + eys[b];\n            if (sa != sb) return sa < sb;\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        auto ord = makeSorted([&](int a, int b) {\n            ll da = (ll)exs[a] - eys[a];\n            ll db = (ll)exs[b] - eys[b];\n            if (da != db) return da < db;\n            return a < b;\n        });\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        addOrder(densityOrder);\n        auto r = densityOrder;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    {\n        vector<int> all(N);\n        iota(all.begin(), all.end(), 0);\n        auto ord = buildMSTPreorder(all);\n        addOrder(ord);\n        auto r = ord;\n        reverse(r.begin(), r.end());\n        addOrder(r);\n    }\n    for (int o = 0; o < 8; ++o) {\n        auto ord = makeSorted([&](int a, int b) {\n            ull ka, kb;\n            {\n                int x = exs[a], y = eys[a];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                ka = hilbertOrder(x, y);\n            }\n            {\n                int x = exs[b], y = eys[b];\n                if (o & 1) x = 20000 - x;\n                if (o & 2) y = 20000 - y;\n                if (o & 4) swap(x, y);\n                kb = hilbertOrder(x, y);\n            }\n            if (ka != kb) return ka < kb;\n            return a < b;\n        });\n        addOrder(ord);\n    }\n\n    vector<int> groupOrderOrig(M), groupOrderAsc(M), groupOrderDesc(M);\n    iota(groupOrderOrig.begin(), groupOrderOrig.end(), 0);\n    groupOrderAsc = groupOrderOrig;\n    groupOrderDesc = groupOrderOrig;\n    sort(groupOrderAsc.begin(), groupOrderAsc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n    sort(groupOrderDesc.begin(), groupOrderDesc.end(), [&](int a, int b) {\n        if (G[a] != G[b]) return G[a] > G[b];\n        return a < b;\n    });\n\n    vector<vector<int>> groupOrders = {\n        groupOrderOrig, groupOrderAsc, groupOrderDesc\n    };\n\n    // Candidate partitions.\n    vector<vector<int>> fallback = buildContiguousPartition(cityOrders[0], groupOrders[0]);\n    vector<vector<int>> bestGroups = fallback;\n    double bestEval = evalPartition(bestGroups);\n\n    for (const auto& ord : cityOrders) {\n        for (const auto& gOrd : groupOrders) {\n            auto groups = buildContiguousPartition(ord, gOrd);\n            if (!validatePartition(groups)) continue;\n            double val = evalPartition(groups);\n            if (val < bestEval) {\n                bestEval = val;\n                bestGroups = move(groups);\n            }\n        }\n    }\n\n    auto dens = buildDensityGreedyPartition();\n    if (validatePartition(dens)) {\n        double val = evalPartition(dens);\n        if (val < bestEval) {\n            bestEval = val;\n            bestGroups = move(dens);\n        }\n    }\n\n    if (!validatePartition(bestGroups)) {\n        bestGroups = fallback;\n    }\n\n    // Build trees for each group.\n    vector<BuiltGroup> built(M);\n    for (int i = 0; i < M; ++i) {\n        built[i] = buildGroupTree(bestGroups[i]);\n        if ((int)built[i].edges.size() != G[i] - 1) {\n            built[i].cities = bestGroups[i];\n            built[i].edges = primTree(bestGroups[i]);\n        }\n    }\n\n    // Final sanity check before output.\n    vector<int> cnt(N, 0);\n    for (int i = 0; i < M; ++i) {\n        if ((int)built[i].cities.size() != G[i]) {\n            built = {};\n            break;\n        }\n        for (int v : built[i].cities) {\n            if (v < 0 || v >= N) {\n                built = {};\n                break;\n            }\n            cnt[v]++;\n        }\n        if (built.empty()) break;\n    }\n    bool ok = !built.empty();\n    if (ok) {\n        for (int v = 0; v < N; ++v) if (cnt[v] != 1) ok = false;\n    }\n    if (!ok) {\n        bestGroups = fallback;\n        built.assign(M, {});\n        for (int i = 0; i < M; ++i) {\n            built[i] = buildGroupTree(bestGroups[i]);\n            if ((int)built[i].edges.size() != G[i] - 1) {\n                built[i].cities = bestGroups[i];\n                built[i].edges = primTree(bestGroups[i]);\n            }\n        }\n    }\n\n    cout << \"!\\n\";\n    for (int i = 0; i < M; ++i) {\n        for (int j = 0; j < (int)built[i].cities.size(); ++j) {\n            if (j) cout << ' ';\n            cout << built[i].cities[j];\n        }\n        cout << '\\n';\n        for (auto [a, b] : built[i].edges) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int NMAX = 20;\nstatic constexpr int VMAX = 400;\nstatic constexpr int ACTION_LIMIT = 2 * 20 * 40; // 1600\n\nint N, M;\nvector<pair<int,int>> pts;\nvector<int> target_order;\n\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 bool inside(int r, int c) { return 0 <= r && r < N && 0 <= c && c < N; }\n\nstruct Board {\n    array<uint64_t, 7> w{}; // 7*64 = 448 >= 400\n};\n\ninline bool blocked(const Board& b, int v) {\n    return (b.w[v >> 6] >> (v & 63)) & 1ULL;\n}\ninline void toggle_cell(Board& b, int v) {\n    b.w[v >> 6] ^= (1ULL << (v & 63));\n}\n\nstruct BFSRes {\n    array<int, VMAX> dist;\n    array<int, VMAX> pre;\n    array<char, VMAX> pact;\n    array<char, VMAX> pdir;\n};\n\nstruct Opt {\n    int dir;\n    int cell;\n};\n\narray<array<int, 4>, VMAX> adj_cell;\nvector<vector<Opt>> cand_dirs;\nvector<array<int, NMAX>> row_rem, col_rem; // suffix counts of future targets\n\nint slide_dest(const Board& b, int u, int d) {\n    int r = u / N, c = u % N;\n    while (true) {\n        int nr = r + dr[d], nc = c + dc[d];\n        if (!inside(nr, nc)) break;\n        int v = id(nr, nc);\n        if (blocked(b, v)) break;\n        r = nr;\n        c = nc;\n    }\n    return id(r, c);\n}\n\nvoid bfs_dist(const Board& b, int s, array<int, VMAX>& dist) {\n    dist.fill(-1);\n    int q[VMAX];\n    int qh = 0, qt = 0;\n    dist[s] = 0;\n    q[qt++] = s;\n\n    while (qh < qt) {\n        int u = q[qh++];\n        int du = dist[u];\n        int r = u / N, c = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move\n            {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (inside(nr, nc)) {\n                    int v = id(nr, nc);\n                    if (!blocked(b, v) && dist[v] == -1) {\n                        dist[v] = du + 1;\n                        q[qt++] = v;\n                    }\n                }\n            }\n            // Slide\n            {\n                int v = slide_dest(b, u, d);\n                if (v != u && dist[v] == -1) {\n                    dist[v] = du + 1;\n                    q[qt++] = v;\n                }\n            }\n        }\n    }\n}\n\nBFSRes bfs_path(const Board& b, int s) {\n    BFSRes res;\n    res.dist.fill(-1);\n    res.pre.fill(-1);\n    res.pact.fill(0);\n    res.pdir.fill(0);\n\n    int q[VMAX];\n    int qh = 0, qt = 0;\n    res.dist[s] = 0;\n    res.pre[s] = -2;\n    q[qt++] = s;\n\n    while (qh < qt) {\n        int u = q[qh++];\n        int du = res.dist[u];\n        int r = u / N, c = u % N;\n\n        for (int d = 0; d < 4; ++d) {\n            // Move\n            {\n                int nr = r + dr[d], nc = c + dc[d];\n                if (inside(nr, nc)) {\n                    int v = id(nr, nc);\n                    if (!blocked(b, v) && res.dist[v] == -1) {\n                        res.dist[v] = du + 1;\n                        res.pre[v] = u;\n                        res.pact[v] = 'M';\n                        res.pdir[v] = dch[d];\n                        q[qt++] = v;\n                    }\n                }\n            }\n            // Slide\n            {\n                int v = slide_dest(b, u, d);\n                if (v != u && res.dist[v] == -1) {\n                    res.dist[v] = du + 1;\n                    res.pre[v] = u;\n                    res.pact[v] = 'S';\n                    res.pdir[v] = dch[d];\n                    q[qt++] = v;\n                }\n            }\n        }\n    }\n    return res;\n}\n\nvector<pair<char,char>> reconstruct_path(const BFSRes& res, int s, int t) {\n    vector<pair<char,char>> path;\n    if (res.dist[t] == -1) return path;\n    for (int v = t; v != s; v = res.pre[v]) {\n        path.push_back({res.pact[v], res.pdir[v]});\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\ninline int cell_util(int start, int v) {\n    int r = v / N, c = v % N;\n    return row_rem[start][r] + col_rem[start][c];\n}\n\nstruct Applied {\n    Board bd;\n    int toggles = 0;\n    int util = 0;\n};\n\nApplied apply_mask(const Board& base, const vector<Opt>& ops, int mask, int utilStart) {\n    Applied res;\n    res.bd = base;\n    for (int i = 0; i < (int)ops.size(); ++i) {\n        if ((mask >> i) & 1) {\n            int cell = ops[i].cell;\n            bool was = blocked(res.bd, cell);\n            toggle_cell(res.bd, cell);\n            ++res.toggles;\n            int u = cell_util(utilStart, cell);\n            res.util += was ? -u : +u;\n        }\n    }\n    return res;\n}\n\nstruct Cand {\n    bool ok = false;\n    bool hasFuture = false;\n    int total = INT_MAX;    // current step + best next step\n    int curCost = INT_MAX;  // current step only\n    int util = INT_MIN;\n    int toggles = INT_MAX;\n    int mask = 0;\n    Board after;\n};\n\nbool better_with_future(const Cand& a, const Cand& b) {\n    if (a.total != b.total) return a.total < b.total;\n    if (a.util != b.util) return a.util > b.util;\n    if (a.curCost != b.curCost) return a.curCost < b.curCost;\n    if (a.toggles != b.toggles) return a.toggles < b.toggles;\n    return a.mask < b.mask;\n}\n\nbool better_without_future(const Cand& a, const Cand& b) {\n    if (a.curCost != b.curCost) return a.curCost < b.curCost;\n    if (a.util != b.util) return a.util > b.util;\n    if (a.toggles != b.toggles) return a.toggles < b.toggles;\n    return a.mask < b.mask;\n}\n\nCand evaluate_current(const Board& board, int idx, int mask) {\n    Cand c;\n    c.mask = mask;\n\n    const auto& ops = cand_dirs[idx];\n    int cur = id(pts[idx].first, pts[idx].second);\n    int nxt = id(pts[idx + 1].first, pts[idx + 1].second);\n\n    int utilStartCur = min(M + 1, idx + 2);\n    Applied ap = apply_mask(board, ops, mask, utilStartCur);\n\n    array<int, VMAX> dist;\n    bfs_dist(ap.bd, cur, dist);\n    if (dist[nxt] == -1) return c;\n\n    // All remaining targets must stay reachable\n    for (int j = idx + 1; j < M; ++j) {\n        if (dist[id(pts[j].first, pts[j].second)] == -1) return c;\n    }\n\n    c.ok = true;\n    c.curCost = ap.toggles + dist[nxt];\n    c.util = ap.util;\n    c.toggles = ap.toggles;\n    c.after = ap.bd;\n\n    // One-step lookahead\n    if (idx + 2 < M) {\n        const auto& ops2 = cand_dirs[idx + 1];\n        int nxt2 = id(pts[idx + 2].first, pts[idx + 2].second);\n        int utilStartNext = min(M + 1, idx + 3);\n\n        bool found = false;\n        int bestFutureCost = INT_MAX;\n        int bestFutureUtil = INT_MIN;\n        int bestFutureToggles = INT_MAX;\n\n        int maxMask2 = 1 << (int)ops2.size();\n        for (int mask2 = 0; mask2 < maxMask2; ++mask2) {\n            Applied ap2 = apply_mask(ap.bd, ops2, mask2, utilStartNext);\n\n            array<int, VMAX> dist2;\n            bfs_dist(ap2.bd, nxt, dist2);\n            if (dist2[nxt2] == -1) continue;\n\n            bool ok2 = true;\n            for (int j = idx + 2; j < M; ++j) {\n                if (dist2[id(pts[j].first, pts[j].second)] == -1) {\n                    ok2 = false;\n                    break;\n                }\n            }\n            if (!ok2) continue;\n\n            int futCost = ap2.toggles + dist2[nxt2];\n            int futUtil = ap2.util;\n\n            if (!found ||\n                futCost < bestFutureCost ||\n                (futCost == bestFutureCost && futUtil > bestFutureUtil) ||\n                (futCost == bestFutureCost && futUtil == bestFutureUtil && ap2.toggles < bestFutureToggles)) {\n                found = true;\n                bestFutureCost = futCost;\n                bestFutureUtil = futUtil;\n                bestFutureToggles = ap2.toggles;\n            }\n        }\n\n        if (found) {\n            c.hasFuture = true;\n            c.total = c.curCost + bestFutureCost;\n            c.util += bestFutureUtil;\n        }\n    }\n\n    return c;\n}\n\nvector<pair<char,char>> build_baseline() {\n    Board empty;\n    vector<pair<char,char>> ans;\n    ans.reserve(ACTION_LIMIT);\n\n    for (int k = 0; k + 1 < M; ++k) {\n        int s = id(pts[k].first, pts[k].second);\n        int t = id(pts[k + 1].first, pts[k + 1].second);\n        auto res = bfs_path(empty, s);\n        auto path = reconstruct_path(res, s, t);\n        ans.insert(ans.end(), path.begin(), path.end());\n    }\n    return ans;\n}\n\nbool simulate_solution(const vector<pair<char,char>>& acts) {\n    Board b;\n    int cur = id(pts[0].first, pts[0].second);\n    int next_idx = 1;\n\n    auto advance = [&]() {\n        while (next_idx < M && cur == id(pts[next_idx].first, pts[next_idx].second)) {\n            ++next_idx;\n        }\n    };\n    advance();\n\n    for (auto [a, ch] : acts) {\n        int d = -1;\n        for (int i = 0; i < 4; ++i) if (dch[i] == ch) d = i;\n        if (d == -1) return false;\n\n        int r = cur / N, c = cur % N;\n        if (a == 'A') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n            toggle_cell(b, id(nr, nc));\n        } else if (a == 'M') {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) return false;\n            int v = id(nr, nc);\n            if (blocked(b, v)) return false;\n            cur = v;\n        } else if (a == 'S') {\n            while (true) {\n                int nr = cur / N + dr[d];\n                int nc = cur % N + dc[d];\n                if (!inside(nr, nc)) break;\n                int v = id(nr, nc);\n                if (blocked(b, v)) break;\n                cur = v;\n            }\n        } else {\n            return false;\n        }\n        advance();\n    }\n    return next_idx == M;\n}\n\nvector<pair<char,char>> build_optimized(bool& ok) {\n    ok = true;\n    Board board;\n    vector<pair<char,char>> ans;\n    ans.reserve(ACTION_LIMIT);\n\n    for (int idx = 0; idx + 1 < M; ++idx) {\n        const auto& ops = cand_dirs[idx];\n        int m = (int)ops.size();\n\n        vector<Cand> cands;\n        cands.reserve(1 << m);\n\n        int maxMask = 1 << m;\n        for (int mask = 0; mask < maxMask; ++mask) {\n            Cand c = evaluate_current(board, idx, mask);\n            if (c.ok) cands.push_back(std::move(c));\n        }\n\n        if (cands.empty()) {\n            ok = false;\n            return {};\n        }\n\n        bool anyFuture = false;\n        for (const auto& c : cands) if (c.hasFuture) anyFuture = true;\n\n        Cand best;\n        bool found = false;\n\n        if (anyFuture) {\n            for (const auto& c : cands) {\n                if (!c.hasFuture) continue;\n                if (!found || better_with_future(c, best)) {\n                    best = c;\n                    found = true;\n                }\n            }\n        } else {\n            for (const auto& c : cands) {\n                if (!found || better_without_future(c, best)) {\n                    best = c;\n                    found = true;\n                }\n            }\n        }\n\n        if (!found) {\n            ok = false;\n            return {};\n        }\n\n        // Emit alters\n        for (int i = 0; i < m; ++i) {\n            if ((best.mask >> i) & 1) {\n                ans.push_back({'A', dch[ops[i].dir]});\n            }\n        }\n\n        // Emit shortest path to next target on the chosen board\n        int s = id(pts[idx].first, pts[idx].second);\n        int t = id(pts[idx + 1].first, pts[idx + 1].second);\n        auto pathRes = bfs_path(best.after, s);\n        auto path = reconstruct_path(pathRes, s, t);\n        if (path.empty() && s != t) {\n            ok = false;\n            return {};\n        }\n        ans.insert(ans.end(), path.begin(), path.end());\n\n        board = best.after;\n        if ((int)ans.size() > ACTION_LIMIT) {\n            ok = false;\n            return {};\n        }\n    }\n\n    return ans;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    pts.resize(M);\n    target_order.assign(N * N, -1);\n\n    for (int i = 0; i < M; ++i) {\n        cin >> pts[i].first >> pts[i].second;\n        target_order[id(pts[i].first, pts[i].second)] = i;\n    }\n\n    // Precompute legal toggle directions around each target (exclude target cells themselves).\n    cand_dirs.assign(M, {});\n    for (int i = 0; i < M; ++i) {\n        int r = pts[i].first, c = pts[i].second;\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc)) continue;\n            int v = id(nr, nc);\n            if (target_order[v] == -1) {\n                cand_dirs[i].push_back({d, v});\n            }\n        }\n    }\n\n    // Suffix counts of future targets by row/column, used as a cheap wall-utility signal.\n    row_rem.assign(M + 2, {});\n    col_rem.assign(M + 2, {});\n    for (int s = 0; s <= M + 1; ++s) {\n        row_rem[s].fill(0);\n        col_rem[s].fill(0);\n    }\n    for (int s = M - 1; s >= 0; --s) {\n        row_rem[s] = row_rem[s + 1];\n        col_rem[s] = col_rem[s + 1];\n        row_rem[s][pts[s].first]++;\n        col_rem[s][pts[s].second]++;\n    }\n\n    bool ok = false;\n    auto optimized = build_optimized(ok);\n    bool optValid = ok && simulate_solution(optimized);\n\n    auto baseline = build_baseline();\n    bool baseValid = simulate_solution(baseline);\n\n    const vector<pair<char,char>>* out = nullptr;\n    if (optValid && (int)optimized.size() < (int)baseline.size()) out = &optimized;\n    else if (baseValid) out = &baseline;\n    else out = &optimized; // extremely unlikely fallback\n\n    for (auto [a, d] : *out) {\n        cout << a << ' ' << d << '\\n';\n    }\n    return 0;\n}"}}}